mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Required changes to use Qt6 and disable support for Qt5. There are still some adjustments related to Qt6 to be done, but these changes are not required to make Qt6 compile on relevant systems. * Build system changes Qt6 * Override enterEvent * Update QKeySequence * QtChart changes * Use QScreen to instepct dotsPerInch * Add app->quit() * Required updates for code related to QString * Use RiaQDateTimeTools * Required changes related to regular expressions * Support compile on Qt < 6.5 When version < 6.5 is found, qt_generate_deploy_app_script() is disabled. Compilation of ResInsight will work, but the install target will be incomplete. * Octave: add missing header. * Qt Advanced Docking: force Qt6 where both Qt5 and Qt6 is available. --------- Co-authored-by: magnesj <1793152+magnesj@users.noreply.github.com> Co-authored-by: Kristian Bendiksen <kristian.bendiksen@gmail.com>
993 lines
40 KiB
C++
993 lines
40 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2018- Equinor ASA
|
|
// Copyright (C) 2015-2018 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 "RimGeoMechResultDefinition.h"
|
|
|
|
#include "RiaMedianCalculator.h"
|
|
#include "RiaResultNames.h"
|
|
|
|
#include "RifGeoMechReaderInterface.h"
|
|
|
|
#include "RigFemAddressDefines.h"
|
|
#include "RigFemPartCollection.h"
|
|
#include "RigFemPartGrid.h"
|
|
#include "RigFemPartResultCalculatorStressAnisotropy.h"
|
|
#include "RigFemPartResultsCollection.h"
|
|
#include "RigFemResultAddress.h"
|
|
#include "RigFormationNames.h"
|
|
#include "RigGeoMechCaseData.h"
|
|
#include "RigWbsParameter.h"
|
|
#include "RigWellPath.h"
|
|
|
|
#include "Rim3dWellLogCurve.h"
|
|
#include "RimGeoMechCase.h"
|
|
#include "RimGeoMechCellColors.h"
|
|
#include "RimGeoMechPropertyFilter.h"
|
|
#include "RimGeoMechView.h"
|
|
#include "RimIntersectionCollection.h"
|
|
#include "RimPlotCurve.h"
|
|
#include "RimProject.h"
|
|
#include "RimRegularLegendConfig.h"
|
|
#include "RimViewLinker.h"
|
|
#include "RimWellPath.h"
|
|
|
|
#include "cafPdmUiDoubleValueEditor.h"
|
|
#include "cafPdmUiTreeSelectionEditor.h"
|
|
|
|
#include <QDoubleValidator>
|
|
|
|
namespace caf
|
|
{
|
|
template <>
|
|
void caf::AppEnum<RigFemResultPosEnum>::setUp()
|
|
{
|
|
addItem( RIG_NODAL, "NODAL", "Nodal" );
|
|
addItem( RIG_ELEMENT_NODAL, "ELEMENT_NODAL", "Element Nodal" );
|
|
addItem( RIG_INTEGRATION_POINT, "INTEGRATION_POINT", "Integration Point" );
|
|
addItem( RIG_ELEMENT_NODAL_FACE, "ELEMENT_NODAL_FACE", "Element Nodal On Face" );
|
|
addItem( RIG_FORMATION_NAMES, "FORMATION_NAMES", "Formation Names" );
|
|
addItem( RIG_ELEMENT, "ELEMENT", "Element" );
|
|
addItem( RIG_WELLPATH_DERIVED, "WELLPATH_DERIVED", "Well Path Derived" );
|
|
addItem( RIG_DIFFERENTIALS, "DIFFERENTIALS", "Differentials" );
|
|
setDefault( RIG_NODAL );
|
|
}
|
|
} // namespace caf
|
|
|
|
CAF_PDM_SOURCE_INIT( RimGeoMechResultDefinition, "GeoMechResultDefinition" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimGeoMechResultDefinition::RimGeoMechResultDefinition()
|
|
{
|
|
CAF_PDM_InitObject( "Color Result", ":/CellResult.png" );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_resultPositionType, "ResultPositionType", "Result Position" );
|
|
m_resultPositionType.uiCapability()->setUiHidden( true );
|
|
|
|
CAF_PDM_InitField( &m_resultFieldName, "ResultFieldName", QString( "" ), "Field Name" );
|
|
m_resultFieldName.uiCapability()->setUiHidden( true );
|
|
|
|
CAF_PDM_InitField( &m_resultComponentName, "ResultComponentName", QString( "" ), "Component" );
|
|
m_resultComponentName.uiCapability()->setUiHidden( true );
|
|
|
|
CAF_PDM_InitField( &m_timeLapseBaseTimestep, "TimeLapseBaseTimeStep", RigFemResultAddress::noTimeLapseValue(), "Base Time Step" );
|
|
CAF_PDM_InitField( &m_referenceTimeStep, "ReferenceTimeStep", 0, "Reference Time Step" );
|
|
|
|
CAF_PDM_InitField( &m_compactionRefLayer, "CompactionRefLayer", 0, "Compaction Ref Layer" );
|
|
m_compactionRefLayer.uiCapability()->setUiHidden( true );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_resultPositionTypeUiField, "ResultPositionTypeUi", "Result Position" );
|
|
m_resultPositionTypeUiField.xmlCapability()->disableIO();
|
|
|
|
CAF_PDM_InitField( &m_resultVariableUiField, "ResultVariableUI", QString( "" ), "Value" );
|
|
m_resultVariableUiField.xmlCapability()->disableIO();
|
|
|
|
m_resultVariableUiField.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
|
|
m_resultVariableUiField.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
|
|
|
|
CAF_PDM_InitField( &m_normalizeByHydrostaticPressure, "NormalizeByHSP", false, "Normalize by Hydrostatic Pressure" );
|
|
CAF_PDM_InitField( &m_normalizationAirGap, "NormalizationAirGap", 0.0, "Air Gap" );
|
|
m_normalizationAirGap.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
|
|
|
|
CAF_PDM_InitField( &m_compactionRefLayerUiField,
|
|
"CompactionRefLayerUi",
|
|
RigFemResultAddress::noCompactionValue(),
|
|
"Compaction Ref Layer",
|
|
"",
|
|
"The compaction is calculated with reference to this layer. Default layer is the topmost "
|
|
"layer "
|
|
"with POR",
|
|
"" );
|
|
m_compactionRefLayerUiField.xmlCapability()->disableIO();
|
|
|
|
m_isChangedByField = false;
|
|
m_addWellPathDerivedResults = false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimGeoMechResultDefinition::~RimGeoMechResultDefinition()
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
|
{
|
|
uiOrdering.add( &m_resultPositionTypeUiField );
|
|
uiOrdering.add( &m_resultVariableUiField );
|
|
|
|
QString valueLabel = "Value";
|
|
if ( m_timeLapseBaseTimestep != RigFemResultAddress::noTimeLapseValue() )
|
|
{
|
|
valueLabel += QString( " (%1)" ).arg( diffResultUiName() );
|
|
}
|
|
m_resultVariableUiField.uiCapability()->setUiName( valueLabel );
|
|
|
|
if ( normalizableResultSelected() )
|
|
{
|
|
caf::PdmUiGroup* normalizationGroup = uiOrdering.addNewGroup( "Result Normalization" );
|
|
normalizationGroup->add( &m_normalizeByHydrostaticPressure );
|
|
if ( m_normalizeByHydrostaticPressure )
|
|
{
|
|
normalizationGroup->add( &m_normalizationAirGap );
|
|
}
|
|
}
|
|
|
|
if ( m_resultPositionTypeUiField() != RIG_FORMATION_NAMES )
|
|
{
|
|
bool isReferenceCaseDependent = referenceCaseDependentResultSelected();
|
|
if ( isReferenceCaseDependent )
|
|
{
|
|
caf::PdmUiGroup* referenceCaseGr = uiOrdering.addNewGroup( "Reference Case" );
|
|
referenceCaseGr->add( &m_referenceTimeStep );
|
|
}
|
|
else
|
|
{
|
|
caf::PdmUiGroup* timeLapseGr = uiOrdering.addNewGroup( "Difference Options" );
|
|
timeLapseGr->add( &m_timeLapseBaseTimestep );
|
|
}
|
|
}
|
|
|
|
if ( m_resultPositionTypeUiField() == RIG_NODAL )
|
|
{
|
|
caf::PdmUiGroup* compactionGroup = uiOrdering.addNewGroup( "Compaction Options" );
|
|
compactionGroup->add( &m_compactionRefLayerUiField );
|
|
|
|
if ( m_compactionRefLayerUiField == RigFemResultAddress::noCompactionValue() )
|
|
{
|
|
if ( m_geomCase && m_geomCase->geoMechData() )
|
|
{
|
|
m_compactionRefLayerUiField =
|
|
(int)m_geomCase->geoMechData()->femParts()->part( 0 )->getOrCreateStructGrid()->reservoirIJKBoundingBox().first.z();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !m_isChangedByField )
|
|
{
|
|
m_resultPositionTypeUiField = m_resultPositionType;
|
|
m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() );
|
|
}
|
|
|
|
m_isChangedByField = false;
|
|
|
|
uiOrdering.skipRemainingFields( true );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QList<caf::PdmOptionItemInfo> RimGeoMechResultDefinition::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
|
{
|
|
QList<caf::PdmOptionItemInfo> options;
|
|
|
|
if ( m_geomCase )
|
|
{
|
|
if ( &m_resultPositionTypeUiField == fieldNeedingOptions )
|
|
{
|
|
std::vector<RigFemResultPosEnum> optionItems = { RIG_NODAL,
|
|
RIG_ELEMENT_NODAL,
|
|
RIG_INTEGRATION_POINT,
|
|
RIG_ELEMENT_NODAL_FACE,
|
|
RIG_FORMATION_NAMES,
|
|
RIG_ELEMENT,
|
|
RIG_DIFFERENTIALS };
|
|
if ( m_addWellPathDerivedResults )
|
|
{
|
|
optionItems.push_back( RIG_WELLPATH_DERIVED );
|
|
}
|
|
for ( RigFemResultPosEnum value : optionItems )
|
|
{
|
|
options.push_back( caf::PdmOptionItemInfo( caf::AppEnum<RigFemResultPosEnum>::uiText( value ), QVariant( value ) ) );
|
|
}
|
|
}
|
|
else if ( &m_resultVariableUiField == fieldNeedingOptions )
|
|
{
|
|
std::map<std::string, std::vector<std::string>> fieldCompNames = getResultMetaDataForUIFieldSetting();
|
|
|
|
QStringList uiVarNames;
|
|
QStringList varNames;
|
|
|
|
getUiAndResultVariableStringList( &uiVarNames, &varNames, fieldCompNames );
|
|
|
|
for ( int oIdx = 0; oIdx < uiVarNames.size(); ++oIdx )
|
|
{
|
|
options.push_back( caf::PdmOptionItemInfo( uiVarNames[oIdx], varNames[oIdx] ) );
|
|
}
|
|
}
|
|
else if ( &m_timeLapseBaseTimestep == fieldNeedingOptions )
|
|
{
|
|
std::vector<std::string> stepNames;
|
|
if ( m_geomCase->geoMechData() )
|
|
{
|
|
stepNames = m_geomCase->geoMechData()->femPartResults()->stepNames();
|
|
}
|
|
|
|
options.push_back( caf::PdmOptionItemInfo( QString( "Disabled" ), RigFemResultAddress::noTimeLapseValue() ) );
|
|
for ( size_t stepIdx = 0; stepIdx < stepNames.size(); ++stepIdx )
|
|
{
|
|
options.push_back(
|
|
caf::PdmOptionItemInfo( QString( "%1 (#%2)" ).arg( QString::fromStdString( stepNames[stepIdx] ) ).arg( stepIdx ),
|
|
static_cast<int>( stepIdx ) ) );
|
|
}
|
|
}
|
|
else if ( &m_referenceTimeStep == fieldNeedingOptions )
|
|
{
|
|
std::vector<std::string> stepNames;
|
|
if ( m_geomCase->geoMechData() )
|
|
{
|
|
stepNames = m_geomCase->geoMechData()->femPartResults()->stepNames();
|
|
}
|
|
|
|
for ( size_t stepIdx = 0; stepIdx < stepNames.size(); ++stepIdx )
|
|
{
|
|
options.push_back(
|
|
caf::PdmOptionItemInfo( QString( "%1 (#%2)" ).arg( QString::fromStdString( stepNames[stepIdx] ) ).arg( stepIdx ),
|
|
static_cast<int>( stepIdx ) ) );
|
|
}
|
|
}
|
|
else if ( &m_compactionRefLayerUiField == fieldNeedingOptions )
|
|
{
|
|
if ( m_geomCase->geoMechData() )
|
|
{
|
|
size_t kCount = m_geomCase->geoMechData()->femParts()->part( 0 )->getOrCreateStructGrid()->cellCountK();
|
|
for ( size_t layerIdx = 0; layerIdx < kCount; ++layerIdx )
|
|
{
|
|
options.push_back( caf::PdmOptionItemInfo( QString::number( layerIdx + 1 ), (int)layerIdx ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::setGeoMechCase( RimGeoMechCase* geomCase )
|
|
{
|
|
m_geomCase = geomCase;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimGeoMechCase* RimGeoMechResultDefinition::geoMechCase() const
|
|
{
|
|
return m_geomCase;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
|
{
|
|
m_isChangedByField = true;
|
|
|
|
if ( &m_resultPositionTypeUiField == changedField )
|
|
{
|
|
if ( m_resultPositionTypeUiField() == RIG_WELLPATH_DERIVED || m_resultPositionType() == RIG_FORMATION_NAMES )
|
|
{
|
|
m_timeLapseBaseTimestep = RigFemResultAddress::noTimeLapseValue();
|
|
m_timeLapseBaseTimestep.uiCapability()->setUiReadOnly( true );
|
|
}
|
|
else
|
|
{
|
|
m_timeLapseBaseTimestep.uiCapability()->setUiReadOnly( false );
|
|
}
|
|
}
|
|
|
|
if ( &m_resultPositionTypeUiField == changedField || &m_timeLapseBaseTimestep == changedField || &m_referenceTimeStep == changedField )
|
|
{
|
|
std::map<std::string, std::vector<std::string>> fieldCompNames = getResultMetaDataForUIFieldSetting();
|
|
QStringList uiVarNames;
|
|
QStringList varNames;
|
|
|
|
getUiAndResultVariableStringList( &uiVarNames, &varNames, fieldCompNames );
|
|
|
|
if ( m_resultPositionTypeUiField() == m_resultPositionType() &&
|
|
varNames.contains( composeFieldCompString( m_resultFieldName(), m_resultComponentName() ) ) )
|
|
{
|
|
m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() );
|
|
}
|
|
else
|
|
{
|
|
m_resultVariableUiField = "";
|
|
}
|
|
|
|
if ( &m_referenceTimeStep == changedField )
|
|
{
|
|
m_geomCase->geoMechData()->femPartResults()->setReferenceTimeStep( m_referenceTimeStep() );
|
|
}
|
|
}
|
|
if ( &m_normalizeByHydrostaticPressure == changedField && m_normalizationAirGap == 0.0 )
|
|
{
|
|
calculateNormalizationAirGapDefault();
|
|
if ( m_normalizeByHydrostaticPressure )
|
|
{
|
|
m_geomCase->geoMechData()->femPartResults()->setNormalizationAirGap( m_normalizationAirGap );
|
|
}
|
|
}
|
|
|
|
// Get the possible property filter owner
|
|
auto propFilter = dynamic_cast<RimGeoMechPropertyFilter*>( parentField()->ownerObject() );
|
|
auto view = firstAncestorOrThisOfType<RimGridView>();
|
|
auto curve = firstAncestorOrThisOfType<RimPlotCurve>();
|
|
auto rim3dWellLogCurve = firstAncestorOrThisOfType<Rim3dWellLogCurve>();
|
|
|
|
if ( &m_resultVariableUiField == changedField || &m_compactionRefLayerUiField == changedField ||
|
|
&m_timeLapseBaseTimestep == changedField || &m_normalizeByHydrostaticPressure == changedField ||
|
|
&m_normalizationAirGap == changedField || &m_referenceTimeStep == changedField || &m_isChecked == changedField )
|
|
{
|
|
QStringList fieldComponentNames = m_resultVariableUiField().split( QRegularExpression( "\\s+" ) );
|
|
if ( !fieldComponentNames.empty() )
|
|
{
|
|
m_resultPositionType = m_resultPositionTypeUiField;
|
|
if ( m_resultPositionType() == RIG_FORMATION_NAMES )
|
|
{
|
|
// Complete string of selected formation is stored in m_resultFieldName
|
|
m_resultFieldName = m_resultVariableUiField();
|
|
m_resultComponentName = "";
|
|
}
|
|
else
|
|
{
|
|
m_resultFieldName = fieldComponentNames[0];
|
|
if ( fieldComponentNames.size() > 1 )
|
|
{
|
|
m_resultComponentName = fieldComponentNames[1];
|
|
}
|
|
else
|
|
{
|
|
m_resultComponentName = "";
|
|
}
|
|
|
|
m_compactionRefLayer = m_compactionRefLayerUiField();
|
|
}
|
|
|
|
if ( propFilter )
|
|
{
|
|
propFilter->setToDefaultValues();
|
|
|
|
if ( view ) view->scheduleGeometryRegen( PROPERTY_FILTERED );
|
|
}
|
|
|
|
if ( view )
|
|
{
|
|
view->scheduleCreateDisplayModelAndRedraw();
|
|
view->intersectionCollection()->scheduleCreateDisplayModelAndRedraw2dIntersectionViews();
|
|
}
|
|
|
|
if ( dynamic_cast<RimGeoMechCellColors*>( this ) )
|
|
{
|
|
updateLegendCategorySettings();
|
|
|
|
if ( view )
|
|
{
|
|
RimViewLinker* viewLinker = view->assosiatedViewLinker();
|
|
if ( viewLinker )
|
|
{
|
|
viewLinker->updateCellResult();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( curve )
|
|
{
|
|
curve->loadDataAndUpdate( true );
|
|
}
|
|
|
|
if ( rim3dWellLogCurve )
|
|
{
|
|
rim3dWellLogCurve->updateCurveIn3dView();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( rim3dWellLogCurve )
|
|
{
|
|
rim3dWellLogCurve->resetMinMaxValues();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::calculateNormalizationAirGapDefault()
|
|
{
|
|
RiaMedianCalculator<double> airGapCalc;
|
|
for ( auto wellPath : RimProject::current()->allWellPaths() )
|
|
{
|
|
if ( wellPath->wellPathGeometry() )
|
|
{
|
|
double airGap = wellPath->wellPathGeometry()->rkbDiff();
|
|
if ( airGap > 0.0 )
|
|
{
|
|
airGapCalc.add( airGap );
|
|
}
|
|
}
|
|
}
|
|
if ( airGapCalc.valid() )
|
|
{
|
|
m_normalizationAirGap = airGapCalc.median();
|
|
}
|
|
else
|
|
{
|
|
m_normalizationAirGap = 0.0;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RimGeoMechResultDefinition::useUndoRedoForFieldChanged()
|
|
{
|
|
// Do not use undo/redo, because a state variable is initialized in fieldChanged(), and the undo/redo framework
|
|
// trigger a call to defineUiOrdering() before fieldChanged causing invalid state in this object.
|
|
// Having a state variable in fieldChanged/defineUiOrdering is a fragile pattern and should be avoided
|
|
|
|
// See CmdFieldChangeExec::redo()
|
|
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::map<std::string, std::vector<std::string>> RimGeoMechResultDefinition::getResultMetaDataForUIFieldSetting()
|
|
{
|
|
RimGeoMechCase* gmCase = m_geomCase;
|
|
std::map<std::string, std::vector<std::string>> fieldWithComponentNames;
|
|
if ( gmCase && gmCase->geoMechData() )
|
|
{
|
|
fieldWithComponentNames = gmCase->geoMechData()->femPartResults()->scalarFieldAndComponentNames( m_resultPositionTypeUiField() );
|
|
}
|
|
|
|
return fieldWithComponentNames;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::getUiAndResultVariableStringList( QStringList* uiNames,
|
|
QStringList* variableNames,
|
|
const std::map<std::string, std::vector<std::string>>& fieldCompNames )
|
|
{
|
|
CVF_ASSERT( uiNames && variableNames );
|
|
|
|
std::map<std::string, std::vector<std::string>>::const_iterator fieldIt;
|
|
for ( fieldIt = fieldCompNames.begin(); fieldIt != fieldCompNames.end(); ++fieldIt )
|
|
{
|
|
QString resultFieldName = QString::fromStdString( fieldIt->first );
|
|
|
|
if ( resultFieldName == "E" || resultFieldName == "S" || resultFieldName == "POR" )
|
|
continue; // We will not show the native POR, Stress and Strain
|
|
|
|
QString resultFieldUiName = convertToUiResultFieldName( resultFieldName );
|
|
|
|
uiNames->push_back( resultFieldUiName );
|
|
variableNames->push_back( resultFieldName );
|
|
|
|
std::vector<std::string>::const_iterator compIt;
|
|
for ( compIt = fieldIt->second.begin(); compIt != fieldIt->second.end(); ++compIt )
|
|
{
|
|
QString resultCompName = QString::fromStdString( *compIt );
|
|
uiNames->push_back( " " + resultCompName );
|
|
variableNames->push_back( composeFieldCompString( resultFieldName, resultCompName ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::composeFieldCompString( const QString& resultFieldName, const QString& resultComponentName )
|
|
{
|
|
if ( resultComponentName.isEmpty() )
|
|
return resultFieldName;
|
|
else
|
|
return resultFieldName + " " + resultComponentName;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::initAfterRead()
|
|
{
|
|
if ( m_resultComponentName() == "STM" || m_resultComponentName() == "SEM" ) m_resultComponentName = "SM";
|
|
|
|
m_resultPositionTypeUiField = m_resultPositionType;
|
|
m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() );
|
|
m_compactionRefLayerUiField = m_compactionRefLayer;
|
|
|
|
m_timeLapseBaseTimestep.uiCapability()->setUiReadOnly( resultPositionType() == RIG_WELLPATH_DERIVED );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
|
|
{
|
|
if ( field == &m_normalizationAirGap )
|
|
{
|
|
auto attr = dynamic_cast<caf::PdmUiDoubleValueEditorAttribute*>( attribute );
|
|
if ( attr )
|
|
{
|
|
attr->m_decimals = 2;
|
|
attr->m_validator = new QDoubleValidator( 0.0, std::numeric_limits<double>::max(), 2 );
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::loadResult()
|
|
{
|
|
if ( m_geomCase && m_geomCase->geoMechData() )
|
|
{
|
|
if ( resultAddress().fieldName == RiaResultNames::wbsFGResult().toStdString() ||
|
|
resultAddress().fieldName == RiaResultNames::wbsSFGResult().toStdString() )
|
|
{
|
|
RigFemResultAddress stressResAddr( RIG_ELEMENT_NODAL, std::string( "ST" ), "" );
|
|
RigFemResultAddress porBarResAddr = RigFemAddressDefines::elementNodalPorBarAddress();
|
|
m_geomCase->geoMechData()->femPartResults()->assertResultsLoaded( stressResAddr );
|
|
m_geomCase->geoMechData()->femPartResults()->assertResultsLoaded( porBarResAddr );
|
|
}
|
|
else
|
|
{
|
|
m_geomCase->geoMechData()->femPartResults()->assertResultsLoaded( resultAddress() );
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::setAddWellPathDerivedResults( bool addWellPathDerivedResults )
|
|
{
|
|
m_addWellPathDerivedResults = addWellPathDerivedResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigFemResultAddress RimGeoMechResultDefinition::resultAddress() const
|
|
{
|
|
// Convert differentials to their underlying position type
|
|
if ( resultPositionType() == RIG_DIFFERENTIALS )
|
|
{
|
|
RigFemResultPosEnum resultPositionType = RIG_ELEMENT_NODAL;
|
|
if ( resultFieldName().toStdString() == RigFemAddressDefines::porBar() )
|
|
{
|
|
resultPositionType = RIG_NODAL;
|
|
}
|
|
|
|
return RigFemResultAddress( resultPositionType,
|
|
resultFieldName().toStdString(),
|
|
resultComponentName().toStdString(),
|
|
m_timeLapseBaseTimestep(),
|
|
RigFemResultAddress::noCompactionValue() );
|
|
}
|
|
else
|
|
{
|
|
RigFemResultAddress address( resultPositionType(),
|
|
resultFieldName().toStdString(),
|
|
resultComponentName().toStdString(),
|
|
m_timeLapseBaseTimestep(),
|
|
resultFieldName().toStdString() == RigFemPartResultsCollection::FIELD_NAME_COMPACTION
|
|
? m_compactionRefLayer()
|
|
: RigFemResultAddress::noCompactionValue(),
|
|
m_normalizeByHydrostaticPressure );
|
|
if ( !RigFemPartResultsCollection::isNormalizableResult( address ) )
|
|
{
|
|
address.normalizedByHydrostaticPressure = false;
|
|
}
|
|
|
|
if ( RigFemPartResultsCollection::isReferenceCaseDependentResult( address ) )
|
|
{
|
|
address.timeLapseBaseStepIdx = RigFemResultAddress::noTimeLapseValue();
|
|
}
|
|
|
|
return address;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<RigFemResultAddress> RimGeoMechResultDefinition::observedResults() const
|
|
{
|
|
return std::vector<RigFemResultAddress>( 1, resultAddress() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigFemResultPosEnum RimGeoMechResultDefinition::resultPositionType() const
|
|
{
|
|
return m_resultPositionType();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::resultFieldName() const
|
|
{
|
|
if ( !isChecked() ) return "";
|
|
|
|
return m_resultFieldName();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::resultComponentName() const
|
|
{
|
|
return m_resultComponentName();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::diffResultUiName() const
|
|
{
|
|
QString diffResultString;
|
|
if ( m_geomCase->geoMechData() )
|
|
{
|
|
if ( referenceCaseDependentResultSelected() )
|
|
{
|
|
std::vector<std::string> timeStepNames = m_geomCase->geoMechData()->femPartResults()->stepNames();
|
|
QString timeStepString = QString::fromStdString( timeStepNames[m_referenceTimeStep()] );
|
|
diffResultString += QString( "<b>Reference Time Step</b>: %1" ).arg( timeStepString );
|
|
}
|
|
else if ( m_timeLapseBaseTimestep != RigFemResultAddress::noTimeLapseValue() )
|
|
{
|
|
std::vector<std::string> timeStepNames = m_geomCase->geoMechData()->femPartResults()->stepNames();
|
|
QString timeStepString = QString::fromStdString( timeStepNames[m_timeLapseBaseTimestep()] );
|
|
diffResultString += QString( "<b>Base Time Step</b>: %1" ).arg( timeStepString );
|
|
}
|
|
}
|
|
return diffResultString;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::diffResultUiShortName() const
|
|
{
|
|
QString diffResultString;
|
|
if ( m_geomCase->geoMechData() )
|
|
{
|
|
if ( referenceCaseDependentResultSelected() )
|
|
{
|
|
diffResultString += QString( "Ref. Time: #%1" ).arg( m_referenceTimeStep() );
|
|
}
|
|
else if ( m_timeLapseBaseTimestep != RigFemResultAddress::noTimeLapseValue() )
|
|
{
|
|
diffResultString += QString( "Base Time: #%1" ).arg( m_timeLapseBaseTimestep() );
|
|
}
|
|
}
|
|
return diffResultString;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigGeoMechCaseData* RimGeoMechResultDefinition::ownerCaseData() const
|
|
{
|
|
return m_geomCase ? m_geomCase->geoMechData() : nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Is the result probably valid and possible to load
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RimGeoMechResultDefinition::hasResult()
|
|
{
|
|
RigGeoMechCaseData* caseData = ownerCaseData();
|
|
if ( caseData )
|
|
{
|
|
RigFemPartResultsCollection* results = caseData->femPartResults();
|
|
if ( results )
|
|
{
|
|
return results->assertResultsLoaded( resultAddress() );
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::resultFieldUiName() const
|
|
{
|
|
return convertToUiResultFieldName( m_resultFieldName() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::resultComponentUiName() const
|
|
{
|
|
return m_resultComponentName();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::resultVariableUiName() const
|
|
{
|
|
QString name = resultFieldName();
|
|
QString resCompName = resultComponentName();
|
|
|
|
if ( !resCompName.isEmpty() )
|
|
{
|
|
name += "." + resCompName;
|
|
}
|
|
return name;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::resultVariableName() const
|
|
{
|
|
if ( m_resultPositionType == RIG_WELLPATH_DERIVED )
|
|
{
|
|
RigWbsParameter param;
|
|
if ( RigWbsParameter::findParameter( resultFieldName(), ¶m ) )
|
|
{
|
|
QString lasName = param.addressString( RigWbsParameter::LAS_FILE );
|
|
if ( !lasName.isEmpty() ) return lasName;
|
|
}
|
|
}
|
|
return resultVariableUiName();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::currentResultUnits() const
|
|
{
|
|
RigFemResultAddress rigFemResultAddress = resultAddress();
|
|
|
|
if ( RigFemPartResultCalculatorStressAnisotropy::isAnisotropyResult( rigFemResultAddress ) )
|
|
{
|
|
return RiaWellLogUnitTools<double>::noUnitString();
|
|
}
|
|
|
|
if ( resultFieldName() == "SE" || resultFieldName() == "ST" ||
|
|
resultFieldName() == QString::fromStdString( RigFemAddressDefines::porBar() ) || resultFieldName() == "SM" ||
|
|
resultFieldName() == "SEM" || resultFieldName() == "Q" )
|
|
{
|
|
auto componentName = resultComponentName();
|
|
if ( componentName.endsWith( "azi" ) || componentName.endsWith( "inc" ) )
|
|
{
|
|
return "Deg";
|
|
}
|
|
|
|
if ( rigFemResultAddress.normalizeByHydrostaticPressure() )
|
|
{
|
|
return "sg";
|
|
}
|
|
|
|
return "Bar";
|
|
}
|
|
else if ( resultFieldName() == "MODULUS" )
|
|
{
|
|
return "GPa";
|
|
}
|
|
else if ( resultFieldName() == "COMPRESSIBILITY" && ( resultComponentName() == "PORE" || resultComponentName() == "VERTICAL" ) )
|
|
{
|
|
return "1/GPa";
|
|
}
|
|
else if ( resultFieldName() == "PORO-PERM" && resultComponentName() == "PERM" )
|
|
{
|
|
return "mD";
|
|
}
|
|
else
|
|
{
|
|
for ( auto resultName : RiaResultNames::wbsDerivedResultNames() )
|
|
{
|
|
if ( resultName == resultFieldName() )
|
|
{
|
|
return RiaWellLogUnitTools<double>::sg_emwUnitString();
|
|
}
|
|
}
|
|
}
|
|
|
|
return RiaWellLogUnitTools<double>::noUnitString();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::defaultLasUnits() const
|
|
{
|
|
if ( m_resultPositionType == RIG_WELLPATH_DERIVED )
|
|
{
|
|
RigWbsParameter param;
|
|
if ( RigWbsParameter::findParameter( resultFieldName(), ¶m ) )
|
|
{
|
|
return param.units( RigWbsParameter::LAS_FILE );
|
|
}
|
|
}
|
|
return currentResultUnits();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
double RimGeoMechResultDefinition::normalizationAirGap() const
|
|
{
|
|
return m_normalizationAirGap;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::setNormalizationAirGap( double airGap )
|
|
{
|
|
m_normalizationAirGap = airGap;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimGeoMechResultDefinition::convertToUiResultFieldName( QString resultFieldName )
|
|
{
|
|
QString newName( resultFieldName );
|
|
|
|
if ( resultFieldName == "E" ) newName = "NativeAbaqus Strain";
|
|
if ( resultFieldName == "S" ) newName = "NativeAbaqus Stress";
|
|
if ( resultFieldName == "NE" ) newName = "E"; // Make NE and NS appear as E and SE
|
|
if ( resultFieldName == QString::fromStdString( RigFemAddressDefines::porBar() ) ) newName = "POR"; // POR-Bar appear as POR
|
|
if ( resultFieldName == "MODULUS" ) newName = "Young's Modulus";
|
|
if ( resultFieldName == "RATIO" ) newName = "Poisson's Ratio";
|
|
if ( resultFieldName == "UCS" ) newName = "UCS bar/ 100";
|
|
|
|
return newName;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RimGeoMechResultDefinition::normalizableResultSelected() const
|
|
{
|
|
return RigFemPartResultsCollection::isNormalizableResult( resultAddress() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RimGeoMechResultDefinition::referenceCaseDependentResultSelected() const
|
|
{
|
|
return RigFemPartResultsCollection::isReferenceCaseDependentResult( resultAddress() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::setResultAddress( const RigFemResultAddress& resultAddress )
|
|
{
|
|
m_resultPositionType = resultAddress.resultPosType;
|
|
m_resultFieldName = QString::fromStdString( resultAddress.fieldName );
|
|
m_resultComponentName = QString::fromStdString( resultAddress.componentName );
|
|
m_timeLapseBaseTimestep = resultAddress.timeLapseBaseStepIdx;
|
|
m_compactionRefLayer = resultAddress.refKLayerIndex;
|
|
m_normalizeByHydrostaticPressure = resultAddress.normalizedByHydrostaticPressure;
|
|
|
|
m_resultPositionTypeUiField = m_resultPositionType;
|
|
m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() );
|
|
m_compactionRefLayerUiField = m_compactionRefLayer;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimGeoMechResultDefinition::updateLegendTextAndRanges( RimRegularLegendConfig* legendConfigToUpdate,
|
|
const QString& legendHeading,
|
|
int viewerStepIndex )
|
|
{
|
|
if ( !ownerCaseData() || !( resultAddress().isValid() ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
double localMin, localMax;
|
|
double localPosClosestToZero, localNegClosestToZero;
|
|
double globalMin, globalMax;
|
|
double globalPosClosestToZero, globalNegClosestToZero;
|
|
|
|
RigGeoMechCaseData* gmCase = ownerCaseData();
|
|
CVF_ASSERT( gmCase );
|
|
|
|
RigFemResultAddress resVarAddress = resultAddress();
|
|
|
|
auto [stepIdx, frameIdx] = gmCase->femPartResults()->stepListIndexToTimeStepAndDataFrameIndex( viewerStepIndex );
|
|
|
|
gmCase->femPartResults()->minMaxScalarValues( resVarAddress, stepIdx, frameIdx, &localMin, &localMax );
|
|
gmCase->femPartResults()->posNegClosestToZero( resVarAddress, stepIdx, frameIdx, &localPosClosestToZero, &localNegClosestToZero );
|
|
|
|
gmCase->femPartResults()->minMaxScalarValues( resVarAddress, &globalMin, &globalMax );
|
|
gmCase->femPartResults()->posNegClosestToZero( resVarAddress, &globalPosClosestToZero, &globalNegClosestToZero );
|
|
|
|
legendConfigToUpdate->setClosestToZeroValues( globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero );
|
|
legendConfigToUpdate->setAutomaticRanges( globalMin, globalMax, localMin, localMax );
|
|
|
|
if ( hasCategoryResult() )
|
|
{
|
|
std::vector<QString> fnVector = gmCase->femPartResults()->formationNames();
|
|
legendConfigToUpdate->setNamedCategories( fnVector );
|
|
}
|
|
|
|
QString legendTitle = legendHeading + caf::AppEnum<RigFemResultPosEnum>( resultPositionType() ).uiText() + "\n" + resultFieldUiName();
|
|
|
|
if ( !resultComponentUiName().isEmpty() )
|
|
{
|
|
legendTitle += ", " + resultComponentUiName();
|
|
}
|
|
|
|
QString unitString = currentResultUnits();
|
|
if ( unitString != RiaWellLogUnitTools<double>::noUnitString() )
|
|
{
|
|
legendTitle += QString( " [%1]" ).arg( unitString );
|
|
}
|
|
|
|
if ( !diffResultUiShortName().isEmpty() )
|
|
{
|
|
legendTitle += QString( "\nTime Diff:\n%1" ).arg( diffResultUiShortName() );
|
|
}
|
|
|
|
legendConfigToUpdate->setTitle( legendTitle );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RimGeoMechResultDefinition::isBiotCoefficientDependent() const
|
|
{
|
|
return ( resultFieldName() == "COMPRESSIBILITY" || resultFieldName() == "PORO-PERM" );
|
|
}
|