#1976 RFT/PLT Plot. Associate sim well and well path. RFT branch index impl

This commit is contained in:
Bjørn Erik Jensen 2017-10-11 13:52:29 +02:00
parent 00985b00c3
commit dcb1c40414
8 changed files with 321 additions and 39 deletions

View File

@ -65,6 +65,9 @@
#include "RiaColorTables.h"
#include "RifReaderEclipseRft.h"
#include "RimWellLogRftCurve.h"
#include "RigWellPath.h"
#include "RimWellLogPlotCollection.h"
#include "RimMainPlotCollection.h"
#include <tuple>
CAF_PDM_SOURCE_INIT(RimWellRftPlot, "WellRftPlot");
@ -93,7 +96,6 @@ RimWellRftPlot::RimWellRftPlot()
CAF_PDM_InitFieldNoDefault(&m_wellName, "WellName", "WellName", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_branchIndex, "BranchIndex", "BranchIndex", "", "", "");
m_branchIndex = 0;
CAF_PDM_InitFieldNoDefault(&m_selectedSources, "Sources", "Sources", "", "", "");
m_selectedSources.uiCapability()->setUiEditorTypeName(caf::PdmUiTreeSelectionEditor::uiEditorTypeName());
@ -351,7 +353,7 @@ std::vector<RimWellLogFileChannel*> RimWellRftPlot::getPressureChannelsFromWellP
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEclipseResultCase* RimWellRftPlot::eclipseCaseFromCaseId(int caseId)
RimEclipseCase* RimWellRftPlot::eclipseCaseFromCaseId(int caseId)
{
const std::vector<std::tuple<RimEclipseResultCase*, bool, bool>>& eclipseCases = eclipseCasesContainingPressure(m_wellName);
auto itr = std::find_if(eclipseCases.begin(), eclipseCases.end(),
@ -461,7 +463,7 @@ std::vector<QDateTime> RimWellRftPlot::timeStepsFromRftCase(RimEclipseResultCase
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QDateTime> RimWellRftPlot::timeStepsFromGridCase(const RimEclipseResultCase* gridCase) const
std::vector<QDateTime> RimWellRftPlot::timeStepsFromGridCase(const RimEclipseCase* gridCase) const
{
auto eclipseCaseData = gridCase->eclipseCaseData();
size_t resultIndex = eclipseCaseData->results(RiaDefines::MATRIX_MODEL)->
@ -608,7 +610,7 @@ void RimWellRftPlot::updateCurvesInPlot(const std::set<std::pair<RimWellRftAddre
plotTrack->addCurve(curve);
auto rftCase = eclipseCaseFromCaseId(curveDefToAdd.first.caseId());
curve->setEclipseResultCase(rftCase);
curve->setEclipseResultCase(dynamic_cast<RimEclipseResultCase*>(rftCase));
RifEclipseRftAddress address(m_wellName, curveDefToAdd.second, RifEclipseRftAddress::PRESSURE);
curve->setRftAddress(address);
@ -795,6 +797,22 @@ QList<caf::PdmOptionItemInfo> RimWellRftPlot::calculateValueOptions(const caf::P
{
calculateValueOptionsForTimeSteps(m_wellName, options);
}
else if (fieldNeedingOptions == &m_branchIndex)
{
RimProject* proj = RiaApplication::instance()->project();
size_t branchCount = proj->simulationWellBranches(m_wellName).size();
for (int bIdx = 0; bIdx < static_cast<int>(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;
}
@ -810,11 +828,9 @@ void RimWellRftPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c
{
setDescription(QString(plotNameFormatString()).arg(m_wellName));
}
else if (changedField == &m_selectedSources)
{
syncCurvesFromUiSelection();
}
else if (changedField == &m_selectedTimeSteps)
else if (changedField == &m_selectedSources ||
changedField == &m_selectedTimeSteps ||
changedField == &m_branchIndex)
{
syncCurvesFromUiSelection();
}
@ -847,7 +863,12 @@ void RimWellRftPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
{
uiOrdering.add(&m_userName);
uiOrdering.add(&m_wellName);
uiOrdering.add(&m_branchIndex);
RimProject* proj = RiaApplication::instance()->project();
if (proj->simulationWellBranches(m_wellName).size() > 1)
{
uiOrdering.add(&m_branchIndex);
}
caf::PdmUiGroup* sourcesGroup = uiOrdering.addNewGroupWithKeyword("Sources", "Sources");
sourcesGroup->add(&m_selectedSources);
@ -863,38 +884,28 @@ void RimWellRftPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
//--------------------------------------------------------------------------------------------------
void RimWellRftPlot::calculateValueOptionsForWells(QList<caf::PdmOptionItemInfo>& options)
{
std::set<QString> wellNames;
auto project = RiaApplication::instance()->project();
RimProject * proj = RiaApplication::instance()->project();
for (RimOilField* oilField : project->oilFields)
if (proj != nullptr)
{
// RFT/Grid wells
auto gridCaseColl = oilField->analysisModels();
for (RimEclipseCase* gCase : gridCaseColl->cases())
const auto simWellNames = proj->simulationWellNames();
std::set<QString> wellNames = std::set<QString>(simWellNames.begin(), simWellNames.end());
// Observed wells
for (const auto& oilField : proj->oilFields())
{
auto gridCase = dynamic_cast<RimEclipseResultCase*>(gCase);
if (gridCase != nullptr)
auto wellPathColl = oilField->wellPathCollection();
for (const auto& wellPath : wellPathColl->wellPaths)
{
auto eclipseCaseData = gridCase->eclipseCaseData();
for (const auto& wellResult : eclipseCaseData->wellResults())
{
wellNames.insert(wellResult->m_wellName);
}
wellNames.insert(wellPath->name());
}
}
// Observed wells
auto wellPathColl = oilField->wellPathCollection();
for (const auto& wellPath : wellPathColl->wellPaths)
for (const auto& wellName : wellNames)
{
wellNames.insert(wellPath->name());
options.push_back(caf::PdmOptionItemInfo(wellName, wellName));
}
}
for (const auto& wellName : wellNames)
{
options.push_back(caf::PdmOptionItemInfo(wellName, wellName));
}
}
//--------------------------------------------------------------------------------------------------

View File

@ -24,6 +24,7 @@
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
#include "cvfCollection.h"
#include "RimWellRftAddress.h"
#include "RimPlotCurve.h"
#include <QPointer>
@ -31,6 +32,7 @@
#include <QMetaType>
class RimEclipseResultCase;
class RimEclipseCase;
class RimEclipseWell;
class RimFlowDiagSolution;
class RimTotalWellAllocationPlot;
@ -42,6 +44,7 @@ class RigSingleWellResultsData;
class RimWellLogFileChannel;
class RimWellPath;
class RimWellLogCurve;
class RigWellPath;
namespace cvf {
class Color3f;
@ -108,7 +111,7 @@ private:
std::vector<RimWellPath*> wellPathsContainingPressure(const QString& wellName) const;
std::vector<RimWellLogFileChannel*> getPressureChannelsFromWellPath(const RimWellPath* wellPath) const;
RimEclipseResultCase* eclipseCaseFromCaseId(int caseId);
RimEclipseCase* eclipseCaseFromCaseId(int caseId);
RimWellPath* wellPathForObservedData(const QString& wellName, const QDateTime& date) const;
@ -116,7 +119,7 @@ private:
std::vector<RimEclipseResultCase*> gridCasesFromEclipseCases(const std::vector<std::tuple<RimEclipseResultCase*, bool, bool>>& eclipseCases) const;
std::vector<RimEclipseResultCase*> rftCasesFromEclipseCases(const std::vector<std::tuple<RimEclipseResultCase*, bool, bool>>& eclipseCases) const;
std::vector<QDateTime> timeStepsFromRftCase(RimEclipseResultCase* gridCase) const;
std::vector<QDateTime> timeStepsFromGridCase(const RimEclipseResultCase* gridCase) const;
std::vector<QDateTime> timeStepsFromGridCase(const RimEclipseCase* gridCase) const;
std::set<std::pair<RimWellRftAddress, QDateTime>> selectedCurveDefs() const;
std::set<std::pair<RimWellRftAddress, QDateTime>> curveDefsFromCurves() const;

View File

@ -25,6 +25,9 @@
#include "RigEclipseCaseData.h"
#include "RigGridBase.h"
#include "RigSimulationWellCenterLineCalculator.h"
#include "RigSimulationWellCoordsAndMD.h"
#include "RigWellPath.h"
#include "RimCalcScript.h"
#include "RimCase.h"
@ -59,6 +62,7 @@
#include "RimRftPlotCollection.h"
#include "RimWellPathCollection.h"
#include "RimWellPathImport.h"
#include "RimWellPath.h"
#include "RiuMainWindow.h"
#include "RiuMainPlotWindow.h"
@ -834,6 +838,81 @@ RimDialogData* RimProject::dialogData() const
return m_dialogData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimEclipseCase*> RimProject::eclipseCases() const
{
std::vector<RimEclipseCase*> allCases;
for (const auto& oilField : oilFields)
{
const auto& cases = oilField->analysisModels->cases;
allCases.insert(allCases.end(), cases.begin(), cases.end());
}
return allCases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QString> RimProject::simulationWellNames() const
{
std::set<QString> wellNames;
for (RimOilField* oilField : oilFields)
{
auto analysisCaseColl = oilField->analysisModels();
for (RimEclipseCase* eclCase : analysisCaseColl->cases())
{
const auto& eclData = eclCase->eclipseCaseData();
if (eclData == nullptr) continue;
const auto names = eclData->simulationWellNames();
wellNames.insert(names.begin(), names.end());
}
}
return std::vector<QString>(wellNames.begin(), wellNames.end());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigWellPath*> RimProject::simulationWellBranches(const QString& simWellName)
{
// Find first case containing the specified simulation well
auto simCases = eclipseCases();
auto caseItr = std::find_if(simCases.begin(), simCases.end(), [&simWellName](const RimEclipseCase* eclCase) {
const auto& eclData = eclCase->eclipseCaseData();
return eclData != nullptr && eclData->hasSimulationWell(simWellName);
});
RimEclipseCase* eclipseCase = caseItr != simCases.end() ? *caseItr : nullptr;
RigEclipseCaseData* eclCaseData = eclipseCase != nullptr ? eclipseCase->eclipseCaseData() : nullptr;
return eclCaseData != nullptr ?
eclCaseData->simulationWellBranches(simWellName) :
std::vector<RigWellPath*>();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimProject::wellPathFromSimulationWell(const QString& simWellName, int branchIndex)
{
std::vector<RimWellPath*> paths;
for (const auto& oilField : oilFields())
{
auto wellPathColl = oilField->wellPathCollection();
for (const auto& path : wellPathColl->wellPaths)
{
if (QString::compare(path->relatedSimulationWell(), simWellName) == 0 &&
(branchIndex < 0 || path->relatedSimulationWellBranch() == branchIndex))
{
return path;
}
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -25,12 +25,14 @@
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmDocument.h"
#include "cvfCollection.h"
#include <vector>
class RigEclipseCaseData;
class RigGridManager;
class RigMainGrid;
class RigWellPath;
class RimCase;
class RimCommandObject;
@ -47,6 +49,7 @@ class RimView;
class RimViewLinker;
class RimViewLinkerCollection;
class RimWellPathImport;
class RimWellPath;
namespace caf
{
@ -115,7 +118,12 @@ public:
void reloadCompletionTypeResultsInAllViews();
void reloadCompletionTypeResultsForEclipseCase(RimEclipseCase* eclipseCase);
RimDialogData* dialogData() const;
RimDialogData* dialogData() const;
std::vector<RimEclipseCase*> eclipseCases() const;
std::vector<QString> simulationWellNames() const;
std::vector<RigWellPath*> simulationWellBranches(const QString& simWellName);
RimWellPath* wellPathFromSimulationWell(const QString& simWellName, int branchIndex = -1);
protected:
// Overridden methods

View File

@ -47,9 +47,15 @@
#include <QDir>
#include <QFileInfo>
#include <QMessageBox>
#include "RiaApplication.h"
CAF_PDM_SOURCE_INIT(RimWellPath, "WellPath");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const char RimWellPath::SIM_WELL_NONE_NAME[] = "None";
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -100,6 +106,9 @@ RimWellPath::RimWellPath()
CAF_PDM_InitField(&wellPathIndexInFile, "WellPathNumberInFile", -1, "Well Number in file", "", "", "");
wellPathIndexInFile.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitField(&m_simWellName, "SimWellName", QString(""), "Well", "", "", "");
CAF_PDM_InitField(&m_branchIndex, "SimBranchIndex", 0, "Branch", "", "", "");
CAF_PDM_InitField(&showWellPathLabel, "ShowWellPathLabel", true, "Show well path label", "", "", "");
CAF_PDM_InitField(&showWellPath, "ShowWellPath", true, "Show well path", "", "", "");
@ -285,6 +294,42 @@ void RimWellPath::fieldChangedByUi(const caf::PdmFieldHandle* changedField, cons
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimWellPath::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &m_simWellName)
{
RimProject* proj = RiaApplication::instance()->project();
options.push_back(caf::PdmOptionItemInfo(SIM_WELL_NONE_NAME, SIM_WELL_NONE_NAME));
for (const auto& wellName : proj->simulationWellNames())
{
options.push_back(caf::PdmOptionItemInfo(wellName, wellName));
}
}
else if (fieldNeedingOptions == &m_branchIndex)
{
RimProject* proj = RiaApplication::instance()->project();
size_t branchCount = proj->simulationWellBranches(m_simWellName).size();
if (branchCount == 0)
branchCount = 1;
int index = 0;
while(index < branchCount)
{
QString uiText = QString("Branch %1").arg(QString::number(index + 1));
options.push_back(caf::PdmOptionItemInfo(uiText, QVariant::fromValue(index)));
index++;
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -360,6 +405,16 @@ void RimWellPath::setWellPathGeometry(RigWellPath* wellPathModel)
//--------------------------------------------------------------------------------------------------
void RimWellPath::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
if (m_simWellName().isEmpty())
{
// Try to set default simulation well name
auto simWellName = tryFindSimulationWellFromWellPathName(m_name);
if (!simWellName.isEmpty())
{
m_simWellName = simWellName;
}
}
caf::PdmUiGroup* appGroup = uiOrdering.addNewGroup("Appearance");
appGroup->add(&showWellPathLabel);
appGroup->add(&wellPathColor);
@ -369,6 +424,13 @@ void RimWellPath::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiO
fileInfoGroup->add(&filepath);
fileInfoGroup->add(&wellPathIndexInFile);
caf::PdmUiGroup* simWellGroup = uiOrdering.addNewGroup("Simulation Well");
simWellGroup->add(&m_simWellName);
RimProject* proj = RiaApplication::instance()->project();
if(proj->simulationWellBranches(m_simWellName).size() > 1)
simWellGroup->add(&m_branchIndex);
caf::PdmUiGroup* ssihubGroup = uiOrdering.addNewGroup("Well Info");
ssihubGroup->add(&id);
ssihubGroup->add(&sourceSystem);
@ -388,6 +450,8 @@ void RimWellPath::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiO
{
m_datumElevation.uiCapability()->setUiHidden(true);
}
uiOrdering.skipRemainingFields(true);
}
//--------------------------------------------------------------------------------------------------
@ -556,4 +620,36 @@ RimWellPath* RimWellPath::fromFilePath(QString filePath)
return wellPath;
}
return nullptr;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QString RimWellPath::relatedSimulationWell() const
{
return m_simWellName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimWellPath::relatedSimulationWellBranch() const
{
return m_branchIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QString RimWellPath::tryFindSimulationWellFromWellPathName(const QString& wellPathName)
{
RimProject* proj = RiaApplication::instance()->project();
for (const auto& simWellName : proj->simulationWellNames())
{
if (QString::compare(simWellName, wellPathName) == 0)
{
return simWellName;
}
}
return "";
}

View File

@ -56,6 +56,9 @@ class RimWellPathFractureCollection;
class RimWellPath : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
static const char SIM_WELL_NONE_NAME[];
public:
RimWellPath();
@ -67,7 +70,8 @@ public:
virtual caf::PdmFieldHandle* objectToggleField();
virtual void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue );
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override;
QString name() const;
void setName(const QString& name);
@ -76,6 +80,9 @@ public:
caf::PdmField<QString> filepath;
caf::PdmField<int> wellPathIndexInFile; // -1 means none.
caf::PdmField<QString> m_simWellName;
caf::PdmField<int> m_branchIndex;
caf::PdmField<bool> showWellPathLabel;
caf::PdmField<bool> showWellPath;
@ -107,6 +114,10 @@ public:
RiaEclipseUnitTools::UnitSystem unitSystem() const;
static RimWellPath* fromFilePath(QString filePath);
const QString relatedSimulationWell() const;
int relatedSimulationWellBranch() const;
static const QString tryFindSimulationWellFromWellPathName(const QString& wellPathName);
private:
void setWellPathGeometry(RigWellPath* wellPathModel);
@ -121,6 +132,7 @@ private:
QString getCacheDirectoryPath();
virtual void setupBeforeSave();
caf::PdmField<QString> id;
caf::PdmField<QString> sourceSystem;
caf::PdmField<QString> utmZone;

View File

@ -28,6 +28,9 @@
#include "RigSingleWellResultsData.h"
#include <QDebug>
#include "RigSimulationWellCenterLineCalculator.h"
#include "RigSimulationWellCoordsAndMD.h"
#include "RigWellPath.h"
//--------------------------------------------------------------------------------------------------
///
@ -319,7 +322,9 @@ const RigCell& RigEclipseCaseData::cellFromWellResultCell(const RigWellResultPoi
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigEclipseCaseData::findSharedSourceFace(cvf::StructGridInterface::FaceType& sharedSourceFace,const RigWellResultPoint& sourceWellCellResult, const RigWellResultPoint& otherWellCellResult) const
bool RigEclipseCaseData::findSharedSourceFace(cvf::StructGridInterface::FaceType& sharedSourceFace,
const RigWellResultPoint& sourceWellCellResult,
const RigWellResultPoint& otherWellCellResult) const
{
size_t gridIndex = sourceWellCellResult.m_gridIndex;
size_t gridCellIndex = sourceWellCellResult.m_gridCellIndex;
@ -432,6 +437,69 @@ void RigEclipseCaseData::computeActiveCellBoundingBoxes()
computeActiveCellsGeometryBoundingBox();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QString> RigEclipseCaseData::simulationWellNames() const
{
std::vector<QString> wellNames;
for (const auto& wellResult : wellResults())
{
wellNames.push_back(wellResult->m_wellName);
}
return wellNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigEclipseCaseData::hasSimulationWell(const QString& simWellName) const
{
const auto wellNames = simulationWellNames();
return std::find(wellNames.begin(), wellNames.end(), simWellName) != wellNames.end();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigWellPath*> RigEclipseCaseData::simulationWellBranches(const QString& simWellName)
{
std::vector<RigWellPath*> branches;
if (!(!simWellName.isEmpty() && simWellName != "None"))
{
return std::vector<RigWellPath*>();
}
const RigSingleWellResultsData* wellResults = findWellResult(simWellName);
if (!wellResults) return std::vector<RigWellPath*>();
std::vector< std::vector <cvf::Vec3d> > pipeBranchesCLCoords;
std::vector< std::vector <RigWellResultPoint> > pipeBranchesCellIds;
RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellFrame(this,
wellResults,
-1,
true,
true,
pipeBranchesCLCoords,
pipeBranchesCellIds);
for (size_t brIdx = 0; brIdx < pipeBranchesCLCoords.size(); ++brIdx)
{
auto wellMdCalculator = RigSimulationWellCoordsAndMD(pipeBranchesCLCoords[brIdx]);
cvf::ref<RigWellPath> newWellPath = new RigWellPath();
newWellPath->m_measuredDepths = wellMdCalculator.measuredDepths();
newWellPath->m_wellPathPoints = wellMdCalculator.wellPathPoints();
branches.push_back(newWellPath.p());
}
return branches;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -42,6 +42,7 @@ class RigCaseCellResultsData;
class RigActiveCellInfo;
class RigSingleWellResultsData;
class RigCell;
class RigWellPath;
class RimEclipseCase;
struct RigWellResultPoint;
@ -78,7 +79,7 @@ public:
RigFormationNames* activeFormationNames();
void setWellResults(const cvf::Collection<RigSingleWellResultsData>& data);
const cvf::Collection<RigSingleWellResultsData>& wellResults() { return m_wellResults; }
const cvf::Collection<RigSingleWellResultsData>& wellResults() const { return m_wellResults; }
const RigSingleWellResultsData* findWellResult(QString wellName) const;
const cvf::UByteArray* wellCellsInGrid(size_t gridIndex);
@ -92,6 +93,10 @@ public:
RiaEclipseUnitTools::UnitSystem unitsType() const { return m_unitsType; }
void setUnitsType(RiaEclipseUnitTools::UnitSystem unitsType) { m_unitsType = unitsType; }
std::vector<QString> simulationWellNames() const;
bool hasSimulationWell(const QString& simWellName) const;
std::vector<RigWellPath*> simulationWellBranches(const QString& simWellName);
private:
void computeActiveCellIJKBBox();
void computeWellCellsPrGrid();