#3183 Refactor MSW export code so fishbones structures are not needed at the time of formatting/writing

* Instead fill up the RicMultiSegmentWellExportInfo structures beforehand
This commit is contained in:
Gaute Lindkvist 2018-08-09 15:44:58 +02:00
parent 5081f12bb5
commit ffd545c75c
11 changed files with 665 additions and 410 deletions

View File

@ -9,6 +9,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicCaseAndFileExportSettingsUi.h
${CMAKE_CURRENT_LIST_DIR}/RicExportFractureCompletionsImpl.h
${CMAKE_CURRENT_LIST_DIR}/RicExportCompletionsForVisibleWellPathsFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicExportCompletionsForVisibleSimWellsFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicMultiSegmentWellExportInfo.h
${CMAKE_CURRENT_LIST_DIR}/RicWellPathFractureTextReportFeatureImpl.h
${CMAKE_CURRENT_LIST_DIR}/RicWellPathFractureReportItem.h
)
@ -24,6 +25,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicCaseAndFileExportSettingsUi.cpp
${CMAKE_CURRENT_LIST_DIR}/RicExportFractureCompletionsImpl.cpp
${CMAKE_CURRENT_LIST_DIR}/RicExportCompletionsForVisibleWellPathsFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicExportCompletionsForVisibleSimWellsFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicMultiSegmentWellExportInfo.cpp
${CMAKE_CURRENT_LIST_DIR}/RicWellPathFractureTextReportFeatureImpl.cpp
${CMAKE_CURRENT_LIST_DIR}/RicWellPathFractureReportItem.cpp
)

View File

