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"
|
2018-09-24 07:51:11 -05:00
|
|
|
|
#include "RiaQDateTimeTools.h"
|
2018-09-17 03:51:08 -05:00
|
|
|
|
#include "RiaSummaryTools.h"
|
2017-07-31 08:10:07 -05:00
|
|
|
|
|
2017-06-12 05:03:42 -05:00
|
|
|
|
#include "RimEclipseCase.h"
|
2018-09-17 03:51:08 -05:00
|
|
|
|
#include "RimEclipseResultCase.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"
|
2018-09-17 03:51:08 -05:00
|
|
|
|
#include "RimObservedEclipseUserData.h"
|
|
|
|
|
#include "RimProject.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"
|
2018-09-24 07:51:11 -05:00
|
|
|
|
#include "RimStimPlanFractureTemplate.h"
|
2018-09-17 03:51:08 -05:00
|
|
|
|
#include "RimSummaryCase.h"
|
|
|
|
|
#include "RimSummaryCaseMainCollection.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-09-17 03:51:08 -05:00
|
|
|
|
#include "RifEclipseSummaryAddress.h"
|
|
|
|
|
#include "RifSummaryReaderInterface.h"
|
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,
|
2018-09-14 04:29:43 -05:00
|
|
|
|
QTextStream* outputStreamForIntermediateResultsText,
|
2019-09-06 03:40:57 -05:00
|
|
|
|
PressureDepletionParameters pdParams )
|
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
|
|
|
|
|
2019-09-06 03:40:57 -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
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
fracturesAlongWellPath.push_back( frac );
|
2017-12-22 07:08:29 -06:00
|
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
return generateCompdatValues( caseToApply,
|
|
|
|
|
wellPath->completions()->wellNameForExport(),
|
|
|
|
|
wellPath->wellPathGeometry(),
|
|
|
|
|
fracturesAlongWellPath,
|
|
|
|
|
fractureDataForReport,
|
|
|
|
|
outputStreamForIntermediateResultsText,
|
|
|
|
|
pdParams );
|
2018-08-03 06:35:03 -05:00
|
|
|
|
}
|
|
|
|
|
|
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>
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RicExportFractureCompletionsImpl::generateCompdatValuesForSimWell( RimEclipseCase* eclipseCase,
|
|
|
|
|
const RimSimWellInView* well,
|
|
|
|
|
QTextStream* outputStreamForIntermediateResultsText,
|
|
|
|
|
PressureDepletionParameters pdParams )
|
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
|
|
|
|
|
2019-09-06 03:40:57 -05: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;
|
2019-09-06 03:40:57 -05:00
|
|
|
|
for ( RimSimWellFracture* fracture : well->simwellFractureCollection->simwellFractures() )
|
2017-06-12 05:03:42 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( fracture->isChecked() && static_cast<size_t>( fracture->branchIndex() ) == branchIndex )
|
2017-06-12 05:03:42 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
fractures.push_back( fracture );
|
2017-06-12 05:03:42 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
std::vector<RigCompletionData> branchCompletions = generateCompdatValues( eclipseCase,
|
|
|
|
|
well->name(),
|
|
|
|
|
branches[branchIndex],
|
|
|
|
|
fractures,
|
|
|
|
|
nullptr,
|
|
|
|
|
outputStreamForIntermediateResultsText,
|
|
|
|
|
pdParams );
|
2017-06-12 05:03:42 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
completionData.insert( completionData.end(), branchCompletions.begin(), branchCompletions.end() );
|
2017-06-12 05:03:42 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return completionData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2018-08-09 04:30:18 -05:00
|
|
|
|
///
|
2017-06-12 05:03:42 -05:00
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
|
std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateCompdatValues(
|
|
|
|
|
RimEclipseCase* caseToApply,
|
|
|
|
|
const QString& wellNameForExport,
|
|
|
|
|
const RigWellPath* wellPathGeometry,
|
|
|
|
|
const std::vector<const RimFracture*>& fractures,
|
|
|
|
|
std::vector<RicWellPathFractureReportItem>* fractureDataReportItems,
|
|
|
|
|
QTextStream* outputStreamForIntermediateResultsText,
|
|
|
|
|
PressureDepletionParameters pdParams )
|
2017-06-12 05:03:42 -05:00
|
|
|
|
{
|
2018-08-03 03:30:44 -05:00
|
|
|
|
std::vector<RigCompletionData> fractureCompletions;
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( !caseToApply || !caseToApply->eclipseCaseData() )
|
2018-08-03 03:30:44 -05:00
|
|
|
|
{
|
|
|
|
|
return fractureCompletions;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-04 08:55:31 -05:00
|
|
|
|
auto cellResultsData = caseToApply->results( RiaDefines::MATRIX_MODEL );
|
|
|
|
|
if ( !cellResultsData )
|
|
|
|
|
{
|
|
|
|
|
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();
|
|
|
|
|
|
2019-10-04 08:55:31 -05:00
|
|
|
|
bool loadingSucceeded = RicExportFractureCompletionsImpl::loadResultsByName( cellResultsData, resultNames );
|
|
|
|
|
if ( !loadingSucceeded )
|
2018-08-24 02:59:37 -05:00
|
|
|
|
{
|
|
|
|
|
QString msg;
|
2019-10-08 01:01:25 -05:00
|
|
|
|
msg += "Compdat Export : One or more of the following required data sources are missing :";
|
2018-08-24 02:59:37 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
for ( const auto& r : resultNames )
|
2018-08-24 02:59:37 -05:00
|
|
|
|
{
|
|
|
|
|
msg += " ";
|
|
|
|
|
msg += r;
|
|
|
|
|
}
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RiaLogging::error( msg );
|
2018-08-24 02:59:37 -05:00
|
|
|
|
|
|
|
|
|
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"};
|
2019-10-04 08:55:31 -05:00
|
|
|
|
RicExportFractureCompletionsImpl::loadResultsByName( cellResultsData, resultNames );
|
2018-08-24 03:17:33 -05:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-24 02:59:37 -05:00
|
|
|
|
{
|
|
|
|
|
// Optional results
|
|
|
|
|
std::vector<QString> resultNames = RigEclipseToStimPlanCellTransmissibilityCalculator::optionalResultNames();
|
2019-10-04 08:55:31 -05:00
|
|
|
|
RicExportFractureCompletionsImpl::loadResultsByName( cellResultsData, resultNames );
|
2018-08-24 02:59:37 -05:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( pdParams.performScaling )
|
2018-09-14 04:29:43 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RigCaseCellResultsData* results = caseToApply->results( RiaDefines::MATRIX_MODEL );
|
|
|
|
|
results->ensureKnownResultLoaded( RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "PRESSURE" ) );
|
2018-09-14 04:29:43 -05:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
return generateCompdatValuesConst( caseToApply,
|
|
|
|
|
wellNameForExport,
|
|
|
|
|
wellPathGeometry,
|
|
|
|
|
fractures,
|
|
|
|
|
fractureDataReportItems,
|
|
|
|
|
outputStreamForIntermediateResultsText,
|
|
|
|
|
pdParams );
|
2018-08-24 03:49:34 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateCompdatValuesConst(
|
|
|
|
|
const RimEclipseCase* caseToApply,
|
2019-04-25 04:42:16 -05:00
|
|
|
|
const QString& wellNameForExport,
|
2018-08-24 03:49:34 -05:00
|
|
|
|
const RigWellPath* wellPathGeometry,
|
|
|
|
|
const std::vector<const RimFracture*>& fractures,
|
|
|
|
|
std::vector<RicWellPathFractureReportItem>* fractureDataReportItems,
|
2018-09-14 04:29:43 -05:00
|
|
|
|
QTextStream* outputStreamForIntermediateResultsText,
|
2019-09-06 03:40:57 -05:00
|
|
|
|
PressureDepletionParameters pdParams )
|
2018-08-24 03:49:34 -05:00
|
|
|
|
{
|
|
|
|
|
std::vector<RigCompletionData> fractureCompletions;
|
|
|
|
|
|
2019-12-11 03:27:49 -06:00
|
|
|
|
if ( !caseToApply || !caseToApply->eclipseCaseData() || !wellPathGeometry )
|
2018-08-24 03:49:34 -05:00
|
|
|
|
{
|
|
|
|
|
return fractureCompletions;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
double cDarcyInCorrectUnit = RiaEclipseUnitTools::darcysConstant( caseToApply->eclipseCaseData()->unitsType() );
|
|
|
|
|
const RigMainGrid* mainGrid = caseToApply->eclipseCaseData()->mainGrid();
|
2018-08-24 03:49:34 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
const RigCaseCellResultsData* results = caseToApply->results( RiaDefines::MATRIX_MODEL );
|
|
|
|
|
const RigActiveCellInfo* actCellInfo = caseToApply->eclipseCaseData()->activeCellInfo( RiaDefines::MATRIX_MODEL );
|
2018-09-18 06:27:59 -05:00
|
|
|
|
|
2018-11-13 09:47:53 -06:00
|
|
|
|
bool performPressureDepletionScaling = pdParams.performScaling;
|
2018-09-19 04:38:37 -05:00
|
|
|
|
|
2018-09-24 07:51:11 -05:00
|
|
|
|
int initialWellProductionTimeStep = 0;
|
2018-11-12 08:00:13 -06:00
|
|
|
|
double currentWellPressure = 0;
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( performPressureDepletionScaling )
|
2018-09-19 04:38:37 -05:00
|
|
|
|
{
|
2018-11-13 09:47:53 -06:00
|
|
|
|
double userWBHP = pdParams.userWBHP;
|
2018-11-12 08:00:13 -06:00
|
|
|
|
|
|
|
|
|
double initialWBHPFromSummary = 0.0;
|
|
|
|
|
double currentWBHPFromSummary = 0.0;
|
2018-09-19 04:38:37 -05:00
|
|
|
|
// Find well pressures (WBHP) from summary case.
|
2019-09-06 03:40:57 -05:00
|
|
|
|
getWellPressuresAndInitialProductionTimeStepFromSummaryData( caseToApply,
|
|
|
|
|
wellNameForExport,
|
|
|
|
|
pdParams.pressureScalingTimeStep,
|
|
|
|
|
&initialWellProductionTimeStep,
|
|
|
|
|
&initialWBHPFromSummary,
|
|
|
|
|
¤tWBHPFromSummary );
|
|
|
|
|
|
|
|
|
|
if ( pdParams.wbhpSource == WBHP_FROM_SUMMARY )
|
2018-11-12 08:00:13 -06:00
|
|
|
|
{
|
2018-11-13 09:47:53 -06:00
|
|
|
|
currentWellPressure = currentWBHPFromSummary;
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( pdParams.pressureScalingTimeStep <= initialWellProductionTimeStep )
|
2018-11-12 08:00:13 -06:00
|
|
|
|
{
|
2018-11-13 09:47:53 -06:00
|
|
|
|
currentWellPressure = userWBHP;
|
2018-11-12 08:00:13 -06:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-11-13 09:47:53 -06:00
|
|
|
|
currentWellPressure = userWBHP;
|
2018-09-19 04:38:37 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-24 07:51:11 -05:00
|
|
|
|
const std::vector<std::vector<double>>* pressureResultVector = nullptr;
|
|
|
|
|
const std::vector<double>* currentMatrixPressures = nullptr;
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( performPressureDepletionScaling )
|
2018-09-14 07:00:27 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
pressureResultVector = &results->cellScalarResults(
|
|
|
|
|
RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "PRESSURE" ) );
|
|
|
|
|
CVF_ASSERT( !pressureResultVector->empty() );
|
2018-09-14 07:00:27 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( pdParams.pressureScalingTimeStep < static_cast<int>( pressureResultVector->size() ) )
|
2018-09-14 07:00:27 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
currentMatrixPressures = &pressureResultVector->at( pdParams.pressureScalingTimeStep );
|
2018-09-14 07:00:27 -05:00
|
|
|
|
}
|
2018-09-19 04:38:37 -05:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Don't perform scaling if the current pressure time step is beyond the case range.
|
2018-11-13 09:47:53 -06:00
|
|
|
|
performPressureDepletionScaling = false;
|
2018-09-19 04:38:37 -05:00
|
|
|
|
}
|
2018-09-14 07:00:27 -05:00
|
|
|
|
}
|
2018-09-24 07:51:11 -05:00
|
|
|
|
|
2018-08-24 03:49:34 -05:00
|
|
|
|
// 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;
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
std::vector<std::vector<RigCompletionData>> sharedComplForFracture( fractures.size() );
|
2018-08-24 03:49:34 -05:00
|
|
|
|
|
2018-08-27 01:49:45 -05:00
|
|
|
|
#pragma omp parallel for
|
2019-09-06 03:40:57 -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
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( !fracTemplate ) continue;
|
2018-01-02 05:53:52 -06:00
|
|
|
|
|
2017-06-01 09:34:30 -05:00
|
|
|
|
const RigFractureGrid* fractureGrid = fracTemplate->fractureGrid();
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( !fractureGrid ) continue;
|
2018-01-15 01:58:51 -06:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
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
|
2019-09-06 03:40:57 -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
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RigEclipseToStimPlanCalculator eclToFractureCalc( caseToApply,
|
|
|
|
|
fracture->transformMatrix(),
|
|
|
|
|
fracTemplate->skinFactor(),
|
|
|
|
|
cDarcyInCorrectUnit,
|
|
|
|
|
*fractureGrid,
|
|
|
|
|
fracture );
|
2017-06-01 09:34:30 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
eclToFractureCalc.appendDataToTransmissibilityCondenser( useFiniteConductivityInFracture, &transCondenser );
|
2017-06-01 09:34:30 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( useFiniteConductivityInFracture )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
calculateInternalFractureTransmissibilities( fractureGrid, cDarcyInCorrectUnit, transCondenser );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( useFiniteConductivityInFracture )
|
2017-06-01 09:34:30 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -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
|
2019-09-06 03:40:57 -05:00
|
|
|
|
std::map<size_t, double> matrixToWellTrans = calculateMatrixToWellTransmissibilities( transCondenser );
|
2018-09-14 04:29:43 -05:00
|
|
|
|
|
2018-11-13 09:47:53 -06:00
|
|
|
|
double maxPressureDrop = 0.0, minPressureDrop = 0.0;
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( performPressureDepletionScaling )
|
2018-09-21 02:23:57 -05:00
|
|
|
|
{
|
|
|
|
|
RigTransmissibilityCondenser scaledCondenser = transCondenser;
|
|
|
|
|
// 1. Scale matrix to fracture transmissibilities by matrix to fracture pressure
|
2019-09-06 03:40:57 -05:00
|
|
|
|
std::map<size_t, double> originalLumpedMatrixToFractureTrans =
|
|
|
|
|
scaledCondenser.scaleMatrixToFracTransByMatrixWellDP( actCellInfo,
|
|
|
|
|
currentWellPressure,
|
|
|
|
|
*currentMatrixPressures,
|
|
|
|
|
&minPressureDrop,
|
|
|
|
|
&maxPressureDrop );
|
2018-09-21 02:23:57 -05:00
|
|
|
|
// 2: Calculate new external transmissibilities
|
2018-09-14 04:29:43 -05:00
|
|
|
|
scaledCondenser.calculateCondensedTransmissibilities();
|
|
|
|
|
|
2018-11-21 06:44:31 -06:00
|
|
|
|
{ // 3: H<>gst<73>l correction.
|
2019-04-25 04:42:16 -05:00
|
|
|
|
|
2018-10-29 02:40:48 -05:00
|
|
|
|
// a. Calculate new effective fracture to well transmissiblities
|
2018-09-24 07:51:11 -05:00
|
|
|
|
std::map<size_t, double> fictitiousFractureToWellTransmissibilities =
|
|
|
|
|
scaledCondenser.calculateFicticiousFractureToWellTransmissibilities();
|
2018-10-29 02:40:48 -05:00
|
|
|
|
// b. Calculate new effective matrix to well transmissibilities
|
2018-09-24 07:51:11 -05:00
|
|
|
|
std::map<size_t, double> effectiveMatrixToWellTrans =
|
2019-09-06 03:40:57 -05:00
|
|
|
|
scaledCondenser
|
|
|
|
|
.calculateEffectiveMatrixToWellTransmissibilities( originalLumpedMatrixToFractureTrans,
|
|
|
|
|
fictitiousFractureToWellTransmissibilities );
|
2018-09-14 04:29:43 -05:00
|
|
|
|
matrixToWellTrans = effectiveMatrixToWellTrans;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-25 04:42:16 -05:00
|
|
|
|
|
2019-11-04 08:08:09 -06:00
|
|
|
|
std::vector<RigCompletionData> allCompletionsForOneFracture =
|
|
|
|
|
generateCompdatValuesForFracture( matrixToWellTrans, wellNameForExport, caseToApply, fracture, fracTemplate );
|
2018-08-09 04:30:18 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( fractureDataReportItems )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RicWellPathFractureReportItem reportItem( wellNameForExport,
|
|
|
|
|
fracture->name(),
|
|
|
|
|
fracTemplate->name(),
|
|
|
|
|
fracture->fractureMD() );
|
|
|
|
|
reportItem.setUnitSystem( fracTemplate->fractureTemplateUnit() );
|
2019-10-08 01:01:25 -05:00
|
|
|
|
|
|
|
|
|
if ( performPressureDepletionScaling )
|
|
|
|
|
{
|
|
|
|
|
QString timeStepString;
|
|
|
|
|
if ( pdParams.pressureScalingTimeStep < caseToApply->timeStepStrings().size() )
|
|
|
|
|
{
|
|
|
|
|
timeStepString = caseToApply->timeStepStrings()[pdParams.pressureScalingTimeStep];
|
|
|
|
|
}
|
|
|
|
|
reportItem.setPressureDepletionParameters( performPressureDepletionScaling,
|
|
|
|
|
timeStepString,
|
|
|
|
|
caf::AppEnum<PressureDepletionWBHPSource>::uiTextFromIndex(
|
|
|
|
|
pdParams.wbhpSource ),
|
|
|
|
|
pdParams.userWBHP,
|
|
|
|
|
currentWellPressure,
|
|
|
|
|
minPressureDrop,
|
|
|
|
|
maxPressureDrop );
|
|
|
|
|
}
|
2019-09-06 03:40:57 -05:00
|
|
|
|
|
|
|
|
|
RicExportFractureCompletionsImpl::calculateAndSetReportItemData( allCompletionsForOneFracture,
|
|
|
|
|
eclToFractureCalc,
|
|
|
|
|
reportItem );
|
|
|
|
|
|
|
|
|
|
#pragma omp critical( critical_section_fractureDataReportItems )
|
2018-10-02 03:26:00 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
fractureDataReportItems->push_back( reportItem );
|
2018-10-02 03:26:00 -05:00
|
|
|
|
}
|
2018-09-10 06:00:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
std::copy( allCompletionsForOneFracture.begin(),
|
|
|
|
|
allCompletionsForOneFracture.end(),
|
|
|
|
|
std::back_inserter( sharedComplForFracture[i] ) );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( outputStreamForIntermediateResultsText )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
#pragma omp critical( critical_section_outputStreamForIntermediateResultsText )
|
2017-06-09 02:28:24 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -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
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
for ( const auto& completions : sharedComplForFracture )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
std::copy( completions.begin(), completions.end(), std::back_inserter( fractureCompletions ) );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
}
|
|
|
|
|
return fractureCompletions;
|
|
|
|
|
}
|
2017-06-01 09:34:30 -05:00
|
|
|
|
|
2018-09-17 03:51:08 -05:00
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2018-09-24 07:51:11 -05:00
|
|
|
|
void RicExportFractureCompletionsImpl::getWellPressuresAndInitialProductionTimeStepFromSummaryData(
|
|
|
|
|
const RimEclipseCase* caseToApply,
|
|
|
|
|
const QString& wellPathName,
|
|
|
|
|
int currentTimeStep,
|
|
|
|
|
int* initialCaseTimeStep,
|
|
|
|
|
double* initialWellPressure,
|
2019-09-06 03:40:57 -05:00
|
|
|
|
double* currentWellPressure )
|
2018-09-17 03:51:08 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
const RimEclipseResultCase* resultCase = dynamic_cast<const RimEclipseResultCase*>( caseToApply );
|
|
|
|
|
if ( resultCase )
|
2018-09-17 03:51:08 -05:00
|
|
|
|
{
|
|
|
|
|
std::vector<QDateTime> caseTimeSteps = resultCase->timeStepDates();
|
2018-09-19 04:38:37 -05:00
|
|
|
|
QDateTime initialProductionDate;
|
2018-09-19 01:52:40 -05:00
|
|
|
|
QDateTime currentDate;
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( currentTimeStep < static_cast<int>( caseTimeSteps.size() ) )
|
2018-09-19 01:52:40 -05:00
|
|
|
|
{
|
|
|
|
|
currentDate = caseTimeSteps[currentTimeStep];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
currentDate = caseTimeSteps.back();
|
|
|
|
|
}
|
2018-09-17 03:51:08 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RifEclipseSummaryAddress wbhpPressureAddress = RifEclipseSummaryAddress::wellAddress( "WBHP",
|
|
|
|
|
wellPathName.toStdString() );
|
|
|
|
|
RimSummaryCaseMainCollection* mainCollection = RiaSummaryTools::summaryCaseMainCollection();
|
|
|
|
|
if ( mainCollection )
|
2018-09-17 03:51:08 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RimSummaryCase* summaryCase = mainCollection->findSummaryCaseFromEclipseResultCase( resultCase );
|
2018-09-17 03:51:08 -05:00
|
|
|
|
|
2019-09-13 09:51:21 -05:00
|
|
|
|
if ( summaryCase && summaryCase->summaryReader() )
|
2018-09-17 03:51:08 -05:00
|
|
|
|
{
|
|
|
|
|
std::vector<double> values;
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( summaryCase->summaryReader()->values( wbhpPressureAddress, &values ) )
|
2018-09-17 03:51:08 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
std::vector<time_t> summaryTimeSteps = summaryCase->summaryReader()->timeSteps( wbhpPressureAddress );
|
|
|
|
|
CVF_ASSERT( values.size() == summaryTimeSteps.size() );
|
|
|
|
|
for ( size_t i = 0; i < summaryTimeSteps.size(); ++i )
|
2018-09-17 03:51:08 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
QDateTime summaryDate = RiaQDateTimeTools::fromTime_t( summaryTimeSteps[i] );
|
|
|
|
|
if ( initialProductionDate.isNull() && values[i] > 0.0 )
|
2018-09-17 03:51:08 -05:00
|
|
|
|
{
|
2018-09-19 04:38:37 -05:00
|
|
|
|
initialProductionDate = summaryDate;
|
2018-09-24 07:51:11 -05:00
|
|
|
|
*initialWellPressure = values[i];
|
2018-09-17 03:51:08 -05:00
|
|
|
|
}
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( summaryDate <= currentDate )
|
2018-09-17 03:51:08 -05:00
|
|
|
|
{
|
|
|
|
|
*currentWellPressure = values[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( initialProductionDate.isValid() )
|
2018-09-19 04:38:37 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
for ( size_t i = 0; i < caseTimeSteps.size(); ++i )
|
2018-09-19 04:38:37 -05:00
|
|
|
|
{
|
2018-11-12 03:06:05 -06:00
|
|
|
|
// Pick last time step that isn't bigger than the initial production time.
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( caseTimeSteps[i] < initialProductionDate )
|
2018-09-19 04:38:37 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
*initialCaseTimeStep = static_cast<int>( i );
|
2018-11-12 03:06:05 -06:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-09-19 04:38:37 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-17 03:51:08 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
|
bool RicExportFractureCompletionsImpl::checkForStimPlanConductivity( const RimFractureTemplate* fracTemplate,
|
|
|
|
|
const RimFracture* fracture )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
auto fracTemplateStimPlan = dynamic_cast<const RimStimPlanFractureTemplate*>( fracTemplate );
|
|
|
|
|
if ( fracTemplateStimPlan )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( !fracTemplateStimPlan->hasConductivity() )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
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() );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-02-16 00:58:07 -06:00
|
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
|
void RicExportFractureCompletionsImpl::calculateInternalFractureTransmissibilities(
|
2019-11-04 07:35:41 -06:00
|
|
|
|
const RigFractureGrid* fractureGrid,
|
|
|
|
|
double cDarcyInCorrectUnit,
|
|
|
|
|
RigTransmissibilityCondenser& transCondenser )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
for ( size_t i = 0; i < fractureGrid->iCellCount(); i++ )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
for ( size_t j = 0; j < fractureGrid->jCellCount(); j++ )
|
2017-06-01 09:34:30 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
size_t fractureCellIndex = fractureGrid->getGlobalIndexFromIJ( i, j );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
const RigFractureCell& fractureCell = fractureGrid->cellFromIndex( fractureCellIndex );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( !fractureCell.hasNonZeroConductivity() ) continue;
|
2018-09-10 06:00:39 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( i < fractureGrid->iCellCount() - 1 )
|
2017-06-01 09:34:30 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -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 );
|
|
|
|
|
|
|
|
|
|
transCondenser.addNeighborTransmissibility( {false,
|
|
|
|
|
RigTransmissibilityCondenser::CellAddress::STIMPLAN,
|
|
|
|
|
fractureCellIndex},
|
|
|
|
|
{false,
|
|
|
|
|
RigTransmissibilityCondenser::CellAddress::STIMPLAN,
|
|
|
|
|
fractureCellNeighbourXIndex},
|
|
|
|
|
horizontalTransToXneigbour );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
}
|
2017-08-24 03:27:02 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( j < fractureGrid->jCellCount() - 1 )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
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 );
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
|
void RicExportFractureCompletionsImpl::calculateFractureToWellTransmissibilities(
|
|
|
|
|
const RimFractureTemplate* fracTemplate,
|
|
|
|
|
const RigFractureGrid* fractureGrid,
|
|
|
|
|
const RimFracture* fracture,
|
|
|
|
|
double cDarcyInCorrectUnit,
|
|
|
|
|
const RigWellPath* wellPathGeometry,
|
|
|
|
|
RigTransmissibilityCondenser& transCondenser )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
|
|
|
|
////
|
|
|
|
|
// If fracture has orientation Azimuth or Transverse, assume only radial inflow
|
2018-02-16 00:58:07 -06:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( fracTemplate->orientationType() == RimFractureTemplate::AZIMUTH ||
|
|
|
|
|
fracTemplate->orientationType() == RimFractureTemplate::TRANSVERSE_WELL_PATH )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
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 );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
}
|
2019-09-06 03:40:57 -05:00
|
|
|
|
else if ( fracTemplate->orientationType() == RimFractureTemplate::ALONG_WELL_PATH )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
|
|
|
|
////
|
|
|
|
|
// If fracture has orientation along well, linear inflow along well and radial flow at endpoints
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RigWellPathStimplanIntersector wellFractureIntersector( wellPathGeometry, fracture );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
const std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection>& fractureWellCells =
|
|
|
|
|
wellFractureIntersector.intersections();
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
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
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
const RigFractureCell& fractureWellCell = fractureGrid->cellFromIndex( fracWellCellIdx );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
|
|
|
|
|
double linearTrans = 0.0;
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( intersection.hlength > 0.0 || intersection.vlength > 0.0 )
|
2018-02-16 00:58:07 -06:00
|
|
|
|
{
|
2018-09-11 06:22:57 -05:00
|
|
|
|
linearTrans =
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RigFractureTransmissibilityEquations::fractureCellToWellLinearTrans( fractureWellCell
|
|
|
|
|
.getConductivityValue(),
|
|
|
|
|
fractureWellCell.cellSizeX(),
|
|
|
|
|
fractureWellCell.cellSizeZ(),
|
|
|
|
|
intersection.vlength,
|
|
|
|
|
intersection.hlength,
|
|
|
|
|
fracture->perforationEfficiency(),
|
|
|
|
|
fracTemplate->skinFactor(),
|
|
|
|
|
cDarcyInCorrectUnit,
|
|
|
|
|
fracture->wellRadius() );
|
2018-02-16 00:58:07 -06:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
transCondenser.addNeighborTransmissibility( {true, RigTransmissibilityCondenser::CellAddress::WELL, 1},
|
|
|
|
|
{false,
|
|
|
|
|
RigTransmissibilityCondenser::CellAddress::STIMPLAN,
|
|
|
|
|
fracWellCellIdx},
|
|
|
|
|
linearTrans );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-02-16 00:58:07 -06:00
|
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
|
std::map<size_t, double> RicExportFractureCompletionsImpl::calculateMatrixToWellTransmissibilities(
|
|
|
|
|
RigTransmissibilityCondenser& transCondenser )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
|
|
|
|
std::map<size_t, double> matrixToWellTransmissibilities;
|
|
|
|
|
|
|
|
|
|
std::set<RigTransmissibilityCondenser::CellAddress> externalCells = transCondenser.externalCells();
|
2019-09-06 03:40:57 -05:00
|
|
|
|
for ( RigTransmissibilityCondenser::CellAddress externalCell : externalCells )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( externalCell.m_cellIndexSpace == RigTransmissibilityCondenser::CellAddress::ECLIPSE )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
double trans = transCondenser.condensedTransmissibility( externalCell,
|
|
|
|
|
{true,
|
|
|
|
|
RigTransmissibilityCondenser::CellAddress::WELL,
|
|
|
|
|
1} );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
matrixToWellTransmissibilities.insert( std::make_pair( externalCell.m_globalCellIdx, trans ) );
|
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
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2018-09-11 06:22:57 -05:00
|
|
|
|
std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateCompdatValuesForFracture(
|
|
|
|
|
const std::map<size_t, double>& matrixToWellTransmissibilites,
|
2019-04-25 04:42:16 -05:00
|
|
|
|
const QString& wellNameForExport,
|
2018-09-11 06:22:57 -05:00
|
|
|
|
const RimEclipseCase* caseToApply,
|
|
|
|
|
const RimFracture* fracture,
|
2019-09-06 03:40:57 -05:00
|
|
|
|
const RimFractureTemplate* fracTemplate )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
|
|
|
|
std::vector<RigCompletionData> allCompletionsForOneFracture;
|
2019-09-06 03:40:57 -05:00
|
|
|
|
for ( const auto& matrixToWellTransmissibility : matrixToWellTransmissibilites )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2018-09-11 06:22:57 -05:00
|
|
|
|
size_t globalCellIndex = matrixToWellTransmissibility.first;
|
|
|
|
|
double trans = matrixToWellTransmissibility.second;
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RigCompletionData compDat( wellNameForExport,
|
|
|
|
|
RigCompletionDataGridCell( globalCellIndex, caseToApply->mainGrid() ),
|
|
|
|
|
fracture->fractureMD() );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
|
|
|
|
|
double diameter = 2.0 * fracture->wellRadius();
|
2019-09-06 03:40:57 -05:00
|
|
|
|
compDat.setFromFracture( trans, fracTemplate->skinFactor(), diameter );
|
|
|
|
|
compDat.addMetadata( fracture->name(), QString::number( trans ) );
|
|
|
|
|
compDat.setSourcePdmObject( fracture );
|
|
|
|
|
allCompletionsForOneFracture.push_back( compDat );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
}
|
2018-09-24 07:52:31 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( fracTemplate->isNonDarcyFlowEnabled() )
|
2018-09-24 07:52:31 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
computeNonDarcyFlowParameters( fracture, allCompletionsForOneFracture );
|
2018-09-24 07:52:31 -05:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
|
return allCompletionsForOneFracture;
|
|
|
|
|
}
|
2018-08-09 04:33:48 -05:00
|
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
|
void RicExportFractureCompletionsImpl::computeNonDarcyFlowParameters(
|
2019-11-04 07:35:41 -06:00
|
|
|
|
const RimFracture* fracture,
|
|
|
|
|
std::vector<RigCompletionData>& allCompletionsForOneFracture )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
|
|
|
|
double dFactorForFracture = fracture->nonDarcyProperties().dFactor;
|
2018-09-11 06:22:57 -05:00
|
|
|
|
double khForFracture = fracture->nonDarcyProperties().conductivity;
|
2018-08-09 04:33:48 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
double sumOfTransmissibilitiesInFracture = sumUpTransmissibilities( allCompletionsForOneFracture );
|
2018-08-09 04:33:48 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
for ( auto& c : allCompletionsForOneFracture )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
|
|
|
|
// 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();
|
2019-09-06 03:40:57 -05:00
|
|
|
|
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
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
c.setKh( khForOneConnection );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-09 04:33:48 -05:00
|
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
|
double RicExportFractureCompletionsImpl::sumUpTransmissibilities(
|
|
|
|
|
const std::vector<RigCompletionData>& allCompletionsForOneFracture )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
|
|
|
|
double transmissibility = 0.0;
|
2019-09-06 03:40:57 -05:00
|
|
|
|
for ( const auto& c : allCompletionsForOneFracture )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
|
|
|
|
transmissibility += c.transmissibility();
|
|
|
|
|
}
|
|
|
|
|
return transmissibility;
|
|
|
|
|
}
|
2018-08-09 04:33:48 -05:00
|
|
|
|
|
2018-09-10 06:00:39 -05:00
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2018-09-11 06:22:57 -05:00
|
|
|
|
void RicExportFractureCompletionsImpl::calculateAndSetReportItemData(
|
|
|
|
|
const std::vector<RigCompletionData>& allCompletionsForOneFracture,
|
|
|
|
|
const RigEclipseToStimPlanCalculator& eclToFractureCalc,
|
2019-09-06 03:40:57 -05:00
|
|
|
|
RicWellPathFractureReportItem& reportItem )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2018-11-21 06:44:31 -06:00
|
|
|
|
double areaWeightedMatrixPermeability = eclToFractureCalc.areaWeightedMatrixPermeability();
|
2019-09-06 03:40:57 -05:00
|
|
|
|
reportItem.setAreaWeightedPermeability( areaWeightedMatrixPermeability );
|
2018-08-09 04:33:48 -05:00
|
|
|
|
|
2018-09-11 06:22:57 -05:00
|
|
|
|
double totalAreaOpenForFlow = eclToFractureCalc.totalEclipseAreaOpenForFlow();
|
|
|
|
|
double areaWeightedConductivity = eclToFractureCalc.areaWeightedConductivity();
|
2018-08-09 04:33:48 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( totalAreaOpenForFlow > 0.0 )
|
2018-09-11 06:22:57 -05:00
|
|
|
|
{
|
|
|
|
|
double halfLength = 0.0;
|
2018-11-09 03:51:17 -06:00
|
|
|
|
double height = eclToFractureCalc.longestYSectionOpenForFlow();
|
2019-09-06 03:40:57 -05:00
|
|
|
|
if ( height > 0.0 )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2018-09-11 06:22:57 -05:00
|
|
|
|
double length = totalAreaOpenForFlow / height;
|
|
|
|
|
halfLength = length / 2.0;
|
2017-06-01 09:34:30 -05:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
reportItem.setHeightAndHalfLength( height, halfLength );
|
2018-09-11 06:22:57 -05:00
|
|
|
|
}
|
2018-11-09 03:51:17 -06:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
double aggregatedTransmissibility = sumUpTransmissibilities( allCompletionsForOneFracture );
|
|
|
|
|
reportItem.setData( aggregatedTransmissibility, allCompletionsForOneFracture.size(), totalAreaOpenForFlow );
|
2018-11-09 03:51:17 -06:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
reportItem.setWidthAndConductivity( eclToFractureCalc.areaWeightedWidth(), areaWeightedConductivity );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
|
void RicExportFractureCompletionsImpl::outputIntermediateResultsText( QTextStream* outputStreamForIntermediateResultsText,
|
|
|
|
|
const RimFracture* fracture,
|
|
|
|
|
RigTransmissibilityCondenser& transCondenser,
|
|
|
|
|
const RigMainGrid* mainGrid,
|
|
|
|
|
const RigFractureGrid* fractureGrid )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
|
( *outputStreamForIntermediateResultsText )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
<< "\n"
|
|
|
|
|
<< "\n"
|
|
|
|
|
<< "\n----------- All Transmissibilities " << fracture->name() << " -------------------- \n\n";
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
( *outputStreamForIntermediateResultsText )
|
|
|
|
|
<< QString::fromStdString( transCondenser.neighborTransDebugOutput( mainGrid, fractureGrid ) );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
( *outputStreamForIntermediateResultsText )
|
2018-09-10 06:00:39 -05:00
|
|
|
|
<< "\n"
|
|
|
|
|
<< "\n"
|
|
|
|
|
<< "\n----------- Condensed Results " << fracture->name() << " -------------------- \n\n";
|
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
( *outputStreamForIntermediateResultsText )
|
|
|
|
|
<< QString::fromStdString( transCondenser.condensedTransDebugOutput( mainGrid, fractureGrid ) );
|
2018-09-10 06:00:39 -05:00
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
|
( *outputStreamForIntermediateResultsText ) << "\n";
|
2017-06-01 09:34:30 -05:00
|
|
|
|
}
|
2019-10-04 08:55:31 -05:00
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
bool RicExportFractureCompletionsImpl::loadResultsByName( RigCaseCellResultsData* cellResultsData,
|
|
|
|
|
const std::vector<QString>& resultNames )
|
|
|
|
|
{
|
|
|
|
|
const std::vector<RiaDefines::ResultCatType> resultCategorySearchOrder = {RiaDefines::STATIC_NATIVE,
|
|
|
|
|
RiaDefines::INPUT_PROPERTY,
|
|
|
|
|
RiaDefines::GENERATED};
|
|
|
|
|
|
|
|
|
|
bool foundDataForAllResults = true;
|
|
|
|
|
|
|
|
|
|
if ( cellResultsData )
|
|
|
|
|
{
|
|
|
|
|
for ( const auto& resultName : resultNames )
|
|
|
|
|
{
|
|
|
|
|
if ( !cellResultsData->findAndLoadResultByName( resultName, resultCategorySearchOrder ) )
|
|
|
|
|
{
|
|
|
|
|
foundDataForAllResults = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return foundDataForAllResults;
|
|
|
|
|
}
|