From daea2b7cd2a3883105a3dd585832f76b31879b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 27 Oct 2016 15:01:21 +0200 Subject: [PATCH] #913 Added SFI as a derived results depending on two user controllable case constants --- .../GeoMechDataModel/RigFemPartResults.cpp | 19 ++++ .../RigFemPartResultsCollection.cpp | 94 +++++++++++++++++++ .../RigFemPartResultsCollection.h | 5 + .../GeoMechDataModel/RigFemResultAddress.h | 39 ++++---- .../ProjectDataModel/RimGeoMechCase.cpp | 39 ++++++++ .../ProjectDataModel/RimGeoMechCase.h | 5 + 6 files changed, 184 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.cpp b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.cpp index de45b44d1a..bf0ea0250d 100644 --- a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.cpp +++ b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.cpp @@ -72,4 +72,23 @@ RigFemScalarResultFrames* RigFemPartResults::findScalarResult(const RigFemResult void RigFemPartResults::deleteScalarResult(const RigFemResultAddress& resVarAddr) { resultSets.erase(resVarAddr); // Refcounting is supposed to destroy the data. + + if (resVarAddr.representsAllTimeLapses()) + { + std::vector addressesToDelete; + for (auto it : resultSets) + { + if (it.first.resultPosType == resVarAddr.resultPosType + && it.first.fieldName == resVarAddr.fieldName + && it.first.componentName == resVarAddr.componentName) + { + addressesToDelete. push_back(it.first); + } + } + + for (RigFemResultAddress& addr: addressesToDelete) + { + resultSets.erase(addr); + } + } } diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.cpp b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.cpp index f67a18d274..45fb9e2515 100644 --- a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.cpp +++ b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.cpp @@ -41,6 +41,7 @@ #include "cafProgressInfo.h" #include "RigFemPartGrid.h" #include "cvfGeometryTools.h" +#include "cvfMath.h" //-------------------------------------------------------------------------------------------------- @@ -59,6 +60,10 @@ RigFemPartResultsCollection::RigFemPartResultsCollection(RifGeoMechReaderInterfa m_femPartResults[pIdx] = new RigFemPartResults; m_femPartResults[pIdx]->initResultSteps(stepNames); } + + m_cohesion = 10.0; + m_frictionAngleRad = cvf::Math::toRadians(30.0); + } //-------------------------------------------------------------------------------------------------- @@ -86,6 +91,20 @@ RigFormationNames* RigFemPartResultsCollection::activeFormationNames() return m_activeFormationNamesData.p(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFemPartResultsCollection::setCalculationParameters(double cohesion, double frictionAngleRad) +{ + m_cohesion = cohesion; + m_frictionAngleRad = frictionAngleRad; + + // Todo, delete all dependent results + this->deleteResult(RigFemResultAddress(RIG_ELEMENT_NODAL, "SE", "SFI", RigFemResultAddress::ALL_TIME_LAPSES)); + this->deleteResult(RigFemResultAddress(RIG_INTEGRATION_POINT, "SE", "SFI", RigFemResultAddress::ALL_TIME_LAPSES)); + +} + //-------------------------------------------------------------------------------------------------- /// Will always return a valid object, but it can be empty //-------------------------------------------------------------------------------------------------- @@ -187,6 +206,7 @@ std::map > RigFemPartResultsCollection::sc fieldCompNames = m_readerInterface->scalarElementNodeFieldAndComponentNames(); fieldCompNames["SE"].push_back("SEM"); + fieldCompNames["SE"].push_back("SFI"); fieldCompNames["SE"].push_back("S11"); fieldCompNames["SE"].push_back("S22"); @@ -242,6 +262,7 @@ std::map > RigFemPartResultsCollection::sc fieldCompNames = m_readerInterface->scalarIntegrationPointFieldAndComponentNames(); fieldCompNames["SE"].push_back("SEM"); + fieldCompNames["SE"].push_back("SFI"); fieldCompNames["SE"].push_back("S11"); fieldCompNames["SE"].push_back("S22"); @@ -479,6 +500,55 @@ RigFemScalarResultFrames* RigFemPartResultsCollection::calculateMeanStressSEM(in return dstDataFrames; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigFemScalarResultFrames* RigFemPartResultsCollection::calculateSFI(int partIndex, const RigFemResultAddress& resVarAddr) +{ + CVF_ASSERT(resVarAddr.fieldName == "SE" && resVarAddr.componentName == "SFI"); + + RigFemScalarResultFrames * se1Frames = nullptr; + RigFemScalarResultFrames * se3Frames = nullptr; + + se1Frames = this->findOrLoadScalarResult(partIndex, RigFemResultAddress(resVarAddr.resultPosType, "SE", "S1")); + se3Frames = this->findOrLoadScalarResult(partIndex, RigFemResultAddress(resVarAddr.resultPosType, "SE", "S3")); + + RigFemScalarResultFrames * dstDataFrames = m_femPartResults[partIndex]->createScalarResult(resVarAddr); + + float cohPrFricAngle = (float)(m_cohesion/tan(m_frictionAngleRad)); + float sinFricAng = sin(m_frictionAngleRad); + + int frameCount = se1Frames->frameCount(); + for ( int fIdx = 0; fIdx < frameCount; ++fIdx ) + { + const std::vector& se1Data = se1Frames->frameData(fIdx); + const std::vector& se3Data = se3Frames->frameData(fIdx); + + std::vector& dstFrameData = dstDataFrames->frameData(fIdx); + size_t valCount = se1Data.size(); + dstFrameData.resize(valCount); + + for ( size_t vIdx = 0; vIdx < valCount; ++vIdx ) + { + float se1 = se1Data[vIdx]; + float se3 = se3Data[vIdx]; + float se1Se3Diff = se1-se3; + + if ( fabs(se1Se3Diff) < 1e-7 ) + { + dstFrameData[vIdx] = std::numeric_limits::infinity(); + } + else + { + dstFrameData[vIdx] = ((cohPrFricAngle + 0.5*(se1Data[vIdx] + se3Data[vIdx])) * sin(m_frictionAngleRad)) / (0.5*(se1Data[vIdx] - se3Data[vIdx])); + } + } + } + + return dstDataFrames; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -724,6 +794,11 @@ RigFemScalarResultFrames* RigFemPartResultsCollection::calculateDerivedResult(in return calculateSurfaceAlignedStress(partIndex, resVarAddr); } + if (resVarAddr.fieldName == "SE" && resVarAddr.componentName == "SFI") + { + return calculateSFI(partIndex, resVarAddr); + } + if(resVarAddr.fieldName == "NE" && resVarAddr.componentName == "EV") { return calculateVolumetricStrain(partIndex, resVarAddr); @@ -1265,6 +1340,25 @@ void RigFemPartResultsCollection::deleteResult(const RigFemResultAddress& resVar } m_resultStatistics.erase(resVarAddr); + + if ( resVarAddr.representsAllTimeLapses() ) + { + std::vector addressesToDelete; + for ( auto it : m_resultStatistics ) + { + if ( it.first.resultPosType == resVarAddr.resultPosType + && it.first.fieldName == resVarAddr.fieldName + && it.first.componentName == resVarAddr.componentName ) + { + addressesToDelete.push_back(it.first); + } + } + + for ( RigFemResultAddress& addr: addressesToDelete ) + { + m_resultStatistics.erase(addr); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.h b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.h index 19acbe0769..b4450b8ca6 100644 --- a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.h +++ b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.h @@ -42,6 +42,7 @@ public: void setActiveFormationNames(RigFormationNames* activeFormationNames); RigFormationNames* activeFormationNames(); + void setCalculationParameters(double cohesion, double frictionAngleRad); std::map > scalarFieldAndComponentNames(RigFemResultPosEnum resPos); std::vector stepNames(); @@ -81,6 +82,7 @@ private: RigFemScalarResultFrames* calculateEnIpPorBarResult(int partIndex, const RigFemResultAddress &convertedResultAddr); RigFemScalarResultFrames* calculateTimeLapseResult(int partIndex, const RigFemResultAddress& resVarAddr); RigFemScalarResultFrames* calculateMeanStressSEM(int partIndex, const RigFemResultAddress& resVarAddr); + RigFemScalarResultFrames* calculateSFI(int partIndex, const RigFemResultAddress& resVarAddr); RigFemScalarResultFrames* calculateMeanStressSTM(int partIndex, const RigFemResultAddress& resVarAddr); RigFemScalarResultFrames* calculateDeviatoricStress(int partIndex, const RigFemResultAddress& resVarAddr); RigFemScalarResultFrames* calculateVolumetricStrain(int partIndex, const RigFemResultAddress& resVarAddr); @@ -91,6 +93,9 @@ private: cvf::cref m_femParts; cvf::ref m_activeFormationNamesData; + double m_cohesion; + double m_frictionAngleRad; + RigStatisticsDataCache* statistics(const RigFemResultAddress& resVarAddr); std::vector< RigFemResultAddress> getResAddrToComponentsToRead(const RigFemResultAddress& resVarAddr); std::map > m_resultStatistics; diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemResultAddress.h b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemResultAddress.h index 854c05d0e6..0010f2bada 100644 --- a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemResultAddress.h +++ b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemResultAddress.h @@ -29,31 +29,36 @@ class RigFemResultAddress { public: -RigFemResultAddress(RigFemResultPosEnum resPosType, - const std::string& aFieldName, - const std::string& aComponentName) - : resultPosType(resPosType), - fieldName(aFieldName), - componentName(aComponentName), - timeLapseBaseFrameIdx(-1) - {} + RigFemResultAddress(RigFemResultPosEnum resPosType, + const std::string& aFieldName, + const std::string& aComponentName) + : resultPosType(resPosType), + fieldName(aFieldName), + componentName(aComponentName), + timeLapseBaseFrameIdx(-1) + { + } -RigFemResultAddress(RigFemResultPosEnum resPosType, - const std::string& aFieldName, - const std::string& aComponentName, - int aTimeLapseBaseFrame) - : resultPosType(resPosType), - fieldName(aFieldName), - componentName(aComponentName), - timeLapseBaseFrameIdx(aTimeLapseBaseFrame) - {} + RigFemResultAddress(RigFemResultPosEnum resPosType, + const std::string& aFieldName, + const std::string& aComponentName, + int aTimeLapseBaseFrame) + : resultPosType(resPosType), + fieldName(aFieldName), + componentName(aComponentName), + timeLapseBaseFrameIdx(aTimeLapseBaseFrame) + { + } RigFemResultPosEnum resultPosType; std::string fieldName; std::string componentName; int timeLapseBaseFrameIdx; + static const int ALL_TIME_LAPSES = -2; + bool isTimeLapse() const { return timeLapseBaseFrameIdx >= 0;} + bool representsAllTimeLapses() const { return timeLapseBaseFrameIdx == ALL_TIME_LAPSES;} bool isValid() const { diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp index 100c7c9749..8cd2bae400 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp @@ -50,6 +50,10 @@ RimGeoMechCase::RimGeoMechCase(void) m_caseFileName.uiCapability()->setUiReadOnly(true); CAF_PDM_InitFieldNoDefault(&geoMechViews, "GeoMechViews", "", "", "", ""); geoMechViews.uiCapability()->setUiHidden(true); + + CAF_PDM_InitField(&m_cohesion, "CaseCohesion", 10.0, "Cohesion", "", "Used to calculate the SE:SFI result", ""); + CAF_PDM_InitField(&m_frictionAngleDeg, "FrctionAngleDeg", 30.0, "Friction Angle [Deg]", "", "Used to calculate the SE:SFI result", ""); + } //-------------------------------------------------------------------------------------------------- @@ -254,6 +258,25 @@ void RimGeoMechCase::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c { updateFormationNamesData(); } + + if (changedField == &m_cohesion || changedField == &m_frictionAngleDeg) + { + + RigGeoMechCaseData* rigCaseData = geoMechData(); + if ( rigCaseData && rigCaseData->femPartResults() ) + { + rigCaseData->femPartResults()->setCalculationParameters(m_cohesion(), cvf::Math::toRadians(m_frictionAngleDeg())); + } + + std::vector views = this->views(); + for ( RimView* view : views ) + { + if ( view ) // Todo: only those using the variable actively + { + view->scheduleCreateDisplayModelAndRedraw(); + } + } + } } //-------------------------------------------------------------------------------------------------- @@ -313,3 +336,19 @@ QString RimGeoMechCase::subStringOfDigits(const QString& inputString, int number return ""; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGeoMechCase::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + uiOrdering.add(&caseUserDescription); + uiOrdering.add(&caseId); + uiOrdering.add(&m_caseFileName); + + auto group = uiOrdering.addNewGroup("Case Options"); + group->add(&activeFormationNames); + group->add(&m_cohesion); + group->add(&m_frictionAngleDeg); + +} + diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechCase.h b/ApplicationCode/ProjectDataModel/RimGeoMechCase.h index 66b2b0ef18..08926ce81a 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechCase.h +++ b/ApplicationCode/ProjectDataModel/RimGeoMechCase.h @@ -73,6 +73,7 @@ public: private: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; virtual void updateFormationNamesData() override; @@ -82,4 +83,8 @@ private: private: cvf::ref m_geoMechCaseData; caf::PdmField m_caseFileName; + caf::PdmField m_cohesion; + caf::PdmField m_frictionAngleDeg; +protected: + };