mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 22:50:25 -05:00
Migrate all assert macros in ApplicationLibCode to CAF_ASSERT and remove every use of cvfAssert.h. CVF_ASSERT is replaced one to one. CVF_TIGHT_ASSERT is also replaced by CAF_ASSERT, which is semantically exact: CVF_ENABLE_TIGHT_ASSERTS is 1 only under _DEBUG, and that is what CAF_ASSERT now does. The two CVF_FAIL_MSG sites become CAF_ASSERT( false && "message" ), preserving the message with the idiom already used elsewhere in the code base. Counts before and after: CVF_ASSERT 1044 to 0, CVF_TIGHT_ASSERT 66 to 0, CVF_FAIL_MSG 2 to 0, cvfAssert.h references 154 to 0. Include handling: files that included cvfAssert.h directly now include cafAssert.h instead, includes left dead by the migration are removed, and files that were relying on cvfAssert.h transitively get an explicit cafAssert.h. Files that reach cafAssert.h through another caf header are left unchanged; a missing include here is a compile error, not a silently disabled assert. ResultStatisticsCache links only LibCore and therefore had no path to cafAssert.h. Add the cafPdmCore directory as a private include path rather than linking the library, since cafAssert.h is header only. Note that this stops these asserts from firing in Release and RelWithDebInfo, where CVF_ASSERT was previously active.
1896 lines
83 KiB
C++
1896 lines
83 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 "RiaRegressionTestRunner.h"
|
|
#include "RiaResultNames.h"
|
|
|
|
#include "RifElementPropertyReader.h"
|
|
#include "RifGeoMechReaderInterface.h"
|
|
|
|
#include "RigFemAddressDefines.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 "RigFemPartResultCalculatorKIndices.h"
|
|
#include "RigFemPartResultCalculatorMudWeightWindow.h"
|
|
#include "RigFemPartResultCalculatorNE.h"
|
|
#include "RigFemPartResultCalculatorNodalDisplacement.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 "Riu3DMainWindowTools.h"
|
|
|
|
#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 )
|
|
{
|
|
CAF_ASSERT( readerInterface );
|
|
CAF_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 );
|
|
}
|
|
|
|
// initialize step cache
|
|
{
|
|
int stepIdx = 0;
|
|
for ( auto& stepName : filteredStepNames )
|
|
{
|
|
int frameIdx = 0;
|
|
for ( auto& frame : m_readerInterface->frameTimes( stepIdx ) )
|
|
{
|
|
auto stepNameComplete = stepName;
|
|
|
|
if ( !RiaRegressionTestRunner::instance()->isRunningRegressionTests() || m_readerInterface->frameTimes( stepIdx ).size() != 1 )
|
|
{
|
|
// Do not add postfix for time steps with a single frame to ensure identical generated snapshot
|
|
// name used by regression tests
|
|
stepNameComplete += " (" + std::to_string( frame ) + ")";
|
|
}
|
|
|
|
m_stepNames.emplace_back( stepNameComplete );
|
|
m_stepList.emplace_back( stepIdx, frameIdx );
|
|
frameIdx++;
|
|
}
|
|
stepIdx++;
|
|
}
|
|
}
|
|
|
|
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_fractureGradientCalculationTypeMudWeightWindow = RimMudWeightWindowParameters::FractureGradientCalculationType::DERIVED_FROM_K0FG;
|
|
m_lowerLimitParameterMudWeightWindow = RimMudWeightWindowParameters::LowerLimitType::PORE_PRESSURE;
|
|
m_upperLimitParameterMudWeightWindow = RimMudWeightWindowParameters::UpperLimitType::FG;
|
|
m_nonReservoirPorePressureTypeMudWeightWindow = RimMudWeightWindowParameters::NonReservoirPorePressureType::PER_ELEMENT;
|
|
|
|
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, RigFemAddressDefines::porBar(), "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 ) ) );
|
|
m_resultCalculators.push_back( std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorKIndices( *this ) ) );
|
|
m_resultCalculators.push_back( std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorNodalDisplacement( *this ) ) );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigFemPartResultsCollection::~RigFemPartResultsCollection()
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::setActiveFormationNames( const RigFormationNames* activeFormationNames )
|
|
{
|
|
// Store a copy, as the owning RimFormationNames can be reloaded or deleted while this data is in use
|
|
m_activeFormationNamesData = activeFormationNames ? *activeFormationNames : RigFormationNames();
|
|
|
|
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.isEmpty() ? nullptr : &m_activeFormationNamesData;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
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 )
|
|
{
|
|
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 )
|
|
{
|
|
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 );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::pair<int, int> RigFemPartResultsCollection::referenceStepAndFrameIndex() const
|
|
{
|
|
return stepListIndexToTimeStepAndDataFrameIndex( 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 )
|
|
{
|
|
CAF_ASSERT( partIndex < (int)( m_femPartResults.size() ) );
|
|
CAF_ASSERT( m_readerInterface.notNull() );
|
|
CAF_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;
|
|
|
|
// is it available as an imported property
|
|
if ( resVarAddr.resultPosType == RIG_ELEMENT )
|
|
{
|
|
std::map<std::string, std::vector<float>> elementProperties =
|
|
m_elementPropertyReader->readAllElementPropertiesInFileContainingField( resVarAddr.fieldName );
|
|
|
|
// We are supposed to get here only once. Create result containers for all imported element results in one go
|
|
for ( auto& [addrString, values] : elementProperties )
|
|
{
|
|
RigFemResultAddress addressForElement( RIG_ELEMENT, addrString, "" );
|
|
RigFemScalarResultFrames* currentFrames = m_femPartResults[partIndex]->createScalarResult( addressForElement );
|
|
currentFrames->enableAsSingleStepResult();
|
|
currentFrames->frameData( 0, 0 ).swap( values );
|
|
}
|
|
|
|
// Try to find the element result and return it
|
|
frames = m_femPartResults[partIndex]->findScalarResult( resVarAddr );
|
|
if ( frames )
|
|
{
|
|
return frames;
|
|
}
|
|
}
|
|
|
|
// We need to read the data as bulk fields, and populate the correct scalar caches
|
|
|
|
std::vector<RigFemResultAddress> resultAddressOfComponents = getResAddrToComponentsToRead( resVarAddr );
|
|
|
|
if ( !resultAddressOfComponents.empty() )
|
|
{
|
|
std::vector<RigFemScalarResultFrames*> resultsForEachComponent;
|
|
for ( const auto& resultAddressOfComponent : resultAddressOfComponents )
|
|
{
|
|
resultsForEachComponent.push_back( m_femPartResults[partIndex]->createScalarResult( resultAddressOfComponent ) );
|
|
}
|
|
|
|
int timeSteps = timeStepCount();
|
|
caf::ProgressInfo progress( timeSteps, "" );
|
|
progress.setProgressDescription(
|
|
QString( "Loading Native Result %1 %2" ).arg( resVarAddr.fieldName.c_str(), resVarAddr.componentName.c_str() ) );
|
|
|
|
for ( int stepIndex = 0; stepIndex < timeSteps; ++stepIndex )
|
|
{
|
|
std::vector<double> frameTimes = m_readerInterface->frameTimes( stepIndex );
|
|
|
|
for ( int frameIndex = 0; frameIndex < int( frameTimes.size() ); frameIndex++ )
|
|
{
|
|
std::vector<std::vector<float>*> componentDataVectors;
|
|
for ( auto& componentResult : resultsForEachComponent )
|
|
{
|
|
componentDataVectors.push_back( &( componentResult->frameData( stepIndex, frameIndex ) ) );
|
|
}
|
|
|
|
switch ( resVarAddr.resultPosType )
|
|
{
|
|
case RIG_NODAL:
|
|
m_readerInterface->readNodeField( resVarAddr.fieldName, partIndex, stepIndex, frameIndex, &componentDataVectors );
|
|
break;
|
|
case RIG_ELEMENT:
|
|
m_readerInterface->readElementField( resVarAddr.fieldName, partIndex, stepIndex, frameIndex, &componentDataVectors );
|
|
break;
|
|
case RIG_ELEMENT_NODAL:
|
|
m_readerInterface->readElementNodeField( resVarAddr.fieldName, partIndex, stepIndex, frameIndex, &componentDataVectors );
|
|
break;
|
|
case RIG_INTEGRATION_POINT:
|
|
m_readerInterface->readIntegrationPointField( resVarAddr.fieldName, partIndex, stepIndex, frameIndex, &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 )
|
|
{
|
|
CAF_ASSERT( partIndex < static_cast<int>( m_femPartResults.size() ) );
|
|
CAF_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[RigFemAddressDefines::porBar()];
|
|
if ( fieldCompNames.contains( "VOIDR" ) ) fieldCompNames["PORO-PERM"].push_back( "PHI0" );
|
|
|
|
if ( fieldCompNames.contains( "U" ) ) fieldCompNames["U"].push_back( "U_LENGTH" );
|
|
|
|
if ( m_readerInterface->populateDerivedResultNames() )
|
|
{
|
|
fieldCompNames[FIELD_NAME_COMPACTION];
|
|
}
|
|
}
|
|
else if ( resPos == RIG_ELEMENT_NODAL )
|
|
{
|
|
fieldCompNames = m_readerInterface->scalarElementNodeFieldAndComponentNames();
|
|
|
|
if ( !m_readerInterface->populateDerivedResultNames() )
|
|
{
|
|
return fieldCompNames;
|
|
}
|
|
|
|
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.contains( "LE" ) )
|
|
{
|
|
fieldCompNames["LE"].push_back( "LE1" );
|
|
fieldCompNames["LE"].push_back( "LE2" );
|
|
fieldCompNames["LE"].push_back( "LE3" );
|
|
}
|
|
|
|
if ( fieldCompNames.contains( "PE" ) )
|
|
{
|
|
fieldCompNames["PE"].push_back( "PE1" );
|
|
fieldCompNames["PE"].push_back( "PE2" );
|
|
fieldCompNames["PE"].push_back( "PE3" );
|
|
}
|
|
|
|
fieldCompNames["INDEX"].push_back( "INDEX_K" );
|
|
}
|
|
else if ( resPos == RIG_INTEGRATION_POINT )
|
|
{
|
|
fieldCompNames = m_readerInterface->scalarIntegrationPointFieldAndComponentNames();
|
|
|
|
if ( !m_readerInterface->populateDerivedResultNames() ) return fieldCompNames;
|
|
|
|
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.contains( "LE" ) )
|
|
{
|
|
fieldCompNames["LE"].push_back( "LE1" );
|
|
fieldCompNames["LE"].push_back( "LE2" );
|
|
fieldCompNames["LE"].push_back( "LE3" );
|
|
}
|
|
|
|
if ( fieldCompNames.contains( "PE" ) )
|
|
{
|
|
fieldCompNames["PE"].push_back( "PE1" );
|
|
fieldCompNames["PE"].push_back( "PE2" );
|
|
fieldCompNames["PE"].push_back( "PE3" );
|
|
}
|
|
}
|
|
else if ( resPos == RIG_ELEMENT_NODAL_FACE )
|
|
{
|
|
if ( !m_readerInterface->populateDerivedResultNames() ) return fieldCompNames;
|
|
|
|
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( "PCRIT" );
|
|
}
|
|
else if ( resPos == RIG_ELEMENT )
|
|
{
|
|
fieldCompNames = m_readerInterface->scalarElementFieldAndComponentNames();
|
|
|
|
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[RigFemAddressDefines::porBar()];
|
|
fieldCompNames[RigFemAddressDefines::porBar()].push_back( "X" );
|
|
fieldCompNames[RigFemAddressDefines::porBar()].push_back( "Y" );
|
|
fieldCompNames[RigFemAddressDefines::porBar()].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:
|
|
fieldAndComponentNames = m_readerInterface->scalarElementFieldAndComponentNames();
|
|
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 ""
|
|
{
|
|
CAF_ASSERT( resVarAddr.componentName.empty() );
|
|
resAddressToComponents.push_back( resVarAddr );
|
|
}
|
|
}
|
|
|
|
return resAddressToComponents;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<std::string> RigFemPartResultsCollection::filteredTimeStepNames() const
|
|
{
|
|
CAF_ASSERT( m_readerInterface.notNull() );
|
|
return m_readerInterface->filteredStepNames();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
int RigFemPartResultsCollection::timeStepCount() const
|
|
{
|
|
return static_cast<int>( filteredTimeStepNames().size() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
int RigFemPartResultsCollection::frameCount( int timeStepIndex ) const
|
|
{
|
|
CAF_ASSERT( m_readerInterface.notNull() );
|
|
return m_readerInterface->frameCount( timeStepIndex );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<std::pair<int, int>>& RigFemPartResultsCollection::stepList()
|
|
{
|
|
return m_stepList;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
int RigFemPartResultsCollection::totalSteps()
|
|
{
|
|
return int( stepList().size() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<std::string> RigFemPartResultsCollection::stepNames() const
|
|
{
|
|
return m_stepNames;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::pair<int, int> RigFemPartResultsCollection::stepListIndexToTimeStepAndDataFrameIndex( int stepIndex ) const
|
|
{
|
|
if ( stepIndex < 0 || stepIndex >= static_cast<int>( m_stepList.size() ) ) return std::make_pair( stepIndex, -1 );
|
|
return m_stepList[stepIndex];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// 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 );
|
|
const int stepCount = scalarResults->timeStepCount();
|
|
for ( int stepIdx = 0; stepIdx < stepCount; stepIdx++ )
|
|
{
|
|
const int frameCount = scalarResults->frameCount( stepIdx );
|
|
for ( int fIdx = 0; fIdx < frameCount; ++fIdx )
|
|
{
|
|
foundResults = foundResults || !scalarResults->frameData( stepIdx, fIdx ).empty();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return foundResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::deleteResult( const RigFemResultAddress& resVarAddr )
|
|
{
|
|
CAF_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 );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
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 stepIndex, int frameIndex )
|
|
{
|
|
CAF_ASSERT( resVarAddr.isValid() );
|
|
|
|
RigFemScalarResultFrames* scalarResults = findOrLoadScalarResult( partIndex, resVarAddr );
|
|
|
|
static std::vector<float> empty;
|
|
if ( scalarResults->frameCount( stepIndex ) == 0 ) return empty;
|
|
|
|
return scalarResults->frameData( stepIndex, frameIndex );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::globalResultValues( const RigFemResultAddress& resVarAddr,
|
|
int timeStepIndex,
|
|
int frameIndex,
|
|
std::vector<float>& resultValues )
|
|
{
|
|
CAF_ASSERT( resVarAddr.isValid() );
|
|
|
|
for ( int i = 0; i < partCount(); i++ )
|
|
{
|
|
const std::vector<float>& partResults = this->resultValues( resVarAddr, i, timeStepIndex, frameIndex );
|
|
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 stepIndex, int frameIndex )
|
|
{
|
|
CAF_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, stepIndex, frameIndex );
|
|
const std::vector<float>& v22 = resultValues( addresses[caf::Ten3f::SYY], partIndex, stepIndex, frameIndex );
|
|
const std::vector<float>& v33 = resultValues( addresses[caf::Ten3f::SZZ], partIndex, stepIndex, frameIndex );
|
|
const std::vector<float>& v12 = resultValues( addresses[caf::Ten3f::SXY], partIndex, stepIndex, frameIndex );
|
|
const std::vector<float>& v13 = resultValues( addresses[caf::Ten3f::SZX], partIndex, stepIndex, frameIndex );
|
|
const std::vector<float>& v23 = resultValues( addresses[caf::Ten3f::SYZ], partIndex, stepIndex, 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 stepIndex,
|
|
int frameIndex,
|
|
double* localMin,
|
|
double* localMax )
|
|
{
|
|
statistics( resVarAddr )->minMaxCellScalarValues( stepIndex, *localMin, *localMax );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::minMaxScalarValues( const RigFemResultAddress& resVarAddr, double* globalMin, double* globalMax )
|
|
{
|
|
statistics( resVarAddr )->minMaxCellScalarValues( *globalMin, *globalMax );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::posNegClosestToZero( const RigFemResultAddress& resVarAddr,
|
|
int frameIndex,
|
|
int stepIndex,
|
|
double* localPosClosestToZero,
|
|
double* localNegClosestToZero )
|
|
{
|
|
statistics( resVarAddr )->posNegClosestToZero( stepIndex, *localPosClosestToZero, *localNegClosestToZero );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::posNegClosestToZero( const RigFemResultAddress& resVarAddr,
|
|
double* globalPosClosestToZero,
|
|
double* globalNegClosestToZero )
|
|
{
|
|
statistics( resVarAddr )->posNegClosestToZero( *globalPosClosestToZero, *globalNegClosestToZero );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::meanScalarValue( const RigFemResultAddress& resVarAddr, double* meanValue )
|
|
{
|
|
CAF_ASSERT( meanValue );
|
|
|
|
statistics( resVarAddr )->meanCellScalarValues( *meanValue );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::meanScalarValue( const RigFemResultAddress& resVarAddr, int stepIndex, int frameIndex, double* meanValue )
|
|
{
|
|
statistics( resVarAddr )->meanCellScalarValues( stepIndex, *meanValue );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::p10p90ScalarValues( const RigFemResultAddress& resVarAddr, double* p10, double* p90 )
|
|
{
|
|
statistics( resVarAddr )->p10p90CellScalarValues( *p10, *p90 );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::p10p90ScalarValues( const RigFemResultAddress& resVarAddr, int stepIndex, int frameIndex, double* p10, double* p90 )
|
|
{
|
|
statistics( resVarAddr )->p10p90CellScalarValues( stepIndex, *p10, *p90 );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::sumScalarValue( const RigFemResultAddress& resVarAddr, double* sum )
|
|
{
|
|
CAF_ASSERT( sum );
|
|
|
|
statistics( resVarAddr )->sumCellScalarValues( *sum );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::sumScalarValue( const RigFemResultAddress& resVarAddr, int stepIndex, int frameIndex, double* sum )
|
|
{
|
|
CAF_ASSERT( sum );
|
|
|
|
statistics( resVarAddr )->sumCellScalarValues( stepIndex, *sum );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<size_t>& RigFemPartResultsCollection::scalarValuesHistogram( const RigFemResultAddress& resVarAddr )
|
|
{
|
|
return statistics( resVarAddr )->cellScalarValuesHistogram();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<size_t>&
|
|
RigFemPartResultsCollection::scalarValuesHistogram( const RigFemResultAddress& resVarAddr, int stepIndex, int frameIndex )
|
|
{
|
|
return statistics( resVarAddr )->cellScalarValuesHistogram( stepIndex );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
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, RigFemAddressDefines::porBar(), "", RigFemResultAddress::allTimeLapsesValue(), -1, true ) );
|
|
results.insert(
|
|
RigFemResultAddress( RIG_ELEMENT_NODAL, RigFemAddressDefines::porBar(), "", 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() )
|
|
{
|
|
deleteResult( result );
|
|
}
|
|
}
|
|
m_normalizationAirGap = normalizationAirGap;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
double RigFemPartResultsCollection::normalizationAirGap() const
|
|
{
|
|
return m_normalizationAirGap;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFemPartResultsCollection::minMaxScalarValuesOverAllTensorComponents( const RigFemResultAddress& resVarAddr,
|
|
int stepIndex,
|
|
int frameIndex,
|
|
double* localMin,
|
|
double* localMax )
|
|
{
|
|
double currentMin = HUGE_VAL;
|
|
double currentMax = -HUGE_VAL;
|
|
|
|
double min, max;
|
|
|
|
for ( const auto& address : tensorPrincipalComponentAdresses( resVarAddr ) )
|
|
{
|
|
statistics( address )->minMaxCellScalarValues( stepIndex, 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 ) )
|
|
{
|
|
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 stepIndex,
|
|
int frameIndex,
|
|
double* localPosClosestToZero,
|
|
double* localNegClosestToZero )
|
|
{
|
|
double currentPosClosestToZero = HUGE_VAL;
|
|
double currentNegClosestToZero = -HUGE_VAL;
|
|
|
|
double pos, neg;
|
|
|
|
for ( const auto& address : tensorPrincipalComponentAdresses( resVarAddr ) )
|
|
{
|
|
statistics( address )->posNegClosestToZero( stepIndex, 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 ) )
|
|
{
|
|
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( "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() )
|
|
{
|
|
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() )
|
|
{
|
|
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() ) );
|
|
}
|
|
}
|