#3267 MSW export. Implement max segment length for fractures and fishbones export

This commit is contained in:
Bjørn Erik Jensen 2018-09-11 09:17:20 +02:00
parent 5e779de956
commit 086fbd6756
6 changed files with 169 additions and 52 deletions

View File

@ -35,6 +35,9 @@ namespace caf
{ {
addItem(RicExportCompletionDataSettingsUi::TRANSMISSIBILITIES, "TRANSMISSIBILITIES", "Calculated Transmissibilities"); addItem(RicExportCompletionDataSettingsUi::TRANSMISSIBILITIES, "TRANSMISSIBILITIES", "Calculated Transmissibilities");
addItem(RicExportCompletionDataSettingsUi::WPIMULT_AND_DEFAULT_CONNECTION_FACTORS, "WPIMULT_AND_DEFAULT_CONNECTION_FACTORS", "Default Connection Factors and WPIMULT (Fractures Not Supported)"); addItem(RicExportCompletionDataSettingsUi::WPIMULT_AND_DEFAULT_CONNECTION_FACTORS, "WPIMULT_AND_DEFAULT_CONNECTION_FACTORS", "Default Connection Factors and WPIMULT (Fractures Not Supported)");
#ifdef _DEBUG
addItem(RicExportCompletionDataSettingsUi::NO_COMPLETIONS, "NO_COMPLETIONS", "None");
#endif
setDefault(RicExportCompletionDataSettingsUi::TRANSMISSIBILITIES); setDefault(RicExportCompletionDataSettingsUi::TRANSMISSIBILITIES);
} }

View File

@ -40,7 +40,11 @@ public:
enum CompdatExport { enum CompdatExport {
TRANSMISSIBILITIES, TRANSMISSIBILITIES,
WPIMULT_AND_DEFAULT_CONNECTION_FACTORS WPIMULT_AND_DEFAULT_CONNECTION_FACTORS,
#ifdef _DEBUG
NO_COMPLETIONS
#endif
}; };
typedef caf::AppEnum<CompdatExport> CompdatExportType; typedef caf::AppEnum<CompdatExport> CompdatExportType;

View File

@ -151,7 +151,7 @@ void RicExportFishbonesWellSegmentsFeature::exportWellSegments(const RimWellPath
return; return;
} }
RicMswExportInfo exportInfo = RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMswExportInfo(settings.caseToApply, wellPath, fishbonesSubs); RicMswExportInfo exportInfo = RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMswExportInfo(settings.caseToApply, wellPath, fishbonesSubs, true);
QTextStream stream(&exportFile); QTextStream stream(&exportFile);
RifEclipseDataTableFormatter formatter(stream); RifEclipseDataTableFormatter formatter(stream);

View File

@ -170,7 +170,7 @@ void RicFishbonesTransmissibilityCalculationFeatureImp::findFishboneLateralsWell
// Generate data // Generate data
const RigEclipseCaseData* caseData = settings.caseToApply()->eclipseCaseData(); const RigEclipseCaseData* caseData = settings.caseToApply()->eclipseCaseData();
RicMswExportInfo exportInfo = RicMswExportInfo exportInfo =
RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMswExportInfo(settings.caseToApply(), wellPath); RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMswExportInfo(settings.caseToApply(), wellPath, false);
RiaEclipseUnitTools::UnitSystem unitSystem = caseData->unitsType(); RiaEclipseUnitTools::UnitSystem unitSystem = caseData->unitsType();
bool isMainBore = false; bool isMainBore = false;

View File

