mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-09 23:16:00 -06:00
#1427 Add simulation Well and branch index to well log extraction curve and make the extraction work in those cases.
This commit is contained in:
parent
63b07b1152
commit
1f7c357b67
@ -28,6 +28,9 @@
|
||||
#include "RigGeoMechCaseData.h"
|
||||
#include "RigGeoMechWellLogExtractor.h"
|
||||
#include "RigResultAccessorFactory.h"
|
||||
#include "RigSimulationWellCenterLineCalculator.h"
|
||||
#include "RigSimulationWellCoordsAndMD.h"
|
||||
#include "RigSingleWellResultsData.h"
|
||||
#include "RigWellLogCurveData.h"
|
||||
#include "RigWellPath.h"
|
||||
|
||||
@ -38,6 +41,7 @@
|
||||
#include "RimGeoMechCase.h"
|
||||
#include "RimGeoMechResultDefinition.h"
|
||||
#include "RimGeoMechView.h"
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimOilField.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimTools.h"
|
||||
@ -63,6 +67,19 @@
|
||||
|
||||
CAF_PDM_SOURCE_INIT(RimWellLogExtractionCurve, "RimWellLogExtractionCurve");
|
||||
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template<>
|
||||
void AppEnum< RimWellLogExtractionCurve::TrajectoryType >::setUp()
|
||||
{
|
||||
addItem(RimWellLogExtractionCurve::WELL_PATH, "WELL_PATH", "Well Path");
|
||||
addItem(RimWellLogExtractionCurve::SIMULATION_WELL, "SIMULATION_WELL", "Simulation Well");
|
||||
setDefault(RimWellLogExtractionCurve::WELL_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -70,17 +87,22 @@ RimWellLogExtractionCurve::RimWellLogExtractionCurve()
|
||||
{
|
||||
CAF_PDM_InitObject("Well Log Curve", "", "", "");
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_wellPath, "CurveWellPath", "Well Path", "", "", "");
|
||||
CAF_PDM_InitFieldNoDefault(&m_trajectoryType, "TrajectoryType", "Trajectory", "", "", "");
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_wellPath, "CurveWellPath", " ", "", "", "");
|
||||
m_wellPath.uiCapability()->setUiTreeChildrenHidden(true);
|
||||
//m_wellPath.uiCapability()->setUiHidden(true);
|
||||
|
||||
CAF_PDM_InitField(&m_simWellName, "SimulationWellName", QString("None"), " ", "", "", "");
|
||||
CAF_PDM_InitField(&m_branchIndex, "Branch", 0, " ", "", "", "");
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_case, "CurveCase", "Case", "", "", "");
|
||||
m_case.uiCapability()->setUiTreeChildrenHidden(true);
|
||||
//m_case.uiCapability()->setUiHidden(true);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_eclipseResultDefinition, "CurveEclipseResult", "", "", "", "");
|
||||
m_eclipseResultDefinition.uiCapability()->setUiHidden(true);
|
||||
m_eclipseResultDefinition.uiCapability()->setUiTreeChildrenHidden(true);
|
||||
m_eclipseResultDefinition = new RimEclipseResultDefinition;
|
||||
m_eclipseResultDefinition->findField("MResultType")->uiCapability()->setUiName("Result Type");
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_geomResultDefinition, "CurveGeomechResult", "", "", "", "");
|
||||
m_geomResultDefinition.uiCapability()->setUiHidden(true);
|
||||
@ -102,6 +124,8 @@ RimWellLogExtractionCurve::RimWellLogExtractionCurve()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellLogExtractionCurve::~RimWellLogExtractionCurve()
|
||||
{
|
||||
clearGeneratedSimWellPaths();
|
||||
|
||||
delete m_geomResultDefinition;
|
||||
delete m_eclipseResultDefinition;
|
||||
}
|
||||
@ -129,6 +153,7 @@ RimWellPath* RimWellLogExtractionCurve::wellPath() const
|
||||
void RimWellLogExtractionCurve::setCase(RimCase* rimCase)
|
||||
{
|
||||
m_case = rimCase;
|
||||
clearGeneratedSimWellPaths();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -165,6 +190,8 @@ void RimWellLogExtractionCurve::setPropertiesFromView(RimView* view)
|
||||
m_geomResultDefinition->setResultAddress(geoMechView->cellResultResultDefinition()->resultAddress());
|
||||
m_timeStep = geoMechView->currentTimeStep();
|
||||
}
|
||||
|
||||
clearGeneratedSimWellPaths();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -181,6 +208,23 @@ void RimWellLogExtractionCurve::clampTimestep()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogExtractionCurve::clampBranchIndex()
|
||||
{
|
||||
int branchCount = static_cast<int>(m_generatedSimulationWellPathBranches.size());
|
||||
if ( branchCount > 0 )
|
||||
{
|
||||
if ( m_branchIndex >= branchCount ) m_branchIndex = branchCount - 1;
|
||||
else if ( m_branchIndex < 0 ) m_branchIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_branchIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -191,6 +235,11 @@ void RimWellLogExtractionCurve::fieldChangedByUi(const caf::PdmFieldHandle* chan
|
||||
if (changedField == &m_case)
|
||||
{
|
||||
clampTimestep();
|
||||
|
||||
auto wellNameSet = findSortedWellNames();
|
||||
if (!wellNameSet.count(m_simWellName())) m_simWellName = "None";
|
||||
|
||||
clearGeneratedSimWellPaths();
|
||||
|
||||
this->loadDataAndUpdate();
|
||||
}
|
||||
@ -198,6 +247,17 @@ void RimWellLogExtractionCurve::fieldChangedByUi(const caf::PdmFieldHandle* chan
|
||||
{
|
||||
this->loadDataAndUpdate();
|
||||
}
|
||||
else if (changedField == &m_simWellName)
|
||||
{
|
||||
clearGeneratedSimWellPaths();
|
||||
|
||||
this->loadDataAndUpdate();
|
||||
}
|
||||
else if (changedField == &m_trajectoryType ||
|
||||
changedField == &m_branchIndex)
|
||||
{
|
||||
this->loadDataAndUpdate();
|
||||
}
|
||||
else if (changedField == &m_timeStep)
|
||||
{
|
||||
this->loadDataAndUpdate();
|
||||
@ -230,12 +290,27 @@ void RimWellLogExtractionCurve::onLoadDataAndUpdate()
|
||||
m_eclipseResultDefinition->setEclipseCase(eclipseCase);
|
||||
m_geomResultDefinition->setGeoMechCase(geomCase);
|
||||
|
||||
RimWellLogPlotCollection* wellLogCollection = NULL;
|
||||
this->firstAncestorOrThisOfType(wellLogCollection);
|
||||
CVF_ASSERT(wellLogCollection);
|
||||
if (!wellLogCollection) return;
|
||||
updateGeneratedSimulationWellpath();
|
||||
clampBranchIndex();
|
||||
|
||||
cvf::ref<RigEclipseWellLogExtractor> eclExtractor = wellLogCollection->findOrCreateExtractor(m_wellPath, eclipseCase);
|
||||
RimWellLogPlotCollection* wellLogCollection;
|
||||
this->firstAncestorOrThisOfTypeAsserted(wellLogCollection);
|
||||
|
||||
cvf::ref<RigEclipseWellLogExtractor> eclExtractor;
|
||||
if ( m_trajectoryType == WELL_PATH )
|
||||
{
|
||||
eclExtractor = wellLogCollection->findOrCreateExtractor(m_wellPath, eclipseCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_branchIndex >= 0 && m_branchIndex < m_generatedSimulationWellPathBranches.size() )
|
||||
{
|
||||
eclExtractor = wellLogCollection->findOrCreateSimWellExtractor(m_simWellName,
|
||||
eclipseCase->caseUserDescription(),
|
||||
m_generatedSimulationWellPathBranches[m_branchIndex].p(),
|
||||
eclipseCase->eclipseCaseData());
|
||||
}
|
||||
}
|
||||
cvf::ref<RigGeoMechWellLogExtractor> geomExtractor = wellLogCollection->findOrCreateExtractor(m_wellPath, geomCase);
|
||||
|
||||
std::vector<double> values;
|
||||
@ -321,6 +396,94 @@ void RimWellLogExtractionCurve::onLoadDataAndUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::set<QString> RimWellLogExtractionCurve::findSortedWellNames()
|
||||
{
|
||||
std::set<QString> sortedWellNames;
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case.value());
|
||||
|
||||
if ( eclipseCase && eclipseCase->eclipseCaseData() )
|
||||
{
|
||||
const cvf::Collection<RigSingleWellResultsData>& wellRes = eclipseCase->eclipseCaseData()->wellResults();
|
||||
|
||||
for ( size_t wIdx = 0; wIdx < wellRes.size(); ++wIdx )
|
||||
{
|
||||
sortedWellNames.insert(wellRes[wIdx]->m_wellName);
|
||||
}
|
||||
}
|
||||
|
||||
return sortedWellNames;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogExtractionCurve::updateGeneratedSimulationWellpath()
|
||||
{
|
||||
if (m_generatedSimulationWellPathBranches.size()) return; // Already created. Nothing to do
|
||||
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case.value());
|
||||
|
||||
if (!(!m_simWellName().isEmpty() && m_simWellName() != "None" && eclipseCase && eclipseCase->eclipseCaseData()))
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
RigEclipseCaseData* eclCaseData = eclipseCase->eclipseCaseData();
|
||||
const RigSingleWellResultsData* wellResults = eclCaseData->findWellResult(m_simWellName());
|
||||
|
||||
if (!wellResults) return;
|
||||
|
||||
std::vector< std::vector <cvf::Vec3d> > pipeBranchesCLCoords;
|
||||
std::vector< std::vector <RigWellResultPoint> > pipeBranchesCellIds;
|
||||
|
||||
RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellFrame(eclCaseData,
|
||||
wellResults,
|
||||
-1,
|
||||
true,
|
||||
true,
|
||||
pipeBranchesCLCoords,
|
||||
pipeBranchesCellIds);
|
||||
|
||||
|
||||
for ( size_t brIdx = 0; brIdx < pipeBranchesCLCoords.size(); ++brIdx )
|
||||
{
|
||||
auto wellMdCalculator = RigSimulationWellCoordsAndMD(pipeBranchesCLCoords[brIdx]); // Todo, branch index
|
||||
|
||||
cvf::ref<RigWellPath> newWellPath = new RigWellPath();
|
||||
newWellPath->m_measuredDepths = wellMdCalculator.measuredDepths();
|
||||
newWellPath->m_wellPathPoints = wellMdCalculator.wellPathPoints();
|
||||
|
||||
m_generatedSimulationWellPathBranches.push_back(newWellPath.p() );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Clean up existing generated well paths
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogExtractionCurve::clearGeneratedSimWellPaths()
|
||||
{
|
||||
RimWellLogPlotCollection* wellLogCollection = nullptr;
|
||||
|
||||
// Need to use this approach, and not firstAnchestor because the curve might not be inside the hierarchy when deleted.
|
||||
|
||||
RimProject * proj = RiaApplication::instance()->project();
|
||||
if (proj && proj->mainPlotCollection() ) wellLogCollection = proj->mainPlotCollection()->wellLogPlotCollection();
|
||||
|
||||
if (!wellLogCollection) return;
|
||||
|
||||
for ( size_t wpIdx = 0; wpIdx < m_generatedSimulationWellPathBranches.size(); ++wpIdx )
|
||||
{
|
||||
wellLogCollection->removeExtractors(m_generatedSimulationWellPathBranches[wpIdx].p());
|
||||
}
|
||||
|
||||
m_generatedSimulationWellPathBranches.clear();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -335,19 +498,13 @@ QList<caf::PdmOptionItemInfo> RimWellLogExtractionCurve::calculateValueOptions(c
|
||||
{
|
||||
RimTools::wellPathOptionItems(&options);
|
||||
|
||||
if (options.size() > 0)
|
||||
{
|
||||
options.push_front(caf::PdmOptionItemInfo("None", nullptr));
|
||||
}
|
||||
options.push_front(caf::PdmOptionItemInfo("None", nullptr));
|
||||
}
|
||||
else if (fieldNeedingOptions == &m_case)
|
||||
{
|
||||
RimTools::caseOptionItems(&options);
|
||||
|
||||
if (options.size() > 0)
|
||||
{
|
||||
options.push_front(caf::PdmOptionItemInfo("None", nullptr));
|
||||
}
|
||||
options.push_front(caf::PdmOptionItemInfo("None", nullptr));
|
||||
}
|
||||
else if (fieldNeedingOptions == &m_timeStep)
|
||||
{
|
||||
@ -363,7 +520,37 @@ QList<caf::PdmOptionItemInfo> RimWellLogExtractionCurve::calculateValueOptions(c
|
||||
options.push_back(caf::PdmOptionItemInfo(timeStepNames[i], i));
|
||||
}
|
||||
}
|
||||
else if (fieldNeedingOptions == &m_simWellName)
|
||||
{
|
||||
std::set<QString> sortedWellNames = this->findSortedWellNames();
|
||||
|
||||
QIcon simWellIcon(":/Well.png");
|
||||
for ( const QString& wname: sortedWellNames )
|
||||
{
|
||||
options.push_back(caf::PdmOptionItemInfo(wname, wname, false, simWellIcon));
|
||||
}
|
||||
|
||||
if ( options.size() == 0 )
|
||||
{
|
||||
options.push_front(caf::PdmOptionItemInfo("None", "None"));
|
||||
}
|
||||
}
|
||||
else if (fieldNeedingOptions == &m_branchIndex)
|
||||
{
|
||||
updateGeneratedSimulationWellpath();
|
||||
|
||||
size_t branchCount = m_generatedSimulationWellPathBranches.size();
|
||||
|
||||
for ( int bIdx = 0; bIdx < branchCount; ++bIdx)
|
||||
{
|
||||
options.push_back(caf::PdmOptionItemInfo("Branch " + QString::number(bIdx + 1), QVariant::fromValue(bIdx) ));
|
||||
}
|
||||
|
||||
if (options.size() == 0)
|
||||
{
|
||||
options.push_front(caf::PdmOptionItemInfo("None", -1));
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -377,25 +564,39 @@ void RimWellLogExtractionCurve::defineUiOrdering(QString uiConfigName, caf::PdmU
|
||||
|
||||
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup("Curve Data");
|
||||
|
||||
curveDataGroup->add(&m_wellPath);
|
||||
curveDataGroup->add(&m_case);
|
||||
|
||||
|
||||
RimGeoMechCase* geomCase = dynamic_cast<RimGeoMechCase*>(m_case.value());
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case.value());
|
||||
|
||||
curveDataGroup->add(&m_trajectoryType);
|
||||
if (m_trajectoryType() == WELL_PATH)
|
||||
{
|
||||
curveDataGroup->add(&m_wellPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
curveDataGroup->add(&m_simWellName);
|
||||
if ( m_generatedSimulationWellPathBranches.size() > 1 )
|
||||
{
|
||||
curveDataGroup->add(&m_branchIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (eclipseCase)
|
||||
{
|
||||
m_eclipseResultDefinition->uiOrdering(uiConfigName, *curveDataGroup);
|
||||
|
||||
if (m_eclipseResultDefinition->hasDynamicResult())
|
||||
{
|
||||
curveDataGroup->add(&m_timeStep);
|
||||
}
|
||||
}
|
||||
else if (geomCase)
|
||||
{
|
||||
m_geomResultDefinition->uiOrdering(uiConfigName, *curveDataGroup);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if ( (eclipseCase && m_eclipseResultDefinition->hasDynamicResult())
|
||||
|| geomCase)
|
||||
{
|
||||
curveDataGroup->add(&m_timeStep);
|
||||
}
|
||||
|
||||
@ -471,9 +672,11 @@ QString RimWellLogExtractionCurve::createCurveAutoName()
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case.value());
|
||||
QString generatedCurveName;
|
||||
|
||||
if (m_addWellNameToCurveName && m_wellPath)
|
||||
if (m_addWellNameToCurveName )
|
||||
{
|
||||
generatedCurveName += wellName();
|
||||
|
||||
// Todo: Branch
|
||||
}
|
||||
|
||||
if (m_addCaseNameToCurveName && m_case())
|
||||
@ -578,13 +781,20 @@ QString RimWellLogExtractionCurve::wellLogChannelName() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellLogExtractionCurve::wellName() const
|
||||
{
|
||||
if (m_wellPath)
|
||||
if ( m_trajectoryType() == WELL_PATH )
|
||||
{
|
||||
return m_wellPath->name();
|
||||
if ( m_wellPath )
|
||||
{
|
||||
return m_wellPath->name();
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString();
|
||||
return m_simWellName;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,12 +23,14 @@
|
||||
|
||||
#include "cafPdmPtrField.h"
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cvfCollection.h"
|
||||
|
||||
class RimCase;
|
||||
class RimEclipseResultDefinition;
|
||||
class RimGeoMechResultDefinition;
|
||||
class RimView;
|
||||
class RimWellPath;
|
||||
class RigWellPath;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
@ -41,6 +43,8 @@ public:
|
||||
RimWellLogExtractionCurve();
|
||||
virtual ~RimWellLogExtractionCurve();
|
||||
|
||||
enum TrajectoryType { WELL_PATH, SIMULATION_WELL};
|
||||
|
||||
void setWellPath(RimWellPath* wellPath);
|
||||
RimWellPath* wellPath() const;
|
||||
|
||||
@ -73,9 +77,16 @@ protected:
|
||||
private:
|
||||
void setLogScaleFromSelectedResult();
|
||||
void clampTimestep();
|
||||
void clampBranchIndex();
|
||||
std::set<QString> findSortedWellNames();
|
||||
void updateGeneratedSimulationWellpath();
|
||||
void clearGeneratedSimWellPaths();
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimWellPath*> m_wellPath;
|
||||
caf::PdmField<caf::AppEnum<TrajectoryType> > m_trajectoryType;
|
||||
caf::PdmField<QString> m_simWellName;
|
||||
caf::PdmField<int> m_branchIndex;
|
||||
caf::PdmPtrField<RimCase*> m_case;
|
||||
caf::PdmChildField<RimEclipseResultDefinition*> m_eclipseResultDefinition;
|
||||
caf::PdmChildField<RimGeoMechResultDefinition*> m_geomResultDefinition;
|
||||
@ -86,5 +97,7 @@ private:
|
||||
caf::PdmField<bool> m_addWellNameToCurveName;
|
||||
caf::PdmField<bool> m_addTimestepToCurveName;
|
||||
caf::PdmField<bool> m_addDateToCurveName;
|
||||
|
||||
cvf::Collection<RigWellPath> m_generatedSimulationWellPathBranches;
|
||||
};
|
||||
|
||||
|
@ -52,6 +52,34 @@ RimWellLogPlotCollection::~RimWellLogPlotCollection()
|
||||
wellLogPlots.deleteAllChildObjects();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigEclipseWellLogExtractor* RimWellLogPlotCollection::findOrCreateSimWellExtractor(const QString& simWellName,
|
||||
const QString& caseUserDescription,
|
||||
const RigWellPath* wellPathGeom,
|
||||
const RigEclipseCaseData* eclCaseData)
|
||||
{
|
||||
if (!(wellPathGeom && eclCaseData))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (size_t exIdx = 0; exIdx < m_extractors.size(); ++exIdx)
|
||||
{
|
||||
if (m_extractors[exIdx]->caseData() == eclCaseData && m_extractors[exIdx]->wellPathData() == wellPathGeom)
|
||||
{
|
||||
return m_extractors[exIdx].p();
|
||||
}
|
||||
}
|
||||
|
||||
std::string errorIdName = (simWellName + " " + caseUserDescription).toStdString();
|
||||
cvf::ref<RigEclipseWellLogExtractor> extractor = new RigEclipseWellLogExtractor(eclCaseData, wellPathGeom, errorIdName);
|
||||
m_extractors.push_back(extractor.p());
|
||||
|
||||
return extractor.p();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -45,7 +45,12 @@ class RimWellLogPlotCollection : public caf::PdmObject
|
||||
public:
|
||||
RimWellLogPlotCollection();
|
||||
virtual ~RimWellLogPlotCollection();
|
||||
|
||||
|
||||
RigEclipseWellLogExtractor* findOrCreateSimWellExtractor(const QString& simWellName,
|
||||
const QString& caseUserDescription,
|
||||
const RigWellPath* wellPathGeom,
|
||||
const RigEclipseCaseData* eclCaseData);
|
||||
|
||||
RigEclipseWellLogExtractor* findOrCreateExtractor(RimWellPath* wellPath, RimEclipseCase* eclCase);
|
||||
RigGeoMechWellLogExtractor* findOrCreateExtractor(RimWellPath* wellPath, RimGeoMechCase* eclCase);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user