///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2015- Statoil ASA // Copyright (C) 2015- Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RigFemPartResultsCollection.h" #include "RiaLogging.h" #include "RiaResultNames.h" #include "RifElementPropertyReader.h" #include "RifGeoMechReaderInterface.h" #include "RigFemNativeStatCalc.h" #include "RigFemPartCollection.h" #include "RigFemPartResultCalculatorBarConverted.h" #include "RigFemPartResultCalculatorCompaction.h" #include "RigFemPartResultCalculatorDSM.h" #include "RigFemPartResultCalculatorED.h" #include "RigFemPartResultCalculatorEV.h" #include "RigFemPartResultCalculatorEnIpPorBar.h" #include "RigFemPartResultCalculatorFOS.h" #include "RigFemPartResultCalculatorFormationIndices.h" #include "RigFemPartResultCalculatorGamma.h" #include "RigFemPartResultCalculatorInitialPorosity.h" #include "RigFemPartResultCalculatorMudWeightWindow.h" #include "RigFemPartResultCalculatorNE.h" #include "RigFemPartResultCalculatorNodalGradients.h" #include "RigFemPartResultCalculatorNormalSE.h" #include "RigFemPartResultCalculatorNormalST.h" #include "RigFemPartResultCalculatorNormalized.h" #include "RigFemPartResultCalculatorPoreCompressibility.h" #include "RigFemPartResultCalculatorPorosityPermeability.h" #include "RigFemPartResultCalculatorPrincipalStrain.h" #include "RigFemPartResultCalculatorPrincipalStress.h" #include "RigFemPartResultCalculatorQ.h" #include "RigFemPartResultCalculatorSFI.h" #include "RigFemPartResultCalculatorSM.h" #include "RigFemPartResultCalculatorShearSE.h" #include "RigFemPartResultCalculatorShearST.h" #include "RigFemPartResultCalculatorShearSlipIndicator.h" #include "RigFemPartResultCalculatorStressAnisotropy.h" #include "RigFemPartResultCalculatorStressGradients.h" #include "RigFemPartResultCalculatorSurfaceAlignedStress.h" #include "RigFemPartResultCalculatorSurfaceAngles.h" #include "RigFemPartResultCalculatorTimeLapse.h" #include "RigFemPartResults.h" #include "RigFemScalarResultFrames.h" #include "RigFormationNames.h" #include "RigStatisticsDataCache.h" #include "RigWbsParameter.h" #include "RimMainPlotCollection.h" #include "RimMudWeightWindowParameters.h" #include "RimProject.h" #include "RimWellLogPlot.h" #include "RimWellLogPlotCollection.h" #include "Riu3DMainWindowTools.h" #ifdef USE_ODB_API #include "RifOdbReader.h" #endif #include "cafProgressInfo.h" #include "cafTensor3.h" #include "cvfMath.h" #include #include #include //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const std::string RigFemPartResultsCollection::FIELD_NAME_COMPACTION = "COMPACTION"; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigFemPartResultsCollection::RigFemPartResultsCollection( RifGeoMechReaderInterface* readerInterface, RifElementPropertyReader* elementPropertyReader, const RigFemPartCollection* femPartCollection ) { CVF_ASSERT( readerInterface ); CVF_ASSERT( elementPropertyReader ); m_readerInterface = readerInterface; m_elementPropertyReader = elementPropertyReader; m_femParts = femPartCollection; m_femPartResults.resize( m_femParts->partCount() ); std::vector filteredStepNames = m_readerInterface->filteredStepNames(); for ( auto& femPartResult : m_femPartResults ) { femPartResult = new RigFemPartResults; femPartResult->initResultSteps( filteredStepNames ); } m_cohesion = 10.0; m_frictionAngleRad = cvf::Math::toRadians( 30.0 ); m_normalizationAirGap = 0.0; m_biotFixedFactor = 1.0; m_biotResultAddress = ""; m_referenceTimeStep = 0; m_initialPermeabilityFixed = 1.0; m_initialPermeabilityResultAddress = ""; m_permeabilityExponent = 1.0; m_airGapMudWeightWindow = 0.0; m_referenceLayerMudWeightWindow = 0; m_shMultiplierMudWeightWindow = 1.05; m_nonReservoirPorePressureAddressMudWeightWindow = ""; m_hydrostaticMultiplierPPNonResMudWeightWindow = 1.0; m_waterDensityShearSlipIndicator = 1.03; m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorTimeLapse( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorSurfaceAngles( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorSurfaceAlignedStress( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorBarConverted( *this, "S-Bar", "S" ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorBarConverted( *this, "POR-Bar", "POR" ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorEnIpPorBar( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorNodalGradients( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorCompaction( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorSFI( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorDSM( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorFOS( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorED( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorEV( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorSM( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorQ( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorStressGradients( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorNormalized( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorNormalST( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorShearST( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorNormalSE( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorShearSE( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorNE( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorGamma( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorPrincipalStrain( *this, "NE", "E" ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorPrincipalStrain( *this, "LE", "LE" ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorPrincipalStrain( *this, "PE", "PE" ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorPrincipalStress( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorStressAnisotropy( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorPoreCompressibility( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorPorosityPermeability( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorInitialPorosity( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorMudWeightWindow( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorShearSlipIndicator( *this ) ) ); m_resultCalculators.push_back( std::unique_ptr( new RigFemPartResultCalculatorFormationIndices( *this ) ) ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigFemPartResultsCollection::~RigFemPartResultsCollection() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::setActiveFormationNames( RigFormationNames* activeFormationNames ) { m_activeFormationNamesData = activeFormationNames; RimProject* project = RimProject::current(); if ( project ) { if ( project->mainPlotCollection() ) { RimWellLogPlotCollection* plotCollection = project->mainPlotCollection()->wellLogPlotCollection(); if ( plotCollection ) { for ( auto wellLogPlot : plotCollection->wellLogPlots() ) { wellLogPlot->loadDataAndUpdate(); } } } } this->deleteResult( RigFemResultAddress( RIG_FORMATION_NAMES, "Active Formation Names", "" ) ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigFemPartResultsCollection::formationNames() const { if ( activeFormationNames() ) { return activeFormationNames()->formationNames(); } return {}; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const RigFormationNames* RigFemPartResultsCollection::activeFormationNames() const { return m_activeFormationNamesData.p(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::addElementPropertyFiles( const std::vector& filenames ) { std::vector newAddresses; for ( const QString& filename : filenames ) { m_elementPropertyReader->addFile( filename.toStdString() ); // Collect all addresses which was added in this file std::vector fields = m_elementPropertyReader->fieldsInFile( filename.toStdString() ); for ( const std::string& field : fields ) { newAddresses.push_back( RigFemResultAddress( RIG_ELEMENT, field, "" ) ); } } // Invalidate previous result if already in cache for ( const RigFemResultAddress& address : newAddresses ) { this->deleteResult( address ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigFemPartResultsCollection::removeElementPropertyFiles( const std::vector& filenames ) { std::vector addressesToRemove; for ( const QString& filename : filenames ) { std::vector fields = m_elementPropertyReader->fieldsInFile( filename.toStdString() ); for ( const std::string& field : fields ) { addressesToRemove.push_back( RigFemResultAddress( RIG_ELEMENT, field, "" ) ); } m_elementPropertyReader->removeFile( filename.toStdString() ); } for ( const RigFemResultAddress& address : addressesToRemove ) { this->deleteResult( address ); } return addressesToRemove; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::map RigFemPartResultsCollection::addressesInElementPropertyFiles( const std::vector& filenames ) { std::map fieldsInFile; for ( const QString& filename : filenames ) { std::vector fields = m_elementPropertyReader->fieldsInFile( filename.toStdString() ); for ( const std::string& field : fields ) { fieldsInFile[field] = filename; } } return fieldsInFile; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::setCalculationParameters( double cohesion, double frictionAngleRad ) { m_cohesion = cohesion; m_frictionAngleRad = frictionAngleRad; std::vector dependentResults; dependentResults.push_back( RigFemResultAddress( RIG_ELEMENT_NODAL, "SE", "SFI" ) ); dependentResults.push_back( RigFemResultAddress( RIG_ELEMENT_NODAL, "SE", "DSM" ) ); dependentResults.push_back( RigFemResultAddress( RIG_ELEMENT_NODAL, "SE", "FOS" ) ); dependentResults.push_back( RigFemResultAddress( RIG_INTEGRATION_POINT, "SE", "SFI" ) ); dependentResults.push_back( RigFemResultAddress( RIG_INTEGRATION_POINT, "SE", "DSM" ) ); dependentResults.push_back( RigFemResultAddress( RIG_INTEGRATION_POINT, "SE", "FOS" ) ); dependentResults.push_back( RigFemResultAddress( RIG_ELEMENT_NODAL_FACE, "SE", "FAULTMOB" ) ); dependentResults.push_back( RigFemResultAddress( RIG_ELEMENT_NODAL_FACE, "SE", "PCRIT" ) ); deleteResultForAllTimeSteps( dependentResults ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::setBiotCoefficientParameters( double biotFixedFactor, const QString& biotResultAddress ) { m_biotFixedFactor = biotFixedFactor; m_biotResultAddress = biotResultAddress; // Invalidate all results which depends on biot coefficient (directly or indirectly) std::vector dependentResults; for ( auto elementType : { RIG_ELEMENT_NODAL, RIG_INTEGRATION_POINT } ) { dependentResults.push_back( RigFemResultAddress( elementType, "COMPRESSIBILITY", "PORE" ) ); dependentResults.push_back( RigFemResultAddress( elementType, "COMPRESSIBILITY", "VERTICAL" ) ); dependentResults.push_back( RigFemResultAddress( elementType, "COMPRESSIBILITY", "VERTICAL-RATIO" ) ); } deleteResultForAllTimeSteps( dependentResults ); // Depends on COMRESSIBILITY.PORE which depends on biot coefficient std::set initPermResults = initialPermeabilityDependentResults(); for ( auto result : initPermResults ) { deleteResult( result ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::setReferenceTimeStep( int referenceTimeStep ) { m_referenceTimeStep = referenceTimeStep; std::set results = referenceCaseDependentResults(); for ( auto result : results ) { deleteResult( result ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int RigFemPartResultsCollection::referenceTimeStep() const { return m_referenceTimeStep; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::setPermeabilityParameters( double fixedInitalPermeability, const QString& initialPermeabilityAddress, double permeabilityExponent ) { m_initialPermeabilityFixed = fixedInitalPermeability; m_initialPermeabilityResultAddress = initialPermeabilityAddress; m_permeabilityExponent = permeabilityExponent; std::set results = initialPermeabilityDependentResults(); for ( auto result : results ) { deleteResult( result ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RigFemPartResultsCollection::initialPermeabilityFixed() const { return m_initialPermeabilityFixed; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RigFemPartResultsCollection::initialPermeabilityAddress() const { return m_initialPermeabilityResultAddress; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RigFemPartResultsCollection::permeabilityExponent() const { return m_permeabilityExponent; } //-------------------------------------------------------------------------------------------------- /// Will always return a valid object, but it can be empty //-------------------------------------------------------------------------------------------------- RigFemScalarResultFrames* RigFemPartResultsCollection::findOrLoadScalarResult( int partIndex, const RigFemResultAddress& resVarAddr ) { CVF_ASSERT( partIndex < (int)( m_femPartResults.size() ) ); CVF_ASSERT( m_readerInterface.notNull() ); CVF_ASSERT( resVarAddr.isValid() ); // If we have it in the cache, return it RigFemScalarResultFrames* frames = m_femPartResults[partIndex]->findScalarResult( resVarAddr ); if ( frames ) return frames; // Check whether a derived result is requested frames = calculateDerivedResult( partIndex, resVarAddr ); if ( frames ) return frames; if ( resVarAddr.resultPosType == RIG_ELEMENT ) { std::map> elementProperties = m_elementPropertyReader->readAllElementPropertiesInFileContainingField( resVarAddr.fieldName ); for ( auto [addrString, values] : elementProperties ) { RigFemResultAddress addressForElement( RIG_ELEMENT, addrString, "" ); RigFemScalarResultFrames* currentFrames = m_femPartResults[partIndex]->createScalarResult( addressForElement ); currentFrames->enableAsSingleFrameResult(); currentFrames->frameData( 0 ).swap( values ); } frames = m_femPartResults[partIndex]->findScalarResult( resVarAddr ); if ( frames ) { return frames; } else { return m_femPartResults[partIndex]->createScalarResult( resVarAddr ); } } // We need to read the data as bulk fields, and populate the correct scalar caches std::vector resultAddressOfComponents = this->getResAddrToComponentsToRead( resVarAddr ); if ( !resultAddressOfComponents.empty() ) { std::vector resultsForEachComponent; for ( const auto& resultAddressOfComponent : resultAddressOfComponents ) { resultsForEachComponent.push_back( m_femPartResults[partIndex]->createScalarResult( resultAddressOfComponent ) ); } int frameCount = this->frameCount(); caf::ProgressInfo progress( frameCount, "" ); progress.setProgressDescription( QString( "Loading Native Result %1 %2" ).arg( resVarAddr.fieldName.c_str(), resVarAddr.componentName.c_str() ) ); for ( int stepIndex = 0; stepIndex < frameCount; ++stepIndex ) { std::vector frameTimes = m_readerInterface->frameTimes( stepIndex ); int fIdx = (int)( frameTimes.size() - 1 ); std::vector*> componentDataVectors; for ( auto& componentResult : resultsForEachComponent ) { componentDataVectors.push_back( &( componentResult->frameData( stepIndex ) ) ); } switch ( resVarAddr.resultPosType ) { case RIG_NODAL: m_readerInterface->readNodeField( resVarAddr.fieldName, partIndex, stepIndex, fIdx, &componentDataVectors ); break; case RIG_ELEMENT_NODAL: m_readerInterface->readElementNodeField( resVarAddr.fieldName, partIndex, stepIndex, fIdx, &componentDataVectors ); break; case RIG_INTEGRATION_POINT: m_readerInterface->readIntegrationPointField( resVarAddr.fieldName, partIndex, stepIndex, fIdx, &componentDataVectors ); break; default: break; } progress.incrementProgress(); } // Now fetch the particular component requested, which should now exist and be read. frames = m_femPartResults[partIndex]->findScalarResult( resVarAddr ); } if ( !frames ) { frames = m_femPartResults[partIndex]->createScalarResult( resVarAddr ); // Create a dummy empty result, if // the request did not specify the // component. } return frames; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigFemScalarResultFrames* RigFemPartResultsCollection::createScalarResult( int partIndex, const RigFemResultAddress& resVarAddr ) { CVF_ASSERT( partIndex < static_cast( m_femPartResults.size() ) ); CVF_ASSERT( resVarAddr.isValid() ); return m_femPartResults[partIndex]->createScalarResult( resVarAddr ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::deleteAllScalarResults() { for ( cvf::ref results : m_femPartResults ) { results->deleteAllScalarResults(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::map> RigFemPartResultsCollection::scalarFieldAndComponentNames( RigFemResultPosEnum resPos ) { std::map> fieldCompNames; if ( resPos == RIG_FORMATION_NAMES ) { if ( activeFormationNames() ) fieldCompNames["Active Formation Names"]; } const std::vector stressComponentNames = getStressComponentNames(); const std::vector stressGradientComponentNames = getStressGradientComponentNames(); const std::vector stressAnisotropyComponentNames = getStressAnisotropyComponentNames(); if ( m_readerInterface.notNull() ) { if ( resPos == RIG_NODAL ) { fieldCompNames = m_readerInterface->scalarNodeFieldAndComponentNames(); fieldCompNames["POR-Bar"]; fieldCompNames[FIELD_NAME_COMPACTION]; } else if ( resPos == RIG_ELEMENT_NODAL ) { fieldCompNames = m_readerInterface->scalarElementNodeFieldAndComponentNames(); fieldCompNames["SE"].push_back( "SM" ); fieldCompNames["SE"].push_back( "SFI" ); fieldCompNames["SE"].push_back( "DSM" ); fieldCompNames["SE"].push_back( "FOS" ); for ( auto& s : stressComponentNames ) { fieldCompNames["SE"].push_back( s ); } for ( auto& s : stressAnisotropyComponentNames ) { fieldCompNames["SE"].push_back( s ); } fieldCompNames["SE"].push_back( "S1inc" ); fieldCompNames["SE"].push_back( "S1azi" ); fieldCompNames["SE"].push_back( "S2inc" ); fieldCompNames["SE"].push_back( "S2azi" ); fieldCompNames["SE"].push_back( "S3inc" ); fieldCompNames["SE"].push_back( "S3azi" ); fieldCompNames["ST"].push_back( "SM" ); fieldCompNames["ST"].push_back( "Q" ); fieldCompNames["ST"].push_back( "DPN" ); for ( auto& s : stressComponentNames ) { fieldCompNames["ST"].push_back( s ); } for ( auto& s : stressAnisotropyComponentNames ) { fieldCompNames["ST"].push_back( s ); } fieldCompNames["ST"].push_back( "S1inc" ); fieldCompNames["ST"].push_back( "S1azi" ); fieldCompNames["ST"].push_back( "S2inc" ); fieldCompNames["ST"].push_back( "S2azi" ); fieldCompNames["ST"].push_back( "S3inc" ); fieldCompNames["ST"].push_back( "S3azi" ); fieldCompNames["Gamma"].push_back( "Gamma1" ); fieldCompNames["Gamma"].push_back( "Gamma2" ); fieldCompNames["Gamma"].push_back( "Gamma3" ); fieldCompNames["Gamma"].push_back( "Gamma11" ); fieldCompNames["Gamma"].push_back( "Gamma22" ); fieldCompNames["Gamma"].push_back( "Gamma33" ); fieldCompNames["NE"].push_back( "EV" ); fieldCompNames["NE"].push_back( "ED" ); fieldCompNames["NE"].push_back( "E11" ); fieldCompNames["NE"].push_back( "E22" ); fieldCompNames["NE"].push_back( "E33" ); fieldCompNames["NE"].push_back( "E12" ); fieldCompNames["NE"].push_back( "E13" ); fieldCompNames["NE"].push_back( "E23" ); fieldCompNames["NE"].push_back( "E1" ); fieldCompNames["NE"].push_back( "E2" ); fieldCompNames["NE"].push_back( "E3" ); fieldCompNames["COMPRESSIBILITY"].push_back( "PORE" ); fieldCompNames["COMPRESSIBILITY"].push_back( "VERTICAL" ); fieldCompNames["COMPRESSIBILITY"].push_back( "VERTICAL-RATIO" ); fieldCompNames["PORO-PERM"].push_back( "PHI0" ); fieldCompNames["PORO-PERM"].push_back( "PHI" ); fieldCompNames["PORO-PERM"].push_back( "DPHI" ); fieldCompNames["PORO-PERM"].push_back( "PERM" ); fieldCompNames["MUD-WEIGHT"].push_back( "MWW" ); fieldCompNames["MUD-WEIGHT"].push_back( "MWM" ); fieldCompNames["MUD-WEIGHT"].push_back( "UMWL" ); fieldCompNames["MUD-WEIGHT"].push_back( "LMWL" ); if ( fieldCompNames.count( "LE" ) > 0 ) { fieldCompNames["LE"].push_back( "LE1" ); fieldCompNames["LE"].push_back( "LE2" ); fieldCompNames["LE"].push_back( "LE3" ); } if ( fieldCompNames.count( "PE" ) > 0 ) { fieldCompNames["PE"].push_back( "PE1" ); fieldCompNames["PE"].push_back( "PE2" ); fieldCompNames["PE"].push_back( "PE3" ); } } else if ( resPos == RIG_INTEGRATION_POINT ) { fieldCompNames = m_readerInterface->scalarIntegrationPointFieldAndComponentNames(); fieldCompNames["SE"].push_back( "SM" ); fieldCompNames["SE"].push_back( "SFI" ); fieldCompNames["SE"].push_back( "DSM" ); fieldCompNames["SE"].push_back( "FOS" ); fieldCompNames["SE"].push_back( "S11" ); fieldCompNames["SE"].push_back( "S22" ); fieldCompNames["SE"].push_back( "S33" ); fieldCompNames["SE"].push_back( "S12" ); fieldCompNames["SE"].push_back( "S13" ); fieldCompNames["SE"].push_back( "S23" ); fieldCompNames["SE"].push_back( "S1" ); fieldCompNames["SE"].push_back( "S2" ); fieldCompNames["SE"].push_back( "S3" ); for ( auto& s : stressAnisotropyComponentNames ) { fieldCompNames["SE"].push_back( s ); } fieldCompNames["SE"].push_back( "S1inc" ); fieldCompNames["SE"].push_back( "S1azi" ); fieldCompNames["SE"].push_back( "S2inc" ); fieldCompNames["SE"].push_back( "S2azi" ); fieldCompNames["SE"].push_back( "S3inc" ); fieldCompNames["SE"].push_back( "S3azi" ); fieldCompNames["ST"].push_back( "SM" ); fieldCompNames["ST"].push_back( "Q" ); fieldCompNames["ST"].push_back( "DPN" ); fieldCompNames["ST"].push_back( "S11" ); fieldCompNames["ST"].push_back( "S22" ); fieldCompNames["ST"].push_back( "S33" ); fieldCompNames["ST"].push_back( "S12" ); fieldCompNames["ST"].push_back( "S13" ); fieldCompNames["ST"].push_back( "S23" ); fieldCompNames["ST"].push_back( "S1" ); fieldCompNames["ST"].push_back( "S2" ); fieldCompNames["ST"].push_back( "S3" ); for ( auto& s : stressAnisotropyComponentNames ) { fieldCompNames["ST"].push_back( s ); } fieldCompNames["ST"].push_back( "S1inc" ); fieldCompNames["ST"].push_back( "S1azi" ); fieldCompNames["ST"].push_back( "S2inc" ); fieldCompNames["ST"].push_back( "S2azi" ); fieldCompNames["ST"].push_back( "S3inc" ); fieldCompNames["ST"].push_back( "S3azi" ); fieldCompNames["Gamma"].push_back( "Gamma1" ); fieldCompNames["Gamma"].push_back( "Gamma2" ); fieldCompNames["Gamma"].push_back( "Gamma3" ); fieldCompNames["Gamma"].push_back( "Gamma11" ); fieldCompNames["Gamma"].push_back( "Gamma22" ); fieldCompNames["Gamma"].push_back( "Gamma33" ); fieldCompNames["NE"].push_back( "EV" ); fieldCompNames["NE"].push_back( "ED" ); fieldCompNames["NE"].push_back( "E11" ); fieldCompNames["NE"].push_back( "E22" ); fieldCompNames["NE"].push_back( "E33" ); fieldCompNames["NE"].push_back( "E12" ); fieldCompNames["NE"].push_back( "E13" ); fieldCompNames["NE"].push_back( "E23" ); fieldCompNames["NE"].push_back( "E1" ); fieldCompNames["NE"].push_back( "E2" ); fieldCompNames["NE"].push_back( "E3" ); fieldCompNames["COMPRESSIBILITY"].push_back( "PORE" ); fieldCompNames["COMPRESSIBILITY"].push_back( "VERTICAL" ); fieldCompNames["COMPRESSIBILITY"].push_back( "VERTICAL-RATIO" ); fieldCompNames["PORO-PERM"].push_back( "PHI0" ); fieldCompNames["PORO-PERM"].push_back( "PHI" ); fieldCompNames["PORO-PERM"].push_back( "DPHI" ); fieldCompNames["PORO-PERM"].push_back( "PERM" ); fieldCompNames["MUD-WEIGHT"].push_back( "MWW" ); fieldCompNames["MUD-WEIGHT"].push_back( "MWM" ); fieldCompNames["MUD-WEIGHT"].push_back( "UMWL" ); fieldCompNames["MUD-WEIGHT"].push_back( "LMWL" ); if ( fieldCompNames.count( "LE" ) > 0 ) { fieldCompNames["LE"].push_back( "LE1" ); fieldCompNames["LE"].push_back( "LE2" ); fieldCompNames["LE"].push_back( "LE3" ); } if ( fieldCompNames.count( "PE" ) > 0 ) { fieldCompNames["PE"].push_back( "PE1" ); fieldCompNames["PE"].push_back( "PE2" ); fieldCompNames["PE"].push_back( "PE3" ); } } else if ( resPos == RIG_ELEMENT_NODAL_FACE ) { fieldCompNames["Plane"].push_back( "Pinc" ); fieldCompNames["Plane"].push_back( "Pazi" ); fieldCompNames["SE"].push_back( "SN" ); fieldCompNames["SE"].push_back( "TP" ); fieldCompNames["SE"].push_back( "TPinc" ); fieldCompNames["SE"].push_back( "TPH" ); fieldCompNames["SE"].push_back( "TPQV" ); fieldCompNames["SE"].push_back( "FAULTMOB" ); fieldCompNames["SE"].push_back( "PCRIT" ); fieldCompNames["ST"].push_back( "SN" ); fieldCompNames["ST"].push_back( "TP" ); fieldCompNames["ST"].push_back( "TPinc" ); fieldCompNames["ST"].push_back( "TPH" ); fieldCompNames["ST"].push_back( "TPQV" ); fieldCompNames["ST"].push_back( "FAULTMOB" ); fieldCompNames["ST"].push_back( "PCRIT" ); } else if ( resPos == RIG_ELEMENT ) { for ( const std::string& field : m_elementPropertyReader->scalarElementFields() ) { fieldCompNames[field]; } } else if ( resPos == RIG_WELLPATH_DERIVED ) { std::vector angles = RiaResultNames::wbsAngleResultNames(); for ( QString angle : angles ) { fieldCompNames[angle.toStdString()]; } std::vector derivedResults = RiaResultNames::wbsDerivedResultNames(); for ( QString result : derivedResults ) { fieldCompNames[result.toStdString()]; } std::set wbsParameters = RigWbsParameter::allParameters(); for ( const RigWbsParameter& parameter : wbsParameters ) { fieldCompNames[parameter.name().toStdString()]; } } else if ( resPos == RIG_DIFFERENTIALS ) { fieldCompNames["POR-Bar"]; fieldCompNames["POR-Bar"].push_back( "X" ); fieldCompNames["POR-Bar"].push_back( "Y" ); fieldCompNames["POR-Bar"].push_back( "Z" ); for ( auto& s : stressGradientComponentNames ) { fieldCompNames["SE"].push_back( s ); } for ( auto& s : stressGradientComponentNames ) { fieldCompNames["ST"].push_back( s ); } } } return fieldCompNames; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigFemScalarResultFrames* RigFemPartResultsCollection::calculateDerivedResult( int partIndex, const RigFemResultAddress& resVarAddr ) { for ( const auto& calculator : m_resultCalculators ) { if ( calculator->isMatching( resVarAddr ) ) return calculator->calculate( partIndex, resVarAddr ); } if ( resVarAddr.fieldName == "ST" && resVarAddr.componentName.empty() ) { // Create and return an empty result return m_femPartResults[partIndex]->createScalarResult( resVarAddr ); } if ( resVarAddr.fieldName == "Gamma" && resVarAddr.componentName.empty() ) { // Create and return an empty result return m_femPartResults[partIndex]->createScalarResult( resVarAddr ); } return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigFemPartResultsCollection::getResAddrToComponentsToRead( const RigFemResultAddress& resVarAddr ) { std::map> fieldAndComponentNames; switch ( resVarAddr.resultPosType ) { case RIG_NODAL: fieldAndComponentNames = m_readerInterface->scalarNodeFieldAndComponentNames(); break; case RIG_ELEMENT_NODAL: fieldAndComponentNames = m_readerInterface->scalarElementNodeFieldAndComponentNames(); break; case RIG_INTEGRATION_POINT: fieldAndComponentNames = m_readerInterface->scalarIntegrationPointFieldAndComponentNames(); break; default: break; } std::vector resAddressToComponents; std::map>::iterator fcIt = fieldAndComponentNames.find( resVarAddr.fieldName ); if ( fcIt != fieldAndComponentNames.end() ) { std::vector compNames = fcIt->second; if ( !resVarAddr.componentName.empty() ) // If we did not request a particular component, do not add the // components { for ( const auto& compName : compNames ) { resAddressToComponents.push_back( RigFemResultAddress( resVarAddr.resultPosType, resVarAddr.fieldName, compName ) ); } } if ( compNames.empty() ) // This is a scalar field. Add one component named "" { CVF_ASSERT( resVarAddr.componentName == "" ); resAddressToComponents.push_back( resVarAddr ); } } return resAddressToComponents; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigFemPartResultsCollection::filteredStepNames() const { CVF_ASSERT( m_readerInterface.notNull() ); return m_readerInterface->filteredStepNames(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int RigFemPartResultsCollection::frameCount() { return static_cast( filteredStepNames().size() ); } //-------------------------------------------------------------------------------------------------- /// Returns whether any of the parts actually had any of the requested results //-------------------------------------------------------------------------------------------------- bool RigFemPartResultsCollection::assertResultsLoaded( const RigFemResultAddress& resVarAddr ) { if ( !resVarAddr.isValid() ) return false; bool foundResults = false; for ( int pIdx = 0; pIdx < static_cast( m_femPartResults.size() ); ++pIdx ) { if ( m_femPartResults[pIdx].notNull() ) { RigFemScalarResultFrames* scalarResults = findOrLoadScalarResult( pIdx, resVarAddr ); for ( int fIdx = 0; fIdx < scalarResults->frameCount(); ++fIdx ) { foundResults = foundResults || !scalarResults->frameData( fIdx ).empty(); } } } return foundResults; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::deleteResult( const RigFemResultAddress& resVarAddr ) { CVF_ASSERT( resVarAddr.isValid() ); for ( auto& femPartResult : m_femPartResults ) { if ( femPartResult.notNull() ) { femPartResult->deleteScalarResult( resVarAddr ); } } 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 ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::deleteResultForAllTimeSteps( const std::vector& addresses ) { for ( const auto& res : addresses ) { auto resToDelete = res; resToDelete.timeLapseBaseStepIdx = RigFemResultAddress::allTimeLapsesValue(); deleteResult( resToDelete ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::deleteResultFrame( const RigFemResultAddress& resVarAddr, int partIndex, int frameIndex ) { CVF_ASSERT( resVarAddr.isValid() ); RigFemScalarResultFrames* frames = m_femPartResults[partIndex]->findScalarResult( resVarAddr ); if ( frames ) { std::vector().swap( frames->frameData( frameIndex ) ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigFemPartResultsCollection::loadedResults() const { std::vector currentResults; for ( auto& femPartResult : m_femPartResults ) { std::vector partResults = femPartResult->loadedResults(); currentResults.insert( currentResults.end(), partResults.begin(), partResults.end() ); } return currentResults; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const std::vector& RigFemPartResultsCollection::resultValues( const RigFemResultAddress& resVarAddr, int partIndex, int frameIndex ) { CVF_ASSERT( resVarAddr.isValid() ); RigFemScalarResultFrames* scalarResults = findOrLoadScalarResult( partIndex, resVarAddr ); return scalarResults->frameData( frameIndex ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::globalResultValues( const RigFemResultAddress& resVarAddr, int timeStepIndex, std::vector& resultValues ) { CVF_ASSERT( resVarAddr.isValid() ); for ( int i = 0; i < partCount(); i++ ) { const std::vector& partResults = this->resultValues( resVarAddr, i, (int)timeStepIndex ); if ( partResults.empty() ) { size_t expectedSize = 0; switch ( resVarAddr.resultPosType ) { case RIG_NODAL: expectedSize = m_femParts->part( i )->nodes().nodeIds.size(); break; case RIG_ELEMENT_NODAL: case RIG_INTEGRATION_POINT: expectedSize = m_femParts->part( i )->elementNodeResultCount(); break; case RIG_ELEMENT_NODAL_FACE: expectedSize = m_femParts->part( i )->elementCount() * 6; break; case RIG_ELEMENT: expectedSize = m_femParts->part( i )->elementCount(); break; default: break; } resultValues.resize( resultValues.size() + expectedSize, NAN ); } else { resultValues.insert( resultValues.end(), partResults.begin(), partResults.end() ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigFemPartResultsCollection::tensors( const RigFemResultAddress& resVarAddr, int partIndex, int frameIndex ) { CVF_ASSERT( resVarAddr.resultPosType == RIG_ELEMENT_NODAL || resVarAddr.resultPosType == RIG_INTEGRATION_POINT ); std::vector outputTensors; std::vector addresses = tensorComponentAddresses( resVarAddr ); if ( addresses.empty() ) { return outputTensors; } const std::vector& v11 = resultValues( addresses[caf::Ten3f::SXX], partIndex, frameIndex ); const std::vector& v22 = resultValues( addresses[caf::Ten3f::SYY], partIndex, frameIndex ); const std::vector& v33 = resultValues( addresses[caf::Ten3f::SZZ], partIndex, frameIndex ); const std::vector& v12 = resultValues( addresses[caf::Ten3f::SXY], partIndex, frameIndex ); const std::vector& v13 = resultValues( addresses[caf::Ten3f::SZX], partIndex, frameIndex ); const std::vector& v23 = resultValues( addresses[caf::Ten3f::SYZ], partIndex, frameIndex ); size_t valCount = v11.size(); outputTensors.resize( valCount ); #pragma omp parallel for for ( long vIdx = 0; vIdx < static_cast( valCount ); ++vIdx ) { caf::Ten3f tensor( v11[vIdx], v22[vIdx], v33[vIdx], v12[vIdx], v23[vIdx], v13[vIdx] ); outputTensors[vIdx] = tensor; } return outputTensors; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigStatisticsDataCache* RigFemPartResultsCollection::statistics( const RigFemResultAddress& resVarAddr ) { RigStatisticsDataCache* statCache = m_resultStatistics[resVarAddr].p(); if ( !statCache ) { RigFemNativeStatCalc* calculator = new RigFemNativeStatCalc( this, resVarAddr ); statCache = new RigStatisticsDataCache( calculator ); m_resultStatistics[resVarAddr] = statCache; } return statCache; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::minMaxScalarValues( const RigFemResultAddress& resVarAddr, int frameIndex, double* localMin, double* localMax ) { this->statistics( resVarAddr )->minMaxCellScalarValues( frameIndex, *localMin, *localMax ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::minMaxScalarValues( const RigFemResultAddress& resVarAddr, double* globalMin, double* globalMax ) { this->statistics( resVarAddr )->minMaxCellScalarValues( *globalMin, *globalMax ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::posNegClosestToZero( const RigFemResultAddress& resVarAddr, int frameIndex, double* localPosClosestToZero, double* localNegClosestToZero ) { this->statistics( resVarAddr )->posNegClosestToZero( frameIndex, *localPosClosestToZero, *localNegClosestToZero ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::posNegClosestToZero( const RigFemResultAddress& resVarAddr, double* globalPosClosestToZero, double* globalNegClosestToZero ) { this->statistics( resVarAddr )->posNegClosestToZero( *globalPosClosestToZero, *globalNegClosestToZero ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::meanScalarValue( const RigFemResultAddress& resVarAddr, double* meanValue ) { CVF_ASSERT( meanValue ); this->statistics( resVarAddr )->meanCellScalarValues( *meanValue ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::meanScalarValue( const RigFemResultAddress& resVarAddr, int frameIndex, double* meanValue ) { this->statistics( resVarAddr )->meanCellScalarValues( frameIndex, *meanValue ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::p10p90ScalarValues( const RigFemResultAddress& resVarAddr, double* p10, double* p90 ) { this->statistics( resVarAddr )->p10p90CellScalarValues( *p10, *p90 ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::p10p90ScalarValues( const RigFemResultAddress& resVarAddr, int frameIndex, double* p10, double* p90 ) { this->statistics( resVarAddr )->p10p90CellScalarValues( frameIndex, *p10, *p90 ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::sumScalarValue( const RigFemResultAddress& resVarAddr, double* sum ) { CVF_ASSERT( sum ); this->statistics( resVarAddr )->sumCellScalarValues( *sum ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::sumScalarValue( const RigFemResultAddress& resVarAddr, int frameIndex, double* sum ) { CVF_ASSERT( sum ); this->statistics( resVarAddr )->sumCellScalarValues( frameIndex, *sum ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const std::vector& RigFemPartResultsCollection::scalarValuesHistogram( const RigFemResultAddress& resVarAddr ) { return this->statistics( resVarAddr )->cellScalarValuesHistogram(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const std::vector& RigFemPartResultsCollection::scalarValuesHistogram( const RigFemResultAddress& resVarAddr, int frameIndex ) { return this->statistics( resVarAddr )->cellScalarValuesHistogram( frameIndex ); } std::vector RigFemPartResultsCollection::tensorPrincipalComponentAdresses( const RigFemResultAddress& resVarAddr ) { std::vector addresses; for ( size_t i = 0; i < 3; ++i ) { addresses.push_back( RigFemResultAddress( resVarAddr.resultPosType, resVarAddr.fieldName, "" ) ); } if ( resVarAddr.fieldName == "SE" || resVarAddr.fieldName == "ST" ) { addresses[0].componentName = "S1"; addresses[1].componentName = "S2"; addresses[2].componentName = "S3"; } else if ( resVarAddr.fieldName == "NE" ) { addresses[0].componentName = "E1"; addresses[1].componentName = "E2"; addresses[2].componentName = "E3"; } else { addresses.clear(); } return addresses; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RigFemPartResultsCollection::isResultInSet( const RigFemResultAddress& result, const std::set& results ) { for ( auto res : results ) { if ( res.resultPosType == result.resultPosType && res.fieldName == result.fieldName && res.componentName == result.componentName ) { return true; } } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RigFemPartResultsCollection::normalizedResults() { std::set validFields = { "SE", "ST" }; std::set validComponents = { "S11", "S22", "S33", "S12", "S13", "S23", "S1", "S2", "S3", "SM" }; std::set results; for ( auto field : validFields ) { for ( auto component : validComponents ) { results.insert( RigFemResultAddress( RIG_ELEMENT_NODAL, field, component, RigFemResultAddress::allTimeLapsesValue(), -1, true ) ); } } results.insert( RigFemResultAddress( RIG_ELEMENT_NODAL, "ST", "Q", RigFemResultAddress::allTimeLapsesValue(), -1, true ) ); results.insert( RigFemResultAddress( RIG_NODAL, "POR-Bar", "", RigFemResultAddress::allTimeLapsesValue(), -1, true ) ); results.insert( RigFemResultAddress( RIG_ELEMENT_NODAL, "POR-Bar", "", RigFemResultAddress::allTimeLapsesValue(), -1, true ) ); return results; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RigFemPartResultsCollection::isNormalizableResult( const RigFemResultAddress& result ) { return isResultInSet( result, normalizedResults() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RigFemPartResultsCollection::referenceCaseDependentResults() { std::set results; for ( auto elementType : { RIG_ELEMENT_NODAL, RIG_INTEGRATION_POINT } ) { results.insert( RigFemResultAddress( elementType, "COMPRESSIBILITY", "PORE", RigFemResultAddress::allTimeLapsesValue() ) ); results.insert( RigFemResultAddress( elementType, "COMPRESSIBILITY", "VERTICAL", RigFemResultAddress::allTimeLapsesValue() ) ); results.insert( RigFemResultAddress( elementType, "COMPRESSIBILITY", "VERTICAL-RATIO", RigFemResultAddress::allTimeLapsesValue() ) ); results.insert( RigFemResultAddress( elementType, "PORO-PERM", "PHI", RigFemResultAddress::allTimeLapsesValue() ) ); results.insert( RigFemResultAddress( elementType, "PORO-PERM", "DPHI", RigFemResultAddress::allTimeLapsesValue() ) ); results.insert( RigFemResultAddress( elementType, "PORO-PERM", "PERM", RigFemResultAddress::allTimeLapsesValue() ) ); } return results; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RigFemPartResultsCollection::mudWeightWindowResults() { std::set results; for ( auto elmType : { RIG_ELEMENT_NODAL, RIG_INTEGRATION_POINT } ) { results.insert( RigFemResultAddress( elmType, "MUD-WEIGHT", "MWW", RigFemResultAddress::allTimeLapsesValue() ) ); results.insert( RigFemResultAddress( elmType, "MUD-WEIGHT", "MWM", RigFemResultAddress::allTimeLapsesValue() ) ); results.insert( RigFemResultAddress( elmType, "MUD-WEIGHT", "UMWL", RigFemResultAddress::allTimeLapsesValue() ) ); results.insert( RigFemResultAddress( elmType, "MUD-WEIGHT", "LMWL", RigFemResultAddress::allTimeLapsesValue() ) ); } return results; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RigFemPartResultsCollection::initialPermeabilityDependentResults() { std::set results; for ( auto elementType : { RIG_ELEMENT_NODAL, RIG_INTEGRATION_POINT } ) { results.insert( RigFemResultAddress( elementType, "PORO-PERM", "PHI", RigFemResultAddress::allTimeLapsesValue() ) ); results.insert( RigFemResultAddress( elementType, "PORO-PERM", "DPHI", RigFemResultAddress::allTimeLapsesValue() ) ); results.insert( RigFemResultAddress( elementType, "PORO-PERM", "PERM", RigFemResultAddress::allTimeLapsesValue() ) ); } return results; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RigFemPartResultsCollection::isReferenceCaseDependentResult( const RigFemResultAddress& result ) { return isResultInSet( result, referenceCaseDependentResults() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::setNormalizationAirGap( double normalizationAirGap ) { if ( std::abs( m_normalizationAirGap - normalizationAirGap ) > 1.0e-8 ) { for ( auto result : normalizedResults() ) { this->deleteResult( result ); } } m_normalizationAirGap = normalizationAirGap; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RigFemPartResultsCollection::normalizationAirGap() const { return m_normalizationAirGap; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::minMaxScalarValuesOverAllTensorComponents( const RigFemResultAddress& resVarAddr, int frameIndex, double* localMin, double* localMax ) { double currentMin = HUGE_VAL; double currentMax = -HUGE_VAL; double min, max; for ( const auto& address : tensorPrincipalComponentAdresses( resVarAddr ) ) { this->statistics( address )->minMaxCellScalarValues( frameIndex, min, max ); if ( min < currentMin ) { currentMin = min; } if ( max > currentMax ) { currentMax = max; } } *localMin = currentMin; *localMax = currentMax; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::minMaxScalarValuesOverAllTensorComponents( const RigFemResultAddress& resVarAddr, double* globalMin, double* globalMax ) { double currentMin = HUGE_VAL; double currentMax = -HUGE_VAL; double min, max; for ( const auto& address : tensorPrincipalComponentAdresses( resVarAddr ) ) { this->statistics( address )->minMaxCellScalarValues( min, max ); if ( min < currentMin ) { currentMin = min; } if ( max > currentMax ) { currentMax = max; } } *globalMin = currentMin; *globalMax = currentMax; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::posNegClosestToZeroOverAllTensorComponents( const RigFemResultAddress& resVarAddr, int frameIndex, double* localPosClosestToZero, double* localNegClosestToZero ) { double currentPosClosestToZero = HUGE_VAL; double currentNegClosestToZero = -HUGE_VAL; double pos, neg; for ( const auto& address : tensorPrincipalComponentAdresses( resVarAddr ) ) { this->statistics( address )->posNegClosestToZero( frameIndex, pos, neg ); if ( pos < currentPosClosestToZero ) { currentPosClosestToZero = pos; } if ( neg > currentNegClosestToZero ) { currentNegClosestToZero = neg; } } *localPosClosestToZero = currentPosClosestToZero; *localNegClosestToZero = currentNegClosestToZero; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::posNegClosestToZeroOverAllTensorComponents( const RigFemResultAddress& resVarAddr, double* globalPosClosestToZero, double* globalNegClosestToZero ) { double currentPosClosestToZero = HUGE_VAL; double currentNegClosestToZero = -HUGE_VAL; double pos, neg; for ( const auto& address : tensorPrincipalComponentAdresses( resVarAddr ) ) { this->statistics( address )->posNegClosestToZero( pos, neg ); if ( pos < currentPosClosestToZero ) { currentPosClosestToZero = pos; } if ( neg > currentNegClosestToZero ) { currentNegClosestToZero = neg; } } *globalPosClosestToZero = currentPosClosestToZero; *globalNegClosestToZero = currentNegClosestToZero; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigFemPartResultsCollection::tensorComponentAddresses( const RigFemResultAddress& resVarAddr ) { std::vector addresses( 6, RigFemResultAddress( resVarAddr.resultPosType, resVarAddr.fieldName, "" ) ); if ( resVarAddr.fieldName == "SE" || resVarAddr.fieldName == "ST" ) { addresses[caf::Ten3f::SXX].componentName = "S11"; addresses[caf::Ten3f::SYY].componentName = "S22"; addresses[caf::Ten3f::SZZ].componentName = "S33"; addresses[caf::Ten3f::SXY].componentName = "S12"; addresses[caf::Ten3f::SZX].componentName = "S13"; addresses[caf::Ten3f::SYZ].componentName = "S23"; } else if ( resVarAddr.fieldName == "NE" ) { addresses[caf::Ten3f::SXX].componentName = "E11"; addresses[caf::Ten3f::SYY].componentName = "E22"; addresses[caf::Ten3f::SZZ].componentName = "E33"; addresses[caf::Ten3f::SXY].componentName = "E12"; addresses[caf::Ten3f::SZX].componentName = "E13"; addresses[caf::Ten3f::SYZ].componentName = "E23"; } else { return std::vector(); } return addresses; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int RigFemPartResultsCollection::partCount() const { return m_femParts->partCount(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const RigFemPartCollection* RigFemPartResultsCollection::parts() const { return m_femParts.p(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigFemPartResultsCollection::getStressComponentNames( bool includeShear ) { std::vector componentNames = { "S11", "S22", "S33", "S1", "S2", "S3" }; if ( includeShear ) { componentNames.push_back( "S12" ); componentNames.push_back( "S13" ); componentNames.push_back( "S23" ); } return componentNames; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigFemPartResultsCollection::getStressAnisotropyComponentNames() { return { "SA12", "SA13", "SA23" }; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigFemPartResultsCollection::getStressGradientComponentNames( bool includeShear ) { std::vector directions = { "X", "Y", "Z" }; std::vector stressComponentNames = getStressComponentNames( includeShear ); std::vector stressGradientComponentNames; for ( auto& s : stressComponentNames ) { for ( auto& d : directions ) { stressGradientComponentNames.push_back( s + "-" + d ); } } return stressGradientComponentNames; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RigFemPartResultsCollection::isValidBiotData( const std::vector& biotData, size_t elementCount ) const { if ( biotData.size() != elementCount ) { QString txt = QString( "Unexpected size of biot coefficient element properties: %1 (expected: %2)" ) .arg( biotData.size() ) .arg( elementCount ); Riu3DMainWindowTools::reportAndShowWarning( "Wrong size of biot data", txt ); return false; } for ( float b : biotData ) { if ( !std::isinf( b ) && ( b < 0.0 || b > 1.0 ) ) { RiaLogging::error( QString( "Found unexpected biot coefficient. The value must be in the [0, 1] interval." ) ); return false; } } return true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::setCalculationParameters( RimMudWeightWindowParameters::ParameterType parameterType, const QString& address, double value ) { parameterAddresses[parameterType] = address; parameterValues[parameterType] = value; // Invalidate dependent results for ( auto result : mudWeightWindowResults() ) { this->deleteResult( result ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RigFemPartResultsCollection::getCalculationParameterValue( RimMudWeightWindowParameters::ParameterType parameterType ) const { auto it = parameterValues.find( parameterType ); if ( it != parameterValues.end() ) return it->second; else { // TODO: log error maybe? return 1.0; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RigFemPartResultsCollection::getCalculationParameterAddress( RimMudWeightWindowParameters::ParameterType parameterType ) const { auto it = parameterAddresses.find( parameterType ); if ( it != parameterAddresses.end() ) return it->second; else { // TODO: log error maybe? return QString(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RigFemPartResultsCollection::airGapMudWeightWindow() const { return m_airGapMudWeightWindow; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RigFemPartResultsCollection::shMultiplierMudWeightWindow() const { return m_shMultiplierMudWeightWindow; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RigFemPartResultsCollection::hydrostaticMultiplierPPNonRes() const { return m_hydrostaticMultiplierPPNonResMudWeightWindow; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimMudWeightWindowParameters::NonReservoirPorePressureType RigFemPartResultsCollection::nonReservoirPorePressureTypeMudWeightWindow() const { return m_nonReservoirPorePressureTypeMudWeightWindow; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const QString& RigFemPartResultsCollection::nonReservoirPorePressureAddressMudWeightWindow() const { return m_nonReservoirPorePressureAddressMudWeightWindow; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimMudWeightWindowParameters::LowerLimitType RigFemPartResultsCollection::lowerLimitParameterMudWeightWindow() const { return m_lowerLimitParameterMudWeightWindow; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimMudWeightWindowParameters::UpperLimitType RigFemPartResultsCollection::upperLimitParameterMudWeightWindow() const { return m_upperLimitParameterMudWeightWindow; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RigFemPartResultsCollection::referenceLayerMudWeightWindow() const { return m_referenceLayerMudWeightWindow; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::setMudWeightWindowParameters( double airGap, RimMudWeightWindowParameters::UpperLimitType upperLimit, RimMudWeightWindowParameters::LowerLimitType lowerLimit, int referenceLayer, RimMudWeightWindowParameters::FractureGradientCalculationType fgCalculationType, double shMultiplier, RimMudWeightWindowParameters::NonReservoirPorePressureType nonReservoirPorePressureType, double hydrostaticMultiplierPPNonRes, const QString& nonReservoirPorePressureAddress ) { m_airGapMudWeightWindow = airGap; m_upperLimitParameterMudWeightWindow = upperLimit; m_lowerLimitParameterMudWeightWindow = lowerLimit; m_referenceLayerMudWeightWindow = referenceLayer; m_fractureGradientCalculationTypeMudWeightWindow = fgCalculationType; m_shMultiplierMudWeightWindow = shMultiplier; m_nonReservoirPorePressureTypeMudWeightWindow = nonReservoirPorePressureType; m_hydrostaticMultiplierPPNonResMudWeightWindow = hydrostaticMultiplierPPNonRes; m_nonReservoirPorePressureAddressMudWeightWindow = nonReservoirPorePressureAddress; // Invalidate dependent results for ( auto result : mudWeightWindowResults() ) { this->deleteResult( result ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimMudWeightWindowParameters::FractureGradientCalculationType RigFemPartResultsCollection::fractureGradientCalculationTypeMudWeightWindow() const { return m_fractureGradientCalculationTypeMudWeightWindow; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RigFemPartResultsCollection::waterDensityShearSlipIndicator() const { return m_waterDensityShearSlipIndicator; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFemPartResultsCollection::setWaterDensityShearSlipIndicator( double waterDensity ) { m_waterDensityShearSlipIndicator = waterDensity; for ( auto elementType : { RIG_ELEMENT_NODAL, RIG_INTEGRATION_POINT } ) { deleteResult( RigFemResultAddress( elementType, "ST", "DPN", RigFemResultAddress::allTimeLapsesValue() ) ); } }