ResInsight/ApplicationLibCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.cpp
2021-10-26 14:01:16 +02:00

1874 lines
79 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// 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 <QString>
#include <cmath>
#include <cstdlib>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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<std::string> 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<RigFemPartResultCalculator>( new RigFemPartResultCalculatorTimeLapse( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorSurfaceAngles( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorSurfaceAlignedStress( *this ) ) );
m_resultCalculators.push_back( std::unique_ptr<RigFemPartResultCalculator>(
new RigFemPartResultCalculatorBarConverted( *this, "S-Bar", "S" ) ) );
m_resultCalculators.push_back( std::unique_ptr<RigFemPartResultCalculator>(
new RigFemPartResultCalculatorBarConverted( *this, "POR-Bar", "POR" ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorEnIpPorBar( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorNodalGradients( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorCompaction( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorSFI( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorDSM( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorFOS( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorED( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorEV( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorSM( *this ) ) );
m_resultCalculators.push_back( std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorQ( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorStressGradients( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorNormalized( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorNormalST( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorShearST( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorNormalSE( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorShearSE( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorNE( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorGamma( *this ) ) );
m_resultCalculators.push_back( std::unique_ptr<RigFemPartResultCalculator>(
new RigFemPartResultCalculatorPrincipalStrain( *this, "NE", "E" ) ) );
m_resultCalculators.push_back( std::unique_ptr<RigFemPartResultCalculator>(
new RigFemPartResultCalculatorPrincipalStrain( *this, "LE", "LE" ) ) );
m_resultCalculators.push_back( std::unique_ptr<RigFemPartResultCalculator>(
new RigFemPartResultCalculatorPrincipalStrain( *this, "PE", "PE" ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorPrincipalStress( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorStressAnisotropy( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorPoreCompressibility( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorPorosityPermeability( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorInitialPorosity( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorMudWeightWindow( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorShearSlipIndicator( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( 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<QString> RigFemPartResultsCollection::formationNames() const
{
if ( activeFormationNames() )
{
return activeFormationNames()->formationNames();
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RigFormationNames* RigFemPartResultsCollection::activeFormationNames() const
{
return m_activeFormationNamesData.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFemPartResultsCollection::addElementPropertyFiles( const std::vector<QString>& filenames )
{
std::vector<RigFemResultAddress> newAddresses;
for ( const QString& filename : filenames )
{
m_elementPropertyReader->addFile( filename.toStdString() );
// Collect all addresses which was added in this file
std::vector<std::string> 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<RigFemResultAddress>
RigFemPartResultsCollection::removeElementPropertyFiles( const std::vector<QString>& filenames )
{
std::vector<RigFemResultAddress> addressesToRemove;
for ( const QString& filename : filenames )
{
std::vector<std::string> 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<std::string, QString>
RigFemPartResultsCollection::addressesInElementPropertyFiles( const std::vector<QString>& filenames )
{
std::map<std::string, QString> fieldsInFile;
for ( const QString& filename : filenames )
{
std::vector<std::string> 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<RigFemResultAddress> 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<RigFemResultAddress> 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<RigFemResultAddress> initPermResults = initialPermeabilityDependentResults();
for ( auto result : initPermResults )
{
deleteResult( result );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFemPartResultsCollection::setReferenceTimeStep( int referenceTimeStep )
{
m_referenceTimeStep = referenceTimeStep;
std::set<RigFemResultAddress> 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<RigFemResultAddress> 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<std::string, std::vector<float>> 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<RigFemResultAddress> resultAddressOfComponents = this->getResAddrToComponentsToRead( resVarAddr );
if ( !resultAddressOfComponents.empty() )
{
std::vector<RigFemScalarResultFrames*> 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<double> frameTimes = m_readerInterface->frameTimes( stepIndex );
int fIdx = (int)( frameTimes.size() - 1 );
std::vector<std::vector<float>*> 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<int>( m_femPartResults.size() ) );
CVF_ASSERT( resVarAddr.isValid() );
return m_femPartResults[partIndex]->createScalarResult( resVarAddr );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFemPartResultsCollection::deleteAllScalarResults()
{
for ( cvf::ref<RigFemPartResults> results : m_femPartResults )
{
results->deleteAllScalarResults();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<std::string, std::vector<std::string>>
RigFemPartResultsCollection::scalarFieldAndComponentNames( RigFemResultPosEnum resPos )
{
std::map<std::string, std::vector<std::string>> fieldCompNames;
if ( resPos == RIG_FORMATION_NAMES )
{
if ( activeFormationNames() ) fieldCompNames["Active Formation Names"];
}
const std::vector<std::string> stressComponentNames = getStressComponentNames();
const std::vector<std::string> stressGradientComponentNames = getStressGradientComponentNames();
const std::vector<std::string> 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<QString> angles = RiaResultNames::wbsAngleResultNames();
for ( QString angle : angles )
{
fieldCompNames[angle.toStdString()];
}
std::vector<QString> derivedResults = RiaResultNames::wbsDerivedResultNames();
for ( QString result : derivedResults )
{
fieldCompNames[result.toStdString()];
}
std::set<RigWbsParameter> 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<RigFemResultAddress>
RigFemPartResultsCollection::getResAddrToComponentsToRead( const RigFemResultAddress& resVarAddr )
{
std::map<std::string, std::vector<std::string>> 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<RigFemResultAddress> resAddressToComponents;
std::map<std::string, std::vector<std::string>>::iterator fcIt = fieldAndComponentNames.find( resVarAddr.fieldName );
if ( fcIt != fieldAndComponentNames.end() )
{
std::vector<std::string> 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<std::string> RigFemPartResultsCollection::filteredStepNames() const
{
CVF_ASSERT( m_readerInterface.notNull() );
return m_readerInterface->filteredStepNames();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RigFemPartResultsCollection::frameCount()
{
return static_cast<int>( 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<int>( 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<RigFemResultAddress> 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<RigFemResultAddress>& 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<float>().swap( frames->frameData( frameIndex ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigFemResultAddress> RigFemPartResultsCollection::loadedResults() const
{
std::vector<RigFemResultAddress> currentResults;
for ( auto& femPartResult : m_femPartResults )
{
std::vector<RigFemResultAddress> partResults = femPartResult->loadedResults();
currentResults.insert( currentResults.end(), partResults.begin(), partResults.end() );
}
return currentResults;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<float>&
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<float>& resultValues )
{
CVF_ASSERT( resVarAddr.isValid() );
for ( int i = 0; i < partCount(); i++ )
{
const std::vector<float>& 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<caf::Ten3f>
RigFemPartResultsCollection::tensors( const RigFemResultAddress& resVarAddr, int partIndex, int frameIndex )
{
CVF_ASSERT( resVarAddr.resultPosType == RIG_ELEMENT_NODAL || resVarAddr.resultPosType == RIG_INTEGRATION_POINT );
std::vector<caf::Ten3f> outputTensors;
std::vector<RigFemResultAddress> addresses = tensorComponentAddresses( resVarAddr );
if ( addresses.empty() )
{
return outputTensors;
}
const std::vector<float>& v11 = resultValues( addresses[caf::Ten3f::SXX], partIndex, frameIndex );
const std::vector<float>& v22 = resultValues( addresses[caf::Ten3f::SYY], partIndex, frameIndex );
const std::vector<float>& v33 = resultValues( addresses[caf::Ten3f::SZZ], partIndex, frameIndex );
const std::vector<float>& v12 = resultValues( addresses[caf::Ten3f::SXY], partIndex, frameIndex );
const std::vector<float>& v13 = resultValues( addresses[caf::Ten3f::SZX], partIndex, frameIndex );
const std::vector<float>& 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<long>( 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<size_t>& RigFemPartResultsCollection::scalarValuesHistogram( const RigFemResultAddress& resVarAddr )
{
return this->statistics( resVarAddr )->cellScalarValuesHistogram();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<size_t>& RigFemPartResultsCollection::scalarValuesHistogram( const RigFemResultAddress& resVarAddr,
int frameIndex )
{
return this->statistics( resVarAddr )->cellScalarValuesHistogram( frameIndex );
}
std::vector<RigFemResultAddress>
RigFemPartResultsCollection::tensorPrincipalComponentAdresses( const RigFemResultAddress& resVarAddr )
{
std::vector<RigFemResultAddress> 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<RigFemResultAddress>& results )
{
for ( auto res : results )
{
if ( res.resultPosType == result.resultPosType && res.fieldName == result.fieldName &&
res.componentName == result.componentName )
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RigFemResultAddress> RigFemPartResultsCollection::normalizedResults()
{
std::set<std::string> validFields = { "SE", "ST" };
std::set<std::string> validComponents = { "S11", "S22", "S33", "S12", "S13", "S23", "S1", "S2", "S3", "SM" };
std::set<RigFemResultAddress> 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<RigFemResultAddress> RigFemPartResultsCollection::referenceCaseDependentResults()
{
std::set<RigFemResultAddress> 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<RigFemResultAddress> RigFemPartResultsCollection::mudWeightWindowResults()
{
std::set<RigFemResultAddress> 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<RigFemResultAddress> RigFemPartResultsCollection::initialPermeabilityDependentResults()
{
std::set<RigFemResultAddress> 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<RigFemResultAddress> RigFemPartResultsCollection::tensorComponentAddresses( const RigFemResultAddress& resVarAddr )
{
std::vector<RigFemResultAddress> 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<RigFemResultAddress>();
}
return addresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RigFemPartResultsCollection::partCount() const
{
return m_femParts->partCount();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RigFemPartCollection* RigFemPartResultsCollection::parts() const
{
return m_femParts.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::string> RigFemPartResultsCollection::getStressComponentNames( bool includeShear )
{
std::vector<std::string> 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<std::string> RigFemPartResultsCollection::getStressAnisotropyComponentNames()
{
return { "SA12", "SA13", "SA23" };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::string> RigFemPartResultsCollection::getStressGradientComponentNames( bool includeShear )
{
std::vector<std::string> directions = { "X", "Y", "Z" };
std::vector<std::string> stressComponentNames = getStressComponentNames( includeShear );
std::vector<std::string> stressGradientComponentNames;
for ( auto& s : stressComponentNames )
{
for ( auto& d : directions )
{
stressGradientComponentNames.push_back( s + "-" + d );
}
}
return stressGradientComponentNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigFemPartResultsCollection::isValidBiotData( const std::vector<float>& 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() ) );
}
}