Rename ApplicationCode to ApplicationLibCode

This commit is contained in:
Gaute Lindkvist
2021-01-06 14:55:29 +01:00
parent 751df1a421
commit 81699db187
3242 changed files with 0 additions and 0 deletions

View File

@@ -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 )

View File

@@ -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();
}

View File

@@ -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;
};

View File

@@ -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();
}

View File

@@ -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;
};

View File

@@ -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 );
}
}

View File

@@ -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;
};

View File

@@ -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();
}

View File

@@ -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;
};

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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();
}
}

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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 );
}
}

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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();
}

View File

@@ -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;
};

View File

@@ -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;
};

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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();
}

View File

@@ -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;
};

View File

@@ -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();
}
}
}

View File

@@ -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
};

View File

@@ -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];
}
}
}

View File

@@ -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;
};