From 252defd96a71ba4f36139983a6ab2e3d5eeacf85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 1 Jun 2017 16:34:30 +0200 Subject: [PATCH] #1493 Include fracture export in the Export Completions Command --- .../CompletionCommands/CMakeLists_files.cmake | 2 + .../RicExportCompletionDataSettingsUi.cpp | 1 + .../RicExportCompletionDataSettingsUi.h | 1 + .../RicExportFractureCompletionsImpl.cpp | 227 ++++++++++++++++++ .../RicExportFractureCompletionsImpl.h | 33 +++ ...RicWellPathExportCompletionDataFeature.cpp | 8 + ...ToStimPlanCellTransmissibilityCalculator.h | 2 +- 7 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 ApplicationCode/Commands/CompletionCommands/RicExportFractureCompletionsImpl.cpp create mode 100644 ApplicationCode/Commands/CompletionCommands/RicExportFractureCompletionsImpl.h diff --git a/ApplicationCode/Commands/CompletionCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/CompletionCommands/CMakeLists_files.cmake index 3f3924da5a..bb39b53e4b 100644 --- a/ApplicationCode/Commands/CompletionCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/CompletionCommands/CMakeLists_files.cmake @@ -9,6 +9,7 @@ ${CEE_CURRENT_LIST_DIR}RicCaseAndFileExportSettingsUi.h ${CEE_CURRENT_LIST_DIR}RicExportCompletionDataSettingsUi.h ${CEE_CURRENT_LIST_DIR}RicExportFishbonesLateralsFeature.h ${CEE_CURRENT_LIST_DIR}RicExportFishbonesWellSegmentsFeature.h +${CEE_CURRENT_LIST_DIR}RicExportFractureCompletionsImpl.h ${CEE_CURRENT_LIST_DIR}RicExportWellSegmentsSettingsUi.h ${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsAtMeasuredDepthFeature.h ${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsFeature.h @@ -22,6 +23,7 @@ ${CEE_CURRENT_LIST_DIR}RicCaseAndFileExportSettingsUi.cpp ${CEE_CURRENT_LIST_DIR}RicExportCompletionDataSettingsUi.cpp ${CEE_CURRENT_LIST_DIR}RicExportFishbonesLateralsFeature.cpp ${CEE_CURRENT_LIST_DIR}RicExportFishbonesWellSegmentsFeature.cpp +${CEE_CURRENT_LIST_DIR}RicExportFractureCompletionsImpl.cpp ${CEE_CURRENT_LIST_DIR}RicExportWellSegmentsSettingsUi.cpp ${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsAtMeasuredDepthFeature.cpp ${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsFeature.cpp diff --git a/ApplicationCode/Commands/CompletionCommands/RicExportCompletionDataSettingsUi.cpp b/ApplicationCode/Commands/CompletionCommands/RicExportCompletionDataSettingsUi.cpp index 8b9c20c62b..d0b500f116 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicExportCompletionDataSettingsUi.cpp +++ b/ApplicationCode/Commands/CompletionCommands/RicExportCompletionDataSettingsUi.cpp @@ -31,6 +31,7 @@ RicExportCompletionDataSettingsUi::RicExportCompletionDataSettingsUi() CAF_PDM_InitField(&includePerforations, "IncludePerforations", true, "Include Perforations", "", "", ""); CAF_PDM_InitField(&includeFishbones, "IncludeFishbones", true, "Include Fishbones", "", "", ""); + CAF_PDM_InitField(&includeFractures, "IncludeFractures", true, "Include Fractures", "", "", ""); CAF_PDM_InitField(&includeWpimult, "IncludeWPIMULT", true, "Include WPIMLUT", "", "", ""); CAF_PDM_InitField(&removeLateralsInMainBoreCells, "RemoveLateralsInMainBoreCells", false, "Remove Laterals in Main Bore Cells", "", "", ""); diff --git a/ApplicationCode/Commands/CompletionCommands/RicExportCompletionDataSettingsUi.h b/ApplicationCode/Commands/CompletionCommands/RicExportCompletionDataSettingsUi.h index cc9f71dc43..8a75d123ff 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicExportCompletionDataSettingsUi.h +++ b/ApplicationCode/Commands/CompletionCommands/RicExportCompletionDataSettingsUi.h @@ -35,6 +35,7 @@ public: caf::PdmField includePerforations; caf::PdmField includeFishbones; + caf::PdmField includeFractures; caf::PdmField includeWpimult; caf::PdmField removeLateralsInMainBoreCells; diff --git a/ApplicationCode/Commands/CompletionCommands/RicExportFractureCompletionsImpl.cpp b/ApplicationCode/Commands/CompletionCommands/RicExportFractureCompletionsImpl.cpp new file mode 100644 index 0000000000..befaf4cfb8 --- /dev/null +++ b/ApplicationCode/Commands/CompletionCommands/RicExportFractureCompletionsImpl.cpp @@ -0,0 +1,227 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicExportFractureCompletionsImpl.h" + +#include +#include "RimEclipseCase.h" +#include "RicExportCompletionDataSettingsUi.h" +#include "RimFracture.h" +#include "RimWellPath.h" +#include "RigEclipseCaseData.h" +#include "RigTransmissibilityCondenser.h" +#include "RigFractureCell.h" +#include "RigFractureGrid.h" +#include "RimFractureTemplate.h" +#include "RigEclipseToStimPlanCellTransmissibilityCalculator.h" +#include "RigFractureTransmissibilityEquations.h" +#include "RigWellPathStimplanIntersector.h" +#include "RigMainGrid.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicExportFractureCompletionsImpl::generateFracturesCompdatValues(const RimWellPath* wellPath, + const RicExportCompletionDataSettingsUi& settings, + QTextStream* outputStreamForIntermediateResultsText) +{ + const RimEclipseCase* caseToApply = settings.caseToApply(); + + std::vector fracturesAlongWellPath; + wellPath->descendantsIncludingThisOfType(fracturesAlongWellPath); + + double cDarcyInCorrectUnit = caseToApply->eclipseCaseData()->darchysValue(); + const RigMainGrid* mainGrid = caseToApply->eclipseCaseData()->mainGrid(); + + // To handle several fractures in the same eclipse cell we need to keep track of the transmissibility + // to the well from each fracture intersecting the cell and sum these transmissibilities at the end. + // std::map > + std::map > eclCellIdxToTransPrFractureMap; + std::vector fractureCompletions; + + for (RimFracture* fracture : fracturesAlongWellPath) + { + using CellIdxSpace = RigTransmissibilityCondenser::CellAddress; + + RimFractureTemplate* fracTemplate = fracture->attachedFractureDefinition(); + const RigFractureGrid* fractureGrid = fracTemplate->fractureGrid(); + + RigTransmissibilityCondenser transCondenser; + + ////// + // Calculate Matrix To Fracture Trans + + std::vector fractureCells = fractureGrid->fractureCells(); + + for (const RigFractureCell fractureCell : fractureCells) + { + if (fractureCell.getConductivtyValue() < 1e-7) continue; + + RigEclipseToStimPlanCellTransmissibilityCalculator eclToFractureTransCalc(caseToApply, + fracture->transformMatrix(), + fracture->attachedFractureDefinition()->skinFactor, + cDarcyInCorrectUnit, + fractureCell); + + const std::vector& fractureCellContributingEclipseCells = eclToFractureTransCalc.globalIndeciesToContributingEclipseCells(); + const std::vector& fractureCellContributingEclipseCellTransmissibilities = eclToFractureTransCalc.contributingEclipseCellTransmissibilities(); + + size_t stimPlanCellIndex = fractureGrid->getGlobalIndexFromIJ(fractureCell.getI(), fractureCell.getJ()); + + for (size_t i = 0; i < fractureCellContributingEclipseCells.size(); i++) + { + transCondenser.addNeighborTransmissibility({ true, CellIdxSpace::ECLIPSE, fractureCellContributingEclipseCells[i] }, + { false, CellIdxSpace::STIMPLAN, stimPlanCellIndex }, + fractureCellContributingEclipseCellTransmissibilities[i]); + } + } + + ////// + // Calculate Transmissibility in the fracture: From one StimPlan Cell to the other + + for (size_t i = 0; i < fractureGrid->iCellCount(); i++) + { + for (size_t j = 0; j < fractureGrid->jCellCount(); j++) + { + size_t fractureCellIndex = fractureGrid->getGlobalIndexFromIJ(i, j); + const RigFractureCell fractureCell = fractureGrid->cellFromIndex(fractureCellIndex); + + if (fractureCell.getConductivtyValue() < 1e-7) continue; + + if (i < fractureGrid->iCellCount()-1) + { + size_t fractureCellNeighbourXIndex = fractureGrid->getGlobalIndexFromIJ(i + 1, j); + const RigFractureCell fractureCellNeighbourX = fractureGrid->cellFromIndex(fractureCellNeighbourXIndex); + + double horizontalTransToXneigbour = + RigFractureTransmissibilityEquations::centerToCenterFractureCellTrans(fractureCell.getConductivtyValue(), + fractureCell.cellSizeX(), + fractureCell.cellSizeZ(), + fractureCellNeighbourX.getConductivtyValue(), + fractureCellNeighbourX.cellSizeX(), + fractureCellNeighbourX.cellSizeZ(), + cDarcyInCorrectUnit); + + transCondenser.addNeighborTransmissibility({ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellIndex }, + { false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellNeighbourXIndex }, + horizontalTransToXneigbour); + + } + + if (j < fractureGrid->jCellCount()-1) + { + size_t fractureCellNeighbourZIndex = fractureGrid->getGlobalIndexFromIJ(i, j + 1); + const RigFractureCell fractureCellNeighbourZ = fractureGrid->cellFromIndex(fractureCellNeighbourZIndex); + + double verticalTransToZneigbour = + RigFractureTransmissibilityEquations::centerToCenterFractureCellTrans(fractureCell.getConductivtyValue(), + fractureCell.cellSizeZ(), + fractureCell.cellSizeX(), + fractureCellNeighbourZ.getConductivtyValue(), + fractureCellNeighbourZ.cellSizeZ(), + fractureCellNeighbourZ.cellSizeX(), + cDarcyInCorrectUnit); + + transCondenser.addNeighborTransmissibility({ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellIndex }, + { false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellNeighbourZIndex }, + verticalTransToZneigbour); + + } + } + } + + ///// + // Calculate transmissibility into the well + + RigWellPathStimplanIntersector wellFractureIntersector(wellPath->wellPathGeometry(), fracture); + const std::map& fractureWellCells = wellFractureIntersector.intersections(); + + for (const auto& fracCellIdxIsectDataPair : fractureWellCells) + { + size_t fracWellCellIdx = fracCellIdxIsectDataPair.first; + RigWellPathStimplanIntersector::WellCellIntersection intersection = fracCellIdxIsectDataPair.second; + + const RigFractureCell fractureWellCell = fractureGrid->cellFromIndex(fracWellCellIdx); + + double radialTrans = 0.0; + if (intersection.endpointCount) + { + radialTrans = RigFractureTransmissibilityEquations::fractureCellToWellRadialTrans(fractureWellCell.getConductivtyValue(), + fractureWellCell.cellSizeX(), + fractureWellCell.cellSizeZ(), + fracture->wellRadius(), + fracTemplate->skinFactor(), + cDarcyInCorrectUnit); + } + + double linearTrans = 0.0; + if (intersection.hlength > 0.0 || intersection.vlength > 0.0 ) + { + linearTrans = RigFractureTransmissibilityEquations::fractureCellToWellLinearTrans(fractureWellCell.getConductivtyValue(), + fractureWellCell.cellSizeX(), + fractureWellCell.cellSizeZ(), + intersection.vlength, + intersection.hlength , + fracture->perforationEfficiency, + fracTemplate->skinFactor(), + cDarcyInCorrectUnit); + } + + double totalWellTrans = 0.5 * intersection.endpointCount * radialTrans + linearTrans; + + transCondenser.addNeighborTransmissibility( { true, RigTransmissibilityCondenser::CellAddress::WELL, 1}, + { false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fracWellCellIdx }, + totalWellTrans); + } + + ///// + // Insert total transmissibility from eclipse-cell to well for this fracture into the map + + std::set externalCells = transCondenser.externalCells(); + for (RigTransmissibilityCondenser::CellAddress externalCell : externalCells) + { + if (externalCell.m_cellIndexSpace == RigTransmissibilityCondenser::CellAddress::ECLIPSE) + { + double trans = transCondenser.condensedTransmissibility(externalCell, { true, RigTransmissibilityCondenser::CellAddress::WELL, 1 }); + + eclCellIdxToTransPrFractureMap[externalCell.m_globalCellIdx][fracture] = trans; + size_t i, j, k; + mainGrid->ijkFromCellIndex(externalCell.m_globalCellIdx, &i, &j, &k); + + RigCompletionData compDat(wellPath->name(), {i,j,k} ); + compDat.setFromFracture(trans, fracture->attachedFractureDefinition()->skinFactor()); + compDat.addMetadata(fracture->name(), QString::number(trans)); + fractureCompletions.push_back(compDat); + } + } + + if ( outputStreamForIntermediateResultsText ) + { + (*outputStreamForIntermediateResultsText) << "\n" << "\n" << "\n----------- All Transimissibilities " << fracture->name() << " -------------------- \n\n"; + (*outputStreamForIntermediateResultsText) << QString::fromStdString(transCondenser.neighborTransDebugOutput(mainGrid, fractureGrid)); + (*outputStreamForIntermediateResultsText) << "\n" << "\n" << "\n----------- Condensed Results " << fracture->name() << " -------------------- \n\n"; + (*outputStreamForIntermediateResultsText) << QString::fromStdString(transCondenser.condensedTransDebugOutput(mainGrid, fractureGrid)); + (*outputStreamForIntermediateResultsText) << "\n" ; + } + } + + return fractureCompletions; + +} + + diff --git a/ApplicationCode/Commands/CompletionCommands/RicExportFractureCompletionsImpl.h b/ApplicationCode/Commands/CompletionCommands/RicExportFractureCompletionsImpl.h new file mode 100644 index 0000000000..1465d9e332 --- /dev/null +++ b/ApplicationCode/Commands/CompletionCommands/RicExportFractureCompletionsImpl.h @@ -0,0 +1,33 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +class RimWellPath; +class RicExportCompletionDataSettingsUi; + +#include +#include "RigCompletionData.h" +class QTextStream; + +class RicExportFractureCompletionsImpl +{ +public: + static std::vector generateFracturesCompdatValues(const RimWellPath* wellPath, + const RicExportCompletionDataSettingsUi& settings, + QTextStream* outputStreamForIntermediateResultsText); + +}; diff --git a/ApplicationCode/Commands/CompletionCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/CompletionCommands/RicWellPathExportCompletionDataFeature.cpp index 9ec3a8fec3..7d51e33d58 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/CompletionCommands/RicWellPathExportCompletionDataFeature.cpp @@ -48,6 +48,7 @@ #include #include #include +#include "RicExportFractureCompletionsImpl.h" CAF_CMD_SOURCE_INIT(RicWellPathExportCompletionDataFeature, "RicWellPathExportCompletionDataFeature"); @@ -169,6 +170,13 @@ void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector appendCompletionData(&completionData, fishbonesWellPathCompletionData); } + if (exportSettings.includeFractures()) + { + std::vector fractureCompletionData = + RicExportFractureCompletionsImpl::generateFracturesCompdatValues(wellPath, exportSettings, &stream); + appendCompletionData(&completionData, fractureCompletionData); + } + // Merge map into a vector of values std::vector completions; for (auto& data : completionData) diff --git a/ApplicationCode/ReservoirDataModel/RigEclipseToStimPlanCellTransmissibilityCalculator.h b/ApplicationCode/ReservoirDataModel/RigEclipseToStimPlanCellTransmissibilityCalculator.h index 2cd4235d8d..a2b68d48c7 100644 --- a/ApplicationCode/ReservoirDataModel/RigEclipseToStimPlanCellTransmissibilityCalculator.h +++ b/ApplicationCode/ReservoirDataModel/RigEclipseToStimPlanCellTransmissibilityCalculator.h @@ -51,7 +51,7 @@ private: double m_cDarcy; double m_fractureSkinFactor; cvf::Mat4f m_fractureTransform; - const RigFractureCell& m_stimPlanCell; + const RigFractureCell& m_stimPlanCell; std::vector m_globalIndeciesToContributingEclipseCells; std::vector m_contributingEclipseCellTransmissibilities;