@ -184,260 +184,11 @@ void RicExportFishbonesWellSegmentsFeature::exportWellSegments(const RimWellPath
return;
}
std::vector<WellSegmentLocation> locations = RicWellPathExportCompletionDataFeatureImpl::findWellSegmentLocations(settings.caseToApply, wellPath, fishbonesSubs);
RicMultiSegmentWellExportInfo exportInfo = RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMSWExportInfo(settings.caseToApply, wellPath, fishbonesSubs);
QTextStream stream(&exportFile);
RifEclipseDataTableFormatter formatter(stream);
generateWelsegsTable(formatter, wellPath, settings, locations);
generateCompsegsTable(formatter, wellPath, settings, locations);
generateWsegvalvTable(formatter, wellPath, settings, locations);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportFishbonesWellSegmentsFeature::generateWelsegsTable(RifEclipseDataTableFormatter& formatter,
const RimWellPath* wellPath,
const RicCaseAndFileExportSettingsUi& settings,
const std::vector<WellSegmentLocation>& locations)
{
RiaEclipseUnitTools::UnitSystem unitSystem = settings.caseToApply->eclipseCaseData()->unitsType();
formatter.keyword("WELSEGS");
double startMD = wellPath->fishbonesCollection()->startMD();
double startTVD = -wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(startMD).z();
{
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("Name"),
RifEclipseOutputTableColumn("Dep 1"),
RifEclipseOutputTableColumn("Tlen 1"),
RifEclipseOutputTableColumn("Vol 1"),
RifEclipseOutputTableColumn("Len&Dep"),
RifEclipseOutputTableColumn("PresDrop"),
};
formatter.header(header);
formatter.add(wellPath->name());
formatter.add(startTVD);
formatter.add(startMD);
formatter.add("1*");
formatter.add(wellPath->fishbonesCollection()->lengthAndDepth().text());
formatter.add(wellPath->fishbonesCollection()->pressureDrop().text());
formatter.rowCompleted();
}
{
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("First Seg"),
RifEclipseOutputTableColumn("Last Seg"),
RifEclipseOutputTableColumn("Branch Num"),
RifEclipseOutputTableColumn("Outlet Seg"),
RifEclipseOutputTableColumn("Length"),
RifEclipseOutputTableColumn("Depth Change"),
RifEclipseOutputTableColumn("Diam"),
RifEclipseOutputTableColumn("Rough"),
};
formatter.header(header);
}
{
formatter.comment("Main stem");
double depth = 0;
double length = 0;
double previousMD = startMD;
double previousTVD = startTVD;
for (const WellSegmentLocation& location : locations)
{
if (wellPath->fishbonesCollection()->lengthAndDepth() == RimFishbonesCollection::INC)
{
depth = location.trueVerticalDepth - previousTVD;
length = location.fishbonesSubs->measuredDepth(location.subIndex) - previousMD;
}
else
{
depth += location.trueVerticalDepth - previousTVD;
length += location.fishbonesSubs->measuredDepth(location.subIndex) - previousMD;
}
formatter.comment(QString("Segment for sub %1").arg(location.subIndex));
formatter.add(location.segmentNumber).add(location.segmentNumber);
formatter.add(1); // All segments on main stem are branch 1
formatter.add(location.segmentNumber - 1); // All main stem segments are connected to the segment below them
formatter.add(length);
formatter.add(depth);
formatter.add(wellPath->fishbonesCollection()->linerDiameter(unitSystem));
formatter.add(wellPath->fishbonesCollection()->roughnessFactor(unitSystem));
formatter.rowCompleted();
previousMD = location.measuredDepth;
previousTVD = location.trueVerticalDepth;
}
}
{
formatter.comment("Laterals");
formatter.comment("Diam: MSW - Tubing Radius");
formatter.comment("Rough: MSW - Open Hole Roughness Factor");
for (const WellSegmentLocation& location : locations)
{
formatter.comment("ICD");
formatter.add(location.icdSegmentNumber).add(location.icdSegmentNumber);
formatter.add(location.icdBranchNumber);
formatter.add(location.segmentNumber);
formatter.add(0.1); // ICDs have 0.1 length
formatter.add(0); // Depth change
formatter.add(wellPath->fishbonesCollection()->linerDiameter(unitSystem));
formatter.add(wellPath->fishbonesCollection()->roughnessFactor(unitSystem));
formatter.rowCompleted();
for (const WellSegmentLateral& lateral : location.laterals)
{
formatter.comment(QString("%1 : Sub index %2 - Lateral %3").arg(location.fishbonesSubs->generatedName()).arg(location.subIndex).arg(lateral.lateralIndex));
double depth = 0;
double length = 0;
for (const WellSegmentLateralIntersection& intersection : lateral.intersections)
{
if (wellPath->fishbonesCollection()->lengthAndDepth() == RimFishbonesCollection::INC)
{
depth = intersection.tvdChangeFromPreviousIntersection;
length = intersection.mdFromPreviousIntersection;
}
else
{
depth += intersection.tvdChangeFromPreviousIntersection;
length += intersection.mdFromPreviousIntersection;
}
double diameter = computeEffectiveDiameter(location.fishbonesSubs->tubingDiameter(unitSystem), location.fishbonesSubs->holeDiameter(unitSystem));
formatter.add(intersection.segmentNumber);
formatter.add(intersection.segmentNumber);
formatter.add(lateral.branchNumber);
formatter.add(intersection.attachedSegmentNumber);
formatter.add(length);
formatter.add(depth);
formatter.add(diameter);
formatter.add(location.fishbonesSubs->openHoleRoughnessFactor(unitSystem));
formatter.rowCompleted();
}
}
}
}
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportFishbonesWellSegmentsFeature::generateCompsegsTable(RifEclipseDataTableFormatter& formatter,
const RimWellPath* wellPath,
const RicCaseAndFileExportSettingsUi& settings,
const std::vector<WellSegmentLocation>& locations)
{
RigMainGrid* grid = settings.caseToApply->eclipseCaseData()->mainGrid();
formatter.keyword("COMPSEGS");
{
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("Name")
};
formatter.header(header);
formatter.add(wellPath->name());
formatter.rowCompleted();
}
{
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("I"),
RifEclipseOutputTableColumn("J"),
RifEclipseOutputTableColumn("K"),
RifEclipseOutputTableColumn("Branch no"),
RifEclipseOutputTableColumn("Start Length"),
RifEclipseOutputTableColumn("End Length"),
RifEclipseOutputTableColumn("Dir Pen"),
RifEclipseOutputTableColumn("End Range"),
RifEclipseOutputTableColumn("Connection Depth")
};
formatter.header(header);
}
for (const WellSegmentLocation& location : locations)
{
for (const WellSegmentLateral& lateral : location.laterals)
{
double aggregatedLength = 0;
for (const WellSegmentLateralIntersection& intersection : lateral.intersections)
{
size_t i, j, k;
grid->ijkFromCellIndex(intersection.globalCellIndex, &i, &j, &k);
formatter.addZeroBasedCellIndex(i).addZeroBasedCellIndex(j).addZeroBasedCellIndex(k);
formatter.add(lateral.branchNumber);
formatter.add(aggregatedLength);
formatter.add(aggregatedLength + intersection.mdFromPreviousIntersection);
formatter.rowCompleted();
aggregatedLength += intersection.mdFromPreviousIntersection;
}
}
}
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportFishbonesWellSegmentsFeature::generateWsegvalvTable(RifEclipseDataTableFormatter& formatter,
const RimWellPath* wellPath,
const RicCaseAndFileExportSettingsUi& settings,
const std::vector<WellSegmentLocation>& locations)
{
RiaEclipseUnitTools::UnitSystem unitSystem = settings.caseToApply->eclipseCaseData()->unitsType();
{
formatter.keyword("WSEGVALV");
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("Well Name"),
RifEclipseOutputTableColumn("Seg No"),
RifEclipseOutputTableColumn("Cv"),
RifEclipseOutputTableColumn("Ac"),
};
formatter.header(header);
}
for (const WellSegmentLocation& location : locations)
{
formatter.add(wellPath->name());
formatter.add(location.icdSegmentNumber);
formatter.add(location.fishbonesSubs->icdFlowCoefficient());
double icdOrificeRadius = location.fishbonesSubs->icdOrificeDiameter(unitSystem) / 2;
double icdArea = icdOrificeRadius * icdOrificeRadius * cvf::PI_D;
formatter.add(icdArea * static_cast<double>(location.fishbonesSubs->icdCount()));
formatter.rowCompleted();
}
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicExportFishbonesWellSegmentsFeature::computeEffectiveDiameter(double innerDiameter, double outerDiameter)
{
double innerRadius = innerDiameter / 2;
double innerArea = cvf::PI_D * innerRadius * innerRadius;
double outerRadius = outerDiameter / 2;
double outerArea = cvf::PI_D * outerRadius * outerRadius;
double effectiveArea = outerArea - innerArea;
double effectiveRadius = cvf::Math::sqrt(effectiveArea / cvf::PI_D);
return effectiveRadius * 2;
RicWellPathExportCompletionDataFeatureImpl::generateWelsegsTable(formatter, exportInfo);
RicWellPathExportCompletionDataFeatureImpl::generateCompsegsTable(formatter, exportInfo);
RicWellPathExportCompletionDataFeatureImpl::generateWsegvalvTable(formatter, exportInfo);
}

