2017-06-01 09:34:30 -05:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Copyright (C) 2017- Statoil ASA
|
2018-08-09 04:30:18 -05:00
|
|
|
//
|
2017-06-01 09:34:30 -05:00
|
|
|
// 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.
|
2018-08-09 04:30:18 -05:00
|
|
|
//
|
2017-06-01 09:34:30 -05:00
|
|
|
// 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.
|
2018-08-09 04:30:18 -05:00
|
|
|
//
|
|
|
|
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
2017-06-01 09:34:30 -05:00
|
|
|
// for more details.
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include "RicExportFractureCompletionsImpl.h"
|
|
|
|
|
2018-08-09 04:33:48 -05:00
|
|
|
#include "RicWellPathFractureReportItem.h"
|
|
|
|
|
2017-07-31 08:10:07 -05:00
|
|
|
#include "RiaLogging.h"
|
|
|
|
|
2017-06-12 05:03:42 -05:00
|
|
|
#include "RimEclipseCase.h"
|
2017-10-13 02:29:42 -05:00
|
|
|
#include "RimEclipseView.h"
|
2017-06-01 09:34:30 -05:00
|
|
|
#include "RimFracture.h"
|
2018-05-30 07:01:50 -05:00
|
|
|
#include "RimFractureContainmentTools.h"
|
2017-06-12 05:03:42 -05:00
|
|
|
#include "RimFractureTemplate.h"
|
2017-10-13 02:29:42 -05:00
|
|
|
#include "RimSimWellFracture.h"
|
2017-06-12 05:03:42 -05:00
|
|
|
#include "RimSimWellFractureCollection.h"
|
2017-10-13 02:29:42 -05:00
|
|
|
#include "RimSimWellInView.h"
|
2017-07-03 06:55:59 -05:00
|
|
|
#include "RimStimPlanFractureTemplate.h"
|
2017-10-13 02:29:42 -05:00
|
|
|
#include "RimWellPath.h"
|
2017-08-08 07:11:05 -05:00
|
|
|
#include "RimWellPathCompletions.h"
|
2017-12-22 07:08:29 -06:00
|
|
|
#include "RimWellPathFracture.h"
|
|
|
|
#include "RimWellPathFractureCollection.h"
|
2017-06-12 05:03:42 -05:00
|
|
|
|
2018-08-09 04:33:48 -05:00
|
|
|
#include "RigCaseCellResultsData.h"
|
2017-06-01 09:34:30 -05:00
|
|
|
#include "RigEclipseCaseData.h"
|
2018-08-09 04:33:48 -05:00
|
|
|
#include "RigEclipseToStimPlanCalculator.h"
|
2018-08-09 04:30:18 -05:00
|
|
|
#include "RigEclipseToStimPlanCellTransmissibilityCalculator.h"
|
2017-06-01 09:34:30 -05:00
|
|
|
#include "RigFractureCell.h"
|
|
|
|
#include "RigFractureGrid.h"
|
|
|
|
#include "RigFractureTransmissibilityEquations.h"
|
|
|
|
#include "RigMainGrid.h"
|
2018-08-09 04:33:48 -05:00
|
|
|
#include "RigResultAccessorFactory.h"
|
2017-10-13 06:44:53 -05:00
|
|
|
#include "RigSimWellData.h"
|
2017-06-12 05:03:42 -05:00
|
|
|
#include "RigSimulationWellCoordsAndMD.h"
|
2018-08-09 04:30:18 -05:00
|
|
|
#include "RigTransmissibilityCondenser.h"
|
2018-08-09 04:33:48 -05:00
|
|
|
#include "RigTransmissibilityEquations.h"
|
2017-06-12 05:03:42 -05:00
|
|
|
#include "RigWellPath.h"
|
2018-08-09 04:30:18 -05:00
|
|
|
#include "RigWellPathStimplanIntersector.h"
|
2017-06-12 05:03:42 -05:00
|
|
|
|
|
|
|
#include <vector>
|
2017-06-01 09:34:30 -05:00
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2018-08-09 04:30:18 -05:00
|
|
|
///
|
2017-06-01 09:34:30 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2018-08-09 04:33:48 -05:00
|
|
|
std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateCompdatValuesForWellPath(
|
|
|
|
RimWellPath* wellPath,
|
|
|
|
RimEclipseCase* caseToApply,
|
|
|
|
std::vector<RicWellPathFractureReportItem>* fractureDataForReport,
|
|
|
|
QTextStream* outputStreamForIntermediateResultsText)
|
2017-06-01 09:34:30 -05:00
|
|
|
{
|
2018-08-24 03:49:34 -05:00
|
|
|
std::vector<const RimFracture*> fracturesAlongWellPath;
|
2017-12-22 07:08:29 -06:00
|
|
|
|
2018-09-07 06:32:53 -05:00
|
|
|
for (auto& frac : wellPath->fractureCollection()->activeFractures())
|
2017-12-22 07:08:29 -06:00
|
|
|
{
|
2018-09-07 06:32:53 -05:00
|
|
|
frac->ensureValidNonDarcyProperties();
|
2018-08-15 02:44:27 -05:00
|
|
|
|
2018-09-07 06:32:53 -05:00
|
|
|
fracturesAlongWellPath.push_back(frac);
|
2017-12-22 07:08:29 -06:00
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
|
2018-08-03 06:35:03 -05:00
|
|
|
return generateCompdatValues(caseToApply,
|
|
|
|
wellPath->completions()->wellNameForExport(),
|
|
|
|
wellPath->wellPathGeometry(),
|
|
|
|
fracturesAlongWellPath,
|
2018-08-09 04:33:48 -05:00
|
|
|
fractureDataForReport,
|
2018-08-03 06:35:03 -05:00
|
|
|
outputStreamForIntermediateResultsText);
|
|
|
|
}
|
|
|
|
|
2017-06-12 05:03:42 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2018-08-09 04:30:18 -05:00
|
|
|
///
|
2017-06-12 05:03:42 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2018-08-09 04:30:18 -05:00
|
|
|
std::vector<RigCompletionData>
|
|
|
|
RicExportFractureCompletionsImpl::generateCompdatValuesForSimWell(RimEclipseCase* eclipseCase,
|
|
|
|
const RimSimWellInView* well,
|
|
|
|
QTextStream* outputStreamForIntermediateResultsText)
|
2017-06-12 05:03:42 -05:00
|
|
|
{
|
|
|
|
std::vector<RigCompletionData> completionData;
|
|
|
|
|
2018-03-02 06:54:42 -06:00
|
|
|
auto branches = well->wellPipeBranches();
|
2017-07-31 08:10:07 -05:00
|
|
|
|
2018-03-02 06:54:42 -06:00
|
|
|
for (size_t branchIndex = 0; branchIndex < branches.size(); ++branchIndex)
|
2017-06-12 05:03:42 -05:00
|
|
|
{
|
2018-08-24 03:49:34 -05:00
|
|
|
std::vector<const RimFracture*> fractures;
|
2017-06-12 05:03:42 -05:00
|
|
|
for (RimSimWellFracture* fracture : well->simwellFractureCollection->simwellFractures())
|
|
|
|
{
|
2017-12-22 07:23:42 -06:00
|
|
|
if (fracture->isChecked() && static_cast<size_t>(fracture->branchIndex()) == branchIndex)
|
2017-06-12 05:03:42 -05:00
|
|
|
{
|
|
|
|
fractures.push_back(fracture);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-09 04:30:18 -05:00
|
|
|
std::vector<RigCompletionData> branchCompletions = generateCompdatValues(
|
2018-08-09 04:33:48 -05:00
|
|
|
eclipseCase, well->name(), branches[branchIndex], fractures, nullptr, outputStreamForIntermediateResultsText);
|
2017-06-12 05:03:42 -05:00
|
|
|
|
|
|
|
completionData.insert(completionData.end(), branchCompletions.begin(), branchCompletions.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
return completionData;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2018-08-09 04:30:18 -05:00
|
|
|
///
|
2017-06-12 05:03:42 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2018-08-09 04:30:18 -05:00
|
|
|
std::vector<RigCompletionData>
|
2018-08-09 04:33:48 -05:00
|
|
|
RicExportFractureCompletionsImpl::generateCompdatValues(RimEclipseCase* caseToApply,
|
|
|
|
const QString& wellPathName,
|
|
|
|
const RigWellPath* wellPathGeometry,
|
2018-08-27 06:04:25 -05:00
|
|
|
const std::vector<const RimFracture*>& fractures,
|
2018-08-09 04:33:48 -05:00
|
|
|
std::vector<RicWellPathFractureReportItem>* fractureDataReportItems,
|
2018-08-09 04:30:18 -05:00
|
|
|
QTextStream* outputStreamForIntermediateResultsText)
|
2017-06-12 05:03:42 -05:00
|
|
|
{
|
2018-08-03 03:30:44 -05:00
|
|
|
std::vector<RigCompletionData> fractureCompletions;
|
|
|
|
|
2018-08-09 04:30:18 -05:00
|
|
|
if (!caseToApply || !caseToApply->eclipseCaseData())
|
2018-08-03 03:30:44 -05:00
|
|
|
{
|
|
|
|
return fractureCompletions;
|
|
|
|
}
|
|
|
|
|
2018-08-24 02:59:37 -05:00
|
|
|
{
|
|
|
|
// Load the data required by computations to be able to use const access only inside OpenMP loop
|
|
|
|
|
|
|
|
std::vector<QString> resultNames = RigEclipseToStimPlanCellTransmissibilityCalculator::requiredResultNames();
|
|
|
|
|
|
|
|
if (!caseToApply->loadStaticResultsByName(resultNames))
|
|
|
|
{
|
|
|
|
QString msg;
|
|
|
|
msg += "Compdat Export : Required data missing. Required results ";
|
|
|
|
|
|
|
|
for (const auto& r : resultNames)
|
|
|
|
{
|
|
|
|
msg += " ";
|
|
|
|
msg += r;
|
|
|
|
}
|
|
|
|
RiaLogging::error(msg);
|
|
|
|
|
|
|
|
return fractureCompletions;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-24 03:17:33 -05:00
|
|
|
{
|
|
|
|
// Load the data required by fracture summary header
|
|
|
|
|
|
|
|
std::vector<QString> resultNames{"TRANX", "TRANY", "TRANZ"};
|
|
|
|
|
|
|
|
caseToApply->loadStaticResultsByName(resultNames);
|
|
|
|
}
|
|
|
|
|
2018-08-24 02:59:37 -05:00
|
|
|
{
|
|
|
|
// Optional results
|
|
|
|
std::vector<QString> resultNames = RigEclipseToStimPlanCellTransmissibilityCalculator::optionalResultNames();
|
|
|
|
|
|
|
|
caseToApply->loadStaticResultsByName(resultNames);
|
|
|
|
}
|
|
|
|
|
2018-08-27 06:04:25 -05:00
|
|
|
return generateCompdatValuesConst(
|
|
|
|
caseToApply, wellPathName, wellPathGeometry, fractures, fractureDataReportItems, outputStreamForIntermediateResultsText);
|
2018-08-24 03:49:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateCompdatValuesConst(
|
|
|
|
const RimEclipseCase* caseToApply,
|
|
|
|
const QString& wellPathName,
|
|
|
|
const RigWellPath* wellPathGeometry,
|
|
|
|
const std::vector<const RimFracture*>& fractures,
|
|
|
|
std::vector<RicWellPathFractureReportItem>* fractureDataReportItems,
|
|
|
|
QTextStream* outputStreamForIntermediateResultsText)
|
|
|
|
{
|
|
|
|
std::vector<RigCompletionData> fractureCompletions;
|
|
|
|
|
|
|
|
if (!caseToApply || !caseToApply->eclipseCaseData())
|
|
|
|
{
|
|
|
|
return fractureCompletions;
|
|
|
|
}
|
|
|
|
|
|
|
|
double cDarcyInCorrectUnit = RiaEclipseUnitTools::darcysConstant(caseToApply->eclipseCaseData()->unitsType());
|
|
|
|
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<const RimFracture*, double>> eclCellIdxToTransPrFractureMap;
|
|
|
|
|
|
|
|
std::vector<std::vector<RigCompletionData>> sharedComplForFracture(fractures.size());
|
|
|
|
|
2018-08-27 01:49:45 -05:00
|
|
|
#pragma omp parallel for
|
2018-08-20 04:47:05 -05:00
|
|
|
for (int i = 0; i < (int)fractures.size(); i++)
|
2017-06-01 09:34:30 -05:00
|
|
|
{
|
2018-08-24 03:49:34 -05:00
|
|
|
const RimFracture* fracture = fractures[i];
|
|
|
|
const RimFractureTemplate* fracTemplate = fracture->fractureTemplate();
|
2018-01-02 05:53:52 -06:00
|
|
|
|
|
|
|
if (!fracTemplate) continue;
|
|
|
|
|
2017-06-01 09:34:30 -05:00
|
|
|
const RigFractureGrid* fractureGrid = fracTemplate->fractureGrid();
|
2018-01-15 01:58:51 -06:00
|
|
|
if (!fractureGrid) continue;
|
|
|
|
|
|
|
|
bool useFiniteConductivityInFracture = (fracTemplate->conductivityType() == RimFractureTemplate::FINITE_CONDUCTIVITY);
|
2017-06-01 09:34:30 -05:00
|
|
|
|
2018-08-09 04:30:18 -05:00
|
|
|
// If finite cond chosen and conductivity not present in stimplan file, do not calculate trans for this fracture
|
2018-09-10 06:00:39 -05:00
|
|
|
if (useFiniteConductivityInFracture && !checkForStimPlanConductivity(fracTemplate, fracture))
|
2017-07-03 06:55:59 -05:00
|
|
|
{
|
2018-09-10 06:00:39 -05:00
|
|
|
continue;
|
2017-07-03 06:55:59 -05:00
|
|
|
}
|
|
|
|
|
2017-06-01 09:34:30 -05:00
|
|
|
RigTransmissibilityCondenser transCondenser;
|
|
|
|
|
|
|
|
//////
|
2018-08-09 04:30:18 -05:00
|
|
|
// Calculate Matrix To Fracture Trans
|
2018-08-15 02:44:27 -05:00
|
|
|
RigEclipseToStimPlanCalculator eclToFractureCalc(
|
|
|
|
caseToApply, fracture->transformMatrix(), fracTemplate->skinFactor(), cDarcyInCorrectUnit, *fractureGrid);
|
2017-06-01 09:34:30 -05:00
|
|
|
|
2018-08-09 04:33:48 -05:00
|
|
|
eclToFractureCalc.appendDataToTransmissibilityCondenser(fracture, useFiniteConductivityInFracture, &transCondenser);
|
2017-06-01 09:34:30 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
if (useFiniteConductivityInFracture)
|
|
|
|
{
|
|
|
|
calculateInternalFractureTransmissibilities(fractureGrid, cDarcyInCorrectUnit, transCondenser);
|
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
|
2017-06-20 09:35:06 -05:00
|
|
|
if (useFiniteConductivityInFracture)
|
2017-06-01 09:34:30 -05:00
|
|
|
{
|
2018-09-10 06:00:39 -05:00
|
|
|
calculateFractureToWellTransmissibilities(fracTemplate, fractureGrid, fracture, cDarcyInCorrectUnit, wellPathGeometry, transCondenser);
|
2017-06-09 02:28:24 -05:00
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
|
|
|
|
/////
|
2018-09-10 06:00:39 -05:00
|
|
|
// Insert total transmissibility from eclipse-cell to well for this fracture into the map
|
|
|
|
std::map<size_t, double> matrixToWellTrans = calculateMatrixToWellTransmissibilities(transCondenser);
|
|
|
|
std::vector<RigCompletionData> allCompletionsForOneFracture = generateCompdatValuesForFracture(matrixToWellTrans, wellPathName, caseToApply, fracture, fracTemplate);
|
2018-08-09 04:30:18 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
if (fracTemplate->isNonDarcyFlowEnabled())
|
2017-06-02 08:04:32 -05:00
|
|
|
{
|
2018-09-10 06:00:39 -05:00
|
|
|
computeNonDarcyFlowParameters(fracture, allCompletionsForOneFracture);
|
|
|
|
}
|
2017-06-14 05:44:08 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
if (fractureDataReportItems)
|
|
|
|
{
|
|
|
|
QString fractureTemplateName = fracTemplate->name();
|
|
|
|
RicWellPathFractureReportItem reportItem(wellPathName, fracture->name(), fractureTemplateName);
|
2018-08-15 02:44:27 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
auto cellAreas = eclToFractureCalc.eclipseCellAreas();
|
2018-08-15 02:44:27 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
double fcd = -1.0;
|
|
|
|
double area = sumUpCellAreas(cellAreas);
|
|
|
|
double transmissibility = sumUpTransmissibilities(allCompletionsForOneFracture);
|
2018-08-15 02:44:27 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
reportItem.setData(transmissibility, allCompletionsForOneFracture.size(), fcd, area);
|
|
|
|
|
|
|
|
calculateAndSetLengthsAndConductivity(fracTemplate, area, reportItem);
|
|
|
|
calculateAndSetAreaWeightedTransmissibility(caseToApply, cellAreas, area, reportItem);
|
|
|
|
|
|
|
|
fractureDataReportItems->push_back(reportItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::copy(allCompletionsForOneFracture.begin(),
|
|
|
|
allCompletionsForOneFracture.end(),
|
|
|
|
std::back_inserter(sharedComplForFracture[i]));
|
|
|
|
|
|
|
|
if (outputStreamForIntermediateResultsText)
|
|
|
|
{
|
|
|
|
#pragma omp critical(critical_section_outputStreamForIntermediateResultsText)
|
2017-06-09 02:28:24 -05:00
|
|
|
{
|
2018-09-10 06:00:39 -05:00
|
|
|
outputIntermediateResultsText(outputStreamForIntermediateResultsText, fracture, transCondenser, mainGrid, fractureGrid);
|
2017-06-02 08:04:32 -05:00
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
}
|
2018-09-10 06:00:39 -05:00
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
for (const auto& completions : sharedComplForFracture)
|
|
|
|
{
|
|
|
|
std::copy(completions.begin(), completions.end(), std::back_inserter(fractureCompletions));
|
|
|
|
}
|
|
|
|
return fractureCompletions;
|
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
bool RicExportFractureCompletionsImpl::checkForStimPlanConductivity(const RimFractureTemplate* fracTemplate, const RimFracture* fracture)
|
|
|
|
{
|
|
|
|
auto fracTemplateStimPlan = dynamic_cast<const RimStimPlanFractureTemplate*>(fracTemplate);
|
|
|
|
if (fracTemplateStimPlan)
|
|
|
|
{
|
|
|
|
if (!fracTemplateStimPlan->hasConductivity())
|
|
|
|
{
|
|
|
|
RiaLogging::error("Trying to export completion data for stimPlan fracture without conductivity data for " +
|
|
|
|
fracture->name());
|
|
|
|
RiaLogging::error("No transmissibilities will be calculated for " + fracture->name());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2018-02-16 00:58:07 -06:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RicExportFractureCompletionsImpl::calculateInternalFractureTransmissibilities(const RigFractureGrid* fractureGrid, double cDarcyInCorrectUnit, RigTransmissibilityCondenser &transCondenser)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < fractureGrid->iCellCount(); i++)
|
|
|
|
{
|
|
|
|
for (size_t j = 0; j < fractureGrid->jCellCount(); j++)
|
2017-06-01 09:34:30 -05:00
|
|
|
{
|
2018-09-10 06:00:39 -05:00
|
|
|
size_t fractureCellIndex = fractureGrid->getGlobalIndexFromIJ(i, j);
|
|
|
|
|
|
|
|
const RigFractureCell& fractureCell = fractureGrid->cellFromIndex(fractureCellIndex);
|
|
|
|
|
|
|
|
if (!fractureCell.hasNonZeroConductivity()) continue;
|
|
|
|
|
|
|
|
if (i < fractureGrid->iCellCount() - 1)
|
2017-06-01 09:34:30 -05:00
|
|
|
{
|
2018-09-10 06:00:39 -05:00
|
|
|
size_t fractureCellNeighbourXIndex = fractureGrid->getGlobalIndexFromIJ(i + 1, j);
|
|
|
|
const RigFractureCell& fractureCellNeighbourX = fractureGrid->cellFromIndex(fractureCellNeighbourXIndex);
|
|
|
|
|
|
|
|
double horizontalTransToXneigbour = RigFractureTransmissibilityEquations::centerToCenterFractureCellTrans(
|
|
|
|
fractureCell.getConductivityValue(),
|
|
|
|
fractureCell.cellSizeX(),
|
|
|
|
fractureCell.cellSizeZ(),
|
|
|
|
fractureCellNeighbourX.getConductivityValue(),
|
|
|
|
fractureCellNeighbourX.cellSizeX(),
|
|
|
|
fractureCellNeighbourX.cellSizeZ(),
|
|
|
|
cDarcyInCorrectUnit);
|
2018-08-09 04:30:18 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
transCondenser.addNeighborTransmissibility(
|
|
|
|
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellIndex },
|
|
|
|
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellNeighbourXIndex },
|
|
|
|
horizontalTransToXneigbour);
|
|
|
|
}
|
2017-08-24 03:27:02 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
if (j < fractureGrid->jCellCount() - 1)
|
|
|
|
{
|
|
|
|
size_t fractureCellNeighbourZIndex = fractureGrid->getGlobalIndexFromIJ(i, j + 1);
|
|
|
|
const RigFractureCell& fractureCellNeighbourZ = fractureGrid->cellFromIndex(fractureCellNeighbourZIndex);
|
|
|
|
|
|
|
|
double verticalTransToZneigbour = RigFractureTransmissibilityEquations::centerToCenterFractureCellTrans(
|
|
|
|
fractureCell.getConductivityValue(),
|
|
|
|
fractureCell.cellSizeZ(),
|
|
|
|
fractureCell.cellSizeX(),
|
|
|
|
fractureCellNeighbourZ.getConductivityValue(),
|
|
|
|
fractureCellNeighbourZ.cellSizeZ(),
|
|
|
|
fractureCellNeighbourZ.cellSizeX(),
|
|
|
|
cDarcyInCorrectUnit);
|
2018-02-07 07:07:49 -06:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
transCondenser.addNeighborTransmissibility(
|
|
|
|
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellIndex },
|
|
|
|
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellNeighbourZIndex },
|
|
|
|
verticalTransToZneigbour);
|
2017-06-01 09:34:30 -05:00
|
|
|
}
|
|
|
|
}
|
2018-09-10 06:00:39 -05:00
|
|
|
}
|
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RicExportFractureCompletionsImpl::calculateFractureToWellTransmissibilities(const RimFractureTemplate* fracTemplate, const RigFractureGrid* fractureGrid, const RimFracture* fracture, double cDarcyInCorrectUnit, const RigWellPath* wellPathGeometry, RigTransmissibilityCondenser &transCondenser)
|
|
|
|
{
|
|
|
|
////
|
|
|
|
// If fracture has orientation Azimuth or Transverse, assume only radial inflow
|
2018-02-16 00:58:07 -06:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
if (fracTemplate->orientationType() == RimFractureTemplate::AZIMUTH ||
|
|
|
|
fracTemplate->orientationType() == RimFractureTemplate::TRANSVERSE_WELL_PATH)
|
|
|
|
{
|
|
|
|
std::pair<size_t, size_t> wellCellIJ = fractureGrid->fractureCellAtWellCenter();
|
|
|
|
size_t wellCellIndex = fractureGrid->getGlobalIndexFromIJ(wellCellIJ.first, wellCellIJ.second);
|
|
|
|
|
|
|
|
const RigFractureCell& wellCell = fractureGrid->cellFromIndex(wellCellIndex);
|
|
|
|
|
|
|
|
double radialTrans =
|
|
|
|
RigFractureTransmissibilityEquations::fractureCellToWellRadialTrans(wellCell.getConductivityValue(),
|
|
|
|
wellCell.cellSizeX(),
|
|
|
|
wellCell.cellSizeZ(),
|
|
|
|
fracture->wellRadius(),
|
|
|
|
fracTemplate->skinFactor(),
|
|
|
|
cDarcyInCorrectUnit);
|
|
|
|
|
|
|
|
transCondenser.addNeighborTransmissibility(
|
|
|
|
{ true, RigTransmissibilityCondenser::CellAddress::WELL, 1 },
|
|
|
|
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, wellCellIndex },
|
|
|
|
radialTrans);
|
|
|
|
}
|
|
|
|
else if (fracTemplate->orientationType() == RimFractureTemplate::ALONG_WELL_PATH)
|
|
|
|
{
|
|
|
|
////
|
|
|
|
// If fracture has orientation along well, linear inflow along well and radial flow at endpoints
|
|
|
|
|
|
|
|
RigWellPathStimplanIntersector wellFractureIntersector(wellPathGeometry, fracture);
|
|
|
|
const std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection>& fractureWellCells =
|
|
|
|
wellFractureIntersector.intersections();
|
|
|
|
|
|
|
|
for (const auto& fracCellIdxIsectDataPair : fractureWellCells)
|
2018-02-16 00:58:07 -06:00
|
|
|
{
|
2018-09-10 06:00:39 -05:00
|
|
|
size_t fracWellCellIdx = fracCellIdxIsectDataPair.first;
|
|
|
|
|
|
|
|
RigWellPathStimplanIntersector::WellCellIntersection intersection = fracCellIdxIsectDataPair.second;
|
2018-02-16 00:58:07 -06:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
const RigFractureCell& fractureWellCell = fractureGrid->cellFromIndex(fracWellCellIdx);
|
|
|
|
|
|
|
|
double linearTrans = 0.0;
|
|
|
|
if (intersection.hlength > 0.0 || intersection.vlength > 0.0)
|
2018-02-16 00:58:07 -06:00
|
|
|
{
|
2018-09-10 06:00:39 -05:00
|
|
|
linearTrans = RigFractureTransmissibilityEquations::fractureCellToWellLinearTrans(
|
|
|
|
fractureWellCell.getConductivityValue(),
|
|
|
|
fractureWellCell.cellSizeX(),
|
|
|
|
fractureWellCell.cellSizeZ(),
|
|
|
|
intersection.vlength,
|
|
|
|
intersection.hlength,
|
|
|
|
fracture->perforationEfficiency(),
|
|
|
|
fracTemplate->skinFactor(),
|
|
|
|
cDarcyInCorrectUnit);
|
2018-02-16 00:58:07 -06:00
|
|
|
}
|
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
transCondenser.addNeighborTransmissibility(
|
|
|
|
{ true, RigTransmissibilityCondenser::CellAddress::WELL, 1 },
|
|
|
|
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fracWellCellIdx },
|
|
|
|
linearTrans);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-16 00:58:07 -06:00
|
|
|
|
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
std::map<size_t, double> RicExportFractureCompletionsImpl::calculateMatrixToWellTransmissibilities(RigTransmissibilityCondenser &transCondenser)
|
|
|
|
{
|
|
|
|
std::map<size_t, double> matrixToWellTransmissibilities;
|
|
|
|
|
|
|
|
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 });
|
|
|
|
|
|
|
|
matrixToWellTransmissibilities.insert(std::make_pair(externalCell.m_globalCellIdx, trans));
|
2018-02-16 04:22:13 -06:00
|
|
|
|
2018-02-16 00:58:07 -06:00
|
|
|
}
|
2018-09-10 06:00:39 -05:00
|
|
|
}
|
|
|
|
return matrixToWellTransmissibilities;
|
|
|
|
}
|
2018-02-16 00:58:07 -06:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateCompdatValuesForFracture(const std::map<size_t, double>& matrixToWellTransmissibilites, const QString& wellPathName, const RimEclipseCase* caseToApply, const RimFracture* fracture, const RimFractureTemplate* fracTemplate)
|
|
|
|
{
|
|
|
|
std::vector<RigCompletionData> allCompletionsForOneFracture;
|
|
|
|
for (const auto& matrixToWellTransmissibility : matrixToWellTransmissibilites)
|
|
|
|
{
|
|
|
|
size_t globalCellIndex = matrixToWellTransmissibility.first;
|
|
|
|
double trans = matrixToWellTransmissibility.second;
|
|
|
|
RigCompletionData compDat(wellPathName,
|
|
|
|
RigCompletionDataGridCell(globalCellIndex, caseToApply->mainGrid()),
|
|
|
|
fracture->fractureMD());
|
|
|
|
|
|
|
|
double diameter = 2.0 * fracture->wellRadius();
|
|
|
|
compDat.setFromFracture(trans, fracTemplate->skinFactor(), diameter);
|
|
|
|
compDat.addMetadata(fracture->name(), QString::number(trans));
|
|
|
|
allCompletionsForOneFracture.push_back(compDat);
|
|
|
|
}
|
|
|
|
return allCompletionsForOneFracture;
|
|
|
|
}
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RicExportFractureCompletionsImpl::computeNonDarcyFlowParameters(const RimFracture* fracture, std::vector<RigCompletionData> allCompletionsForOneFracture)
|
|
|
|
{
|
|
|
|
double dFactorForFracture = fracture->nonDarcyProperties().dFactor;
|
|
|
|
double khForFracture = fracture->nonDarcyProperties().conductivity;
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
double sumOfTransmissibilitiesInFracture = 0.0;
|
|
|
|
for (const auto& c : allCompletionsForOneFracture)
|
|
|
|
{
|
|
|
|
sumOfTransmissibilitiesInFracture += c.transmissibility();
|
|
|
|
}
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
for (auto& c : allCompletionsForOneFracture)
|
|
|
|
{
|
|
|
|
// NOTE : What is supposed to happen when the transmissibility is close to zero?
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
double dFactorForOneConnection = dFactorForFracture * sumOfTransmissibilitiesInFracture / c.transmissibility();
|
|
|
|
c.setDFactor(dFactorForOneConnection);
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
double khForOneConnection = khForFracture * c.transmissibility() / sumOfTransmissibilitiesInFracture;
|
2018-08-31 05:50:17 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
c.setKh(khForOneConnection);
|
|
|
|
}
|
|
|
|
}
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
double RicExportFractureCompletionsImpl::sumUpCellAreas(const std::map<size_t, double>& cellAreas)
|
|
|
|
{
|
|
|
|
double area = 0.0;
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
for (const auto& cellArea : cellAreas)
|
|
|
|
{
|
|
|
|
area += cellArea.second;
|
|
|
|
}
|
|
|
|
return area;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
double RicExportFractureCompletionsImpl::sumUpTransmissibilities(const std::vector<RigCompletionData>& allCompletionsForOneFracture)
|
|
|
|
{
|
|
|
|
double transmissibility = 0.0;
|
|
|
|
for (const auto& c : allCompletionsForOneFracture)
|
|
|
|
{
|
|
|
|
transmissibility += c.transmissibility();
|
|
|
|
}
|
|
|
|
return transmissibility;
|
|
|
|
}
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RicExportFractureCompletionsImpl::calculateAndSetLengthsAndConductivity(const RimFractureTemplate* fracTemplate,
|
|
|
|
double area,
|
|
|
|
RicWellPathFractureReportItem& reportItem)
|
|
|
|
{
|
|
|
|
double conductivity = 0.0;
|
|
|
|
double width = 0.0;
|
|
|
|
double height = 0.0;
|
|
|
|
double halfLength = 0.0;
|
|
|
|
RiaEclipseUnitTools::UnitSystem unitSystem = RiaEclipseUnitTools::UNITS_METRIC;
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
{
|
|
|
|
auto* ellipseTemplate = dynamic_cast<const RimEllipseFractureTemplate*>(fracTemplate);
|
|
|
|
if (ellipseTemplate)
|
|
|
|
{
|
|
|
|
unitSystem = ellipseTemplate->fractureTemplateUnit();
|
|
|
|
conductivity = ellipseTemplate->conductivity();
|
|
|
|
width = ellipseTemplate->width();
|
|
|
|
height = ellipseTemplate->height();
|
|
|
|
halfLength = ellipseTemplate->halfLength();
|
|
|
|
}
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
auto* stimplanTemplate = dynamic_cast<const RimStimPlanFractureTemplate*>(fracTemplate);
|
|
|
|
if (stimplanTemplate)
|
|
|
|
{
|
|
|
|
unitSystem = stimplanTemplate->fractureTemplateUnit();
|
|
|
|
conductivity = stimplanTemplate->areaWeightedConductivity();
|
|
|
|
width = stimplanTemplate->areaWeightedWidth();
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
height = stimplanTemplate->longestYRange();
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
double xLength = 0.0;
|
|
|
|
if (height > 1e-9)
|
|
|
|
{
|
|
|
|
xLength = area / height;
|
2018-08-09 04:33:48 -05:00
|
|
|
}
|
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
// Compute half length defined as (total area / (H/2) )
|
|
|
|
halfLength = xLength / 2.0;
|
2018-08-09 04:33:48 -05:00
|
|
|
}
|
2018-09-10 06:00:39 -05:00
|
|
|
}
|
|
|
|
reportItem.setUnitSystem(unitSystem);
|
|
|
|
reportItem.setWidthAndConductivity(width, conductivity);
|
|
|
|
reportItem.setHeightAndHalfLength(height, halfLength);
|
|
|
|
}
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RicExportFractureCompletionsImpl::calculateAndSetAreaWeightedTransmissibility(const RimEclipseCase* caseToApply,
|
|
|
|
std::map<size_t, double> cellAreas,
|
|
|
|
double area,
|
|
|
|
RicWellPathFractureReportItem& reportItem)
|
|
|
|
{
|
|
|
|
double areaWeightedEclipseTransmissibility = 0.0;
|
2018-02-16 00:58:07 -06:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
if (caseToApply && caseToApply->eclipseCaseData())
|
|
|
|
{
|
|
|
|
cvf::ref<RigResultAccessor> tranxAccessObject = RigResultAccessorFactory::createFromUiResultName(
|
|
|
|
caseToApply->eclipseCaseData(), 0, RiaDefines::MATRIX_MODEL, 0, "TRANX");
|
|
|
|
|
|
|
|
cvf::ref<RigResultAccessor> tranyAccessObject = RigResultAccessorFactory::createFromUiResultName(
|
|
|
|
caseToApply->eclipseCaseData(), 0, RiaDefines::MATRIX_MODEL, 0, "TRANY");
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
cvf::ref<RigResultAccessor> tranzAccessObject = RigResultAccessorFactory::createFromUiResultName(
|
|
|
|
caseToApply->eclipseCaseData(), 0, RiaDefines::MATRIX_MODEL, 0, "TRANZ");
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
if (tranxAccessObject.notNull() && tranyAccessObject.notNull() && tranzAccessObject.notNull())
|
|
|
|
{
|
|
|
|
for (const auto& cellArea : cellAreas)
|
|
|
|
{
|
|
|
|
double tranx = tranxAccessObject->cellScalarGlobIdx(cellArea.first);
|
|
|
|
double trany = tranyAccessObject->cellScalarGlobIdx(cellArea.first);
|
|
|
|
double tranz = tranzAccessObject->cellScalarGlobIdx(cellArea.first);
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
double transmissibilityForCell = RigTransmissibilityEquations::totalConnectionFactor(tranx, trany, tranz);
|
2018-08-09 04:33:48 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
areaWeightedEclipseTransmissibility += transmissibilityForCell * cellArea.second / area;
|
2018-08-27 03:46:06 -05:00
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
}
|
2018-08-09 04:30:18 -05:00
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
reportItem.setAreaWeightedTransmissibility(areaWeightedEclipseTransmissibility);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RicExportFractureCompletionsImpl::outputIntermediateResultsText(QTextStream* outputStreamForIntermediateResultsText,
|
|
|
|
const RimFracture* fracture,
|
|
|
|
RigTransmissibilityCondenser& transCondenser,
|
|
|
|
const RigMainGrid* mainGrid,
|
|
|
|
const RigFractureGrid* fractureGrid)
|
|
|
|
{
|
|
|
|
(*outputStreamForIntermediateResultsText)
|
|
|
|
<< "\n"
|
|
|
|
<< "\n"
|
|
|
|
<< "\n----------- All Transmissibilities " << 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";
|
2017-06-01 09:34:30 -05:00
|
|
|
}
|