mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Rename ApplicationCode to ApplicationLibCode
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
|
||||
set (SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelTemplate.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModel.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelTemplateCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelCalculator.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelCurve.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelElasticPropertyCalculator.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelLayerCalculator.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelPlotCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelPropertyCalculator.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelPropertyCurve.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelStressCalculator.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelWellLogCalculator.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimElasticProperties.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimElasticPropertyScaling.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimElasticPropertyScalingCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFaciesProperties.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimNonNetLayers.h
|
||||
)
|
||||
|
||||
set (SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelTemplate.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelTemplateCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelCalculator.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelCurve.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelElasticPropertyCalculator.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelLayerCalculator.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelPlotCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelPlot.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelStressCalculator.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimStimPlanModelWellLogCalculator.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimElasticProperties.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimElasticPropertyScaling.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimElasticPropertyScalingCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFaciesProperties.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimNonNetLayers.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES
|
||||
${SOURCE_GROUP_HEADER_FILES}
|
||||
)
|
||||
|
||||
list(APPEND CODE_SOURCE_FILES
|
||||
${SOURCE_GROUP_SOURCE_FILES}
|
||||
)
|
||||
|
||||
list(APPEND QT_MOC_HEADERS
|
||||
)
|
||||
|
||||
source_group( "ProjectDataModel\\StimPlanModel" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake )
|
||||
@@ -0,0 +1,296 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimElasticProperties.h"
|
||||
|
||||
#include "RimElasticPropertyScalingCollection.h"
|
||||
#include "RimStimPlanModelTemplate.h"
|
||||
|
||||
#include "RicElasticPropertiesImportTools.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiLineEditor.h"
|
||||
#include "cafPdmUiTextEditor.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimElasticProperties, "ElasticProperties" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimElasticProperties::RimElasticProperties()
|
||||
: changed( this )
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "RimElasticProperties", "", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_filePath, "FilePath", "File Path", "", "", "" );
|
||||
m_filePath.uiCapability()->setUiReadOnly( true );
|
||||
m_filePath.uiCapability()->setUiEditorTypeName( caf::PdmUiLineEditor::uiEditorTypeName() );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_propertiesTable, "PropertiesTable", "Properties Table", "", "", "" );
|
||||
m_propertiesTable.uiCapability()->setUiEditorTypeName( caf::PdmUiTextEditor::uiEditorTypeName() );
|
||||
m_propertiesTable.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
|
||||
m_propertiesTable.uiCapability()->setUiReadOnly( true );
|
||||
m_propertiesTable.xmlCapability()->disableIO();
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_showScaledProperties, "ShowScaledProperties", true, "Show Scaled Properties", "", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_scalings, "PropertyScalingCollection", "PropertyScalingCollection", "", "", "" );
|
||||
m_scalings.uiCapability()->setUiHidden( true );
|
||||
m_scalings.uiCapability()->setUiTreeHidden( true );
|
||||
m_scalings = new RimElasticPropertyScalingCollection;
|
||||
m_scalings->changed.connect( this, &RimElasticProperties::elasticPropertyScalingCollectionChanged );
|
||||
|
||||
setUiName( "Elastic Properties" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimElasticProperties::~RimElasticProperties()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimElasticProperties::filePath() const
|
||||
{
|
||||
return m_filePath.v().path();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticProperties::setFilePath( const QString& filePath )
|
||||
{
|
||||
m_filePath = filePath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticProperties::setPropertiesForFacies( FaciesKey& key, const RigElasticProperties& properties )
|
||||
{
|
||||
m_properties.insert( std::pair<FaciesKey, RigElasticProperties>( key, properties ) );
|
||||
m_propertiesTable = generatePropertiesTable();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimElasticProperties::hasPropertiesForFacies( FaciesKey& key ) const
|
||||
{
|
||||
return m_properties.find( key ) != m_properties.end();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const RigElasticProperties& RimElasticProperties::propertiesForFacies( FaciesKey& key ) const
|
||||
{
|
||||
assert( hasPropertiesForFacies( key ) );
|
||||
return m_properties.find( key )->second;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticProperties::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
if ( changedField == &m_showScaledProperties )
|
||||
{
|
||||
m_propertiesTable = generatePropertiesTable();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticProperties::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_filePath );
|
||||
uiOrdering.add( &m_showScaledProperties );
|
||||
uiOrdering.add( &m_propertiesTable );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticProperties::defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute )
|
||||
{
|
||||
if ( field == &m_propertiesTable )
|
||||
{
|
||||
auto myAttr = dynamic_cast<caf::PdmUiTextEditorAttribute*>( attribute );
|
||||
if ( myAttr )
|
||||
{
|
||||
myAttr->wrapMode = caf::PdmUiTextEditorAttribute::NoWrap;
|
||||
myAttr->textMode = caf::PdmUiTextEditorAttribute::HTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimElasticProperties::generatePropertiesTable()
|
||||
{
|
||||
QString header( "<table border=1>"
|
||||
" <thead>"
|
||||
" <tr bgcolor=lightblue>"
|
||||
" <th>Field</th>"
|
||||
" <th>Formation</th>"
|
||||
" <th>Facies</th>"
|
||||
" <th>Porosity</th>"
|
||||
" <th>Young's<br>Modulus</th>"
|
||||
" <th>Poisson's<br>Ratio</th>"
|
||||
" <th>K-Ic</th>"
|
||||
" <th>Proppant<br>Embedment</th>"
|
||||
" <th>Biot<br>Coefficient</th>"
|
||||
" <th>k0</th>"
|
||||
" <th>Fluid Loss<br>Coefficient</th>"
|
||||
" <th>Spurt Loss</th>"
|
||||
" <th>Immobile Fluid<br>Saturation</th>"
|
||||
" </tr>"
|
||||
" </thead>"
|
||||
" <tbody>" );
|
||||
|
||||
std::vector<RiaDefines::CurveProperty> properties = scalableProperties();
|
||||
|
||||
QString body;
|
||||
for ( auto prop : m_properties )
|
||||
{
|
||||
const QString& fieldName = prop.second.fieldName();
|
||||
const QString& formationName = prop.second.formationName();
|
||||
const QString& faciesName = prop.second.faciesName();
|
||||
|
||||
const std::vector<double>& porosity = prop.second.porosity();
|
||||
|
||||
for ( size_t i = 0; i < porosity.size(); i++ )
|
||||
{
|
||||
QString line = QString( "<tr>"
|
||||
" <td>%1</td>"
|
||||
" <td>%2</td>"
|
||||
" <td>%3</td>"
|
||||
" <td align=right>%4</td>" )
|
||||
.arg( fieldName )
|
||||
.arg( formationName )
|
||||
.arg( faciesName )
|
||||
.arg( porosity[i] );
|
||||
|
||||
for ( auto property : properties )
|
||||
{
|
||||
double scale = 1.0;
|
||||
if ( m_showScaledProperties() )
|
||||
{
|
||||
scale = getPropertyScaling( formationName, faciesName, property );
|
||||
}
|
||||
double value = prop.second.getValue( property, i, scale );
|
||||
|
||||
QString propertyElement = QString( "<td align=right>%1</td>" ).arg( value );
|
||||
line.append( propertyElement );
|
||||
}
|
||||
|
||||
line.append( "</tr>" );
|
||||
|
||||
body.append( line );
|
||||
}
|
||||
}
|
||||
|
||||
QString footer( "</tbody></table>" );
|
||||
|
||||
return header + body + footer;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticProperties::loadDataAndUpdate()
|
||||
{
|
||||
if ( !m_filePath().path().isEmpty() )
|
||||
{
|
||||
RimStimPlanModelTemplate* stimPlanModelTemplate;
|
||||
firstAncestorOrThisOfType( stimPlanModelTemplate );
|
||||
RicElasticPropertiesImportTools::importElasticPropertiesFromFile( m_filePath().path(), stimPlanModelTemplate );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimElasticPropertyScalingCollection* RimElasticProperties::scalingCollection()
|
||||
{
|
||||
return m_scalings.value();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaDefines::CurveProperty> RimElasticProperties::scalableProperties()
|
||||
{
|
||||
std::vector<RiaDefines::CurveProperty> properties = {
|
||||
RiaDefines::CurveProperty::YOUNGS_MODULUS,
|
||||
RiaDefines::CurveProperty::POISSONS_RATIO,
|
||||
RiaDefines::CurveProperty::K_IC,
|
||||
RiaDefines::CurveProperty::PROPPANT_EMBEDMENT,
|
||||
RiaDefines::CurveProperty::BIOT_COEFFICIENT,
|
||||
RiaDefines::CurveProperty::K0,
|
||||
RiaDefines::CurveProperty::FLUID_LOSS_COEFFICIENT,
|
||||
RiaDefines::CurveProperty::SPURT_LOSS,
|
||||
RiaDefines::CurveProperty::IMMOBILE_FLUID_SATURATION,
|
||||
};
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimElasticProperties::isScalableProperty( RiaDefines::CurveProperty property )
|
||||
{
|
||||
std::vector<RiaDefines::CurveProperty> properties = scalableProperties();
|
||||
return std::find( properties.begin(), properties.end(), property ) != properties.end();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimElasticProperties::getPropertyScaling( const QString& formationName,
|
||||
const QString& faciesName,
|
||||
RiaDefines::CurveProperty property ) const
|
||||
{
|
||||
if ( m_scalings )
|
||||
{
|
||||
return m_scalings->getScaling( formationName, faciesName, property );
|
||||
}
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticProperties::elasticPropertyScalingCollectionChanged( const caf::SignalEmitter* emitter )
|
||||
{
|
||||
m_propertiesTable = generatePropertiesTable();
|
||||
changed.send();
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafFilePath.h"
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
#include "RigElasticProperties.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <tuple>
|
||||
|
||||
class RimElasticPropertyScalingCollection;
|
||||
|
||||
typedef std::tuple<QString, QString, QString> FaciesKey;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimElasticProperties : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimElasticProperties();
|
||||
~RimElasticProperties() override;
|
||||
|
||||
caf::Signal<> changed;
|
||||
|
||||
QString filePath() const;
|
||||
void setFilePath( const QString& filePath );
|
||||
|
||||
void setPropertiesForFacies( FaciesKey& key, const RigElasticProperties& properties );
|
||||
bool hasPropertiesForFacies( FaciesKey& key ) const;
|
||||
const RigElasticProperties& propertiesForFacies( FaciesKey& key ) const;
|
||||
|
||||
void loadDataAndUpdate();
|
||||
|
||||
RimElasticPropertyScalingCollection* scalingCollection();
|
||||
|
||||
static std::vector<RiaDefines::CurveProperty> scalableProperties();
|
||||
static bool isScalableProperty( RiaDefines::CurveProperty );
|
||||
|
||||
double getPropertyScaling( const QString& formationName,
|
||||
const QString& faciesName,
|
||||
RiaDefines::CurveProperty property ) const;
|
||||
|
||||
protected:
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
private:
|
||||
void elasticPropertyScalingCollectionChanged( const caf::SignalEmitter* emitter );
|
||||
QString generatePropertiesTable();
|
||||
|
||||
caf::PdmField<caf::FilePath> m_filePath;
|
||||
caf::PdmField<QString> m_propertiesTable;
|
||||
caf::PdmChildField<RimElasticPropertyScalingCollection*> m_scalings;
|
||||
caf::PdmField<bool> m_showScaledProperties;
|
||||
|
||||
std::map<FaciesKey, RigElasticProperties> m_properties;
|
||||
};
|
||||
@@ -0,0 +1,264 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimElasticPropertyScaling.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RimColorLegend.h"
|
||||
#include "RimColorLegendItem.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimElasticProperties.h"
|
||||
#include "RimFaciesProperties.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimStimPlanModelTemplate.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiLineEditor.h"
|
||||
#include "cafPdmUiTextEditor.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimElasticPropertyScaling, "ElasticPropertyScaling" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimElasticPropertyScaling::RimElasticPropertyScaling()
|
||||
: changed( this )
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "ElasticPropertyScaling", "", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_formation, "Formation", "Formation", "", "", "" );
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_facies, "Facies", "Facies", "", "", "" );
|
||||
caf::AppEnum<RiaDefines::CurveProperty> defaultProperty = RiaDefines::CurveProperty::YOUNGS_MODULUS;
|
||||
CAF_PDM_InitScriptableField( &m_property, "Property", defaultProperty, "Property", "", "", "" );
|
||||
CAF_PDM_InitScriptableField( &m_scale, "Scale", 1.0, "Scale", "", "", "" );
|
||||
|
||||
nameField()->uiCapability()->setUiReadOnly( true );
|
||||
|
||||
setUiName( "Property Scaling" );
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimElasticPropertyScaling::~RimElasticPropertyScaling()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo>
|
||||
RimElasticPropertyScaling::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
if ( fieldNeedingOptions == &m_formation )
|
||||
{
|
||||
std::vector<QString> formationNames = getFormationNames();
|
||||
for ( const QString& formationName : formationNames )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( formationName, formationName ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_facies )
|
||||
{
|
||||
RimColorLegend* faciesColors = getFaciesColorLegend();
|
||||
if ( !faciesColors ) return options;
|
||||
|
||||
for ( RimColorLegendItem* item : faciesColors->colorLegendItems() )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( item->categoryName(), item->categoryName() ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_property )
|
||||
{
|
||||
std::vector<RiaDefines::CurveProperty> properties = RimElasticProperties::scalableProperties();
|
||||
for ( auto property : properties )
|
||||
{
|
||||
options.push_back(
|
||||
caf::PdmOptionItemInfo( caf::AppEnum<RiaDefines::CurveProperty>::uiText( property ), property ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( useOptionsOnly ) *useOptionsOnly = true;
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScaling::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
updateAutoName();
|
||||
changed.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEclipseCase* RimElasticPropertyScaling::getEclipseCase()
|
||||
{
|
||||
// Find an eclipse case
|
||||
RimProject* proj = RimProject::current();
|
||||
if ( proj->eclipseCases().empty() ) return nullptr;
|
||||
|
||||
return proj->eclipseCases()[0];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigEclipseCaseData* RimElasticPropertyScaling::getEclipseCaseData()
|
||||
{
|
||||
// Find an eclipse case
|
||||
RimEclipseCase* eclipseCase = getEclipseCase();
|
||||
if ( !eclipseCase ) return nullptr;
|
||||
|
||||
return eclipseCase->eclipseCaseData();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScaling::updateAutoName()
|
||||
{
|
||||
QString name = QString( "%1/%2 - %3: %4" )
|
||||
.arg( m_formation )
|
||||
.arg( m_facies )
|
||||
.arg( caf::AppEnum<RiaDefines::CurveProperty>::uiText( m_property() ) )
|
||||
.arg( m_scale );
|
||||
setName( name );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimColorLegend* RimElasticPropertyScaling::getFaciesColorLegend()
|
||||
{
|
||||
RimStimPlanModelTemplate* stimPlanModelTemplate;
|
||||
firstAncestorOrThisOfType( stimPlanModelTemplate );
|
||||
if ( !stimPlanModelTemplate ) return nullptr;
|
||||
|
||||
RimFaciesProperties* faciesProperties = stimPlanModelTemplate->faciesProperties();
|
||||
if ( !faciesProperties ) return nullptr;
|
||||
|
||||
return faciesProperties->colorLegend();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<QString> RimElasticPropertyScaling::getFormationNames()
|
||||
{
|
||||
RigEclipseCaseData* eclipseCaseData = getEclipseCaseData();
|
||||
if ( !eclipseCaseData ) return std::vector<QString>();
|
||||
|
||||
return eclipseCaseData->formationNames();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScaling::setFormation( const QString& formation )
|
||||
{
|
||||
m_formation = formation;
|
||||
updateAutoName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScaling::setFacies( const QString& facies )
|
||||
{
|
||||
m_facies = facies;
|
||||
updateAutoName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScaling::setScale( double scale )
|
||||
{
|
||||
m_scale = scale;
|
||||
updateAutoName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScaling::setProperty( RiaDefines::CurveProperty property )
|
||||
{
|
||||
m_property = property;
|
||||
updateAutoName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const QString& RimElasticPropertyScaling::formation() const
|
||||
{
|
||||
return m_formation();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const QString& RimElasticPropertyScaling::facies() const
|
||||
{
|
||||
return m_facies();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::CurveProperty RimElasticPropertyScaling::property() const
|
||||
{
|
||||
return m_property();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimElasticPropertyScaling::scale() const
|
||||
{
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScaling::ensureDefaultFormationAndFacies()
|
||||
{
|
||||
RimColorLegend* faciesColorLegend = getFaciesColorLegend();
|
||||
if ( faciesColorLegend && !faciesColorLegend->colorLegendItems().empty() )
|
||||
{
|
||||
m_facies = faciesColorLegend->colorLegendItems().front()->categoryName();
|
||||
}
|
||||
|
||||
std::vector<QString> formationNames = getFormationNames();
|
||||
if ( !formationNames.empty() )
|
||||
{
|
||||
m_formation = formationNames.front();
|
||||
}
|
||||
|
||||
updateAutoName();
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RimCheckableNamedObject.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
class RimEclipseCase;
|
||||
class RigEclipseCaseData;
|
||||
class RimColorLegend;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimElasticPropertyScaling : public RimCheckableNamedObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimElasticPropertyScaling();
|
||||
~RimElasticPropertyScaling() override;
|
||||
|
||||
const QString& formation() const;
|
||||
const QString& facies() const;
|
||||
RiaDefines::CurveProperty property() const;
|
||||
double scale() const;
|
||||
|
||||
void setFormation( const QString& formation );
|
||||
void setFacies( const QString& facies );
|
||||
void setScale( double m_scale );
|
||||
void setProperty( RiaDefines::CurveProperty property );
|
||||
void ensureDefaultFormationAndFacies();
|
||||
|
||||
caf::Signal<> changed;
|
||||
|
||||
protected:
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
||||
bool* useOptionsOnly ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
static RimEclipseCase* getEclipseCase();
|
||||
static RigEclipseCaseData* getEclipseCaseData();
|
||||
|
||||
private:
|
||||
void updateAutoName();
|
||||
RimColorLegend* getFaciesColorLegend();
|
||||
std::vector<QString> getFormationNames();
|
||||
|
||||
caf::PdmField<QString> m_formation;
|
||||
caf::PdmField<QString> m_facies;
|
||||
caf::PdmField<caf::AppEnum<RiaDefines::CurveProperty>> m_property;
|
||||
caf::PdmField<double> m_scale;
|
||||
};
|
||||
@@ -0,0 +1,124 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimElasticPropertyScalingCollection.h"
|
||||
|
||||
#include "RimElasticPropertyScaling.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimElasticPropertyScalingCollection, "ElasticPropertyScalingCollection" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimElasticPropertyScalingCollection::RimElasticPropertyScalingCollection()
|
||||
: changed( this )
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Elastic Property Scalings", "", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_elasticPropertyScalings,
|
||||
"ElasticPropertyScalings",
|
||||
"Elastic Property Scalings",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
m_elasticPropertyScalings.uiCapability()->setUiHidden( true );
|
||||
m_elasticPropertyScalings.uiCapability()->setUiTreeHidden( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimElasticPropertyScalingCollection::~RimElasticPropertyScalingCollection()
|
||||
{
|
||||
m_elasticPropertyScalings.deleteAllChildObjects();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimElasticPropertyScaling*> RimElasticPropertyScalingCollection::elasticPropertyScalings() const
|
||||
{
|
||||
std::vector<RimElasticPropertyScaling*> templates;
|
||||
for ( auto& templ : m_elasticPropertyScalings )
|
||||
{
|
||||
templates.push_back( templ );
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScalingCollection::addElasticPropertyScaling( RimElasticPropertyScaling* scaling )
|
||||
{
|
||||
scaling->changed.connect( this, &RimElasticPropertyScalingCollection::elasticPropertyScalingChanged );
|
||||
m_elasticPropertyScalings.push_back( scaling );
|
||||
scaling->ensureDefaultFormationAndFacies();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScalingCollection::elasticPropertyScalingChanged( const caf::SignalEmitter* emitter )
|
||||
{
|
||||
changed.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScalingCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
|
||||
std::vector<caf::PdmObjectHandle*>& referringObjects )
|
||||
{
|
||||
changed.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimElasticPropertyScalingCollection::getScaling( const QString& formationName,
|
||||
const QString& faciesName,
|
||||
RiaDefines::CurveProperty property ) const
|
||||
{
|
||||
for ( const RimElasticPropertyScaling* scaling : m_elasticPropertyScalings )
|
||||
{
|
||||
if ( scaling->property() == property && scaling->formation() == formationName &&
|
||||
scaling->facies() == faciesName && scaling->isChecked() )
|
||||
{
|
||||
return scaling->scale();
|
||||
}
|
||||
}
|
||||
|
||||
// No scaling found. Default is not scaling (1.0).
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimElasticPropertyScalingCollection::initAfterRead()
|
||||
{
|
||||
for ( auto& scaling : m_elasticPropertyScalings )
|
||||
{
|
||||
scaling->changed.connect( this, &RimElasticPropertyScalingCollection::elasticPropertyScalingChanged );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
class RimElasticPropertyScaling;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimElasticPropertyScalingCollection : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimElasticPropertyScalingCollection();
|
||||
~RimElasticPropertyScalingCollection() override;
|
||||
|
||||
caf::Signal<> changed;
|
||||
|
||||
std::vector<RimElasticPropertyScaling*> elasticPropertyScalings() const;
|
||||
void addElasticPropertyScaling( RimElasticPropertyScaling* templ );
|
||||
|
||||
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
|
||||
std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
|
||||
|
||||
double getScaling( const QString& formationName, const QString& faciesName, RiaDefines::CurveProperty property ) const;
|
||||
|
||||
protected:
|
||||
void initAfterRead() override;
|
||||
|
||||
private:
|
||||
void elasticPropertyScalingChanged( const caf::SignalEmitter* emitter );
|
||||
caf::PdmChildArrayField<RimElasticPropertyScaling*> m_elasticPropertyScalings;
|
||||
};
|
||||
@@ -0,0 +1,241 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimFaciesProperties.h"
|
||||
|
||||
#include "RimColorLegend.h"
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimRegularLegendConfig.h"
|
||||
#include "RimStimPlanModelTemplate.h"
|
||||
#include "RimTools.h"
|
||||
|
||||
#include "RicFaciesPropertiesImportTools.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiLineEditor.h"
|
||||
#include "cafPdmUiTextEditor.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimFaciesProperties, "FaciesProperties" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimFaciesProperties::RimFaciesProperties()
|
||||
: changed( this )
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "RimFaciesProperties", "", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_filePath, "FilePath", "File Path", "", "", "" );
|
||||
m_filePath.uiCapability()->setUiReadOnly( true );
|
||||
m_filePath.uiCapability()->setUiEditorTypeName( caf::PdmUiLineEditor::uiEditorTypeName() );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_propertiesTable, "PropertiesTable", "Properties Table", "", "", "" );
|
||||
m_propertiesTable.uiCapability()->setUiEditorTypeName( caf::PdmUiTextEditor::uiEditorTypeName() );
|
||||
m_propertiesTable.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
|
||||
m_propertiesTable.uiCapability()->setUiReadOnly( true );
|
||||
m_propertiesTable.xmlCapability()->disableIO();
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_faciesDefinition, "FaciesDefinition", "", "", "", "" );
|
||||
m_faciesDefinition.uiCapability()->setUiHidden( true );
|
||||
m_faciesDefinition.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
m_faciesDefinition = new RimEclipseResultDefinition;
|
||||
m_faciesDefinition->findField( "MResultType" )->uiCapability()->setUiName( "Facies Definiton" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_colorLegend, "ColorLegend", "Colors", "", "", "" );
|
||||
m_colorLegend = RimRegularLegendConfig::mapToColorLegend( RimRegularLegendConfig::ColorRangesType::NORMAL );
|
||||
|
||||
setUiName( "Facies Properties" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimFaciesProperties::~RimFaciesProperties()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimFaciesProperties::filePath() const
|
||||
{
|
||||
return m_filePath.v().path();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFaciesProperties::setFilePath( const QString& filePath )
|
||||
{
|
||||
m_filePath = filePath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFaciesProperties::setFaciesCodeName( int code, const QString& name )
|
||||
{
|
||||
m_faciesCodeNames[code] = name;
|
||||
m_propertiesTable = generatePropertiesTable();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFaciesProperties::clearFaciesCodeNames()
|
||||
{
|
||||
m_faciesCodeNames.clear();
|
||||
m_propertiesTable = generatePropertiesTable();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimFaciesProperties::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
||||
bool* useOptionsOnly )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
if ( fieldNeedingOptions == &m_colorLegend )
|
||||
{
|
||||
RimTools::colorLegendOptionItems( &options );
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFaciesProperties::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_filePath );
|
||||
uiOrdering.add( &m_propertiesTable );
|
||||
uiOrdering.add( &m_colorLegend );
|
||||
|
||||
caf::PdmUiGroup* faciesDefinitionGroup = uiOrdering.addNewGroup( "Facies Definition" );
|
||||
m_faciesDefinition->uiOrdering( uiConfigName, *faciesDefinitionGroup );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFaciesProperties::defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute )
|
||||
{
|
||||
if ( field == &m_propertiesTable )
|
||||
{
|
||||
auto myAttr = dynamic_cast<caf::PdmUiTextEditorAttribute*>( attribute );
|
||||
if ( myAttr )
|
||||
{
|
||||
myAttr->wrapMode = caf::PdmUiTextEditorAttribute::NoWrap;
|
||||
myAttr->textMode = caf::PdmUiTextEditorAttribute::HTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFaciesProperties::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
changed.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimFaciesProperties::generatePropertiesTable()
|
||||
{
|
||||
QString header( "<table border=1>"
|
||||
" <thead>"
|
||||
" <tr bgcolor=lightblue>"
|
||||
" <th>Name</th>"
|
||||
" <th>Index</th>"
|
||||
" </tr>"
|
||||
" </thead>"
|
||||
" <tbody>" );
|
||||
|
||||
QString body;
|
||||
for ( auto prop : m_faciesCodeNames )
|
||||
{
|
||||
int index = prop.first;
|
||||
const QString& name = prop.second;
|
||||
|
||||
QString format( "<tr>"
|
||||
" <td>%1</td>"
|
||||
" <td>%2</td>"
|
||||
"</tr>" );
|
||||
|
||||
QString line = format.arg( name ).arg( index );
|
||||
body.append( line );
|
||||
}
|
||||
|
||||
QString footer( "</tbody></table>" );
|
||||
|
||||
return header + body + footer;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFaciesProperties::loadDataAndUpdate()
|
||||
{
|
||||
if ( !m_filePath().path().isEmpty() )
|
||||
{
|
||||
RimStimPlanModelTemplate* stimPlanModelTemplate;
|
||||
firstAncestorOrThisOfType( stimPlanModelTemplate );
|
||||
RicFaciesPropertiesImportTools::importFaciesPropertiesFromFile( m_filePath().path(), stimPlanModelTemplate );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFaciesProperties::setEclipseCase( RimEclipseCase* eclipseCase )
|
||||
{
|
||||
m_faciesDefinition->setEclipseCase( eclipseCase );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimColorLegend* RimFaciesProperties::colorLegend() const
|
||||
{
|
||||
return m_colorLegend;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFaciesProperties::setColorLegend( RimColorLegend* colorLegend )
|
||||
{
|
||||
m_colorLegend = colorLegend;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const RimEclipseResultDefinition* RimFaciesProperties::faciesDefinition() const
|
||||
{
|
||||
return m_faciesDefinition.value();
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafFilePath.h"
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
class RimEclipseResultDefinition;
|
||||
class RimColorLegend;
|
||||
class RimEclipseCase;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimFaciesProperties : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimFaciesProperties();
|
||||
~RimFaciesProperties() override;
|
||||
|
||||
caf::Signal<> changed;
|
||||
|
||||
QString filePath() const;
|
||||
void setFilePath( const QString& filePath );
|
||||
|
||||
void setFaciesCodeName( int code, const QString& name );
|
||||
void clearFaciesCodeNames();
|
||||
|
||||
void setEclipseCase( RimEclipseCase* eclipseCase );
|
||||
|
||||
void loadDataAndUpdate();
|
||||
|
||||
RimColorLegend* colorLegend() const;
|
||||
void setColorLegend( RimColorLegend* colorLegend );
|
||||
|
||||
const RimEclipseResultDefinition* faciesDefinition() const;
|
||||
|
||||
protected:
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering );
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
||||
bool* useOptionsOnly ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
private:
|
||||
QString generatePropertiesTable();
|
||||
|
||||
caf::PdmField<caf::FilePath> m_filePath;
|
||||
caf::PdmField<QString> m_propertiesTable;
|
||||
caf::PdmChildField<RimEclipseResultDefinition*> m_faciesDefinition;
|
||||
caf::PdmPtrField<RimColorLegend*> m_colorLegend;
|
||||
|
||||
std::map<int, QString> m_faciesCodeNames;
|
||||
};
|
||||
@@ -0,0 +1,172 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimNonNetLayers.h"
|
||||
|
||||
#include "RimColorLegend.h"
|
||||
#include "RimColorLegendItem.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
#include "RimFaciesProperties.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimStimPlanModelTemplate.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiDoubleValueEditor.h"
|
||||
#include "cafPdmUiLineEditor.h"
|
||||
#include "cafPdmUiTextEditor.h"
|
||||
|
||||
#include <QDoubleValidator>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimNonNetLayers, "NonNetLayers" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimNonNetLayers::RimNonNetLayers()
|
||||
: changed( this )
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "RimNonNetLayers", "", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_cutOff, "Cutoff", 0.0, "Cutoff", "", "", "" );
|
||||
m_cutOff.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_facies, "Facies", "Facies", "", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_resultDefinition, "FaciesDefinition", "", "", "", "" );
|
||||
m_resultDefinition.uiCapability()->setUiHidden( true );
|
||||
m_resultDefinition.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
m_resultDefinition = new RimEclipseResultDefinition;
|
||||
m_resultDefinition->findField( "MResultType" )->uiCapability()->setUiName( "Facies Definiton" );
|
||||
m_resultDefinition->setResultType( RiaDefines::ResultCatType::STATIC_NATIVE );
|
||||
m_resultDefinition->setResultVariable( "NTG" );
|
||||
|
||||
setUiName( "Non-Net Layers" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimNonNetLayers::~RimNonNetLayers()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimNonNetLayers::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
||||
bool* useOptionsOnly )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
if ( fieldNeedingOptions == &m_facies )
|
||||
{
|
||||
RimColorLegend* faciesColors = getFaciesColorLegend();
|
||||
if ( !faciesColors ) return options;
|
||||
|
||||
for ( RimColorLegendItem* item : faciesColors->colorLegendItems() )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( item->categoryName(), item->categoryName() ) );
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimNonNetLayers::defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute )
|
||||
{
|
||||
if ( field == &m_cutOff )
|
||||
{
|
||||
auto uiDoubleValueEditorAttr = dynamic_cast<caf::PdmUiDoubleValueEditorAttribute*>( attribute );
|
||||
if ( uiDoubleValueEditorAttr )
|
||||
{
|
||||
uiDoubleValueEditorAttr->m_validator = new QDoubleValidator( 0.0, 1.0, 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimNonNetLayers::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
caf::PdmUiGroup* resultDefinitionGroup = uiOrdering.addNewGroup( "Facies Definition" );
|
||||
m_resultDefinition->uiOrdering( uiConfigName, *resultDefinitionGroup );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimNonNetLayers::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
changed.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimNonNetLayers::setEclipseCase( RimEclipseCase* eclipseCase )
|
||||
{
|
||||
m_resultDefinition->setEclipseCase( eclipseCase );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const RimEclipseResultDefinition* RimNonNetLayers::resultDefinition() const
|
||||
{
|
||||
return m_resultDefinition.value();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimNonNetLayers::cutOff() const
|
||||
{
|
||||
return m_cutOff;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const QString& RimNonNetLayers::facies() const
|
||||
{
|
||||
return m_facies();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimColorLegend* RimNonNetLayers::getFaciesColorLegend()
|
||||
{
|
||||
RimStimPlanModelTemplate* stimPlanModelTemplate;
|
||||
firstAncestorOrThisOfType( stimPlanModelTemplate );
|
||||
if ( !stimPlanModelTemplate ) return nullptr;
|
||||
|
||||
RimFaciesProperties* faciesProperties = stimPlanModelTemplate->faciesProperties();
|
||||
if ( !faciesProperties ) return nullptr;
|
||||
|
||||
return faciesProperties->colorLegend();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimCheckableObject.h"
|
||||
|
||||
#include "cafFilePath.h"
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
|
||||
class RimEclipseResultDefinition;
|
||||
class RimEclipseCase;
|
||||
class RimColorLegend;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimNonNetLayers : public RimCheckableObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimNonNetLayers();
|
||||
~RimNonNetLayers() override;
|
||||
|
||||
caf::Signal<> changed;
|
||||
|
||||
void setEclipseCase( RimEclipseCase* eclipseCase );
|
||||
|
||||
const RimEclipseResultDefinition* resultDefinition() const;
|
||||
double cutOff() const;
|
||||
const QString& facies() const;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
||||
bool* useOptionsOnly ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute ) override;
|
||||
|
||||
RimColorLegend* getFaciesColorLegend();
|
||||
|
||||
private:
|
||||
caf::PdmField<double> m_cutOff;
|
||||
caf::PdmChildField<RimEclipseResultDefinition*> m_resultDefinition;
|
||||
caf::PdmField<QString> m_facies;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,261 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RimCheckableNamedObject.h"
|
||||
#include "RimWellPathComponentInterface.h"
|
||||
|
||||
#include "RigWellLogExtractor.h"
|
||||
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cafPdmFieldCvfVec3d.h"
|
||||
#include "cafPdmProxyValueField.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
class RimEclipseCase;
|
||||
class RimWellPath;
|
||||
class RimModeledWellPath;
|
||||
class RimElasticProperties;
|
||||
class RigEclipseCaseData;
|
||||
class RimAnnotationCollectionBase;
|
||||
class RimUserDefinedPolylinesAnnotation;
|
||||
class RimFaciesProperties;
|
||||
class RimStimPlanModelTemplate;
|
||||
class RimTextAnnotation;
|
||||
class RimStimPlanModelCalculator;
|
||||
class RimColorLegend;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimStimPlanModel : public RimCheckableNamedObject, public RimWellPathComponentInterface
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum class ExtractionType
|
||||
{
|
||||
TRUE_VERTICAL_THICKNESS,
|
||||
TRUE_STRATIGRAPHIC_THICKNESS,
|
||||
};
|
||||
|
||||
enum class FractureOrientation
|
||||
{
|
||||
ALONG_WELL_PATH,
|
||||
TRANSVERSE_WELL_PATH,
|
||||
AZIMUTH
|
||||
};
|
||||
|
||||
enum class MissingValueStrategy
|
||||
{
|
||||
DEFAULT_VALUE,
|
||||
LINEAR_INTERPOLATION,
|
||||
OTHER_CURVE_PROPERTY
|
||||
};
|
||||
|
||||
enum class BurdenStrategy
|
||||
{
|
||||
DEFAULT_VALUE,
|
||||
GRADIENT
|
||||
};
|
||||
|
||||
RimStimPlanModel( void );
|
||||
~RimStimPlanModel( void ) override;
|
||||
|
||||
void setMD( double md );
|
||||
|
||||
int timeStep() const;
|
||||
void setTimeStep( int timeStep );
|
||||
|
||||
RimEclipseCase* eclipseCase() const;
|
||||
void setEclipseCase( RimEclipseCase* eclipseCase );
|
||||
|
||||
void setEclipseCaseAndTimeStep( RimEclipseCase* eclipseCase, int timeStep );
|
||||
|
||||
cvf::Vec3d anchorPosition() const;
|
||||
cvf::Vec3d thicknessDirection() const;
|
||||
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
cvf::Vec3d fracturePosition() const;
|
||||
|
||||
double defaultPorosity() const;
|
||||
double defaultPermeability() const;
|
||||
|
||||
double verticalStress() const;
|
||||
double verticalStressGradient() const;
|
||||
double stressDepth() const;
|
||||
|
||||
double overburdenHeight() const;
|
||||
double underburdenHeight() const;
|
||||
|
||||
double defaultOverburdenPorosity() const;
|
||||
double defaultUnderburdenPorosity() const;
|
||||
|
||||
double defaultOverburdenPermeability() const;
|
||||
double defaultUnderburdenPermeability() const;
|
||||
|
||||
QString overburdenFormation() const;
|
||||
QString overburdenFacies() const;
|
||||
|
||||
QString underburdenFormation() const;
|
||||
QString underburdenFacies() const;
|
||||
|
||||
double referenceTemperature() const;
|
||||
double referenceTemperatureGradient() const;
|
||||
double referenceTemperatureDepth() const;
|
||||
|
||||
bool useDetailedFluidLoss() const;
|
||||
|
||||
double perforationLength() const;
|
||||
FractureOrientation fractureOrientation() const;
|
||||
|
||||
double formationDip() const;
|
||||
bool hasBarrier() const;
|
||||
double distanceToBarrier() const;
|
||||
double barrierDip() const;
|
||||
int wellPenetrationLayer() const;
|
||||
|
||||
// RimWellPathCompletionsInterface overrides.
|
||||
RiaDefines::WellPathComponentType componentType() const override;
|
||||
QString componentLabel() const override;
|
||||
QString componentTypeLabel() const override;
|
||||
cvf::Color3f defaultComponentColor() const override;
|
||||
double startMD() const override;
|
||||
double endMD() const override;
|
||||
bool isEnabled() const override;
|
||||
|
||||
RimWellPath* wellPath() const;
|
||||
|
||||
void loadDataAndUpdate();
|
||||
|
||||
RimModeledWellPath* thicknessDirectionWellPath() const;
|
||||
void setThicknessDirectionWellPath( RimModeledWellPath* thicknessDirectionWellPath );
|
||||
|
||||
double getDefaultValueForProperty( RiaDefines::CurveProperty ) const;
|
||||
bool hasDefaultValueForProperty( RiaDefines::CurveProperty ) const;
|
||||
|
||||
RiaDefines::CurveProperty getDefaultPropertyForMissingValues( RiaDefines::CurveProperty curveProperty ) const;
|
||||
double getDefaultForMissingOverburdenValue( RiaDefines::CurveProperty curveProperty ) const;
|
||||
double getDefaultForMissingUnderburdenValue( RiaDefines::CurveProperty curveProperty ) const;
|
||||
double getDefaultForMissingValue( RiaDefines::CurveProperty curveProperty ) const;
|
||||
double getOverburdenGradient( RiaDefines::CurveProperty curveProperty ) const;
|
||||
double getUnderburdenGradient( RiaDefines::CurveProperty curveProperty ) const;
|
||||
|
||||
void setStimPlanModelTemplate( RimStimPlanModelTemplate* stimPlanModelTemplate );
|
||||
RimStimPlanModelTemplate* stimPlanModelTemplate() const;
|
||||
|
||||
void updateReferringPlots();
|
||||
|
||||
std::shared_ptr<RimStimPlanModelCalculator> calculator() const;
|
||||
|
||||
RimStimPlanModel::MissingValueStrategy missingValueStrategy( RiaDefines::CurveProperty curveProperty ) const;
|
||||
RimStimPlanModel::BurdenStrategy burdenStrategy( RiaDefines::CurveProperty curveProperty ) const;
|
||||
RiaDefines::ResultCatType eclipseResultCategory( RiaDefines::CurveProperty curveProperty ) const;
|
||||
QString eclipseResultVariable( RiaDefines::CurveProperty curveProperty ) const;
|
||||
|
||||
static double findFaciesValue( const RimColorLegend& colorLegend, const QString& name );
|
||||
|
||||
bool isScaledByNetToGross( RiaDefines::CurveProperty curveProperty ) const;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
||||
bool* useOptionsOnly ) override;
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute ) override;
|
||||
void initAfterRead() override;
|
||||
|
||||
private:
|
||||
void updatePositionFromMeasuredDepth();
|
||||
void updateThicknessDirection();
|
||||
void updateDistanceToBarrierAndDip();
|
||||
cvf::Vec3d calculateTSTDirection() const;
|
||||
bool findThicknessTargetPoints( cvf::Vec3d& topPosition, cvf::Vec3d& bottomPosition );
|
||||
static double calculateFormationDip( const cvf::Vec3d& direction );
|
||||
|
||||
static QString vecToString( const cvf::Vec3d& vec );
|
||||
void updateThicknessDirectionWellPathName();
|
||||
|
||||
RigEclipseCaseData* getEclipseCaseData() const;
|
||||
|
||||
void updateBarrierProperties();
|
||||
void addBarrierAnnotation( const cvf::Vec3d& startPosition, const cvf::Vec3d& endPosition, const QString& barrierText );
|
||||
void clearBarrierAnnotation();
|
||||
RimAnnotationCollectionBase* annotationCollection();
|
||||
|
||||
static std::vector<WellPathCellIntersectionInfo> generateBarrierIntersections( RigEclipseCaseData* eclipseCaseData,
|
||||
const cvf::Vec3d& position,
|
||||
const cvf::Vec3d& directionToBarrier );
|
||||
|
||||
static std::vector<WellPathCellIntersectionInfo>
|
||||
generateBarrierIntersectionsBetweenPoints( RigEclipseCaseData* eclipseCaseData,
|
||||
const cvf::Vec3d& startPosition,
|
||||
const cvf::Vec3d& endPosition );
|
||||
|
||||
void updateViewsAndPlots();
|
||||
void stimPlanModelTemplateChanged( const caf::SignalEmitter* emitter );
|
||||
|
||||
void hideOtherFaults( const QString& targetFaultName );
|
||||
void showAllFaults();
|
||||
|
||||
RimColorLegend* getFaciesColorLegend() const;
|
||||
void updateExtractionDepthBoundaries();
|
||||
|
||||
protected:
|
||||
caf::PdmField<double> m_MD;
|
||||
caf::PdmPtrField<RimEclipseCase*> m_eclipseCase;
|
||||
caf::PdmField<int> m_timeStep;
|
||||
caf::PdmField<caf::AppEnum<ExtractionType>> m_extractionType;
|
||||
caf::PdmField<double> m_extractionDepthTop;
|
||||
caf::PdmField<double> m_extractionDepthBottom;
|
||||
caf::PdmField<cvf::Vec3d> m_anchorPosition;
|
||||
caf::PdmField<cvf::Vec3d> m_thicknessDirection;
|
||||
caf::PdmField<double> m_boundingBoxVertical;
|
||||
caf::PdmField<double> m_boundingBoxHorizontal;
|
||||
caf::PdmPtrField<RimModeledWellPath*> m_thicknessDirectionWellPath;
|
||||
caf::PdmField<double> m_relativePermeabilityFactorDefault;
|
||||
caf::PdmField<double> m_poroElasticConstantDefault;
|
||||
caf::PdmField<double> m_thermalExpansionCoeffientDefault;
|
||||
caf::PdmField<bool> m_useDetailedFluidLoss;
|
||||
|
||||
caf::PdmPtrField<RimStimPlanModelTemplate*> m_stimPlanModelTemplate;
|
||||
caf::PdmField<bool> m_editStimPlanModelTemplate;
|
||||
|
||||
caf::PdmField<caf::AppEnum<FractureOrientation>> m_fractureOrientation;
|
||||
caf::PdmField<double> m_azimuthAngle;
|
||||
caf::PdmField<double> m_perforationLength;
|
||||
|
||||
caf::PdmField<double> m_formationDip;
|
||||
caf::PdmField<bool> m_autoComputeBarrier;
|
||||
caf::PdmField<bool> m_hasBarrier;
|
||||
caf::PdmField<double> m_distanceToBarrier;
|
||||
caf::PdmField<double> m_barrierDip;
|
||||
caf::PdmField<int> m_wellPenetrationLayer;
|
||||
caf::PdmPtrField<RimUserDefinedPolylinesAnnotation*> m_barrierAnnotation;
|
||||
caf::PdmPtrField<RimTextAnnotation*> m_barrierTextAnnotation;
|
||||
caf::PdmField<QString> m_barrierFaultName;
|
||||
caf::PdmField<bool> m_showOnlyBarrierFault;
|
||||
caf::PdmField<bool> m_showAllFaults;
|
||||
|
||||
std::shared_ptr<RimStimPlanModelCalculator> m_calculator;
|
||||
};
|
||||
@@ -0,0 +1,581 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelCalculator.h"
|
||||
|
||||
#include "RiaDefines.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
#include "RimStimPlanModel.h"
|
||||
#include "RimStimPlanModelCalculator.h"
|
||||
#include "RimStimPlanModelElasticPropertyCalculator.h"
|
||||
#include "RimStimPlanModelLayerCalculator.h"
|
||||
#include "RimStimPlanModelPropertyCalculator.h"
|
||||
#include "RimStimPlanModelStressCalculator.h"
|
||||
#include "RimStimPlanModelWellLogCalculator.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelCalculator::RimStimPlanModelCalculator()
|
||||
{
|
||||
m_resultCalculators.push_back(
|
||||
std::unique_ptr<RimStimPlanModelPropertyCalculator>( new RimStimPlanModelWellLogCalculator( this ) ) );
|
||||
m_resultCalculators.push_back(
|
||||
std::unique_ptr<RimStimPlanModelPropertyCalculator>( new RimStimPlanModelElasticPropertyCalculator( this ) ) );
|
||||
m_resultCalculators.push_back(
|
||||
std::unique_ptr<RimStimPlanModelPropertyCalculator>( new RimStimPlanModelLayerCalculator( this ) ) );
|
||||
m_resultCalculators.push_back(
|
||||
std::unique_ptr<RimStimPlanModelPropertyCalculator>( new RimStimPlanModelStressCalculator( this ) ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCalculator::setStimPlanModel( RimStimPlanModel* stimPlanModel )
|
||||
{
|
||||
m_stimPlanModel = stimPlanModel;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModel* RimStimPlanModelCalculator::stimPlanModel()
|
||||
{
|
||||
return m_stimPlanModel;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelCalculator::extractCurveData( RiaDefines::CurveProperty curveProperty,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const
|
||||
{
|
||||
for ( const auto& calculator : m_resultCalculators )
|
||||
{
|
||||
if ( calculator->isMatching( curveProperty ) )
|
||||
{
|
||||
return calculator
|
||||
->calculate( curveProperty, m_stimPlanModel, timeStep, values, measuredDepthValues, tvDepthValues, rkbDiff );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::extractValues( RiaDefines::CurveProperty curveProperty, int timeStep ) const
|
||||
{
|
||||
std::vector<double> values;
|
||||
std::vector<double> measuredDepthValues;
|
||||
std::vector<double> tvDepthValues;
|
||||
double rkbDiff;
|
||||
|
||||
extractCurveData( curveProperty, timeStep, values, measuredDepthValues, tvDepthValues, rkbDiff );
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCalculator::calculateLayers( std::vector<std::pair<double, double>>& layerBoundaryDepths,
|
||||
std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes ) const
|
||||
{
|
||||
std::vector<double> layerValues;
|
||||
std::vector<double> measuredDepthValues;
|
||||
std::vector<double> depths;
|
||||
double rkbDiff;
|
||||
|
||||
extractCurveData( RiaDefines::CurveProperty::LAYERS,
|
||||
m_stimPlanModel->timeStep(),
|
||||
layerValues,
|
||||
measuredDepthValues,
|
||||
depths,
|
||||
rkbDiff );
|
||||
|
||||
if ( layerValues.size() != depths.size() ) return;
|
||||
|
||||
size_t startIndex = 0;
|
||||
for ( size_t i = 0; i < depths.size(); i++ )
|
||||
{
|
||||
if ( startIndex != i && ( layerValues[startIndex] != layerValues[i] || i == depths.size() - 1 ) )
|
||||
{
|
||||
layerBoundaryDepths.push_back( std::make_pair( depths[startIndex], depths[i] ) );
|
||||
layerBoundaryIndexes.push_back( std::make_pair( startIndex, i ) );
|
||||
startIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelCalculator::findValueAtTopOfLayer( const std::vector<double>& values,
|
||||
const std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes,
|
||||
size_t layerNo )
|
||||
{
|
||||
size_t index = layerBoundaryIndexes[layerNo].first;
|
||||
return values.at( index );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelCalculator::findValueAtBottomOfLayer( const std::vector<double>& values,
|
||||
const std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes,
|
||||
size_t layerNo )
|
||||
{
|
||||
size_t index = layerBoundaryIndexes[layerNo].second;
|
||||
return values.at( index );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCalculator::computeAverageByLayer( const std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes,
|
||||
const std::vector<double>& inputVector,
|
||||
std::vector<double>& result )
|
||||
{
|
||||
for ( auto boundaryIndex : layerBoundaryIndexes )
|
||||
{
|
||||
double sum = 0.0;
|
||||
int nValues = 0;
|
||||
for ( size_t i = boundaryIndex.first; i < boundaryIndex.second; i++ )
|
||||
{
|
||||
sum += inputVector[i];
|
||||
nValues++;
|
||||
}
|
||||
result.push_back( sum / nValues );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCalculator::extractTopOfLayerValues( const std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes,
|
||||
const std::vector<double>& inputVector,
|
||||
std::vector<double>& result )
|
||||
{
|
||||
for ( size_t i = 0; i < layerBoundaryIndexes.size(); i++ )
|
||||
{
|
||||
result.push_back( findValueAtTopOfLayer( inputVector, layerBoundaryIndexes, i ) );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateTrueVerticalDepth() const
|
||||
{
|
||||
std::vector<std::pair<double, double>> layerBoundaryDepths;
|
||||
std::vector<std::pair<size_t, size_t>> layerBoundaryIndexes;
|
||||
|
||||
calculateLayers( layerBoundaryDepths, layerBoundaryIndexes );
|
||||
|
||||
std::vector<double> tvdTopZone;
|
||||
for ( auto p : layerBoundaryDepths )
|
||||
{
|
||||
double depthInFeet = RiaEclipseUnitTools::meterToFeet( p.first );
|
||||
tvdTopZone.push_back( depthInFeet );
|
||||
}
|
||||
|
||||
return tvdTopZone;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double>
|
||||
RimStimPlanModelCalculator::findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty curveProperty ) const
|
||||
{
|
||||
std::vector<std::pair<double, double>> layerBoundaryDepths;
|
||||
std::vector<std::pair<size_t, size_t>> layerBoundaryIndexes;
|
||||
calculateLayers( layerBoundaryDepths, layerBoundaryIndexes );
|
||||
|
||||
std::vector<double> values = extractValues( curveProperty, m_stimPlanModel->timeStep() );
|
||||
std::vector<double> result;
|
||||
computeAverageByLayer( layerBoundaryIndexes, values, result );
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::findCurveAndComputeTopOfLayer( RiaDefines::CurveProperty curveProperty ) const
|
||||
{
|
||||
std::vector<std::pair<double, double>> layerBoundaryDepths;
|
||||
std::vector<std::pair<size_t, size_t>> layerBoundaryIndexes;
|
||||
calculateLayers( layerBoundaryDepths, layerBoundaryIndexes );
|
||||
|
||||
std::vector<double> values = extractValues( curveProperty, m_stimPlanModel->timeStep() );
|
||||
std::vector<double> result;
|
||||
extractTopOfLayerValues( layerBoundaryIndexes, values, result );
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculatePorosity() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::POROSITY );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateReservoirPressure() const
|
||||
{
|
||||
std::vector<double> pressureBar = findCurveAndComputeTopOfLayer( RiaDefines::CurveProperty::PRESSURE );
|
||||
|
||||
std::vector<double> pressurePsi;
|
||||
for ( double p : pressureBar )
|
||||
{
|
||||
pressurePsi.push_back( RiaEclipseUnitTools::barToPsi( p ) );
|
||||
}
|
||||
|
||||
return pressurePsi;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateHorizontalPermeability() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::PERMEABILITY_X );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateVerticalPermeability() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::PERMEABILITY_Z );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateStress() const
|
||||
{
|
||||
std::vector<double> stress;
|
||||
std::vector<double> stressGradients;
|
||||
std::vector<double> initialStress;
|
||||
calculateStressWithGradients( stress, stressGradients, initialStress );
|
||||
return stress;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateInitialStress() const
|
||||
{
|
||||
std::vector<double> stress;
|
||||
std::vector<double> stressGradients;
|
||||
std::vector<double> initialStress;
|
||||
calculateStressWithGradients( stress, stressGradients, initialStress );
|
||||
return initialStress;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelCalculator::calculateStressWithGradients( std::vector<double>& stress,
|
||||
std::vector<double>& stressGradients,
|
||||
std::vector<double>& initialStress ) const
|
||||
{
|
||||
// Reference stress
|
||||
const double verticalStressRef = m_stimPlanModel->verticalStress();
|
||||
const double verticalStressGradientRef = m_stimPlanModel->verticalStressGradient();
|
||||
const double stressDepthRef = m_stimPlanModel->stressDepth();
|
||||
|
||||
std::vector<std::pair<double, double>> layerBoundaryDepths;
|
||||
std::vector<std::pair<size_t, size_t>> layerBoundaryIndexes;
|
||||
calculateLayers( layerBoundaryDepths, layerBoundaryIndexes );
|
||||
|
||||
int timeStep = m_stimPlanModel->timeStep();
|
||||
|
||||
// Biot coefficient
|
||||
std::vector<double> biotData = extractValues( RiaDefines::CurveProperty::BIOT_COEFFICIENT, timeStep );
|
||||
|
||||
// K0
|
||||
std::vector<double> k0Data = extractValues( RiaDefines::CurveProperty::K0, timeStep );
|
||||
|
||||
// Pressure at the give time step
|
||||
std::vector<double> timeStepPressureData = extractValues( RiaDefines::CurveProperty::PRESSURE, timeStep );
|
||||
|
||||
// Initial pressure
|
||||
std::vector<double> initialPressureData = extractValues( RiaDefines::CurveProperty::INITIAL_PRESSURE, timeStep );
|
||||
|
||||
// Poissons ratio
|
||||
std::vector<double> poissonsRatioData = extractValues( RiaDefines::CurveProperty::POISSONS_RATIO, timeStep );
|
||||
|
||||
// Check that we have data from all curves
|
||||
if ( biotData.empty() || k0Data.empty() || timeStepPressureData.empty() || initialPressureData.empty() ||
|
||||
poissonsRatioData.empty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( biotData.size() < layerBoundaryIndexes.size() || k0Data.size() < layerBoundaryIndexes.size() ||
|
||||
timeStepPressureData.size() < layerBoundaryIndexes.size() ||
|
||||
initialPressureData.size() < layerBoundaryIndexes.size() ||
|
||||
poissonsRatioData.size() < layerBoundaryIndexes.size() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<double> stressForGradients;
|
||||
std::vector<double> pressureForGradients;
|
||||
std::vector<double> depthForGradients;
|
||||
|
||||
// Calculate the stress
|
||||
for ( size_t i = 0; i < layerBoundaryDepths.size(); i++ )
|
||||
{
|
||||
double depthTopOfZone = layerBoundaryDepths[i].first;
|
||||
double depthBottomOfZone = layerBoundaryDepths[i].second;
|
||||
|
||||
// Data from curves at the top zone depth
|
||||
double k0 = findValueAtTopOfLayer( k0Data, layerBoundaryIndexes, i );
|
||||
double biot = findValueAtTopOfLayer( biotData, layerBoundaryIndexes, i );
|
||||
double poissonsRatio = findValueAtTopOfLayer( poissonsRatioData, layerBoundaryIndexes, i );
|
||||
double initialPressure = findValueAtTopOfLayer( initialPressureData, layerBoundaryIndexes, i );
|
||||
double timeStepPressure = findValueAtTopOfLayer( timeStepPressureData, layerBoundaryIndexes, i );
|
||||
|
||||
// Vertical stress
|
||||
// Use difference between reference depth and depth of top of zone
|
||||
double depthDiff = depthTopOfZone - stressDepthRef;
|
||||
double Sv = verticalStressRef + verticalStressGradientRef * depthDiff;
|
||||
|
||||
double Sh_init = k0 * Sv + initialPressure * ( 1.0 - k0 );
|
||||
double pressureDiff = timeStepPressure - initialPressure;
|
||||
|
||||
// Vertical stress diff assumed to be zero
|
||||
double Sv_diff = 0.0;
|
||||
double deltaHorizontalStress = poissonsRatio / ( 1.0 - poissonsRatio ) * ( Sv_diff - biot * pressureDiff ) +
|
||||
( biot * pressureDiff );
|
||||
|
||||
double depletionStress = Sh_init + deltaHorizontalStress;
|
||||
stress.push_back( RiaEclipseUnitTools::barToPsi( depletionStress ) );
|
||||
|
||||
initialStress.push_back( RiaEclipseUnitTools::barToPsi( Sh_init ) );
|
||||
|
||||
// Cache some results for the gradients calculation
|
||||
stressForGradients.push_back( Sv );
|
||||
pressureForGradients.push_back( initialPressure );
|
||||
depthForGradients.push_back( depthTopOfZone );
|
||||
|
||||
if ( i == layerBoundaryDepths.size() - 1 )
|
||||
{
|
||||
// Use the bottom of the last layer to compute gradient for last layer
|
||||
double bottomInitialPressure = findValueAtBottomOfLayer( initialPressureData, layerBoundaryIndexes, i );
|
||||
|
||||
double bottomDepthDiff = depthBottomOfZone - stressDepthRef;
|
||||
double bottomSv = verticalStressRef + verticalStressGradientRef * bottomDepthDiff;
|
||||
stressForGradients.push_back( bottomSv );
|
||||
pressureForGradients.push_back( bottomInitialPressure );
|
||||
depthForGradients.push_back( depthBottomOfZone );
|
||||
}
|
||||
}
|
||||
|
||||
assert( stressForGradients.size() == layerBoundaryDepths.size() + 1 );
|
||||
assert( pressureForGradients.size() == layerBoundaryDepths.size() + 1 );
|
||||
assert( depthForGradients.size() == layerBoundaryDepths.size() + 1 );
|
||||
|
||||
// Second pass to calculate the stress gradients
|
||||
for ( size_t i = 0; i < layerBoundaryDepths.size(); i++ )
|
||||
{
|
||||
double diffStress = stressForGradients[i + 1] - stressForGradients[i];
|
||||
double diffPressure = pressureForGradients[i + 1] - pressureForGradients[i];
|
||||
double diffDepth = depthForGradients[i + 1] - depthForGradients[i];
|
||||
double k0 = findValueAtTopOfLayer( k0Data, layerBoundaryIndexes, i );
|
||||
double stressGradient = ( diffStress * k0 + diffPressure * ( 1.0 - k0 ) ) / diffDepth;
|
||||
stressGradients.push_back( RiaEclipseUnitTools::barPerMeterToPsiPerFeet( stressGradient ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateStressGradient() const
|
||||
{
|
||||
std::vector<double> stress;
|
||||
std::vector<double> stressGradients;
|
||||
std::vector<double> initialStress;
|
||||
calculateStressWithGradients( stress, stressGradients, initialStress );
|
||||
return stressGradients;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCalculator::calculateTemperature( std::vector<double>& temperatures ) const
|
||||
{
|
||||
// Reference temperature. Unit: degrees celsius
|
||||
const double referenceTemperature = m_stimPlanModel->referenceTemperature();
|
||||
|
||||
// Reference temperature gradient. Unit: degrees Celsius per meter
|
||||
const double referenceTemperatureGradient = m_stimPlanModel->referenceTemperatureGradient();
|
||||
|
||||
// Reference depth for temperature. Unit: meter.
|
||||
const double referenceTemperatureDepth = m_stimPlanModel->referenceTemperatureDepth();
|
||||
|
||||
std::vector<std::pair<double, double>> layerBoundaryDepths;
|
||||
std::vector<std::pair<size_t, size_t>> layerBoundaryIndexes;
|
||||
calculateLayers( layerBoundaryDepths, layerBoundaryIndexes );
|
||||
|
||||
// Calculate the temperatures
|
||||
for ( size_t i = 0; i < layerBoundaryDepths.size(); i++ )
|
||||
{
|
||||
double depthTopOfZone = layerBoundaryDepths[i].first;
|
||||
|
||||
// Use difference between reference depth and depth of top of zone
|
||||
double depthDiff = depthTopOfZone - referenceTemperatureDepth;
|
||||
double temperature = referenceTemperature + referenceTemperatureGradient * depthDiff;
|
||||
|
||||
temperatures.push_back( temperature );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateYoungsModulus() const
|
||||
{
|
||||
std::vector<double> valuesGPa = findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::YOUNGS_MODULUS );
|
||||
std::vector<double> valuesMMpsi;
|
||||
for ( auto value : valuesGPa )
|
||||
{
|
||||
valuesMMpsi.push_back( value * 0.14503773773 );
|
||||
}
|
||||
|
||||
return valuesMMpsi;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculatePoissonsRatio() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::POISSONS_RATIO );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateKIc() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::K_IC );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateFluidLossCoefficient() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::FLUID_LOSS_COEFFICIENT );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateSpurtLoss() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::SPURT_LOSS );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateProppandEmbedment() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::PROPPANT_EMBEDMENT );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateImmobileFluidSaturation() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::IMMOBILE_FLUID_SATURATION );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateTemperature() const
|
||||
{
|
||||
std::vector<double> temperaturesCelsius;
|
||||
calculateTemperature( temperaturesCelsius );
|
||||
|
||||
// Convert to Fahrenheit
|
||||
std::vector<double> temperaturesFahrenheit;
|
||||
for ( double t : temperaturesCelsius )
|
||||
{
|
||||
temperaturesFahrenheit.push_back( t * 1.8 + 32.0 );
|
||||
}
|
||||
|
||||
return temperaturesFahrenheit;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateRelativePermeabilityFactor() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::RELATIVE_PERMEABILITY_FACTOR );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculatePoroElasticConstant() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::PORO_ELASTIC_CONSTANT );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimStimPlanModelCalculator::calculateThermalExpansionCoefficient() const
|
||||
{
|
||||
// SI unit is 1/Celsius
|
||||
std::vector<double> coefficientCelsius =
|
||||
findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::THERMAL_EXPANSION_COEFFICIENT );
|
||||
|
||||
// Field unit is 1/Fahrenheit
|
||||
std::vector<double> coefficientFahrenheit;
|
||||
for ( double c : coefficientCelsius )
|
||||
{
|
||||
coefficientFahrenheit.push_back( c / 1.8 );
|
||||
}
|
||||
|
||||
return coefficientFahrenheit;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RimStimPlanModelPropertyCalculator.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class RimStimPlanModel;
|
||||
|
||||
class RimStimPlanModelCalculator
|
||||
{
|
||||
public:
|
||||
RimStimPlanModelCalculator();
|
||||
|
||||
void setStimPlanModel( RimStimPlanModel* stimPlanModel );
|
||||
RimStimPlanModel* stimPlanModel();
|
||||
|
||||
bool extractCurveData( RiaDefines::CurveProperty curveProperty,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const;
|
||||
|
||||
std::vector<double> extractValues( RiaDefines::CurveProperty curveProperty, int timeStep ) const;
|
||||
|
||||
std::vector<double> calculateTrueVerticalDepth() const;
|
||||
std::vector<double> calculatePorosity() const;
|
||||
std::vector<double> calculateVerticalPermeability() const;
|
||||
std::vector<double> calculateHorizontalPermeability() const;
|
||||
std::vector<double> calculateReservoirPressure() const;
|
||||
std::vector<double> calculateStress() const;
|
||||
std::vector<double> calculateInitialStress() const;
|
||||
std::vector<double> calculateStressGradient() const;
|
||||
std::vector<double> calculateYoungsModulus() const;
|
||||
std::vector<double> calculatePoissonsRatio() const;
|
||||
std::vector<double> calculateKIc() const;
|
||||
std::vector<double> calculateFluidLossCoefficient() const;
|
||||
std::vector<double> calculateSpurtLoss() const;
|
||||
std::vector<double> calculateProppandEmbedment() const;
|
||||
|
||||
std::vector<double> calculateImmobileFluidSaturation() const;
|
||||
std::vector<double> calculateTemperature() const;
|
||||
std::vector<double> calculateRelativePermeabilityFactor() const;
|
||||
std::vector<double> calculatePoroElasticConstant() const;
|
||||
std::vector<double> calculateThermalExpansionCoefficient() const;
|
||||
|
||||
void calculateTemperature( std::vector<double>& temperatures ) const;
|
||||
|
||||
protected:
|
||||
std::vector<double> findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty curveProperty ) const;
|
||||
std::vector<double> findCurveXValuesByProperty( RiaDefines::CurveProperty curveProperty ) const;
|
||||
std::vector<double> findCurveAndComputeTopOfLayer( RiaDefines::CurveProperty curveProperty ) const;
|
||||
|
||||
void calculateLayers( std::vector<std::pair<double, double>>& layerBoundaryDepths,
|
||||
std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes ) const;
|
||||
bool calculateStressWithGradients( std::vector<double>& stress,
|
||||
std::vector<double>& stressGradients,
|
||||
std::vector<double>& initialStress ) const;
|
||||
|
||||
static double findValueAtTopOfLayer( const std::vector<double>& values,
|
||||
const std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes,
|
||||
size_t layerNo );
|
||||
static double findValueAtBottomOfLayer( const std::vector<double>& values,
|
||||
const std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes,
|
||||
size_t layerNo );
|
||||
static void computeAverageByLayer( const std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes,
|
||||
const std::vector<double>& inputVector,
|
||||
std::vector<double>& result );
|
||||
static void extractTopOfLayerValues( const std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes,
|
||||
const std::vector<double>& inputVector,
|
||||
std::vector<double>& result );
|
||||
|
||||
private:
|
||||
RimStimPlanModel* m_stimPlanModel;
|
||||
std::vector<std::unique_ptr<RimStimPlanModelPropertyCalculator>> m_resultCalculators;
|
||||
};
|
||||
@@ -0,0 +1,121 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelCollection.h"
|
||||
|
||||
#include "RimProject.h"
|
||||
#include "RimStimPlanModel.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimStimPlanModelCollection, "StimPlanModelCollection" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelCollection::RimStimPlanModelCollection( void )
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "StimPlan Models", "", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_stimPlanModels, "StimPlanModels", "", "", "", "" );
|
||||
m_stimPlanModels.uiCapability()->setUiHidden( true );
|
||||
|
||||
setName( "StimPlan Models" );
|
||||
nameField()->uiCapability()->setUiHidden( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelCollection::~RimStimPlanModelCollection()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCollection::addStimPlanModel( RimStimPlanModel* fracture )
|
||||
{
|
||||
m_stimPlanModels.push_back( fracture );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCollection::deleteStimPlanModels()
|
||||
{
|
||||
m_stimPlanModels.deleteAllChildObjects();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimStimPlanModel*> RimStimPlanModelCollection::allStimPlanModels() const
|
||||
{
|
||||
return m_stimPlanModels.childObjects();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimStimPlanModel*> RimStimPlanModelCollection::activeStimPlanModels() const
|
||||
{
|
||||
std::vector<RimStimPlanModel*> active;
|
||||
|
||||
if ( isChecked() )
|
||||
{
|
||||
for ( const auto& f : allStimPlanModels() )
|
||||
{
|
||||
if ( f->isChecked() )
|
||||
{
|
||||
active.push_back( f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
RimProject* proj;
|
||||
this->firstAncestorOrThisOfTypeAsserted( proj );
|
||||
if ( changedField == &m_isChecked )
|
||||
{
|
||||
proj->reloadCompletionTypeResultsInAllViews();
|
||||
}
|
||||
else
|
||||
{
|
||||
proj->scheduleCreateDisplayModelAndRedrawAllViews();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimCheckableNamedObject.h"
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimStimPlanModel;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimStimPlanModelCollection : public RimCheckableNamedObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimStimPlanModelCollection( void );
|
||||
~RimStimPlanModelCollection( void ) override;
|
||||
|
||||
void addStimPlanModel( RimStimPlanModel* fracture );
|
||||
void deleteStimPlanModels();
|
||||
|
||||
std::vector<RimStimPlanModel*> allStimPlanModels() const;
|
||||
std::vector<RimStimPlanModel*> activeStimPlanModels() const;
|
||||
|
||||
private:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
private:
|
||||
caf::PdmChildArrayField<RimStimPlanModel*> m_stimPlanModels;
|
||||
};
|
||||
@@ -0,0 +1,174 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelCurve.h"
|
||||
|
||||
#include "RiaApplication.h"
|
||||
#include "RiaInterpolationTools.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaPreferences.h"
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
#include "RimModeledWellPath.h"
|
||||
#include "RimStimPlanModel.h"
|
||||
#include "RimStimPlanModelCalculator.h"
|
||||
#include "RimStimPlanModelPlot.h"
|
||||
|
||||
#include "RiuQwtPlotCurve.h"
|
||||
#include "RiuQwtPlotWidget.h"
|
||||
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimStimPlanModelCurve, "StimPlanModelCurve" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelCurve::RimStimPlanModelCurve()
|
||||
{
|
||||
CAF_PDM_InitObject( "StimPlan Model Curve", "", "", "" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_stimPlanModel, "StimPlanModel", "StimPlan Model", "", "", "" );
|
||||
m_stimPlanModel.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
m_stimPlanModel.uiCapability()->setUiHidden( true );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_curveProperty, "CurveProperty", "Curve Property", "", "", "" );
|
||||
m_curveProperty.uiCapability()->setUiHidden( true );
|
||||
|
||||
m_wellPath = nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelCurve::~RimStimPlanModelCurve()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCurve::setStimPlanModel( RimStimPlanModel* stimPlanModel )
|
||||
{
|
||||
m_stimPlanModel = stimPlanModel;
|
||||
m_case = stimPlanModel->eclipseCase();
|
||||
m_timeStep = stimPlanModel->timeStep();
|
||||
m_wellPath = stimPlanModel->thicknessDirectionWellPath();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCurve::setEclipseResultCategory( RiaDefines::ResultCatType catType )
|
||||
{
|
||||
m_eclipseResultDefinition->setResultType( catType );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCurve::setCurveProperty( RiaDefines::CurveProperty curveProperty )
|
||||
{
|
||||
m_curveProperty = curveProperty;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::CurveProperty RimStimPlanModelCurve::curveProperty() const
|
||||
{
|
||||
return m_curveProperty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
RimWellLogExtractionCurve::fieldChangedByUi( changedField, oldValue, newValue );
|
||||
RimStimPlanModelPlot* stimPlanModelPlot;
|
||||
firstAncestorOrThisOfTypeAsserted( stimPlanModelPlot );
|
||||
|
||||
if ( stimPlanModelPlot )
|
||||
{
|
||||
stimPlanModelPlot->loadDataAndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelCurve::performDataExtraction( bool* isUsingPseudoLength )
|
||||
{
|
||||
std::vector<double> values;
|
||||
std::vector<double> measuredDepthValues;
|
||||
std::vector<double> tvDepthValues;
|
||||
double rkbDiff = 0.0;
|
||||
|
||||
RiaDefines::DepthUnitType depthUnit = RiaDefines::DepthUnitType::UNIT_METER;
|
||||
QString xUnits = RiaWellLogUnitTools<double>::noUnitString();
|
||||
|
||||
*isUsingPseudoLength = false;
|
||||
|
||||
if ( m_stimPlanModel && m_stimPlanModel->eclipseCase() )
|
||||
{
|
||||
RimEclipseCase* eclipseCase = m_stimPlanModel->eclipseCase();
|
||||
|
||||
bool isOk = m_stimPlanModel->calculator()->extractCurveData( curveProperty(),
|
||||
m_stimPlanModel->timeStep(),
|
||||
values,
|
||||
measuredDepthValues,
|
||||
tvDepthValues,
|
||||
rkbDiff );
|
||||
if ( !isOk )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RiaEclipseUnitTools::UnitSystem eclipseUnitsType = eclipseCase->eclipseCaseData()->unitsType();
|
||||
if ( eclipseUnitsType == RiaEclipseUnitTools::UnitSystem::UNITS_FIELD )
|
||||
{
|
||||
// See https://github.com/OPM/ResInsight/issues/538
|
||||
|
||||
depthUnit = RiaDefines::DepthUnitType::UNIT_FEET;
|
||||
}
|
||||
}
|
||||
|
||||
bool performDataSmoothing = false;
|
||||
if ( !values.empty() && !measuredDepthValues.empty() && measuredDepthValues.size() == values.size() )
|
||||
{
|
||||
this->setValuesWithMdAndTVD( values, measuredDepthValues, tvDepthValues, rkbDiff, depthUnit, !performDataSmoothing, xUnits );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimStimPlanModelCurve::createCurveAutoName()
|
||||
{
|
||||
QString textWithLineFeed = caf::AppEnum<RiaDefines::CurveProperty>::uiText( m_curveProperty() ).trimmed();
|
||||
textWithLineFeed.replace( " ", "\n" );
|
||||
|
||||
return textWithLineFeed;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimStimPlanModelPropertyCurve.h"
|
||||
#include "RimWellLogExtractionCurve.h"
|
||||
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimStimPlanModel;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimStimPlanModelCurve : public RimWellLogExtractionCurve, public RimStimPlanModelPropertyCurve
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimStimPlanModelCurve();
|
||||
~RimStimPlanModelCurve() override;
|
||||
|
||||
void setStimPlanModel( RimStimPlanModel* stimPlanModel );
|
||||
|
||||
void setEclipseResultCategory( RiaDefines::ResultCatType catType );
|
||||
|
||||
void setCurveProperty( RiaDefines::CurveProperty ) override;
|
||||
RiaDefines::CurveProperty curveProperty() const override;
|
||||
|
||||
protected:
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
void performDataExtraction( bool* isUsingPseudoLength ) override;
|
||||
|
||||
QString createCurveAutoName();
|
||||
|
||||
caf::PdmPtrField<RimStimPlanModel*> m_stimPlanModel;
|
||||
caf::PdmField<caf::AppEnum<RiaDefines::CurveProperty>> m_curveProperty;
|
||||
};
|
||||
@@ -0,0 +1,374 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelElasticPropertyCalculator.h"
|
||||
|
||||
#include "RiaDefines.h"
|
||||
#include "RiaInterpolationTools.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseWellLogExtractor.h"
|
||||
#include "RigElasticProperties.h"
|
||||
#include "RigResultAccessor.h"
|
||||
#include "RigResultAccessorFactory.h"
|
||||
#include "RigWellLogCurveData.h"
|
||||
#include "RigWellPath.h"
|
||||
|
||||
#include "RimCase.h"
|
||||
#include "RimColorLegend.h"
|
||||
#include "RimColorLegendItem.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseInputProperty.h"
|
||||
#include "RimEclipseInputPropertyCollection.h"
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
#include "RimElasticProperties.h"
|
||||
#include "RimFaciesProperties.h"
|
||||
#include "RimModeledWellPath.h"
|
||||
#include "RimNonNetLayers.h"
|
||||
#include "RimStimPlanModel.h"
|
||||
#include "RimStimPlanModelCalculator.h"
|
||||
#include "RimStimPlanModelElasticPropertyCalculator.h"
|
||||
#include "RimStimPlanModelTemplate.h"
|
||||
#include "RimTools.h"
|
||||
#include "RimWellLogFile.h"
|
||||
#include "RimWellLogPlot.h"
|
||||
#include "RimWellLogTrack.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimWellPathCollection.h"
|
||||
#include "RimWellPlotTools.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelElasticPropertyCalculator::RimStimPlanModelElasticPropertyCalculator(
|
||||
RimStimPlanModelCalculator* stimPlanModelCalculator )
|
||||
: m_stimPlanModelCalculator( stimPlanModelCalculator )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelElasticPropertyCalculator::isMatching( RiaDefines::CurveProperty curveProperty ) const
|
||||
{
|
||||
std::vector<RiaDefines::CurveProperty> matching = { RiaDefines::CurveProperty::YOUNGS_MODULUS,
|
||||
RiaDefines::CurveProperty::POISSONS_RATIO,
|
||||
RiaDefines::CurveProperty::BIOT_COEFFICIENT,
|
||||
RiaDefines::CurveProperty::K0,
|
||||
RiaDefines::CurveProperty::K_IC,
|
||||
RiaDefines::CurveProperty::PROPPANT_EMBEDMENT,
|
||||
RiaDefines::CurveProperty::FLUID_LOSS_COEFFICIENT,
|
||||
RiaDefines::CurveProperty::SPURT_LOSS,
|
||||
RiaDefines::CurveProperty::RELATIVE_PERMEABILITY_FACTOR,
|
||||
RiaDefines::CurveProperty::PORO_ELASTIC_CONSTANT,
|
||||
RiaDefines::CurveProperty::THERMAL_EXPANSION_COEFFICIENT,
|
||||
RiaDefines::CurveProperty::IMMOBILE_FLUID_SATURATION };
|
||||
|
||||
return std::find( matching.begin(), matching.end(), curveProperty ) != matching.end();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelElasticPropertyCalculator::calculate( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const
|
||||
{
|
||||
RimEclipseCase* eclipseCase = stimPlanModel->eclipseCase();
|
||||
if ( !eclipseCase )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !stimPlanModel->thicknessDirectionWellPath() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RigWellPath* wellPathGeometry = stimPlanModel->thicknessDirectionWellPath()->wellPathGeometry();
|
||||
if ( !wellPathGeometry )
|
||||
{
|
||||
RiaLogging::error( "No well path geometry found for layer data exctration." );
|
||||
return false;
|
||||
}
|
||||
|
||||
RigEclipseWellLogExtractor eclExtractor( eclipseCase->eclipseCaseData(), wellPathGeometry, "fracture model" );
|
||||
|
||||
measuredDepthValues = eclExtractor.cellIntersectionMDs();
|
||||
tvDepthValues = eclExtractor.cellIntersectionTVDs();
|
||||
rkbDiff = eclExtractor.wellPathGeometry()->rkbDiff();
|
||||
|
||||
// Extract formation data
|
||||
cvf::ref<RigResultAccessor> formationResultAccessor =
|
||||
RigResultAccessorFactory::createFromResultAddress( eclipseCase->eclipseCaseData(),
|
||||
0,
|
||||
RiaDefines::PorosityModelType::MATRIX_MODEL,
|
||||
0,
|
||||
RigEclipseResultAddress( RiaDefines::ResultCatType::FORMATION_NAMES,
|
||||
RiaDefines::activeFormationNamesResultName() ) );
|
||||
if ( !formationResultAccessor.notNull() )
|
||||
{
|
||||
RiaLogging::error( QString( "No formation result found." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
CurveSamplingPointData curveData =
|
||||
RimWellLogTrack::curveSamplingPointData( &eclExtractor, formationResultAccessor.p() );
|
||||
|
||||
std::vector<double> formationValues = curveData.data;
|
||||
|
||||
std::vector<QString> formationNamesVector = RimWellLogTrack::formationNamesVector( eclipseCase );
|
||||
|
||||
RimStimPlanModelTemplate* stimPlanModelTemplate = stimPlanModel->stimPlanModelTemplate();
|
||||
if ( !stimPlanModelTemplate )
|
||||
{
|
||||
RiaLogging::error( QString( "No fracture model template found" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
RimFaciesProperties* faciesProperties = stimPlanModelTemplate->faciesProperties();
|
||||
if ( !faciesProperties )
|
||||
{
|
||||
RiaLogging::error( QString( "No facies properties found when extracting elastic properties." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
RimColorLegend* colorLegend = faciesProperties->colorLegend();
|
||||
if ( !colorLegend )
|
||||
{
|
||||
RiaLogging::error( QString( "No color legend found when extracting elastic properties." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
RimElasticProperties* elasticProperties = stimPlanModelTemplate->elasticProperties();
|
||||
if ( !elasticProperties )
|
||||
{
|
||||
RiaLogging::error( QString( "No elastic properties found" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<double> faciesValues =
|
||||
m_stimPlanModelCalculator->extractValues( RiaDefines::CurveProperty::FACIES, timeStep );
|
||||
|
||||
if ( faciesValues.empty() )
|
||||
{
|
||||
RiaLogging::error( QString( "No facies values found." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<double> poroValues =
|
||||
m_stimPlanModelCalculator->extractValues( RiaDefines::CurveProperty::POROSITY_UNSCALED, timeStep );
|
||||
|
||||
double overburdenHeight = stimPlanModel->overburdenHeight();
|
||||
if ( overburdenHeight > 0.0 )
|
||||
{
|
||||
QString overburdenFormation = stimPlanModel->overburdenFormation();
|
||||
addOverburden( formationNamesVector,
|
||||
formationValues,
|
||||
tvDepthValues,
|
||||
measuredDepthValues,
|
||||
overburdenHeight,
|
||||
overburdenFormation );
|
||||
}
|
||||
|
||||
double underburdenHeight = stimPlanModel->underburdenHeight();
|
||||
if ( underburdenHeight > 0.0 )
|
||||
{
|
||||
QString underburdenFormation = stimPlanModel->underburdenFormation();
|
||||
addUnderburden( formationNamesVector,
|
||||
formationValues,
|
||||
tvDepthValues,
|
||||
measuredDepthValues,
|
||||
underburdenHeight,
|
||||
underburdenFormation );
|
||||
}
|
||||
|
||||
std::vector<double> netToGrossValues =
|
||||
m_stimPlanModelCalculator->extractValues( RiaDefines::CurveProperty::NET_TO_GROSS, timeStep );
|
||||
|
||||
CAF_ASSERT( tvDepthValues.size() == faciesValues.size() );
|
||||
CAF_ASSERT( tvDepthValues.size() == poroValues.size() );
|
||||
CAF_ASSERT( tvDepthValues.size() == formationValues.size() );
|
||||
|
||||
bool isScaledByNetToGross = false;
|
||||
double netToGrossCutoff = 1.0;
|
||||
QString netToGrossFaciesName = "";
|
||||
if ( stimPlanModel->stimPlanModelTemplate() && stimPlanModel->stimPlanModelTemplate()->nonNetLayers() )
|
||||
{
|
||||
isScaledByNetToGross = stimPlanModel->isScaledByNetToGross( curveProperty ) && !netToGrossValues.empty() &&
|
||||
stimPlanModel->stimPlanModelTemplate()->nonNetLayers()->isChecked();
|
||||
netToGrossCutoff = stimPlanModel->stimPlanModelTemplate()->nonNetLayers()->cutOff();
|
||||
netToGrossFaciesName = stimPlanModel->stimPlanModelTemplate()->nonNetLayers()->facies();
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < tvDepthValues.size(); i++ )
|
||||
{
|
||||
// Avoid using the field name in the match for now
|
||||
QString fieldName = "";
|
||||
QString faciesName = findFaciesName( *colorLegend, faciesValues[i] );
|
||||
int idx = static_cast<int>( formationValues[i] );
|
||||
QString formationName = formationNamesVector[idx];
|
||||
double porosity = poroValues[i];
|
||||
|
||||
FaciesKey faciesKey = std::make_tuple( fieldName, formationName, faciesName );
|
||||
if ( elasticProperties->hasPropertiesForFacies( faciesKey ) )
|
||||
{
|
||||
if ( RimElasticProperties::isScalableProperty( curveProperty ) )
|
||||
{
|
||||
const RigElasticProperties& rigElasticProperties = elasticProperties->propertiesForFacies( faciesKey );
|
||||
double scale = elasticProperties->getPropertyScaling( formationName, faciesName, curveProperty );
|
||||
double val = rigElasticProperties.getValueForPorosity( curveProperty, porosity, scale );
|
||||
if ( std::isinf( val ) )
|
||||
{
|
||||
RiaLogging::error(
|
||||
QString( "Elastic property interpolation failed. Formation='%1', "
|
||||
"facies='%2', depth=%3, porosity=%4. Property defined for porosity range: [%5, %6]" )
|
||||
.arg( formationName )
|
||||
.arg( faciesName )
|
||||
.arg( tvDepthValues[i] )
|
||||
.arg( porosity )
|
||||
.arg( rigElasticProperties.porosityMin() )
|
||||
.arg( rigElasticProperties.porosityMax() ) );
|
||||
}
|
||||
|
||||
//
|
||||
if ( isScaledByNetToGross && !std::isinf( val ) )
|
||||
{
|
||||
double netToGross = netToGrossValues[i];
|
||||
if ( netToGross < netToGrossCutoff )
|
||||
{
|
||||
FaciesKey ntgFaciesKey = std::make_tuple( "", formationName, netToGrossFaciesName );
|
||||
const RigElasticProperties& rigNtgElasticProperties =
|
||||
elasticProperties->propertiesForFacies( ntgFaciesKey );
|
||||
double ntgScale =
|
||||
elasticProperties->getPropertyScaling( formationName, netToGrossFaciesName, curveProperty );
|
||||
double ntgValue = rigNtgElasticProperties.getValueForPorosity( curveProperty, porosity, ntgScale );
|
||||
val = val * netToGross + ( 1.0 - netToGross ) * ntgValue;
|
||||
if ( std::isinf( val ) )
|
||||
{
|
||||
RiaLogging::error( QString( "Elastic property (NTG) interpolation failed. Formation='%1', "
|
||||
"facies='%2', depth=%3, porosity=%4. Property defined for "
|
||||
"porosity range: [%5, %6]" )
|
||||
.arg( formationName )
|
||||
.arg( netToGrossFaciesName )
|
||||
.arg( tvDepthValues[i] )
|
||||
.arg( porosity )
|
||||
.arg( rigNtgElasticProperties.porosityMin() )
|
||||
.arg( rigNtgElasticProperties.porosityMax() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
values.push_back( val );
|
||||
}
|
||||
else if ( stimPlanModel->hasDefaultValueForProperty( curveProperty ) )
|
||||
{
|
||||
double val = stimPlanModel->getDefaultValueForProperty( curveProperty );
|
||||
values.push_back( val );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RiaLogging::error( QString( "Missing elastic properties. Field='%1', formation='%2', facies='%3'" )
|
||||
.arg( fieldName )
|
||||
.arg( formationName )
|
||||
.arg( faciesName ) );
|
||||
values.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimStimPlanModelElasticPropertyCalculator::findFaciesName( const RimColorLegend& colorLegend, double value )
|
||||
{
|
||||
for ( auto item : colorLegend.colorLegendItems() )
|
||||
{
|
||||
if ( item->categoryValue() == static_cast<int>( value ) ) return item->categoryName();
|
||||
}
|
||||
|
||||
return "not found";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelElasticPropertyCalculator::addOverburden( std::vector<QString>& formationNames,
|
||||
std::vector<double>& formationValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
double overburdenHeight,
|
||||
const QString& formationName )
|
||||
{
|
||||
if ( !tvDepthValues.empty() )
|
||||
{
|
||||
// Prepend the new "fake" depth for start of overburden
|
||||
double tvdTop = tvDepthValues[0];
|
||||
tvDepthValues.insert( tvDepthValues.begin(), tvdTop );
|
||||
tvDepthValues.insert( tvDepthValues.begin(), tvdTop - overburdenHeight );
|
||||
|
||||
// TODO: this is not always correct
|
||||
double mdTop = measuredDepthValues[0];
|
||||
measuredDepthValues.insert( measuredDepthValues.begin(), mdTop );
|
||||
measuredDepthValues.insert( measuredDepthValues.begin(), mdTop - overburdenHeight );
|
||||
|
||||
formationNames.push_back( formationName );
|
||||
|
||||
formationValues.insert( formationValues.begin(), formationNames.size() - 1 );
|
||||
formationValues.insert( formationValues.begin(), formationNames.size() - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelElasticPropertyCalculator::addUnderburden( std::vector<QString>& formationNames,
|
||||
std::vector<double>& formationValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
double underburdenHeight,
|
||||
const QString& formationName )
|
||||
{
|
||||
if ( !tvDepthValues.empty() )
|
||||
{
|
||||
size_t lastIndex = tvDepthValues.size() - 1;
|
||||
|
||||
double tvdBottom = tvDepthValues[lastIndex];
|
||||
tvDepthValues.push_back( tvdBottom );
|
||||
tvDepthValues.push_back( tvdBottom + underburdenHeight );
|
||||
|
||||
// TODO: this is not always correct
|
||||
double mdBottom = measuredDepthValues[lastIndex];
|
||||
measuredDepthValues.push_back( mdBottom );
|
||||
measuredDepthValues.push_back( mdBottom + underburdenHeight );
|
||||
|
||||
formationNames.push_back( formationName );
|
||||
|
||||
formationValues.push_back( formationNames.size() - 1 );
|
||||
formationValues.push_back( formationNames.size() - 1 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "RimStimPlanModelPropertyCalculator.h"
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimStimPlanModelCalculator;
|
||||
class RimStimPlanModel;
|
||||
class RimColorLegend;
|
||||
|
||||
class QString;
|
||||
|
||||
class RimStimPlanModelElasticPropertyCalculator : public RimStimPlanModelPropertyCalculator
|
||||
{
|
||||
public:
|
||||
RimStimPlanModelElasticPropertyCalculator( RimStimPlanModelCalculator* calculator );
|
||||
|
||||
bool calculate( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const override;
|
||||
|
||||
bool isMatching( RiaDefines::CurveProperty curveProperty ) const override;
|
||||
|
||||
protected:
|
||||
static void addOverburden( std::vector<QString>& formationNames,
|
||||
std::vector<double>& formationValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
double overburdenHeight,
|
||||
const QString& formationName );
|
||||
|
||||
static void addUnderburden( std::vector<QString>& formationNames,
|
||||
std::vector<double>& formationValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
double underburdenHeight,
|
||||
const QString& formationName );
|
||||
|
||||
static QString findFaciesName( const RimColorLegend& colorLegend, double value );
|
||||
|
||||
private:
|
||||
RimStimPlanModelCalculator* m_stimPlanModelCalculator;
|
||||
};
|
||||
@@ -0,0 +1,178 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelLayerCalculator.h"
|
||||
|
||||
#include "RiaDefines.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseWellLogExtractor.h"
|
||||
#include "RigResultAccessor.h"
|
||||
#include "RigResultAccessorFactory.h"
|
||||
#include "RigWellPath.h"
|
||||
|
||||
#include "RimCase.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
#include "RimModeledWellPath.h"
|
||||
#include "RimNonNetLayers.h"
|
||||
#include "RimStimPlanModel.h"
|
||||
#include "RimStimPlanModelCalculator.h"
|
||||
#include "RimStimPlanModelLayerCalculator.h"
|
||||
#include "RimStimPlanModelTemplate.h"
|
||||
#include "RimWellLogTrack.h"
|
||||
#include "RimWellPath.h"
|
||||
|
||||
#include "cafAssert.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelLayerCalculator::RimStimPlanModelLayerCalculator( RimStimPlanModelCalculator* stimPlanModelCalculator )
|
||||
: m_stimPlanModelCalculator( stimPlanModelCalculator )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelLayerCalculator::isMatching( RiaDefines::CurveProperty curveProperty ) const
|
||||
{
|
||||
return curveProperty == RiaDefines::CurveProperty::LAYERS;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelLayerCalculator::calculate( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const
|
||||
{
|
||||
RimEclipseCase* eclipseCase = stimPlanModel->eclipseCase();
|
||||
if ( !eclipseCase )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !stimPlanModel->thicknessDirectionWellPath() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RigWellPath* wellPathGeometry = stimPlanModel->thicknessDirectionWellPath()->wellPathGeometry();
|
||||
if ( !wellPathGeometry )
|
||||
{
|
||||
RiaLogging::error( "No well path geometry found for layer data exctration." );
|
||||
return false;
|
||||
}
|
||||
|
||||
RigEclipseWellLogExtractor eclExtractor( eclipseCase->eclipseCaseData(), wellPathGeometry, "fracture model" );
|
||||
|
||||
rkbDiff = eclExtractor.wellPathGeometry()->rkbDiff();
|
||||
|
||||
// Extract formation data
|
||||
cvf::ref<RigResultAccessor> formationResultAccessor =
|
||||
RigResultAccessorFactory::createFromResultAddress( eclipseCase->eclipseCaseData(),
|
||||
0,
|
||||
RiaDefines::PorosityModelType::MATRIX_MODEL,
|
||||
0,
|
||||
RigEclipseResultAddress( RiaDefines::ResultCatType::FORMATION_NAMES,
|
||||
RiaDefines::activeFormationNamesResultName() ) );
|
||||
if ( !formationResultAccessor.notNull() )
|
||||
{
|
||||
RiaLogging::error( QString( "No formation result found." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
CurveSamplingPointData curveData =
|
||||
RimWellLogTrack::curveSamplingPointData( &eclExtractor, formationResultAccessor.p() );
|
||||
|
||||
std::vector<QString> formationNamesVector = RimWellLogTrack::formationNamesVector( eclipseCase );
|
||||
|
||||
double overburdenHeight = stimPlanModel->overburdenHeight();
|
||||
if ( overburdenHeight > 0.0 )
|
||||
{
|
||||
RimWellLogTrack::addOverburden( formationNamesVector, curveData, overburdenHeight );
|
||||
}
|
||||
|
||||
double underburdenHeight = stimPlanModel->underburdenHeight();
|
||||
if ( underburdenHeight > 0.0 )
|
||||
{
|
||||
RimWellLogTrack::addUnderburden( formationNamesVector, curveData, underburdenHeight );
|
||||
}
|
||||
|
||||
// Extract facies data
|
||||
std::vector<double> faciesValues =
|
||||
m_stimPlanModelCalculator->extractValues( RiaDefines::CurveProperty::FACIES, timeStep );
|
||||
if ( faciesValues.empty() )
|
||||
{
|
||||
RiaLogging::error( QString( "Empty facies data found for layer curve." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<double> netToGrossValues =
|
||||
m_stimPlanModelCalculator->extractValues( RiaDefines::CurveProperty::NET_TO_GROSS, timeStep );
|
||||
if ( netToGrossValues.empty() )
|
||||
{
|
||||
RiaLogging::warning( QString( "Empty net-to-gross data found for layer curve." ) );
|
||||
}
|
||||
|
||||
measuredDepthValues = curveData.md;
|
||||
tvDepthValues = curveData.tvd;
|
||||
|
||||
CAF_ASSERT( faciesValues.size() == curveData.data.size() );
|
||||
|
||||
values.resize( faciesValues.size() );
|
||||
|
||||
int layerNo = 0;
|
||||
double previousFormation = -1.0;
|
||||
double previousFacies = -1.0;
|
||||
double previousNetToGross = -1.0;
|
||||
double netToGrossCutoff = 1.0;
|
||||
bool useNetToGross = false;
|
||||
|
||||
if ( stimPlanModel->stimPlanModelTemplate() && stimPlanModel->stimPlanModelTemplate()->nonNetLayers() )
|
||||
{
|
||||
netToGrossCutoff = stimPlanModel->stimPlanModelTemplate()->nonNetLayers()->cutOff();
|
||||
useNetToGross = !netToGrossValues.empty() && stimPlanModel->stimPlanModelTemplate()->nonNetLayers()->isChecked();
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < faciesValues.size(); i++ )
|
||||
{
|
||||
if ( previousFormation != curveData.data[i] || previousFacies != faciesValues[i] ||
|
||||
( useNetToGross && netToGrossValues[i] <= netToGrossCutoff && previousNetToGross != netToGrossValues[i] ) )
|
||||
{
|
||||
layerNo++;
|
||||
}
|
||||
|
||||
values[i] = layerNo;
|
||||
previousFormation = curveData.data[i];
|
||||
previousFacies = faciesValues[i];
|
||||
if ( useNetToGross )
|
||||
{
|
||||
previousNetToGross = netToGrossValues[i];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "RimStimPlanModelPropertyCalculator.h"
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimStimPlanModelCalculator;
|
||||
class RimStimPlanModel;
|
||||
|
||||
class RimStimPlanModelLayerCalculator : public RimStimPlanModelPropertyCalculator
|
||||
{
|
||||
public:
|
||||
RimStimPlanModelLayerCalculator( RimStimPlanModelCalculator* calculator );
|
||||
|
||||
bool calculate( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const override;
|
||||
|
||||
bool isMatching( RiaDefines::CurveProperty curveProperty ) const override;
|
||||
|
||||
private:
|
||||
RimStimPlanModelCalculator* m_stimPlanModelCalculator;
|
||||
};
|
||||
@@ -0,0 +1,216 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelPlot.h"
|
||||
|
||||
#include "RiaDefines.h"
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "Riu3DMainWindowTools.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimStimPlanModel.h"
|
||||
#include "RimStimPlanModelCurve.h"
|
||||
#include "RimStimPlanModelPropertyCurve.h"
|
||||
#include "RimTools.h"
|
||||
#include "RimWellLogTrack.h"
|
||||
|
||||
#include "cafPdmBase.h"
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiGroup.h"
|
||||
#include "cafPdmUiToolButtonEditor.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimStimPlanModelPlot, "StimPlanModelPlot" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelPlot::RimStimPlanModelPlot()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "StimPlan Model Plot", "", "", "A fracture model plot" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_stimPlanModel, "StimPlanModel", "StimPlan Model", "", "", "" );
|
||||
m_stimPlanModel.uiCapability()->setUiReadOnly( true );
|
||||
|
||||
CAF_PDM_InitField( &m_editStimPlanModel, "EditModel", false, "Edit", "", "", "" );
|
||||
m_editStimPlanModel.uiCapability()->setUiEditorTypeName( caf::PdmUiToolButtonEditor::uiEditorTypeName() );
|
||||
m_editStimPlanModel.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_eclipseCase, "EclipseCase", "Case", "", "", "" );
|
||||
CAF_PDM_InitScriptableField( &m_timeStep, "TimeStep", 0, "Time Step", "", "", "" );
|
||||
|
||||
setLegendsVisible( true );
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelPlot::setStimPlanModel( RimStimPlanModel* stimPlanModel )
|
||||
{
|
||||
m_stimPlanModel = stimPlanModel;
|
||||
m_eclipseCase = stimPlanModel->eclipseCase();
|
||||
m_timeStep = stimPlanModel->timeStep();
|
||||
|
||||
m_nameConfig->setCustomName( stimPlanModel->name() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModel* RimStimPlanModelPlot::stimPlanModel()
|
||||
{
|
||||
return m_stimPlanModel;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_stimPlanModel, { true, 2, 1 } );
|
||||
uiOrdering.add( &m_editStimPlanModel, { false, 1, 0 } );
|
||||
uiOrdering.add( &m_eclipseCase );
|
||||
uiOrdering.add( &m_timeStep );
|
||||
|
||||
caf::PdmUiGroup* depthGroup = uiOrdering.addNewGroup( "Depth Axis" );
|
||||
RimDepthTrackPlot::uiOrderingForDepthAxis( uiConfigName, *depthGroup );
|
||||
|
||||
caf::PdmUiGroup* titleGroup = uiOrdering.addNewGroup( "Plot Title" );
|
||||
RimDepthTrackPlot::uiOrderingForAutoName( uiConfigName, *titleGroup );
|
||||
|
||||
caf::PdmUiGroup* plotLayoutGroup = uiOrdering.addNewGroup( "Plot Layout" );
|
||||
RimPlotWindow::uiOrderingForPlotLayout( uiConfigName, *plotLayoutGroup );
|
||||
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo>
|
||||
RimStimPlanModelPlot::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
|
||||
if ( fieldNeedingOptions == &m_stimPlanModel )
|
||||
{
|
||||
// The user is not allowed to change this field, but option box looks good
|
||||
options.push_back( caf::PdmOptionItemInfo( m_stimPlanModel->name(), m_stimPlanModel ) );
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_eclipseCase )
|
||||
{
|
||||
RimTools::eclipseCaseOptionItems( &options );
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_timeStep )
|
||||
{
|
||||
RimTools::timeStepsForCase( m_eclipseCase(), &options );
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
if ( m_stimPlanModel )
|
||||
{
|
||||
if ( changedField == &m_eclipseCase || changedField == &m_timeStep )
|
||||
{
|
||||
m_stimPlanModel->setEclipseCaseAndTimeStep( m_eclipseCase(), m_timeStep() );
|
||||
}
|
||||
else if ( changedField == &m_editStimPlanModel )
|
||||
{
|
||||
m_editStimPlanModel = false;
|
||||
if ( m_stimPlanModel != nullptr )
|
||||
{
|
||||
Riu3DMainWindowTools::selectAsCurrentItem( m_stimPlanModel() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelPlot::onLoadDataAndUpdate()
|
||||
{
|
||||
if ( stimPlanModel() != nullptr )
|
||||
{
|
||||
// Update eclipse case and time step
|
||||
m_eclipseCase = stimPlanModel()->eclipseCase();
|
||||
m_timeStep = stimPlanModel()->timeStep();
|
||||
updateConnectedEditors();
|
||||
|
||||
// Enable and disable detailed fluid loss curves
|
||||
std::vector<RiaDefines::CurveProperty> fluidLossCurves = { RiaDefines::CurveProperty::PORO_ELASTIC_CONSTANT,
|
||||
RiaDefines::CurveProperty::RELATIVE_PERMEABILITY_FACTOR,
|
||||
RiaDefines::CurveProperty::THERMAL_EXPANSION_COEFFICIENT,
|
||||
RiaDefines::CurveProperty::IMMOBILE_FLUID_SATURATION };
|
||||
|
||||
bool detailedFluidLoss = stimPlanModel()->useDetailedFluidLoss();
|
||||
|
||||
for ( auto curveProperty : fluidLossCurves )
|
||||
{
|
||||
RimWellLogExtractionCurve* curve = findCurveByProperty( curveProperty );
|
||||
if ( curve )
|
||||
{
|
||||
RimWellLogTrack* track = nullptr;
|
||||
curve->firstAncestorOfType( track );
|
||||
if ( track )
|
||||
{
|
||||
track->setShowWindow( detailedFluidLoss );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RimDepthTrackPlot::onLoadDataAndUpdate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelPlot::applyDataSource()
|
||||
{
|
||||
this->updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellLogExtractionCurve* RimStimPlanModelPlot::findCurveByProperty( RiaDefines::CurveProperty curveProperty ) const
|
||||
{
|
||||
std::vector<RimStimPlanModelPropertyCurve*> curves;
|
||||
descendantsIncludingThisOfType( curves );
|
||||
|
||||
for ( RimStimPlanModelPropertyCurve* curve : curves )
|
||||
{
|
||||
if ( curve->curveProperty() == curveProperty )
|
||||
{
|
||||
return dynamic_cast<RimWellLogExtractionCurve*>( curve );
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "RimDepthTrackPlot.h"
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
class RimStimPlanModel;
|
||||
class RimWellLogExtractionCurve;
|
||||
class RimEclipseCase;
|
||||
|
||||
class RimStimPlanModelPlot : public RimDepthTrackPlot
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimStimPlanModelPlot();
|
||||
|
||||
void setStimPlanModel( RimStimPlanModel* stimPlanModel );
|
||||
RimStimPlanModel* stimPlanModel();
|
||||
|
||||
protected:
|
||||
RimWellLogExtractionCurve* findCurveByProperty( RiaDefines::CurveProperty curveProperty ) const;
|
||||
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
||||
bool* useOptionsOnly ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
void onLoadDataAndUpdate() override;
|
||||
|
||||
private:
|
||||
void applyDataSource();
|
||||
|
||||
caf::PdmPtrField<RimStimPlanModel*> m_stimPlanModel;
|
||||
caf::PdmField<bool> m_editStimPlanModel;
|
||||
caf::PdmPtrField<RimEclipseCase*> m_eclipseCase;
|
||||
caf::PdmField<int> m_timeStep;
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelPlotCollection.h"
|
||||
|
||||
#include "RimStimPlanModelPlot.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimStimPlanModelPlotCollection, "StimPlanModelPlotCollection" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelPlotCollection::RimStimPlanModelPlotCollection()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "StimPlan Model Plots", ":/WellLogPlots16x16.png", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_stimPlanModelPlots, "StimPlanModelPlots", "", "", "", "" );
|
||||
m_stimPlanModelPlots.uiCapability()->setUiHidden( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelPlotCollection::~RimStimPlanModelPlotCollection()
|
||||
{
|
||||
m_stimPlanModelPlots.deleteAllChildObjects();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelPlotCollection::reloadAllPlots()
|
||||
{
|
||||
for ( const auto& w : m_stimPlanModelPlots() )
|
||||
{
|
||||
w->loadDataAndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelPlotCollection::addStimPlanModelPlot( RimStimPlanModelPlot* newPlot )
|
||||
{
|
||||
m_stimPlanModelPlots.push_back( newPlot );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimStimPlanModelPlot*> RimStimPlanModelPlotCollection::stimPlanModelPlots() const
|
||||
{
|
||||
return m_stimPlanModelPlots.childObjects();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelPlotCollection::deleteAllPlots()
|
||||
{
|
||||
m_stimPlanModelPlots.deleteAllChildObjects();
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
class RimStimPlanModelPlot;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimStimPlanModelPlotCollection : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimStimPlanModelPlotCollection();
|
||||
~RimStimPlanModelPlotCollection() override;
|
||||
|
||||
void addStimPlanModelPlot( RimStimPlanModelPlot* newPlot );
|
||||
|
||||
std::vector<RimStimPlanModelPlot*> stimPlanModelPlots() const;
|
||||
|
||||
void reloadAllPlots();
|
||||
|
||||
void deleteAllPlots();
|
||||
|
||||
private:
|
||||
caf::PdmChildArrayField<RimStimPlanModelPlot*> m_stimPlanModelPlots;
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimStimPlanModelCalculator;
|
||||
class RimStimPlanModel;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimStimPlanModelPropertyCalculator
|
||||
{
|
||||
public:
|
||||
virtual ~RimStimPlanModelPropertyCalculator(){};
|
||||
|
||||
virtual bool isMatching( RiaDefines::CurveProperty curveProperty ) const = 0;
|
||||
virtual bool calculate( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const = 0;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RimWellLogExtractionCurve.h"
|
||||
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimStimPlanModelPropertyCurve
|
||||
{
|
||||
public:
|
||||
virtual void setCurveProperty( RiaDefines::CurveProperty ) = 0;
|
||||
virtual RiaDefines::CurveProperty curveProperty() const = 0;
|
||||
};
|
||||
@@ -0,0 +1,167 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelStressCalculator.h"
|
||||
|
||||
#include "RiaDefines.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseWellLogExtractor.h"
|
||||
#include "RigWellPath.h"
|
||||
|
||||
#include "RigWellPathGeometryTools.h"
|
||||
#include "RimCase.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimModeledWellPath.h"
|
||||
#include "RimStimPlanModel.h"
|
||||
#include "RimStimPlanModelCalculator.h"
|
||||
#include "RimStimPlanModelStressCalculator.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelStressCalculator::RimStimPlanModelStressCalculator( RimStimPlanModelCalculator* stimPlanModelCalculator )
|
||||
: m_stimPlanModelCalculator( stimPlanModelCalculator )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelStressCalculator::isMatching( RiaDefines::CurveProperty curveProperty ) const
|
||||
{
|
||||
std::vector<RiaDefines::CurveProperty> matching = { RiaDefines::CurveProperty::INITIAL_STRESS,
|
||||
RiaDefines::CurveProperty::STRESS,
|
||||
RiaDefines::CurveProperty::STRESS_GRADIENT,
|
||||
RiaDefines::CurveProperty::TEMPERATURE };
|
||||
|
||||
return std::find( matching.begin(), matching.end(), curveProperty ) != matching.end();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelStressCalculator::calculate( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const
|
||||
{
|
||||
RimEclipseCase* eclipseCase = stimPlanModel->eclipseCase();
|
||||
if ( !eclipseCase )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !stimPlanModel->thicknessDirectionWellPath() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RigWellPath* wellPathGeometry = stimPlanModel->thicknessDirectionWellPath()->wellPathGeometry();
|
||||
if ( !wellPathGeometry )
|
||||
{
|
||||
RiaLogging::error( "No well path geometry found for stress data exctration." );
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<double> tvDepthInFeet = m_stimPlanModelCalculator->calculateTrueVerticalDepth();
|
||||
for ( double f : tvDepthInFeet )
|
||||
{
|
||||
tvDepthValues.push_back( RiaEclipseUnitTools::feetToMeter( f ) );
|
||||
}
|
||||
|
||||
if ( curveProperty == RiaDefines::CurveProperty::STRESS )
|
||||
{
|
||||
values = m_stimPlanModelCalculator->calculateStress();
|
||||
std::vector<double> stressGradients = m_stimPlanModelCalculator->calculateStressGradient();
|
||||
addDatapointsForBottomOfLayers( tvDepthValues, values, stressGradients );
|
||||
}
|
||||
else if ( curveProperty == RiaDefines::CurveProperty::INITIAL_STRESS )
|
||||
{
|
||||
values = m_stimPlanModelCalculator->calculateInitialStress();
|
||||
std::vector<double> stressGradients = m_stimPlanModelCalculator->calculateStressGradient();
|
||||
addDatapointsForBottomOfLayers( tvDepthValues, values, stressGradients );
|
||||
}
|
||||
else if ( curveProperty == RiaDefines::CurveProperty::STRESS_GRADIENT )
|
||||
{
|
||||
values = m_stimPlanModelCalculator->calculateStressGradient();
|
||||
}
|
||||
else if ( curveProperty == RiaDefines::CurveProperty::TEMPERATURE )
|
||||
{
|
||||
m_stimPlanModelCalculator->calculateTemperature( values );
|
||||
}
|
||||
|
||||
if ( eclipseCase )
|
||||
{
|
||||
RigEclipseWellLogExtractor eclExtractor( eclipseCase->eclipseCaseData(), wellPathGeometry, "fracture model" );
|
||||
|
||||
rkbDiff = wellPathGeometry->rkbDiff();
|
||||
|
||||
// Generate MD data by interpolation
|
||||
const std::vector<double>& mdValuesOfWellPath = wellPathGeometry->measuredDepths();
|
||||
std::vector<double> tvdValuesOfWellPath = wellPathGeometry->trueVerticalDepths();
|
||||
if ( mdValuesOfWellPath.empty() )
|
||||
{
|
||||
RiaLogging::error( "Well path geometry had no MD values." );
|
||||
return false;
|
||||
}
|
||||
|
||||
measuredDepthValues =
|
||||
RigWellPathGeometryTools::interpolateMdFromTvd( mdValuesOfWellPath, tvdValuesOfWellPath, tvDepthValues );
|
||||
CVF_ASSERT( measuredDepthValues.size() == tvDepthValues.size() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelStressCalculator::addDatapointsForBottomOfLayers( std::vector<double>& tvDepthValues,
|
||||
std::vector<double>& stress,
|
||||
const std::vector<double>& stressGradients )
|
||||
{
|
||||
std::vector<double> tvdWithBottomLayers;
|
||||
std::vector<double> valuesWithBottomLayers;
|
||||
for ( size_t i = 0; i < stress.size(); i++ )
|
||||
{
|
||||
// Add the data point at top of the layer
|
||||
double topLayerDepth = tvDepthValues[i];
|
||||
double stressValue = stress[i];
|
||||
tvdWithBottomLayers.push_back( topLayerDepth );
|
||||
valuesWithBottomLayers.push_back( stressValue );
|
||||
|
||||
// Add extra data points for bottom part of the layer
|
||||
if ( i < stress.size() - 1 )
|
||||
{
|
||||
double bottomLayerDepth = tvDepthValues[i + 1];
|
||||
double diffDepthFeet = RiaEclipseUnitTools::meterToFeet( bottomLayerDepth - topLayerDepth );
|
||||
double bottomStress = stressValue + diffDepthFeet * stressGradients[i];
|
||||
|
||||
tvdWithBottomLayers.push_back( bottomLayerDepth );
|
||||
valuesWithBottomLayers.push_back( bottomStress );
|
||||
}
|
||||
}
|
||||
|
||||
stress = valuesWithBottomLayers;
|
||||
tvDepthValues = tvdWithBottomLayers;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "RimStimPlanModelPropertyCalculator.h"
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimStimPlanModelCalculator;
|
||||
class RimStimPlanModel;
|
||||
|
||||
class QString;
|
||||
|
||||
class RimStimPlanModelStressCalculator : public RimStimPlanModelPropertyCalculator
|
||||
{
|
||||
public:
|
||||
RimStimPlanModelStressCalculator( RimStimPlanModelCalculator* calculator );
|
||||
|
||||
bool calculate( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const override;
|
||||
|
||||
bool isMatching( RiaDefines::CurveProperty curveProperty ) const override;
|
||||
|
||||
private:
|
||||
static void addDatapointsForBottomOfLayers( std::vector<double>& tvDepthValues,
|
||||
std::vector<double>& stress,
|
||||
const std::vector<double>& stressGradients );
|
||||
|
||||
RimStimPlanModelCalculator* m_stimPlanModelCalculator;
|
||||
};
|
||||
@@ -0,0 +1,643 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelTemplate.h"
|
||||
|
||||
#include "RiaColorTables.h"
|
||||
#include "RiaCompletionTypeCalculationScheduler.h"
|
||||
#include "RiaEclipseUnitTools.h"
|
||||
#include "RiaFractureDefines.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "Riu3DMainWindowTools.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigWellPath.h"
|
||||
|
||||
#include "Rim3dView.h"
|
||||
#include "RimColorLegend.h"
|
||||
#include "RimColorLegendCollection.h"
|
||||
#include "RimColorLegendItem.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseCellColors.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimElasticProperties.h"
|
||||
#include "RimEllipseFractureTemplate.h"
|
||||
#include "RimFaciesProperties.h"
|
||||
#include "RimNonNetLayers.h"
|
||||
#include "RimOilField.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimStimPlanModelPlot.h"
|
||||
#include "RimTools.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimWellPathCollection.h"
|
||||
#include "RimWellPathGeometryDef.h"
|
||||
#include "RimWellPathTarget.h"
|
||||
|
||||
#include "cafPdmFieldCvfVec3d.h"
|
||||
#include "cafPdmFieldScriptingCapabilityCvfVec3d.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiDoubleSliderEditor.h"
|
||||
#include "cafPdmUiDoubleValueEditor.h"
|
||||
#include "cafPdmUiPushButtonEditor.h"
|
||||
#include "cafPdmUiToolButtonEditor.h"
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
|
||||
#include "cvfBoundingBox.h"
|
||||
#include "cvfGeometryTools.h"
|
||||
#include "cvfMath.h"
|
||||
#include "cvfMatrix4.h"
|
||||
#include "cvfPlane.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimStimPlanModelTemplate, "StimPlanModelTemplate" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelTemplate::RimStimPlanModelTemplate()
|
||||
: changed( this )
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "StimPlanModelTemplate", "", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_id, "Id", -1, "ID", "", "", "" );
|
||||
m_id.uiCapability()->setUiReadOnly( true );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_defaultPorosity, "DefaultPorosity", 0.0, "Default Porosity", "", "", "" );
|
||||
CAF_PDM_InitScriptableField( &m_defaultPermeability, "DefaultPermeability", 10.0e-6, "Default Permeability", "", "", "" );
|
||||
|
||||
// Stress unit: bar
|
||||
// Stress gradient unit: bar/m
|
||||
// Depth is meter
|
||||
double defaultStressGradient = 0.238;
|
||||
double defaultStressDepth = computeDefaultStressDepth();
|
||||
double defaultStress = defaultStressDepth * defaultStressGradient;
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_verticalStress, "VerticalStress", defaultStress, "Vertical Stress", "", "", "" );
|
||||
m_verticalStress.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
|
||||
CAF_PDM_InitScriptableField( &m_verticalStressGradient,
|
||||
"VerticalStressGradient",
|
||||
defaultStressGradient,
|
||||
"Vertical Stress Gradient",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
CAF_PDM_InitScriptableField( &m_stressDepth, "StressDepth", defaultStressDepth, "Stress Depth", "", "", "" );
|
||||
m_stressDepth.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_referenceTemperature, "ReferenceTemperature", 70.0, "Temperature [C]", "", "", "" );
|
||||
CAF_PDM_InitScriptableField( &m_referenceTemperatureGradient,
|
||||
"ReferenceTemperatureGradient",
|
||||
0.025,
|
||||
"Temperature Gradient [C/m]",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
CAF_PDM_InitScriptableField( &m_referenceTemperatureDepth,
|
||||
"ReferenceTemperatureDepth",
|
||||
2500.0,
|
||||
"Temperature Depth [m]",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_overburdenHeight, "OverburdenHeight", 50.0, "Overburden Height", "", "", "" );
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_overburdenFormation, "OverburdenFormation", "Overburden Formation", "", "", "" );
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_overburdenFacies, "OverburdenFacies", "Overburden Facies", "", "", "" );
|
||||
CAF_PDM_InitScriptableField( &m_overburdenPorosity, "OverburdenPorosity", 0.0, "Overburden Porosity", "", "", "" );
|
||||
CAF_PDM_InitScriptableField( &m_overburdenPermeability,
|
||||
"OverburdenPermeability",
|
||||
10.0e-6,
|
||||
"Overburden Permeability",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
CAF_PDM_InitScriptableField( &m_overburdenFluidDensity,
|
||||
"OverburdenFluidDensity",
|
||||
1.03,
|
||||
"Overburden Fluid Density [g/cm^3]",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_underburdenHeight, "UnderburdenHeight", 50.0, "Underburden Height", "", "", "" );
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_underburdenFormation, "UnderburdenFormation", "Underburden Formation", "", "", "" );
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_underburdenFacies, "UnderburdenFacies", "Underburden Facies", "", "", "" );
|
||||
CAF_PDM_InitScriptableField( &m_underburdenPorosity, "UnderburdenPorosity", 0.0, "Underburden Porosity", "", "", "" );
|
||||
CAF_PDM_InitScriptableField( &m_underburdenPermeability,
|
||||
"UnderburdenPermeability",
|
||||
10.0e-6,
|
||||
"Underburden Permeability",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
CAF_PDM_InitScriptableField( &m_underburdenFluidDensity,
|
||||
"UnderburdenFluidDensity",
|
||||
1.03,
|
||||
"Underburden Fluid Density [g/cm^3]",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_elasticProperties, "ElasticProperties", "Elastic Properties", "", "", "" );
|
||||
m_elasticProperties.uiCapability()->setUiHidden( true );
|
||||
m_elasticProperties.uiCapability()->setUiTreeHidden( true );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_faciesProperties, "FaciesProperties", "Facies Properties", "", "", "" );
|
||||
m_faciesProperties.uiCapability()->setUiHidden( true );
|
||||
m_faciesProperties.uiCapability()->setUiTreeHidden( true );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_nonNetLayers, "NonNetLayers", "Non-Net Layers", "", "", "" );
|
||||
m_nonNetLayers.uiCapability()->setUiHidden( true );
|
||||
m_nonNetLayers.uiCapability()->setUiTreeHidden( true );
|
||||
setNonNetLayers( new RimNonNetLayers );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelTemplate::~RimStimPlanModelTemplate()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
changed.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo>
|
||||
RimStimPlanModelTemplate::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
|
||||
if ( fieldNeedingOptions == &m_overburdenFormation || fieldNeedingOptions == &m_underburdenFormation )
|
||||
{
|
||||
RigEclipseCaseData* eclipseCaseData = getEclipseCaseData();
|
||||
if ( !eclipseCaseData ) return options;
|
||||
|
||||
std::vector<QString> formationNames = eclipseCaseData->formationNames();
|
||||
for ( const QString& formationName : formationNames )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( formationName, formationName ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_overburdenFacies || fieldNeedingOptions == &m_underburdenFacies )
|
||||
{
|
||||
if ( !m_faciesProperties ) return options;
|
||||
|
||||
RimColorLegend* faciesColors = m_faciesProperties->colorLegend();
|
||||
if ( faciesColors )
|
||||
{
|
||||
for ( RimColorLegendItem* item : faciesColors->colorLegendItems() )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( item->categoryName(), item->categoryName() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( nameField() );
|
||||
uiOrdering.add( &m_id );
|
||||
|
||||
caf::PdmUiOrdering* defaultsGroup = uiOrdering.addNewGroup( "Defaults" );
|
||||
defaultsGroup->add( &m_defaultPorosity );
|
||||
defaultsGroup->add( &m_defaultPermeability );
|
||||
|
||||
caf::PdmUiOrdering* referenceStressGroup = uiOrdering.addNewGroup( "Reference Stress" );
|
||||
referenceStressGroup->add( &m_verticalStress );
|
||||
referenceStressGroup->add( &m_verticalStressGradient );
|
||||
referenceStressGroup->add( &m_stressDepth );
|
||||
|
||||
caf::PdmUiOrdering* temperatureGroup = uiOrdering.addNewGroup( "Temperature" );
|
||||
temperatureGroup->add( &m_referenceTemperature );
|
||||
temperatureGroup->add( &m_referenceTemperatureGradient );
|
||||
temperatureGroup->add( &m_referenceTemperatureDepth );
|
||||
|
||||
caf::PdmUiOrdering* overburdenGroup = uiOrdering.addNewGroup( "Overburden" );
|
||||
overburdenGroup->add( &m_overburdenHeight );
|
||||
overburdenGroup->add( &m_overburdenFormation );
|
||||
overburdenGroup->add( &m_overburdenFacies );
|
||||
overburdenGroup->add( &m_overburdenPorosity );
|
||||
overburdenGroup->add( &m_overburdenPermeability );
|
||||
overburdenGroup->add( &m_overburdenFluidDensity );
|
||||
|
||||
caf::PdmUiOrdering* underburdenGroup = uiOrdering.addNewGroup( "Underburden" );
|
||||
underburdenGroup->add( &m_underburdenHeight );
|
||||
underburdenGroup->add( &m_underburdenFormation );
|
||||
underburdenGroup->add( &m_underburdenFacies );
|
||||
underburdenGroup->add( &m_underburdenPorosity );
|
||||
underburdenGroup->add( &m_underburdenPermeability );
|
||||
underburdenGroup->add( &m_underburdenFluidDensity );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute )
|
||||
{
|
||||
if ( field == &m_stressDepth || field == &m_verticalStress )
|
||||
{
|
||||
auto doubleAttr = dynamic_cast<caf::PdmUiDoubleValueEditorAttribute*>( attribute );
|
||||
if ( doubleAttr )
|
||||
{
|
||||
doubleAttr->m_decimals = 2;
|
||||
doubleAttr->m_numberFormat = caf::PdmUiDoubleValueEditorAttribute::NumberFormat::FIXED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::setId( int id )
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RimStimPlanModelTemplate::id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimElasticProperties* RimStimPlanModelTemplate::elasticProperties() const
|
||||
{
|
||||
return m_elasticProperties;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::setElasticProperties( RimElasticProperties* elasticProperties )
|
||||
{
|
||||
if ( m_elasticProperties )
|
||||
{
|
||||
m_elasticProperties->changed.disconnect( this );
|
||||
}
|
||||
|
||||
m_elasticProperties = elasticProperties;
|
||||
|
||||
if ( m_elasticProperties )
|
||||
{
|
||||
m_elasticProperties->changed.connect( this, &RimStimPlanModelTemplate::elasticPropertiesChanged );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimFaciesProperties* RimStimPlanModelTemplate::faciesProperties() const
|
||||
{
|
||||
return m_faciesProperties;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::setFaciesProperties( RimFaciesProperties* faciesProperties )
|
||||
{
|
||||
if ( m_faciesProperties )
|
||||
{
|
||||
m_faciesProperties->changed.disconnect( this );
|
||||
}
|
||||
|
||||
m_faciesProperties = faciesProperties;
|
||||
|
||||
if ( m_faciesProperties )
|
||||
{
|
||||
m_faciesProperties->changed.connect( this, &RimStimPlanModelTemplate::faciesPropertiesChanged );
|
||||
RimEclipseCase* eclipseCase = getEclipseCase();
|
||||
if ( !eclipseCase ) return;
|
||||
|
||||
m_faciesProperties->setEclipseCase( eclipseCase );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::setNonNetLayers( RimNonNetLayers* nonNetLayers )
|
||||
{
|
||||
if ( m_nonNetLayers )
|
||||
{
|
||||
m_nonNetLayers->changed.disconnect( this );
|
||||
}
|
||||
|
||||
m_nonNetLayers = nonNetLayers;
|
||||
|
||||
if ( m_nonNetLayers )
|
||||
{
|
||||
m_nonNetLayers->changed.connect( this, &RimStimPlanModelTemplate::nonNetLayersChanged );
|
||||
RimEclipseCase* eclipseCase = getEclipseCase();
|
||||
if ( !eclipseCase ) return;
|
||||
|
||||
m_nonNetLayers->setEclipseCase( eclipseCase );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimNonNetLayers* RimStimPlanModelTemplate::nonNetLayers() const
|
||||
{
|
||||
return m_nonNetLayers;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::initAfterRead()
|
||||
{
|
||||
RimEclipseCase* eclipseCase = getEclipseCase();
|
||||
if ( !eclipseCase ) return;
|
||||
|
||||
if ( m_faciesProperties )
|
||||
{
|
||||
m_faciesProperties->setEclipseCase( eclipseCase );
|
||||
}
|
||||
|
||||
if ( m_nonNetLayers )
|
||||
{
|
||||
m_nonNetLayers->setEclipseCase( eclipseCase );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::faciesPropertiesChanged( const caf::SignalEmitter* emitter )
|
||||
{
|
||||
changed.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::elasticPropertiesChanged( const caf::SignalEmitter* emitter )
|
||||
{
|
||||
changed.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::nonNetLayersChanged( const caf::SignalEmitter* emitter )
|
||||
{
|
||||
changed.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplate::loadDataAndUpdate()
|
||||
{
|
||||
if ( m_elasticProperties )
|
||||
{
|
||||
m_elasticProperties->loadDataAndUpdate();
|
||||
}
|
||||
|
||||
if ( m_faciesProperties )
|
||||
{
|
||||
m_faciesProperties->loadDataAndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::defaultPorosity() const
|
||||
{
|
||||
return m_defaultPorosity();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::defaultPermeability() const
|
||||
{
|
||||
return m_defaultPermeability();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::overburdenFluidDensity() const
|
||||
{
|
||||
return m_overburdenFluidDensity;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::underburdenFluidDensity() const
|
||||
{
|
||||
return m_underburdenFluidDensity;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::overburdenHeight() const
|
||||
{
|
||||
return m_overburdenHeight;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::underburdenHeight() const
|
||||
{
|
||||
return m_underburdenHeight;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::defaultOverburdenPorosity() const
|
||||
{
|
||||
return m_overburdenPorosity;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::defaultUnderburdenPorosity() const
|
||||
{
|
||||
return m_underburdenPorosity;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::defaultOverburdenPermeability() const
|
||||
{
|
||||
return m_overburdenPermeability;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::defaultUnderburdenPermeability() const
|
||||
{
|
||||
return m_underburdenPermeability;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimStimPlanModelTemplate::overburdenFormation() const
|
||||
{
|
||||
return m_overburdenFormation;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimStimPlanModelTemplate::overburdenFacies() const
|
||||
{
|
||||
return m_overburdenFacies;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimStimPlanModelTemplate::underburdenFormation() const
|
||||
{
|
||||
return m_underburdenFormation;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimStimPlanModelTemplate::underburdenFacies() const
|
||||
{
|
||||
return m_underburdenFacies;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::verticalStress() const
|
||||
{
|
||||
return m_verticalStress;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::verticalStressGradient() const
|
||||
{
|
||||
return m_verticalStressGradient;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::stressDepth() const
|
||||
{
|
||||
return m_stressDepth;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::referenceTemperature() const
|
||||
{
|
||||
return m_referenceTemperature;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::referenceTemperatureGradient() const
|
||||
{
|
||||
return m_referenceTemperatureGradient;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::referenceTemperatureDepth() const
|
||||
{
|
||||
return m_referenceTemperatureDepth;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimStimPlanModelTemplate::computeDefaultStressDepth()
|
||||
{
|
||||
const double stressDepth = 1000.0;
|
||||
|
||||
RimEclipseCase* eclipseCase = getEclipseCase();
|
||||
if ( !eclipseCase ) return stressDepth;
|
||||
|
||||
// Use top of active cells as reference stress depth
|
||||
return -eclipseCase->activeCellsBoundingBox().max().z();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEclipseCase* RimStimPlanModelTemplate::getEclipseCase()
|
||||
{
|
||||
// Find an eclipse case
|
||||
RimProject* proj = RimProject::current();
|
||||
if ( proj->eclipseCases().empty() ) return nullptr;
|
||||
|
||||
return proj->eclipseCases()[0];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigEclipseCaseData* RimStimPlanModelTemplate::getEclipseCaseData()
|
||||
{
|
||||
// Find an eclipse case
|
||||
RimEclipseCase* eclipseCase = getEclipseCase();
|
||||
if ( !eclipseCase ) return nullptr;
|
||||
|
||||
return eclipseCase->eclipseCaseData();
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RiaEclipseUnitTools.h"
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RimNamedObject.h"
|
||||
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmProxyValueField.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
class RimEclipseCase;
|
||||
class RimElasticProperties;
|
||||
class RigEclipseCaseData;
|
||||
class RimFaciesProperties;
|
||||
class RimNonNetLayers;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimStimPlanModelTemplate : public RimNamedObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimStimPlanModelTemplate( void );
|
||||
~RimStimPlanModelTemplate( void ) override;
|
||||
|
||||
caf::Signal<> changed;
|
||||
|
||||
void setId( int id );
|
||||
int id() const;
|
||||
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
double defaultPorosity() const;
|
||||
double defaultPermeability() const;
|
||||
|
||||
double overburdenHeight() const;
|
||||
double underburdenHeight() const;
|
||||
|
||||
double defaultOverburdenPorosity() const;
|
||||
double defaultUnderburdenPorosity() const;
|
||||
|
||||
double defaultOverburdenPermeability() const;
|
||||
double defaultUnderburdenPermeability() const;
|
||||
|
||||
QString overburdenFormation() const;
|
||||
QString overburdenFacies() const;
|
||||
|
||||
QString underburdenFormation() const;
|
||||
QString underburdenFacies() const;
|
||||
|
||||
double overburdenFluidDensity() const;
|
||||
double underburdenFluidDensity() const;
|
||||
|
||||
double referenceTemperature() const;
|
||||
double referenceTemperatureGradient() const;
|
||||
double referenceTemperatureDepth() const;
|
||||
|
||||
double verticalStress() const;
|
||||
double verticalStressGradient() const;
|
||||
double stressDepth() const;
|
||||
|
||||
void loadDataAndUpdate();
|
||||
|
||||
void setElasticProperties( RimElasticProperties* elasticProperties );
|
||||
RimElasticProperties* elasticProperties() const;
|
||||
|
||||
void setFaciesProperties( RimFaciesProperties* faciesProperties );
|
||||
RimFaciesProperties* faciesProperties() const;
|
||||
|
||||
void setNonNetLayers( RimNonNetLayers* nonNetLayers );
|
||||
RimNonNetLayers* nonNetLayers() const;
|
||||
|
||||
void updateReferringPlots();
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
||||
bool* useOptionsOnly ) override;
|
||||
void initAfterRead() override;
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute ) override;
|
||||
|
||||
private:
|
||||
static RimEclipseCase* getEclipseCase();
|
||||
static RigEclipseCaseData* getEclipseCaseData();
|
||||
|
||||
void faciesPropertiesChanged( const caf::SignalEmitter* emitter );
|
||||
void elasticPropertiesChanged( const caf::SignalEmitter* emitter );
|
||||
void nonNetLayersChanged( const caf::SignalEmitter* emitter );
|
||||
|
||||
static double computeDefaultStressDepth();
|
||||
|
||||
caf::PdmField<int> m_id;
|
||||
caf::PdmField<double> m_defaultPorosity;
|
||||
caf::PdmField<double> m_defaultPermeability;
|
||||
caf::PdmField<double> m_verticalStress;
|
||||
caf::PdmField<double> m_verticalStressGradient;
|
||||
caf::PdmField<double> m_stressDepth;
|
||||
caf::PdmField<double> m_referenceTemperature;
|
||||
caf::PdmField<double> m_referenceTemperatureGradient;
|
||||
caf::PdmField<double> m_referenceTemperatureDepth;
|
||||
caf::PdmField<double> m_overburdenHeight;
|
||||
caf::PdmField<double> m_overburdenPorosity;
|
||||
caf::PdmField<double> m_overburdenPermeability;
|
||||
caf::PdmField<QString> m_overburdenFormation;
|
||||
caf::PdmField<QString> m_overburdenFacies;
|
||||
caf::PdmField<double> m_overburdenFluidDensity;
|
||||
caf::PdmField<double> m_underburdenHeight;
|
||||
caf::PdmField<double> m_underburdenPorosity;
|
||||
caf::PdmField<double> m_underburdenPermeability;
|
||||
caf::PdmField<QString> m_underburdenFormation;
|
||||
caf::PdmField<QString> m_underburdenFacies;
|
||||
caf::PdmField<double> m_underburdenFluidDensity;
|
||||
caf::PdmChildField<RimElasticProperties*> m_elasticProperties;
|
||||
caf::PdmChildField<RimFaciesProperties*> m_faciesProperties;
|
||||
caf::PdmChildField<RimNonNetLayers*> m_nonNetLayers;
|
||||
};
|
||||
@@ -0,0 +1,151 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelTemplateCollection.h"
|
||||
|
||||
#include "RimCase.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimFracture.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimStimPlanModelTemplate.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimStimPlanModelTemplateCollection, "StimPlanModelTemplateCollection" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelTemplateCollection::RimStimPlanModelTemplateCollection()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "StimPlan Model Templates", ":/FractureTemplates16x16.png", "", "" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_stimPlanModelTemplates,
|
||||
"StimPlanModelTemplates",
|
||||
"StimPlan Model Templates",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
m_stimPlanModelTemplates.uiCapability()->setUiHidden( true );
|
||||
|
||||
CAF_PDM_InitField( &m_nextValidId, "NextValidId", 0, "", "", "", "" );
|
||||
m_nextValidId.uiCapability()->setUiHidden( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelTemplateCollection::~RimStimPlanModelTemplateCollection()
|
||||
{
|
||||
m_stimPlanModelTemplates.deleteAllChildObjects();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelTemplate* RimStimPlanModelTemplateCollection::stimPlanModelTemplate( int id ) const
|
||||
{
|
||||
for ( const auto& templ : m_stimPlanModelTemplates )
|
||||
{
|
||||
if ( templ->id() == id ) return templ;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimStimPlanModelTemplate*> RimStimPlanModelTemplateCollection::stimPlanModelTemplates() const
|
||||
{
|
||||
std::vector<RimStimPlanModelTemplate*> templates;
|
||||
for ( auto& templ : m_stimPlanModelTemplates )
|
||||
{
|
||||
templates.push_back( templ );
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplateCollection::addStimPlanModelTemplate( RimStimPlanModelTemplate* templ )
|
||||
{
|
||||
templ->setId( nextFractureTemplateId() );
|
||||
m_stimPlanModelTemplates.push_back( templ );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplateCollection::loadAndUpdateData()
|
||||
{
|
||||
for ( RimStimPlanModelTemplate* f : m_stimPlanModelTemplates() )
|
||||
{
|
||||
f->loadDataAndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplateCollection::initAfterRead()
|
||||
{
|
||||
// Assign template id if not already assigned
|
||||
for ( auto& templ : m_stimPlanModelTemplates )
|
||||
{
|
||||
if ( templ->id() < 0 ) templ->setId( nextFractureTemplateId() );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RimStimPlanModelTemplateCollection::nextFractureTemplateId()
|
||||
{
|
||||
int newId = m_nextValidId;
|
||||
m_nextValidId = m_nextValidId + 1;
|
||||
|
||||
return newId;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelTemplateCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
|
||||
std::vector<caf::PdmObjectHandle*>& referringObjects )
|
||||
{
|
||||
RimProject* proj = nullptr;
|
||||
firstAncestorOrThisOfType( proj );
|
||||
if ( proj )
|
||||
{
|
||||
proj->scheduleCreateDisplayModelAndRedrawAllViews();
|
||||
}
|
||||
|
||||
std::vector<Rim3dView*> views;
|
||||
proj->allVisibleViews( views );
|
||||
for ( Rim3dView* visibleView : views )
|
||||
{
|
||||
if ( dynamic_cast<RimEclipseView*>( visibleView ) )
|
||||
{
|
||||
visibleView->updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
class RimStimPlanModelTemplate;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimStimPlanModelTemplateCollection : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimStimPlanModelTemplateCollection();
|
||||
~RimStimPlanModelTemplateCollection() override;
|
||||
|
||||
RimStimPlanModelTemplate* stimPlanModelTemplate( int id ) const;
|
||||
std::vector<RimStimPlanModelTemplate*> stimPlanModelTemplates() const;
|
||||
void addStimPlanModelTemplate( RimStimPlanModelTemplate* templ );
|
||||
|
||||
void loadAndUpdateData();
|
||||
|
||||
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
|
||||
std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
|
||||
|
||||
protected:
|
||||
void initAfterRead() override;
|
||||
|
||||
private:
|
||||
int nextFractureTemplateId();
|
||||
|
||||
caf::PdmChildArrayField<RimStimPlanModelTemplate*> m_stimPlanModelTemplates;
|
||||
caf::PdmField<int> m_nextValidId; // Unique fracture template ID within a project
|
||||
};
|
||||
@@ -0,0 +1,445 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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 "RimStimPlanModelWellLogCalculator.h"
|
||||
|
||||
#include "RiaDefines.h"
|
||||
#include "RiaInterpolationTools.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseWellLogExtractor.h"
|
||||
#include "RigResultAccessor.h"
|
||||
#include "RigResultAccessorFactory.h"
|
||||
#include "RigWellLogCurveData.h"
|
||||
#include "RigWellPath.h"
|
||||
|
||||
#include "RimCase.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseInputProperty.h"
|
||||
#include "RimEclipseInputPropertyCollection.h"
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
#include "RimModeledWellPath.h"
|
||||
#include "RimNonNetLayers.h"
|
||||
#include "RimStimPlanModel.h"
|
||||
#include "RimStimPlanModelCalculator.h"
|
||||
#include "RimStimPlanModelTemplate.h"
|
||||
#include "RimWellPath.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimStimPlanModelWellLogCalculator::RimStimPlanModelWellLogCalculator( RimStimPlanModelCalculator* stimPlanModelCalculator )
|
||||
: m_stimPlanModelCalculator( stimPlanModelCalculator )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelWellLogCalculator::isMatching( RiaDefines::CurveProperty curveProperty ) const
|
||||
{
|
||||
std::vector<RiaDefines::CurveProperty> matching = {
|
||||
RiaDefines::CurveProperty::FACIES,
|
||||
RiaDefines::CurveProperty::POROSITY,
|
||||
RiaDefines::CurveProperty::POROSITY_UNSCALED,
|
||||
RiaDefines::CurveProperty::PERMEABILITY_X,
|
||||
RiaDefines::CurveProperty::PERMEABILITY_Z,
|
||||
RiaDefines::CurveProperty::INITIAL_PRESSURE,
|
||||
RiaDefines::CurveProperty::PRESSURE,
|
||||
RiaDefines::CurveProperty::NET_TO_GROSS,
|
||||
};
|
||||
|
||||
return std::find( matching.begin(), matching.end(), curveProperty ) != matching.end();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelWellLogCalculator::calculate( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const
|
||||
{
|
||||
RimEclipseCase* eclipseCase = stimPlanModel->eclipseCase();
|
||||
if ( !eclipseCase )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !stimPlanModel->thicknessDirectionWellPath() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RigWellPath* wellPathGeometry = stimPlanModel->thicknessDirectionWellPath()->wellPathGeometry();
|
||||
if ( !wellPathGeometry )
|
||||
{
|
||||
RiaLogging::error( "No well path geometry found for well log exctration" );
|
||||
return false;
|
||||
}
|
||||
|
||||
RigEclipseWellLogExtractor eclExtractor( eclipseCase->eclipseCaseData(), wellPathGeometry, "fracture model" );
|
||||
|
||||
measuredDepthValues = eclExtractor.cellIntersectionMDs();
|
||||
tvDepthValues = eclExtractor.cellIntersectionTVDs();
|
||||
rkbDiff = eclExtractor.wellPathGeometry()->rkbDiff();
|
||||
|
||||
RimEclipseResultDefinition eclipseResultDefinition;
|
||||
eclipseResultDefinition.setEclipseCase( eclipseCase );
|
||||
eclipseResultDefinition.setResultType( stimPlanModel->eclipseResultCategory( curveProperty ) );
|
||||
eclipseResultDefinition.setPorosityModel( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
||||
eclipseResultDefinition.setResultVariable( stimPlanModel->eclipseResultVariable( curveProperty ) );
|
||||
|
||||
eclipseResultDefinition.loadResult();
|
||||
|
||||
if ( stimPlanModel->eclipseResultCategory( curveProperty ) != RiaDefines::ResultCatType::DYNAMIC_NATIVE ||
|
||||
curveProperty == RiaDefines::CurveProperty::INITIAL_PRESSURE )
|
||||
{
|
||||
timeStep = 0;
|
||||
}
|
||||
|
||||
cvf::ref<RigResultAccessor> resAcc =
|
||||
RigResultAccessorFactory::createFromResultDefinition( eclipseCase->eclipseCaseData(),
|
||||
0,
|
||||
timeStep,
|
||||
&eclipseResultDefinition );
|
||||
|
||||
if ( resAcc.notNull() )
|
||||
{
|
||||
eclExtractor.curveData( resAcc.p(), &values );
|
||||
}
|
||||
else
|
||||
{
|
||||
RiaLogging::error( QString( "No result found for %1" ).arg( eclipseResultDefinition.resultVariable() ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
double overburdenHeight = stimPlanModel->overburdenHeight();
|
||||
if ( overburdenHeight > 0.0 )
|
||||
{
|
||||
addOverburden( curveProperty, stimPlanModel, tvDepthValues, measuredDepthValues, values );
|
||||
}
|
||||
|
||||
double underburdenHeight = stimPlanModel->underburdenHeight();
|
||||
if ( underburdenHeight > 0.0 )
|
||||
{
|
||||
addUnderburden( curveProperty, stimPlanModel, tvDepthValues, measuredDepthValues, values );
|
||||
}
|
||||
|
||||
if ( hasMissingValues( values ) )
|
||||
{
|
||||
if ( stimPlanModel->missingValueStrategy( curveProperty ) == RimStimPlanModel::MissingValueStrategy::DEFAULT_VALUE )
|
||||
{
|
||||
// Try to locate a backup accessor (e.g. PORO_1 for PORO)
|
||||
cvf::ref<RigResultAccessor> backupResAcc = findMissingValuesAccessor( eclipseCase->eclipseCaseData(),
|
||||
eclipseCase->inputPropertyCollection(),
|
||||
0,
|
||||
timeStep,
|
||||
&eclipseResultDefinition );
|
||||
|
||||
if ( backupResAcc.notNull() )
|
||||
{
|
||||
RiaLogging::info( QString( "Reading missing values from input properties for %1." )
|
||||
.arg( eclipseResultDefinition.resultVariable() ) );
|
||||
std::vector<double> replacementValues;
|
||||
eclExtractor.curveData( backupResAcc.p(), &replacementValues );
|
||||
|
||||
double overburdenHeight = stimPlanModel->overburdenHeight();
|
||||
if ( overburdenHeight > 0.0 )
|
||||
{
|
||||
double defaultOverburdenValue = std::numeric_limits<double>::infinity();
|
||||
if ( stimPlanModel->burdenStrategy( curveProperty ) == RimStimPlanModel::BurdenStrategy::DEFAULT_VALUE )
|
||||
{
|
||||
defaultOverburdenValue = stimPlanModel->getDefaultForMissingOverburdenValue( curveProperty );
|
||||
}
|
||||
|
||||
replacementValues.insert( replacementValues.begin(), defaultOverburdenValue );
|
||||
replacementValues.insert( replacementValues.begin(), defaultOverburdenValue );
|
||||
}
|
||||
|
||||
double underburdenHeight = stimPlanModel->underburdenHeight();
|
||||
if ( underburdenHeight > 0.0 )
|
||||
{
|
||||
double defaultUnderburdenValue = std::numeric_limits<double>::infinity();
|
||||
if ( stimPlanModel->burdenStrategy( curveProperty ) == RimStimPlanModel::BurdenStrategy::DEFAULT_VALUE )
|
||||
{
|
||||
defaultUnderburdenValue = stimPlanModel->getDefaultForMissingUnderburdenValue( curveProperty );
|
||||
}
|
||||
|
||||
replacementValues.push_back( defaultUnderburdenValue );
|
||||
replacementValues.push_back( defaultUnderburdenValue );
|
||||
}
|
||||
|
||||
replaceMissingValues( values, replacementValues );
|
||||
}
|
||||
|
||||
// If the backup accessor is not found, or does not provide all the missing values:
|
||||
// use default value from the fracture model
|
||||
if ( !backupResAcc.notNull() || hasMissingValues( values ) )
|
||||
{
|
||||
double defaultValue = stimPlanModel->getDefaultForMissingValue( curveProperty );
|
||||
replaceMissingValues( values, defaultValue );
|
||||
}
|
||||
}
|
||||
else if ( stimPlanModel->missingValueStrategy( curveProperty ) ==
|
||||
RimStimPlanModel::MissingValueStrategy::LINEAR_INTERPOLATION )
|
||||
{
|
||||
RiaLogging::info(
|
||||
QString( "Interpolating missing values for %1" ).arg( eclipseResultDefinition.resultVariable() ) );
|
||||
RiaInterpolationTools::interpolateMissingValues( measuredDepthValues, values );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the missing data from other curve
|
||||
RiaDefines::CurveProperty replacementProperty =
|
||||
stimPlanModel->getDefaultPropertyForMissingValues( curveProperty );
|
||||
|
||||
std::vector<double> initialValues;
|
||||
std::vector<double> initialMds;
|
||||
std::vector<double> initialTvds;
|
||||
double initialRkbDiff = -1.0;
|
||||
calculate( replacementProperty, stimPlanModel, timeStep, initialValues, initialMds, initialTvds, initialRkbDiff );
|
||||
|
||||
if ( initialValues.empty() )
|
||||
{
|
||||
RiaLogging::error( QString( "Empty replacement data found for fracture model curve." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
CVF_ASSERT( values.size() == initialValues.size() );
|
||||
replaceMissingValues( values, initialValues );
|
||||
}
|
||||
}
|
||||
|
||||
if ( stimPlanModel->isScaledByNetToGross( curveProperty ) )
|
||||
{
|
||||
std::vector<double> netToGross =
|
||||
m_stimPlanModelCalculator->extractValues( RiaDefines::CurveProperty::NET_TO_GROSS, timeStep );
|
||||
|
||||
scaleByNetToGross( stimPlanModel, netToGross, values );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimStimPlanModelWellLogCalculator::hasMissingValues( const std::vector<double>& values )
|
||||
{
|
||||
for ( double v : values )
|
||||
{
|
||||
if ( v == std::numeric_limits<double>::infinity() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelWellLogCalculator::replaceMissingValues( std::vector<double>& values, double defaultValue )
|
||||
{
|
||||
for ( double& v : values )
|
||||
{
|
||||
if ( v == std::numeric_limits<double>::infinity() )
|
||||
{
|
||||
v = defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelWellLogCalculator::replaceMissingValues( std::vector<double>& values,
|
||||
const std::vector<double>& replacementValues )
|
||||
{
|
||||
CVF_ASSERT( values.size() == replacementValues.size() );
|
||||
for ( size_t i = 0; i < values.size(); i++ )
|
||||
{
|
||||
if ( values[i] == std::numeric_limits<double>::infinity() )
|
||||
{
|
||||
values[i] = replacementValues[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::ref<RigResultAccessor>
|
||||
RimStimPlanModelWellLogCalculator::findMissingValuesAccessor( RigEclipseCaseData* caseData,
|
||||
RimEclipseInputPropertyCollection* inputPropertyCollection,
|
||||
int gridIndex,
|
||||
int timeStepIndex,
|
||||
RimEclipseResultDefinition* eclipseResultDefinition ) const
|
||||
{
|
||||
QString resultName = eclipseResultDefinition->resultVariable();
|
||||
|
||||
for ( RimEclipseInputProperty* inputProperty : inputPropertyCollection->inputProperties() )
|
||||
{
|
||||
// Look for input properties starting with the same name as result definition
|
||||
if ( inputProperty && inputProperty->resultName().startsWith( resultName ) )
|
||||
{
|
||||
RiaLogging::info(
|
||||
QString( "Found missing values result for %1: %2" ).arg( resultName ).arg( inputProperty->resultName() ) );
|
||||
|
||||
RigEclipseResultAddress resultAddress( RiaDefines::ResultCatType::INPUT_PROPERTY, inputProperty->resultName() );
|
||||
caseData->results( eclipseResultDefinition->porosityModel() )->ensureKnownResultLoaded( resultAddress );
|
||||
cvf::ref<RigResultAccessor> resAcc =
|
||||
RigResultAccessorFactory::createFromResultAddress( caseData,
|
||||
gridIndex,
|
||||
eclipseResultDefinition->porosityModel(),
|
||||
timeStepIndex,
|
||||
resultAddress );
|
||||
|
||||
return resAcc;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelWellLogCalculator::addOverburden( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
std::vector<double>& tvDepthValues,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& values ) const
|
||||
{
|
||||
if ( !values.empty() )
|
||||
{
|
||||
double overburdenHeight = stimPlanModel->overburdenHeight();
|
||||
double tvdOverburdenBottom = tvDepthValues[0];
|
||||
double tvdOverburdenTop = tvdOverburdenBottom - overburdenHeight;
|
||||
|
||||
double overburdenTopValue = std::numeric_limits<double>::infinity();
|
||||
double overburdenBottomValue = std::numeric_limits<double>::infinity();
|
||||
if ( stimPlanModel->burdenStrategy( curveProperty ) == RimStimPlanModel::BurdenStrategy::DEFAULT_VALUE )
|
||||
{
|
||||
overburdenTopValue = stimPlanModel->getDefaultForMissingOverburdenValue( curveProperty );
|
||||
overburdenBottomValue = overburdenTopValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
double gradient = stimPlanModel->getOverburdenGradient( curveProperty );
|
||||
overburdenBottomValue = values[0];
|
||||
overburdenTopValue = overburdenBottomValue + gradient * -overburdenHeight;
|
||||
}
|
||||
|
||||
// Prepend the new "fake" depth for start of overburden
|
||||
tvDepthValues.insert( tvDepthValues.begin(), tvdOverburdenBottom );
|
||||
tvDepthValues.insert( tvDepthValues.begin(), tvdOverburdenTop );
|
||||
|
||||
// TODO: this is not always correct
|
||||
double mdTop = measuredDepthValues[0];
|
||||
measuredDepthValues.insert( measuredDepthValues.begin(), mdTop );
|
||||
measuredDepthValues.insert( measuredDepthValues.begin(), mdTop - overburdenHeight );
|
||||
|
||||
values.insert( values.begin(), overburdenBottomValue );
|
||||
values.insert( values.begin(), overburdenTopValue );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelWellLogCalculator::addUnderburden( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
std::vector<double>& tvDepthValues,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& values ) const
|
||||
{
|
||||
if ( !values.empty() )
|
||||
{
|
||||
size_t lastIndex = tvDepthValues.size() - 1;
|
||||
|
||||
double underburdenHeight = stimPlanModel->underburdenHeight();
|
||||
double tvdUnderburdenTop = tvDepthValues[lastIndex];
|
||||
double tvdUnderburdenBottom = tvdUnderburdenTop + underburdenHeight;
|
||||
|
||||
double underburdenTopValue = std::numeric_limits<double>::infinity();
|
||||
double underburdenBottomValue = std::numeric_limits<double>::infinity();
|
||||
if ( stimPlanModel->burdenStrategy( curveProperty ) == RimStimPlanModel::BurdenStrategy::DEFAULT_VALUE )
|
||||
{
|
||||
underburdenTopValue = stimPlanModel->getDefaultForMissingUnderburdenValue( curveProperty );
|
||||
underburdenBottomValue = underburdenTopValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
double gradient = stimPlanModel->getUnderburdenGradient( curveProperty );
|
||||
underburdenTopValue = values[lastIndex];
|
||||
underburdenBottomValue = underburdenTopValue + gradient * underburdenHeight;
|
||||
}
|
||||
|
||||
// Append the new "fake" depth for start of underburden
|
||||
tvDepthValues.push_back( tvdUnderburdenTop );
|
||||
tvDepthValues.push_back( tvdUnderburdenBottom );
|
||||
|
||||
// Append the new "fake" md
|
||||
// TODO: check if this is correct???
|
||||
double mdBottom = measuredDepthValues[lastIndex];
|
||||
measuredDepthValues.push_back( mdBottom );
|
||||
measuredDepthValues.push_back( mdBottom + underburdenHeight );
|
||||
|
||||
values.push_back( underburdenTopValue );
|
||||
values.push_back( underburdenBottomValue );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimStimPlanModelWellLogCalculator::scaleByNetToGross( const RimStimPlanModel* stimPlanModel,
|
||||
const std::vector<double>& netToGross,
|
||||
std::vector<double>& values )
|
||||
{
|
||||
if ( netToGross.size() != values.size() )
|
||||
{
|
||||
RiaLogging::error( QString( "Different sizes for net to gross calculation." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
double netToGrossCutoff = 1.0;
|
||||
bool useNetToGross = false;
|
||||
|
||||
if ( stimPlanModel->stimPlanModelTemplate() && stimPlanModel->stimPlanModelTemplate()->nonNetLayers() )
|
||||
{
|
||||
netToGrossCutoff = stimPlanModel->stimPlanModelTemplate()->nonNetLayers()->cutOff();
|
||||
useNetToGross = !netToGross.empty() && stimPlanModel->stimPlanModelTemplate()->nonNetLayers()->isChecked();
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < values.size(); i++ )
|
||||
{
|
||||
double ntg = netToGross[i];
|
||||
if ( useNetToGross && ntg <= netToGrossCutoff )
|
||||
{
|
||||
values[i] = ntg * values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "RimStimPlanModelCalculator.h"
|
||||
#include "RimStimPlanModelPropertyCalculator.h"
|
||||
|
||||
#include "RiaStimPlanModelDefines.h"
|
||||
|
||||
#include "cvfObject.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RigEclipseCaseData;
|
||||
class RimEclipseInputPropertyCollection;
|
||||
class RimEclipseResultDefinition;
|
||||
class RigResultAccessor;
|
||||
|
||||
class RimStimPlanModelWellLogCalculator : public RimStimPlanModelPropertyCalculator
|
||||
{
|
||||
public:
|
||||
RimStimPlanModelWellLogCalculator( RimStimPlanModelCalculator* stimPlanModelCalculator );
|
||||
|
||||
bool calculate( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
int timeStep,
|
||||
std::vector<double>& values,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& tvDepthValues,
|
||||
double& rkbDiff ) const override;
|
||||
|
||||
bool isMatching( RiaDefines::CurveProperty curveProperty ) const override;
|
||||
|
||||
protected:
|
||||
static bool hasMissingValues( const std::vector<double>& values );
|
||||
static void replaceMissingValues( std::vector<double>& values, double defaultValue );
|
||||
static void replaceMissingValues( std::vector<double>& values, const std::vector<double>& replacementValues );
|
||||
cvf::ref<RigResultAccessor> findMissingValuesAccessor( RigEclipseCaseData* caseData,
|
||||
RimEclipseInputPropertyCollection* inputPropertyCollection,
|
||||
int gridIndex,
|
||||
int timeStepIndex,
|
||||
RimEclipseResultDefinition* eclipseResultDefinition ) const;
|
||||
|
||||
void addOverburden( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
std::vector<double>& tvDepthValues,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& values ) const;
|
||||
|
||||
void addUnderburden( RiaDefines::CurveProperty curveProperty,
|
||||
const RimStimPlanModel* stimPlanModel,
|
||||
std::vector<double>& tvDepthValues,
|
||||
std::vector<double>& measuredDepthValues,
|
||||
std::vector<double>& values ) const;
|
||||
|
||||
static void scaleByNetToGross( const RimStimPlanModel* stimPlanModel,
|
||||
const std::vector<double>& netToGross,
|
||||
std::vector<double>& values );
|
||||
|
||||
RimStimPlanModelCalculator* m_stimPlanModelCalculator;
|
||||
};
|
||||
Reference in New Issue
Block a user