View File

@ -21,15 +21,17 @@
#include "RifEclipseDataTableFormatter.h"
#include "RicCaseAndFileExportSettingsUi.h"
#include "RicMultiSegmentWellExportInfo.h"
#include "RicWellPathExportCompletionDataFeatureImpl.h"
#include "cafCmdFeature.h"
class RimFishbonesCollection;
class RimFishbonesMultipleSubs;
class RimWellPath;
//==================================================================================================
///
//==================================================================================================
@ -48,10 +50,5 @@ public:
private:
static RimFishbonesCollection* selectedFishbonesCollection();
static RimWellPath* selectedWellPath();
static void generateWelsegsTable(RifEclipseDataTableFormatter& formatter, const RimWellPath* wellPath, const RicCaseAndFileExportSettingsUi& settings, const std::vector<WellSegmentLocation>& locations);
static void generateCompsegsTable(RifEclipseDataTableFormatter& formatter, const RimWellPath* wellPath, const RicCaseAndFileExportSettingsUi& settings, const std::vector<WellSegmentLocation>& locations);
static void generateWsegvalvTable(RifEclipseDataTableFormatter& formatter, const RimWellPath* wellPath, const RicCaseAndFileExportSettingsUi& settings, const std::vector<WellSegmentLocation>& locations);
static double computeEffectiveDiameter(double innerDiameter, double outerDiameter);
};

View File

