#1493 Include fracture export in the Export Completions Command

This commit is contained in:
Jacob Støren 2017-06-01 16:34:30 +02:00
parent 0318a8c455
commit 252defd96a
7 changed files with 273 additions and 1 deletions

View File

@ -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

View File

@ -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", "", "", "");

View File

@ -35,6 +35,7 @@ public:
caf::PdmField<bool> includePerforations;
caf::PdmField<bool> includeFishbones;
caf::PdmField<bool> includeFractures;
caf::PdmField<bool> includeWpimult;
caf::PdmField<bool> removeLateralsInMainBoreCells;

View File

@ -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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicExportFractureCompletionsImpl.h"
#include <vector>
#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<RigCompletionData> RicExportFractureCompletionsImpl::generateFracturesCompdatValues(const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings,
QTextStream* outputStreamForIntermediateResultsText)
{
const RimEclipseCase* caseToApply = settings.caseToApply();
std::vector<RimFracture*> 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 <eclipseCellIndex ,map< fracture, trans> >
std::map <size_t, std::map<RimFracture*, double> > eclCellIdxToTransPrFractureMap;
std::vector<RigCompletionData> 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<RigFractureCell> 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<size_t>& fractureCellContributingEclipseCells = eclToFractureTransCalc.globalIndeciesToContributingEclipseCells();
const std::vector<double>& 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<size_t, RigWellPathStimplanIntersector::WellCellIntersection >& 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<RigTransmissibilityCondenser::CellAddress> 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;
}

View File

@ -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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
class RimWellPath;
class RicExportCompletionDataSettingsUi;
#include <vector>
#include "RigCompletionData.h"
class QTextStream;
class RicExportFractureCompletionsImpl
{
public:
static std::vector<RigCompletionData> generateFracturesCompdatValues(const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings,
QTextStream* outputStreamForIntermediateResultsText);
};

View File

@ -48,6 +48,7 @@
#include <QAction>
#include <QFileDialog>
#include <QMessageBox>
#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<RigCompletionData> fractureCompletionData =
RicExportFractureCompletionsImpl::generateFracturesCompdatValues(wellPath, exportSettings, &stream);
appendCompletionData(&completionData, fractureCompletionData);
}
// Merge map into a vector of values
std::vector<RigCompletionData> completions;
for (auto& data : completionData)

View File

@ -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<size_t> m_globalIndeciesToContributingEclipseCells;
std::vector<double> m_contributingEclipseCellTransmissibilities;