@ -70,9 +70,28 @@
#include <QDir> #include <QDir>
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Internal functions /// Internal definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
class SubSegmentIntersectionInfo
{
public:
SubSegmentIntersectionInfo(size_t globCellIndex, double startTVD, double endTVD, double startMD, double endMD, cvf::Vec3d lengthsInCell)
: globCellIndex(globCellIndex), startTVD(startTVD), endTVD(endTVD), startMD(startMD), endMD(endMD), intersectionLengthsInCellCS(lengthsInCell) {}
size_t globCellIndex;
double startTVD;
double endTVD;
double startMD;
double endMD;
cvf::Vec3d intersectionLengthsInCellCS;
};
const RimWellPath* findWellPathFromExportName(const QString& wellNameForExport); const RimWellPath* findWellPathFromExportName(const QString& wellNameForExport);
std::vector<SubSegmentIntersectionInfo>
spiltIntersectionSegmentsToMaxLength(const RigWellPath* pathGeometry,
const std::vector<WellPathCellIntersectionInfo>& intersections,
double maxSegmentLength);
int numberOfSplittedSegments(double startMd, double endMd, double maxSegmentLength);
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
@ -1594,11 +1613,12 @@ std::vector<RigCompletionData> RicWellPathExportCompletionDataFeatureImpl::gener
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RicMswExportInfo RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMswExportInfo(const RimEclipseCase* caseToApply, RicMswExportInfo RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMswExportInfo(const RimEclipseCase* caseToApply,
const RimWellPath* wellPath) const RimWellPath* wellPath,
bool enableSegmentSplitting)
{ {
std::vector<RimFishbonesMultipleSubs*> fishbonesSubs = wellPath->fishbonesCollection()->activeFishbonesSubs(); std::vector<RimFishbonesMultipleSubs*> fishbonesSubs = wellPath->fishbonesCollection()->activeFishbonesSubs();
return generateFishbonesMswExportInfo(caseToApply, wellPath, fishbonesSubs); return generateFishbonesMswExportInfo(caseToApply, wellPath, fishbonesSubs, enableSegmentSplitting);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -1607,7 +1627,8 @@ RicMswExportInfo RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMs
RicMswExportInfo RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMswExportInfo( RicMswExportInfo RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMswExportInfo(
const RimEclipseCase* caseToApply, const RimEclipseCase* caseToApply,
const RimWellPath* wellPath, const RimWellPath* wellPath,
const std::vector<RimFishbonesMultipleSubs*>& fishbonesSubs) const std::vector<RimFishbonesMultipleSubs*>& fishbonesSubs,
bool enableSegmentSplitting)
{ {
RiaEclipseUnitTools::UnitSystem unitSystem = caseToApply->eclipseCaseData()->unitsType(); RiaEclipseUnitTools::UnitSystem unitSystem = caseToApply->eclipseCaseData()->unitsType();
@ -1619,43 +1640,57 @@ RicMswExportInfo RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMs
exportInfo.setLinerDiameter(wellPath->fishbonesCollection()->mswParameters()->linerDiameter(unitSystem)); exportInfo.setLinerDiameter(wellPath->fishbonesCollection()->mswParameters()->linerDiameter(unitSystem));
exportInfo.setRoughnessFactor(wellPath->fishbonesCollection()->mswParameters()->roughnessFactor(unitSystem)); exportInfo.setRoughnessFactor(wellPath->fishbonesCollection()->mswParameters()->roughnessFactor(unitSystem));
double maxSegmentLength = enableSegmentSplitting ? 500 : std::numeric_limits<double>::max(); // Fetch value from fishbones collection
bool foundSubGridIntersections = false; bool foundSubGridIntersections = false;
double startMD = wellPath->fishbonesCollection()->startMD(); double subStartMD = wellPath->fishbonesCollection()->startMD();
for (RimFishbonesMultipleSubs* subs : fishbonesSubs) for (RimFishbonesMultipleSubs* subs : fishbonesSubs)
{ {
for (auto& sub : subs->installedLateralIndices()) for (auto& sub : subs->installedLateralIndices())
{ {
double endMD = subs->measuredDepth(sub.subIndex); double subEndMD = subs->measuredDepth(sub.subIndex);
cvf::Vec3d position = wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(startMD); double subEndTVD = -wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(subEndMD).z();
cvf::Vec3d endPosition = wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(endMD); int subSegCount = numberOfSplittedSegments(subStartMD, subEndMD, maxSegmentLength);
double startTVD = -position.z(); double subSegLen = (subEndMD - subStartMD) / subSegCount;
double endTVD = -endPosition.z();
RicMswSegment location = RicMswSegment(subs->generatedName(), startMD, endMD, startTVD, endTVD, sub.subIndex); double startMd = subStartMD;
location.setEffectiveDiameter(subs->effectiveDiameter(unitSystem)); double startTvd = -wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(startMd).z();
location.setHoleDiameter(subs->holeDiameter(unitSystem)); for (int ssi = 0; ssi < subSegCount; ssi++)
location.setOpenHoleRoughnessFactor(subs->openHoleRoughnessFactor(unitSystem));
location.setSkinFactor(subs->skinFactor());
location.setIcdFlowCoefficient(subs->icdFlowCoefficient());
double icdOrificeRadius = subs->icdOrificeDiameter(unitSystem) / 2;
location.setIcdArea(icdOrificeRadius * icdOrificeRadius * cvf::PI_D * subs->icdCount());
// Add completion for ICD
RicMswCompletion icdCompletion(RigCompletionData::ICD, QString("ICD"));
RicMswSubSegment icdSegment(endMD, 0.1, endTVD, 0.0);
icdCompletion.addSubSegment(icdSegment);
location.addCompletion(icdCompletion);
for (size_t lateralIndex : sub.lateralIndices)
{ {
QString label = QString("Lateral %1").arg(lateralIndex); double endMd = startMd + subSegLen;
location.addCompletion(RicMswCompletion(RigCompletionData::FISHBONES, label, lateralIndex)); double endTvd = -wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(endMd).z();
RicMswSegment location = RicMswSegment(subs->generatedName(), startMd, endMd, startTvd, endTvd, sub.subIndex);
location.setEffectiveDiameter(subs->effectiveDiameter(unitSystem));
location.setHoleDiameter(subs->holeDiameter(unitSystem));
location.setOpenHoleRoughnessFactor(subs->openHoleRoughnessFactor(unitSystem));
location.setSkinFactor(subs->skinFactor());
location.setIcdFlowCoefficient(subs->icdFlowCoefficient());
double icdOrificeRadius = subs->icdOrificeDiameter(unitSystem) / 2;
location.setIcdArea(icdOrificeRadius * icdOrificeRadius * cvf::PI_D * subs->icdCount());
if (ssi == 0)
{
// Add completion for ICD
RicMswCompletion icdCompletion(RigCompletionData::ICD, QString("ICD"));
RicMswSubSegment icdSegment(subEndMD, 0.1, subEndTVD, 0.0);
icdCompletion.addSubSegment(icdSegment);
location.addCompletion(icdCompletion);
for (size_t lateralIndex : sub.lateralIndices)
{
QString label = QString("Lateral %1").arg(lateralIndex);
location.addCompletion(RicMswCompletion(RigCompletionData::FISHBONES, label, lateralIndex));
}
assignFishbonesLateralIntersections(caseToApply, subs, &location, &foundSubGridIntersections, maxSegmentLength);
}
exportInfo.addWellSegmentLocation(location);
startMd = endMd;
startTvd = endTvd;
} }
assignFishbonesLateralIntersections(caseToApply, subs, &location, &foundSubGridIntersections);
exportInfo.addWellSegmentLocation(location); subStartMD = subEndMD;
startMD = endMD;
} }
} }
exportInfo.setHasSubGridIntersections(foundSubGridIntersections); exportInfo.setHasSubGridIntersections(foundSubGridIntersections);
@ -1697,6 +1732,9 @@ RicMswExportInfo
std::vector<WellPathCellIntersectionInfo> intersections = std::vector<WellPathCellIntersectionInfo> intersections =
RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath(caseToApply->eclipseCaseData(), coords, mds); RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath(caseToApply->eclipseCaseData(), coords, mds);
double maxSegmentLength = 500; // Fetch value from fractures collection
std::vector<SubSegmentIntersectionInfo> subSegIntersections = spiltIntersectionSegmentsToMaxLength(wellPathGeometry, intersections, maxSegmentLength);
double initialMD = 0.0; double initialMD = 0.0;
if (wellPath->fractureCollection()->referenceMDType() == RimWellPathFractureCollection::MANUAL_REFERENCE_MD) if (wellPath->fractureCollection()->referenceMDType() == RimWellPathFractureCollection::MANUAL_REFERENCE_MD)
{ {
@ -1726,11 +1764,11 @@ RicMswExportInfo
bool foundSubGridIntersections = false; bool foundSubGridIntersections = false;
// Main bore // Main bore
int mainBoreSegment = 0; int mainBoreSegment = 1;
for (const auto& cellIntInfo : intersections) for (const auto& cellIntInfo : subSegIntersections)
{ {
double startTVD = -cellIntInfo.startPoint.z(); double startTVD = cellIntInfo.startTVD;
double endTVD = -cellIntInfo.endPoint.z(); double endTVD = cellIntInfo.endTVD;
size_t localGridIdx = 0u; size_t localGridIdx = 0u;
const RigGridBase* localGrid = grid->gridAndGridLocalIdxFromGlobalCellIdx(cellIntInfo.globCellIndex, &localGridIdx); const RigGridBase* localGrid = grid->gridAndGridLocalIdxFromGlobalCellIdx(cellIntInfo.globCellIndex, &localGridIdx);
@ -1758,14 +1796,11 @@ RicMswExportInfo
if (cvf::Math::valueInRange(fractureStartMD, cellIntInfo.startMD, cellIntInfo.endMD)) if (cvf::Math::valueInRange(fractureStartMD, cellIntInfo.startMD, cellIntInfo.endMD))
{ {
cvf::Vec3d position = wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(fractureStartMD);
std::vector<const RimFracture*> fractureVector(1, fracture);
std::vector<RigCompletionData> completionData = std::vector<RigCompletionData> completionData =
RicExportFractureCompletionsImpl::generateCompdatValues(caseToApply, RicExportFractureCompletionsImpl::generateCompdatValues(caseToApply,
wellPath->completions()->wellNameForExport(), wellPath->completions()->wellNameForExport(),
wellPath->wellPathGeometry(), wellPath->wellPathGeometry(),
fractureVector, { fracture },
nullptr, nullptr,
nullptr); nullptr);
@ -1800,7 +1835,8 @@ void RicWellPathExportCompletionDataFeatureImpl::assignFishbonesLateralIntersect
const RimEclipseCase* caseToApply, const RimEclipseCase* caseToApply,
const RimFishbonesMultipleSubs* fishbonesSubs, const RimFishbonesMultipleSubs* fishbonesSubs,
RicMswSegment* location, RicMswSegment* location,
bool* foundSubGridIntersections) bool* foundSubGridIntersections,
double maxSegmentLength)
{ {
CVF_ASSERT(foundSubGridIntersections != nullptr); CVF_ASSERT(foundSubGridIntersections != nullptr);
@ -1836,10 +1872,16 @@ void RicWellPathExportCompletionDataFeatureImpl::assignFishbonesLateralIntersect
std::vector<WellPathCellIntersectionInfo> intersections = std::vector<WellPathCellIntersectionInfo> intersections =
RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath( RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath(
caseToApply->eclipseCaseData(), lateralCoords, lateralMDs); caseToApply->eclipseCaseData(), lateralCoords, lateralMDs);
RigWellPath pathGeometry;
pathGeometry.m_wellPathPoints = lateralCoords;
pathGeometry.m_measuredDepths = lateralMDs;
std::vector<SubSegmentIntersectionInfo> subSegIntersections = spiltIntersectionSegmentsToMaxLength(&pathGeometry, intersections, maxSegmentLength);
double previousExitMD = lateralMDs.front(); double previousExitMD = lateralMDs.front();
double previousExitTVD = lateralCoords.front().z(); double previousExitTVD = lateralCoords.front().z();
for (const auto& cellIntInfo : intersections) for (const auto& cellIntInfo : subSegIntersections)
{ {
size_t localGridIdx = 0u; size_t localGridIdx = 0u;
const RigGridBase* localGrid = grid->gridAndGridLocalIdxFromGlobalCellIdx(cellIntInfo.globCellIndex, &localGridIdx); const RigGridBase* localGrid = grid->gridAndGridLocalIdxFromGlobalCellIdx(cellIntInfo.globCellIndex, &localGridIdx);
@ -1853,15 +1895,15 @@ void RicWellPathExportCompletionDataFeatureImpl::assignFishbonesLateralIntersect
size_t i = 0u, j = 0u, k = 0u; size_t i = 0u, j = 0u, k = 0u;
localGrid->ijkFromCellIndex(localGridIdx, &i, &j, &k); localGrid->ijkFromCellIndex(localGridIdx, &i, &j, &k);
RicMswSubSegment subSegment( RicMswSubSegment subSegment(
previousExitMD, cellIntInfo.endMD - previousExitMD, previousExitTVD, cellIntInfo.endPoint.z() - previousExitTVD); previousExitMD, cellIntInfo.endMD - previousExitMD, previousExitTVD, -cellIntInfo.endTVD - previousExitTVD);
RicMswSubSegmentCellIntersection intersection( RicMswSubSegmentCellIntersection intersection(
gridName, cellIntInfo.globCellIndex, cvf::Vec3st(i, j, k), cellIntInfo.intersectionLengthsInCellCS); gridName, cellIntInfo.globCellIndex, cvf::Vec3st(i, j, k), cellIntInfo.intersectionLengthsInCellCS);
subSegment.addIntersection(intersection); subSegment.addIntersection(intersection);
completion.addSubSegment(subSegment); completion.addSubSegment(subSegment);
previousExitMD = cellIntInfo.endMD; previousExitMD = cellIntInfo.endMD;
previousExitTVD = cellIntInfo.endPoint.z(); previousExitTVD = -cellIntInfo.endTVD;
} }
} }
} }
@ -2258,7 +2300,7 @@ void RicWellPathExportCompletionDataFeatureImpl::exportWellSegments(RimEclipseCa
} }
RicMswExportInfo exportInfo = RicMswExportInfo exportInfo =
RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMswExportInfo(eclipseCase, wellPath, fishbonesSubs); RicWellPathExportCompletionDataFeatureImpl::generateFishbonesMswExportInfo(eclipseCase, wellPath, fishbonesSubs, true);
QTextStream stream(exportFile.get()); QTextStream stream(exportFile.get());
RifEclipseDataTableFormatter formatter(stream); RifEclipseDataTableFormatter formatter(stream);
@ -2291,6 +2333,7 @@ void RicWellPathExportCompletionDataFeatureImpl::exportWellSegments(
RicWellPathExportCompletionDataFeatureImpl::generateCompsegTables(formatter, exportInfo); RicWellPathExportCompletionDataFeatureImpl::generateCompsegTables(formatter, exportInfo);
RicWellPathExportCompletionDataFeatureImpl::generateWsegvalvTable(formatter, exportInfo); RicWellPathExportCompletionDataFeatureImpl::generateWsegvalvTable(formatter, exportInfo);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Internal function /// Internal function
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -2304,3 +2347,67 @@ const RimWellPath* findWellPathFromExportName(const QString& wellNameForExport)
} }
return nullptr; return nullptr;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<SubSegmentIntersectionInfo> spiltIntersectionSegmentsToMaxLength(const RigWellPath* pathGeometry,
const std::vector<WellPathCellIntersectionInfo>& intersections,
double maxSegmentLength)
{
std::vector<SubSegmentIntersectionInfo> out;
if (!pathGeometry) return out;
for (int i = 0; i < intersections.size(); i++)
{
const auto& intersection = intersections[i];
double segLen = intersection.endMD - intersection.startMD;
int segCount = (int)std::trunc(segLen / maxSegmentLength) + 1;
// Calc effective max length
double effectiveMaxSegLen = segLen / segCount;
if (segCount == 1)
{
out.push_back(SubSegmentIntersectionInfo(intersection.globCellIndex,
-intersection.startPoint.z(),
-intersection.endPoint.z(),
intersection.startMD,
intersection.endMD,
intersection.intersectionLengthsInCellCS));
}
else
{
double currStartMd = intersection.startMD;
double currEndMd = currStartMd;
double lastTvd = -intersection.startPoint.z();
for(int i = 0; i < segCount; i++)
{
bool lasti = i == (segCount - 1);
currEndMd = currStartMd + effectiveMaxSegLen;
cvf::Vec3d segEndPoint = pathGeometry->interpolatedPointAlongWellPath(currEndMd);
out.push_back(SubSegmentIntersectionInfo(intersection.globCellIndex,
lastTvd,
lasti ? -intersection.endPoint.z() : -segEndPoint.z(),
currStartMd,
lasti ? intersection.endMD : currEndMd,
intersection.intersectionLengthsInCellCS / segCount));
currStartMd = currEndMd;
lastTvd = -segEndPoint.z();
}
}
}
return out;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int numberOfSplittedSegments(double startMd, double endMd, double maxSegmentLength)
{
return (int)(std::trunc((endMd - startMd) / maxSegmentLength) + 1);
}

View File

@ -57,11 +57,13 @@ class RicWellPathExportCompletionDataFeatureImpl
public: public:
static RicMswExportInfo generateFishbonesMswExportInfo(const RimEclipseCase* caseToApply, static RicMswExportInfo generateFishbonesMswExportInfo(const RimEclipseCase* caseToApply,
const RimWellPath* wellPath); const RimWellPath* wellPath,
bool enableSegmentSplitting);
static RicMswExportInfo generateFishbonesMswExportInfo(const RimEclipseCase* caseToApply, static RicMswExportInfo generateFishbonesMswExportInfo(const RimEclipseCase* caseToApply,
const RimWellPath* wellPath, const RimWellPath* wellPath,
const std::vector<RimFishbonesMultipleSubs*>& fishbonesSubs); const std::vector<RimFishbonesMultipleSubs*>& fishbonesSubs,
bool enableSegmentSplitting);
static RicMswExportInfo generateFracturesMswExportInfo(RimEclipseCase* caseToApply, static RicMswExportInfo generateFracturesMswExportInfo(RimEclipseCase* caseToApply,
const RimWellPath* wellPath); const RimWellPath* wellPath);
@ -178,7 +180,8 @@ private:
static void assignFishbonesLateralIntersections(const RimEclipseCase* caseToApply, static void assignFishbonesLateralIntersections(const RimEclipseCase* caseToApply,
const RimFishbonesMultipleSubs* fishbonesSubs, const RimFishbonesMultipleSubs* fishbonesSubs,
RicMswSegment* location, RicMswSegment* location,
bool* foundSubGridIntersections); bool* foundSubGridIntersections,
double maxSegmentLength);
static void assignFractureIntersections(const RimEclipseCase* caseToApply, static void assignFractureIntersections(const RimEclipseCase* caseToApply,
const RimWellPathFracture* fracture, const RimWellPathFracture* fracture,