@ -69,22 +69,22 @@ void RicFishbonesTransmissibilityCalculationFeatureImp::findFishboneLateralsWell
// Generate data
const RigEclipseCaseData* caseData = settings.caseToApply()->eclipseCaseData();
std::vector<WellSegmentLocation> locations = RicWellPathExportCompletionDataFeatureImpl::findWellSegmentLocations(settings.caseToApply, wellPath);
RicMultiSegmentWellExportInfo exportInfo = RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMSWExportInfo(settings.caseToApply(), wellPath);
RiaEclipseUnitTools::UnitSystem unitSystem = caseData->unitsType();
bool isMainBore = false;
for (const WellSegmentLocation& location : locations)
for (const RicWellSegmentLocation& location : exportInfo.wellSegmentLocations())
{
for (const WellSegmentLateral& lateral : location.laterals)
for (const RicWellSegmentLateral& lateral : location.laterals)
{
for (const WellSegmentLateralIntersection& intersection : lateral.intersections)
for (const RicWellSegmentLateralIntersection& intersection : lateral.intersections)
{
double diameter = location.fishbonesSubs->holeDiameter(unitSystem);
QString completionMetaData = (location.fishbonesSubs->generatedName() + QString(": Sub: %1 Lateral: %2").arg(location.subIndex).arg(lateral.lateralIndex));
double diameter = location.holeDiameter;
QString completionMetaData = (location.label + QString(": Sub: %1 Lateral: %2").arg(location.subIndex).arg(lateral.lateralIndex));
WellBorePartForTransCalc wellBorePart = WellBorePartForTransCalc(intersection.lengthsInCell,
diameter / 2,
location.fishbonesSubs->skinFactor(),
location.skinFactor,
isMainBore,
completionMetaData);

View File

@ -0,0 +1,141 @@
#include "RicMultiSegmentWellExportInfo.h"
#include "RigWellPath.h"
#include "RimWellPath.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicWellSegmentLocation::operator<(const RicWellSegmentLocation& rhs) const
{
return measuredDepth < rhs.measuredDepth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMultiSegmentWellExportInfo::setTopWellBoreVolume(double topWellBoreVolume)
{
m_topWellBoreVolume = topWellBoreVolume;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMultiSegmentWellExportInfo::setLinerDiameter(double linerDiameter)
{
m_linerDiameter = linerDiameter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMultiSegmentWellExportInfo::setRoughnessFactor(double roughnessFactor)
{
m_roughnessFactor = roughnessFactor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMultiSegmentWellExportInfo::addWellSegmentLocation(const RicWellSegmentLocation& location)
{
m_wellSegmentLocations.push_back(location);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMultiSegmentWellExportInfo::sortLocations()
{
std::sort(m_wellSegmentLocations.begin(), m_wellSegmentLocations.end());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RimWellPath* RicMultiSegmentWellExportInfo::wellPath() const
{
return m_wellPath;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicMultiSegmentWellExportInfo::initialMD() const
{
return m_initialMD;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicMultiSegmentWellExportInfo::initialTVD() const
{
return -m_wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(m_initialMD).z();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RicMultiSegmentWellExportInfo::unitSystem() const
{
return m_unitSystem;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicMultiSegmentWellExportInfo::topWellBoreVolume() const
{
return m_topWellBoreVolume;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicMultiSegmentWellExportInfo::linerDiameter() const
{
return m_linerDiameter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicMultiSegmentWellExportInfo::roughnessFactor() const
{
return m_roughnessFactor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicMultiSegmentWellExportInfo::lengthAndDepthText() const
{
return m_lengthAndDepthText;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicMultiSegmentWellExportInfo::pressureDropText() const
{
return m_pressureDropText;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<RicWellSegmentLocation>& RicMultiSegmentWellExportInfo::wellSegmentLocations() const
{
return m_wellSegmentLocations;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RicWellSegmentLocation>& RicMultiSegmentWellExportInfo::wellSegmentLocations()
{
return m_wellSegmentLocations;
}

View File

@ -0,0 +1,173 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 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 "cvfBase.h"
#include "cvfVector3.h"
#include <QString>
class RimWellPath;
class RimFishbonesMultipleSubs;
//==================================================================================================
///
//==================================================================================================
struct RicWellSegmentLateralIntersection
{
RicWellSegmentLateralIntersection(size_t globalCellIndex,
const cvf::Vec3st& cellIJK,
double length,
double depth,
const cvf::Vec3d& lengthsInCell)
: segmentNumber(std::numeric_limits<int>::infinity())
, attachedSegmentNumber(std::numeric_limits<int>::infinity())
, globalCellIndex(globalCellIndex)
, cellIJK(cellIJK)
, mdFromPreviousIntersection(length)
, tvdChangeFromPreviousIntersection(depth)
, lengthsInCell(lengthsInCell)
, mainBoreCell(false)
{
}
int segmentNumber;
int attachedSegmentNumber;
size_t globalCellIndex;
cvf::Vec3st cellIJK;
bool mainBoreCell;
double mdFromPreviousIntersection;
double tvdChangeFromPreviousIntersection;
cvf::Vec3d lengthsInCell;
};
//==================================================================================================
///
//==================================================================================================
struct RicWellSegmentLateral
{
RicWellSegmentLateral(size_t lateralIndex)
: lateralIndex(lateralIndex)
, branchNumber(0)
{
}
size_t lateralIndex;
int branchNumber;
std::vector<RicWellSegmentLateralIntersection> intersections;
};
//==================================================================================================
///
//==================================================================================================
struct RicWellSegmentLocation
{
RicWellSegmentLocation(const QString& label,
double measuredDepth,
double trueVerticalDepth,
size_t subIndex,
int segmentNumber = -1)
: label(label)
, measuredDepth(measuredDepth)
, trueVerticalDepth(trueVerticalDepth)
, effectiveDiameter(0.15)
, holeDiameter(std::numeric_limits<double>::infinity())
, openHoleRoughnessFactor(5.0e-5)
, skinFactor(std::numeric_limits<double>::infinity())
, icdFlowCoefficient(std::numeric_limits<double>::infinity())
, icdArea(std::numeric_limits<double>::infinity())
, subIndex(subIndex)
, segmentNumber(segmentNumber)
, icdBranchNumber(-1)
, icdSegmentNumber(-1)
{
}
bool operator<(const RicWellSegmentLocation& rhs) const;
QString label;
double measuredDepth;
double trueVerticalDepth;
double effectiveDiameter;
double holeDiameter;
double linerDiameter;
double openHoleRoughnessFactor;
double skinFactor;
double icdFlowCoefficient;
double icdArea;
size_t subIndex;
int segmentNumber;
int icdBranchNumber;
int icdSegmentNumber;
std::vector<RicWellSegmentLateral> laterals;
};
class RicMultiSegmentWellExportInfo
{
public:
RicMultiSegmentWellExportInfo(const RimWellPath* wellPath,
RiaEclipseUnitTools::UnitSystem unitSystem,
double initialMD,
const QString& lengthAndDepthText,
const QString& pressureDropText)
: m_wellPath(wellPath)
, m_initialMD(initialMD)
, m_unitSystem(unitSystem)
, m_topWellBoreVolume(std::numeric_limits<double>::infinity())
, m_linerDiameter(0.15)
, m_roughnessFactor(5.0e-5)
, m_lengthAndDepthText(lengthAndDepthText)
, m_pressureDropText(pressureDropText)
{}
void setTopWellBoreVolume(double topWellBoreVolume);
void setLinerDiameter(double linerDiameter);
void setRoughnessFactor(double roughnessFactor);
void addWellSegmentLocation(const RicWellSegmentLocation& location);
void sortLocations();
const RimWellPath* wellPath() const;
RiaEclipseUnitTools::UnitSystem unitSystem() const;
double initialMD() const;
double initialTVD() const;
double topWellBoreVolume() const;
double linerDiameter() const;
double roughnessFactor() const;
QString lengthAndDepthText() const;
QString pressureDropText() const;
const std::vector<RicWellSegmentLocation>& wellSegmentLocations() const;
std::vector<RicWellSegmentLocation>& wellSegmentLocations();
protected:
const RimWellPath* m_wellPath;
RiaEclipseUnitTools::UnitSystem m_unitSystem;
double m_initialMD;
double m_topWellBoreVolume;
double m_linerDiameter;
double m_roughnessFactor;
QString m_lengthAndDepthText;
QString m_pressureDropText;
std::vector<RicWellSegmentLocation> m_wellSegmentLocations;
};

View File

@ -173,10 +173,7 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompletions(const std::ve
std::vector<RigCompletionData> fractureCompletionData =
RicExportFractureCompletionsImpl::generateCompdatValuesForWellPath(
wellPath,
exportSettings.caseToApply(),
reportItems,
fractureTransmissibilityExportInformationStream.get());
wellPath, exportSettings.caseToApply(), reportItems, fractureTransmissibilityExportInformationStream.get());
appendCompletionData(&completionsPerEclipseCellAllCompletionTypes, fractureCompletionData);
appendCompletionData(&completionsPerEclipseCellFracture, fractureCompletionData);
@ -400,6 +397,220 @@ std::vector<RigCompletionData>
return completionsPerEclipseCell;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::generateWelsegsTable(RifEclipseDataTableFormatter& formatter,
const RicMultiSegmentWellExportInfo& exportInfo)
{
formatter.keyword("WELSEGS");
double startMD = exportInfo.initialMD();
double startTVD = exportInfo.initialTVD();
{
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("Name"),
RifEclipseOutputTableColumn("Dep 1"),
RifEclipseOutputTableColumn("Tlen 1"),
RifEclipseOutputTableColumn("Vol 1"),
RifEclipseOutputTableColumn("Len&Dep"),
RifEclipseOutputTableColumn("PresDrop"),
};
formatter.header(header);
formatter.add(exportInfo.wellPath()->name());
formatter.add(startTVD);
formatter.add(startMD);
formatter.add(exportInfo.topWellBoreVolume());
formatter.add(exportInfo.lengthAndDepthText());
formatter.add(exportInfo.pressureDropText());
formatter.rowCompleted();
}
{
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("First Seg"),
RifEclipseOutputTableColumn("Last Seg"),
RifEclipseOutputTableColumn("Branch Num"),
RifEclipseOutputTableColumn("Outlet Seg"),
RifEclipseOutputTableColumn("Length"),
RifEclipseOutputTableColumn("Depth Change"),
RifEclipseOutputTableColumn("Diam"),
RifEclipseOutputTableColumn("Rough"),
};
formatter.header(header);
}
{
formatter.comment("Main stem");
double depth = 0;
double length = 0;
double previousMD = startMD;
double previousTVD = startTVD;
for (const RicWellSegmentLocation& location : exportInfo.wellSegmentLocations())
{
if (exportInfo.lengthAndDepthText() == QString("INC"))
{
depth = location.trueVerticalDepth - previousTVD;
length = location.measuredDepth - previousMD;
}
else
{
depth += location.trueVerticalDepth - previousTVD;
length += location.measuredDepth - previousMD;
}
formatter.comment(QString("Segment for sub %1").arg(location.subIndex));
formatter.add(location.segmentNumber).add(location.segmentNumber);
formatter.add(1); // All segments on main stem are branch 1
formatter.add(location.segmentNumber - 1); // All main stem segments are connected to the segment below them
formatter.add(length);
formatter.add(depth);
formatter.add(exportInfo.linerDiameter());
formatter.add(exportInfo.roughnessFactor());
formatter.rowCompleted();
previousMD = location.measuredDepth;
previousTVD = location.trueVerticalDepth;
}
}
{
formatter.comment("Laterals");
formatter.comment("Diam: MSW - Tubing Radius");
formatter.comment("Rough: MSW - Open Hole Roughness Factor");
for (const RicWellSegmentLocation& location : exportInfo.wellSegmentLocations())
{
formatter.comment("ICD");
formatter.add(location.icdSegmentNumber).add(location.icdSegmentNumber);
formatter.add(location.icdBranchNumber);
formatter.add(location.segmentNumber);
formatter.add(0.1); // ICDs have 0.1 length
formatter.add(0); // Depth change
formatter.add(exportInfo.linerDiameter());
formatter.add(exportInfo.roughnessFactor());
formatter.rowCompleted();
for (const RicWellSegmentLateral& lateral : location.laterals)
{
formatter.comment(QString("%1 : Sub index %2 - Lateral %3")
.arg(location.label)
.arg(location.subIndex)
.arg(lateral.lateralIndex));
double depth = 0;
double length = 0;
for (const RicWellSegmentLateralIntersection& intersection : lateral.intersections)
{
if (exportInfo.lengthAndDepthText() == QString("INC"))
{
depth = intersection.tvdChangeFromPreviousIntersection;
length = intersection.mdFromPreviousIntersection;
}
else
{
depth += intersection.tvdChangeFromPreviousIntersection;
length += intersection.mdFromPreviousIntersection;
}
double diameter = location.effectiveDiameter;
formatter.add(intersection.segmentNumber);
formatter.add(intersection.segmentNumber);
formatter.add(lateral.branchNumber);
formatter.add(intersection.attachedSegmentNumber);
formatter.add(length);
formatter.add(depth);
formatter.add(diameter);
formatter.add(location.openHoleRoughnessFactor);
formatter.rowCompleted();
}
}
}
}
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::generateCompsegsTable(RifEclipseDataTableFormatter& formatter,
const RicMultiSegmentWellExportInfo& exportInfo)
{
formatter.keyword("COMPSEGS");
{
std::vector<RifEclipseOutputTableColumn> header = {RifEclipseOutputTableColumn("Name")};
formatter.header(header);
formatter.add(exportInfo.wellPath()->name());
formatter.rowCompleted();
}
{
std::vector<RifEclipseOutputTableColumn> header = {RifEclipseOutputTableColumn("I"),
RifEclipseOutputTableColumn("J"),
RifEclipseOutputTableColumn("K"),
RifEclipseOutputTableColumn("Branch no"),
RifEclipseOutputTableColumn("Start Length"),
RifEclipseOutputTableColumn("End Length"),
RifEclipseOutputTableColumn("Dir Pen"),
RifEclipseOutputTableColumn("End Range"),
RifEclipseOutputTableColumn("Connection Depth")};
formatter.header(header);
}
for (const RicWellSegmentLocation& location : exportInfo.wellSegmentLocations())
{
for (const RicWellSegmentLateral& lateral : location.laterals)
{
double aggregatedLength = 0;
for (const RicWellSegmentLateralIntersection& intersection : lateral.intersections)
{
cvf::Vec3st ijk = intersection.cellIJK;
formatter.addZeroBasedCellIndex(ijk.x()).addZeroBasedCellIndex(ijk.y()).addZeroBasedCellIndex(ijk.z());
formatter.add(lateral.branchNumber);
formatter.add(aggregatedLength);
formatter.add(aggregatedLength + intersection.mdFromPreviousIntersection);
formatter.rowCompleted();
aggregatedLength += intersection.mdFromPreviousIntersection;
}
}
}
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::generateWsegvalvTable(RifEclipseDataTableFormatter& formatter,
const RicMultiSegmentWellExportInfo& exportInfo)
{
{
formatter.keyword("WSEGVALV");
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("Well Name"),
RifEclipseOutputTableColumn("Seg No"),
RifEclipseOutputTableColumn("Cv"),
RifEclipseOutputTableColumn("Ac"),
};
formatter.header(header);
}
for (const RicWellSegmentLocation& location : exportInfo.wellSegmentLocations())
{
formatter.add(exportInfo.wellPath()->name());
formatter.add(location.icdSegmentNumber);
formatter.add(location.icdFlowCoefficient);
formatter.add(location.icdArea);
formatter.rowCompleted();
}
formatter.tableCompleted();
}
//==================================================================================================
///
//==================================================================================================
@ -953,18 +1164,9 @@ std::vector<RigCompletionData> RicWellPathExportCompletionDataFeatureImpl::gener
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicWellPathExportCompletionDataFeatureImpl::wellSegmentLocationOrdering(const WellSegmentLocation& first,
const WellSegmentLocation& second)
{
return first.measuredDepth < second.measuredDepth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<WellSegmentLocation>
RicWellPathExportCompletionDataFeatureImpl::findWellSegmentLocations(const RimEclipseCase* caseToApply,
const RimWellPath* wellPath)
RicMultiSegmentWellExportInfo
RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMSWExportInfo(const RimEclipseCase* caseToApply,
const RimWellPath* wellPath)
{
std::vector<RimFishbonesMultipleSubs*> fishbonesSubs;
@ -979,55 +1181,72 @@ std::vector<WellSegmentLocation>
}
}
return findWellSegmentLocations(caseToApply, wellPath, fishbonesSubs);
return generateFishbonesMSWExportInfo(caseToApply, wellPath, fishbonesSubs);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<WellSegmentLocation> RicWellPathExportCompletionDataFeatureImpl::findWellSegmentLocations(
RicMultiSegmentWellExportInfo RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMSWExportInfo(
const RimEclipseCase* caseToApply,
const RimWellPath* wellPath,
const std::vector<RimFishbonesMultipleSubs*>& fishbonesSubs)
{
std::vector<WellSegmentLocation> wellSegmentLocations;
RiaEclipseUnitTools::UnitSystem unitSystem = caseToApply->eclipseCaseData()->unitsType();
RicMultiSegmentWellExportInfo exportInfo(wellPath,
unitSystem,
wellPath->fishbonesCollection()->startMD(),
wellPath->fishbonesCollection()->lengthAndDepth().text(),
wellPath->fishbonesCollection()->pressureDrop().text());
exportInfo.setLinerDiameter(wellPath->fishbonesCollection()->linerDiameter(unitSystem));
exportInfo.setRoughnessFactor(wellPath->fishbonesCollection()->roughnessFactor(unitSystem));
for (RimFishbonesMultipleSubs* subs : fishbonesSubs)
{
for (auto& sub : subs->installedLateralIndices())
{
double measuredDepth = subs->measuredDepth(sub.subIndex);
cvf::Vec3d position = wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(measuredDepth);
WellSegmentLocation location = WellSegmentLocation(subs, measuredDepth, -position.z(), sub.subIndex);
double measuredDepth = subs->measuredDepth(sub.subIndex);
cvf::Vec3d position = wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(measuredDepth);
RicWellSegmentLocation location =
RicWellSegmentLocation(subs->generatedName(), measuredDepth, -position.z(), sub.subIndex);
location.effectiveDiameter = subs->effectiveDiameter(unitSystem);
location.holeDiameter = subs->holeDiameter(unitSystem);
location.openHoleRoughnessFactor = subs->openHoleRoughnessFactor(unitSystem);
location.skinFactor = subs->skinFactor();
location.icdFlowCoefficient = subs->icdFlowCoefficient();
double icdOrificeRadius = subs->icdOrificeDiameter(unitSystem) / 2;
location.icdArea = icdOrificeRadius * icdOrificeRadius * cvf::PI_D * subs->icdCount();
for (size_t lateralIndex : sub.lateralIndices)
{
location.laterals.push_back(WellSegmentLateral(lateralIndex));
location.laterals.push_back(RicWellSegmentLateral(lateralIndex));
}
wellSegmentLocations.push_back(location);
assignLateralIntersections(caseToApply, subs, &location);
exportInfo.addWellSegmentLocation(location);
}
}
std::sort(wellSegmentLocations.begin(), wellSegmentLocations.end(), wellSegmentLocationOrdering);
exportInfo.sortLocations();
assignLateralIntersectionsAndBranchAndSegmentNumbers(caseToApply, &wellSegmentLocations);
assignBranchAndSegmentNumbers(caseToApply, &exportInfo);
return wellSegmentLocations;
return exportInfo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::assignLateralIntersections(const RimEclipseCase* caseToApply,
WellSegmentLocation* location,
int* branchNum,
int* segmentNum)
void RicWellPathExportCompletionDataFeatureImpl::assignLateralIntersections(const RimEclipseCase* caseToApply,
const RimFishbonesMultipleSubs* fishbonesSubs,
RicWellSegmentLocation* location)
{
for (WellSegmentLateral& lateral : location->laterals)
{
++(*branchNum);
lateral.branchNumber = (*branchNum);
const RigMainGrid* grid = caseToApply->eclipseCaseData()->mainGrid();
for (RicWellSegmentLateral& lateral : location->laterals)
{
std::vector<std::pair<cvf::Vec3d, double>> lateralCoordMDPairs =
location->fishbonesSubs->coordsAndMDForLateral(location->subIndex, lateral.lateralIndex);
fishbonesSubs->coordsAndMDForLateral(location->subIndex, lateral.lateralIndex);
if (lateralCoordMDPairs.empty())
{
@ -1052,22 +1271,20 @@ void RicWellPathExportCompletionDataFeatureImpl::assignLateralIntersections(cons
double previousExitMD = lateralMDs.front();
double previousExitTVD = lateralCoords.front().z();
int attachedSegmentNumber = location->icdSegmentNumber;
for (const auto& cellIntInfo : intersections)
{
++(*segmentNum);
WellSegmentLateralIntersection lateralIntersection((*segmentNum),
attachedSegmentNumber,
cellIntInfo.globCellIndex,
cellIntInfo.endMD - previousExitMD,
cellIntInfo.endPoint.z() - previousExitTVD,
cellIntInfo.intersectionLengthsInCellCS);
size_t i = 0u, j = 0u, k = 0u;
grid->ijkFromCellIndex(cellIntInfo.globCellIndex, &i, &j, &k);
RicWellSegmentLateralIntersection lateralIntersection(cellIntInfo.globCellIndex,
cvf::Vec3st(i, j, k),
cellIntInfo.endMD - previousExitMD,
cellIntInfo.endPoint.z() - previousExitTVD,
cellIntInfo.intersectionLengthsInCellCS);
lateral.intersections.push_back(lateralIntersection);
attachedSegmentNumber = (*segmentNum);
previousExitMD = cellIntInfo.endMD;
previousExitTVD = cellIntInfo.endPoint.z();
previousExitMD = cellIntInfo.endMD;
previousExitTVD = cellIntInfo.endPoint.z();
}
}
}
@ -1075,15 +1292,38 @@ void RicWellPathExportCompletionDataFeatureImpl::assignLateralIntersections(cons
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::assignLateralIntersectionsAndBranchAndSegmentNumbers(
const RimEclipseCase* caseToApply,
std::vector<WellSegmentLocation>* locations)
void RicWellPathExportCompletionDataFeatureImpl::assignBranchAndSegmentNumbers(const RimEclipseCase* caseToApply,
RicWellSegmentLocation* location,
int* branchNum,
int* segmentNum)
{
for (RicWellSegmentLateral& lateral : location->laterals)
{
++(*branchNum);
lateral.branchNumber = (*branchNum);
int attachedSegmentNumber = location->icdSegmentNumber;
for (auto& intersection : lateral.intersections)
{
++(*segmentNum);
intersection.segmentNumber = *segmentNum;
intersection.attachedSegmentNumber = attachedSegmentNumber;
attachedSegmentNumber = *segmentNum;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::assignBranchAndSegmentNumbers(const RimEclipseCase* caseToApply,
RicMultiSegmentWellExportInfo* exportInfo)
{
int segmentNumber = 1;
int branchNumber = 1;
// First loop over the locations so that each segment on the main stem is an incremental number
for (WellSegmentLocation& location : *locations)
for (RicWellSegmentLocation& location : exportInfo->wellSegmentLocations())
{
location.segmentNumber = ++segmentNumber;
location.icdBranchNumber = ++branchNumber;
@ -1091,9 +1331,9 @@ void RicWellPathExportCompletionDataFeatureImpl::assignLateralIntersectionsAndBr
}
// Then assign branch and segment numbers to each lateral parts
for (WellSegmentLocation& location : *locations)
for (RicWellSegmentLocation& location : exportInfo->wellSegmentLocations())
{
assignLateralIntersections(caseToApply, &location, &branchNumber, &segmentNumber);
assignBranchAndSegmentNumbers(caseToApply, &location, &branchNumber, &segmentNumber);
}
}

View File

@ -21,6 +21,7 @@
#include "RigCompletionData.h"
#include "RicExportCompletionDataSettingsUi.h"
#include "RicMultiSegmentWellExportInfo.h"
#include "RicWellPathFractureReportItem.h"
#include "cvfBase.h"
@ -38,82 +39,6 @@ class RimWellPath;
class RifEclipseDataTableFormatter;
class RigVirtualPerforationTransmissibilities;
//==================================================================================================
///
//==================================================================================================
struct WellSegmentLateralIntersection
{
WellSegmentLateralIntersection(int segmentNumber,
int attachedSegmentNumber,
size_t globalCellIndex,
double length,
double depth,
const cvf::Vec3d& lengthsInCell)
: segmentNumber(segmentNumber)
, attachedSegmentNumber(attachedSegmentNumber)
, globalCellIndex(globalCellIndex)
, mdFromPreviousIntersection(length)
, tvdChangeFromPreviousIntersection(depth)
, lengthsInCell(lengthsInCell)
, mainBoreCell(false)
{
}
int segmentNumber;
int attachedSegmentNumber;
size_t globalCellIndex;
bool mainBoreCell;
double mdFromPreviousIntersection;
double tvdChangeFromPreviousIntersection;
cvf::Vec3d lengthsInCell;
};
//==================================================================================================
///
//==================================================================================================
struct WellSegmentLateral
{
WellSegmentLateral(size_t lateralIndex)
: lateralIndex(lateralIndex)
, branchNumber(0)
{
}
size_t lateralIndex;
int branchNumber;
std::vector<WellSegmentLateralIntersection> intersections;
};
//==================================================================================================
///
//==================================================================================================
struct WellSegmentLocation
{
WellSegmentLocation(const RimFishbonesMultipleSubs* subs,
double measuredDepth,
double trueVerticalDepth,
size_t subIndex,
int segmentNumber = -1)
: fishbonesSubs(subs)
, measuredDepth(measuredDepth)
, trueVerticalDepth(trueVerticalDepth)
, subIndex(subIndex)
, segmentNumber(segmentNumber)
, icdBranchNumber(-1)
, icdSegmentNumber(-1)
{
}
const RimFishbonesMultipleSubs* fishbonesSubs;
double measuredDepth;
double trueVerticalDepth;
size_t subIndex;
int segmentNumber;
int icdBranchNumber;
int icdSegmentNumber;
std::vector<WellSegmentLateral> laterals;
};
//==================================================================================================
///
//==================================================================================================
@ -121,12 +46,12 @@ class RicWellPathExportCompletionDataFeatureImpl
{
public:
static std::vector<WellSegmentLocation> findWellSegmentLocations(const RimEclipseCase* caseToApply,
const RimWellPath* wellPath);
static RicMultiSegmentWellExportInfo generateFishbonesMSWExportInfo(const RimEclipseCase* caseToApply,
const RimWellPath* wellPath);
static std::vector<WellSegmentLocation> findWellSegmentLocations(const RimEclipseCase* caseToApply,
const RimWellPath* wellPath,
const std::vector<RimFishbonesMultipleSubs*>& fishbonesSubs);
static RicMultiSegmentWellExportInfo generateFishbonesMSWExportInfo(const RimEclipseCase* caseToApply,
const RimWellPath* wellPath,
const std::vector<RimFishbonesMultipleSubs*>& fishbonesSubs);
static CellDirection calculateDirectionInCell(RimEclipseCase* eclipseCase,
size_t globalCellIndex,
@ -154,6 +79,10 @@ public:
RimEclipseCase* eclipseCase,
size_t timeStepIndex);
static void generateWelsegsTable(RifEclipseDataTableFormatter& formatter, const RicMultiSegmentWellExportInfo& exportInfo);
static void generateCompsegsTable(RifEclipseDataTableFormatter& formatter, const RicMultiSegmentWellExportInfo& exportInfo);
static void generateWsegvalvTable(RifEclipseDataTableFormatter& formatter, const RicMultiSegmentWellExportInfo& exportInfo);
private:
static double calculateTransmissibilityAsEclipseDoes(RimEclipseCase* eclipseCase,
double skinFactor,
@ -189,16 +118,15 @@ private:
static std::vector<RigCompletionData> generatePerforationsCompdatValues(const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings);
static bool wellSegmentLocationOrdering(const WellSegmentLocation& first,
const WellSegmentLocation& second);
static void assignLateralIntersections(const RimEclipseCase* caseToApply,
WellSegmentLocation* location,
int* branchNum,
int* segmentNum);
static void assignLateralIntersectionsAndBranchAndSegmentNumbers(const RimEclipseCase* caseToApply,
std::vector<WellSegmentLocation>* locations);
const RimFishbonesMultipleSubs* fishbonesSubs,
RicWellSegmentLocation* location);
static void assignBranchAndSegmentNumbers(const RimEclipseCase* caseToApply,
RicWellSegmentLocation* location,
int* branchNum,
int* segmentNum);
static void assignBranchAndSegmentNumbers(const RimEclipseCase* caseToApply,
RicMultiSegmentWellExportInfo* exportInfo);
static void appendCompletionData(std::map<RigCompletionDataGridCell, std::vector<RigCompletionData>>* completionData,
const std::vector<RigCompletionData>& data);

View File

@ -343,6 +343,11 @@ int RifEclipseDataTableFormatter::tableWidth() const
//--------------------------------------------------------------------------------------------------
QString RifEclipseDataTableFormatter::format(double num, RifEclipseOutputTableDoubleFormatting doubleFormat)
{
if (num == std::numeric_limits<double>::infinity())
{
return QString("1*"); // Eclipse default column value
}
switch (doubleFormat.format)
{
case RifEclipseOutputTableDoubleFormat::RIF_FLOAT:

View File

@ -240,6 +240,23 @@ double RimFishbonesMultipleSubs::tubingDiameter(RiaEclipseUnitTools::UnitSystem
return 0.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFishbonesMultipleSubs::effectiveDiameter(RiaEclipseUnitTools::UnitSystem unitSystem) const
{
double innerRadius = tubingDiameter(unitSystem) / 2;
double outerRadius = holeDiameter(unitSystem) / 2;
double innerArea = cvf::PI_D * innerRadius * innerRadius;
double outerArea = cvf::PI_D * outerRadius * outerRadius;
double effectiveArea = outerArea - innerArea;
double effectiveRadius = cvf::Math::sqrt(effectiveArea / cvf::PI_D);
return effectiveRadius * 2;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -86,6 +86,7 @@ public:
double tubingDiameter(RiaEclipseUnitTools::UnitSystem unitSystem) const;
double holeDiameter(RiaEclipseUnitTools::UnitSystem unitSystem) const { return m_pipeProperties()->holeDiameter(unitSystem); }
double effectiveDiameter(RiaEclipseUnitTools::UnitSystem unitSystem) const;
double skinFactor() const { return m_pipeProperties()->skinFactor(); }
double openHoleRoughnessFactor(RiaEclipseUnitTools::UnitSystem unitSystem) const;
double icdOrificeDiameter(RiaEclipseUnitTools::UnitSystem unitSystem) const;