mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#2546 Well Connection Factors : Several changes related to data access
Moved rig classes from command feature into ReservoirDataModel\Completions\
This commit is contained in:
@@ -4,15 +4,9 @@ ${CMAKE_CURRENT_LIST_DIR}/RicExportCompletionDataSettingsUi.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicWellPathExportCompletionDataFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicWellPathExportCompletionDataFeatureImpl.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicFishbonesTransmissibilityCalculationFeatureImp.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigCompletionData.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigCompletionDataGridCell.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicExportFishbonesWellSegmentsFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCaseAndFileExportSettingsUi.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicExportFractureCompletionsImpl.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigEclipseToStimPlanCellTransmissibilityCalculator.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigTransmissibilityCondenser.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigFractureTransmissibilityEquations.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigWellPathStimplanIntersector.h
|
||||
)
|
||||
|
||||
|
||||
@@ -21,15 +15,9 @@ ${CMAKE_CURRENT_LIST_DIR}/RicExportCompletionDataSettingsUi.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicWellPathExportCompletionDataFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicWellPathExportCompletionDataFeatureImpl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicFishbonesTransmissibilityCalculationFeatureImp.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigCompletionData.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigCompletionDataGridCell.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicExportFishbonesWellSegmentsFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCaseAndFileExportSettingsUi.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicExportFractureCompletionsImpl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigEclipseToStimPlanCellTransmissibilityCalculator.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigTransmissibilityCondenser.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigFractureTransmissibilityEquations.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigWellPathStimplanIntersector.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
|
||||
#include "cvfPlane.h"
|
||||
|
||||
#include "RigVirtualPerforationTransmissibilities.h"
|
||||
#include <QDir>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -315,6 +316,146 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompletions(const std::ve
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
void RicWellPathExportCompletionDataFeatureImpl::computeVirtualPerfTrans(
|
||||
RigVirtualPerforationTransmissibilities* virtualPerfTrans,
|
||||
RimEclipseCase* eclipseCase,
|
||||
const std::vector<RimWellPath*>& inputWellPaths)
|
||||
{
|
||||
CVF_ASSERT(eclipseCase);
|
||||
|
||||
std::vector<RimWellPath*> usedWellPaths;
|
||||
|
||||
{
|
||||
for (RimWellPath* wellPath : inputWellPaths)
|
||||
{
|
||||
if (wellPath->unitSystem() == eclipseCase->eclipseCaseData()->unitsType())
|
||||
{
|
||||
usedWellPaths.push_back(wellPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
RiaLogging::error("Well path unit systems must match unit system of chosen eclipse case.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RicExportCompletionDataSettingsUi exportSettings;
|
||||
exportSettings.caseToApply = eclipseCase;
|
||||
exportSettings.includeFishbones = true;
|
||||
exportSettings.includePerforations = true;
|
||||
exportSettings.includeFractures = true;
|
||||
|
||||
bool anyPerforationsPresent = false;
|
||||
for (const auto& w : usedWellPaths)
|
||||
{
|
||||
if (!w->perforationIntervalCollection()->perforations().empty())
|
||||
{
|
||||
anyPerforationsPresent = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto wellPath : usedWellPaths)
|
||||
{
|
||||
std::vector<RigCompletionData> completionsPerEclipseCell;
|
||||
|
||||
// Compute completions that do not change between time steps
|
||||
|
||||
if (exportSettings.includeFishbones)
|
||||
{
|
||||
std::vector<RigCompletionData> completionData =
|
||||
RicFishbonesTransmissibilityCalculationFeatureImp::generateFishboneCompdatValuesUsingAdjustedCellVolume(
|
||||
wellPath, exportSettings);
|
||||
|
||||
std::copy(completionData.begin(), completionData.end(), std::back_inserter(completionsPerEclipseCell));
|
||||
}
|
||||
|
||||
if (exportSettings.includeFractures())
|
||||
{
|
||||
std::vector<RigCompletionData> completionData =
|
||||
RicExportFractureCompletionsImpl::generateCompdatValuesForWellPath(wellPath, exportSettings, nullptr);
|
||||
|
||||
std::copy(completionData.begin(), completionData.end(), std::back_inserter(completionsPerEclipseCell));
|
||||
}
|
||||
|
||||
if (!anyPerforationsPresent)
|
||||
{
|
||||
virtualPerfTrans->appendCompletionDataForWellPath(wellPath, completionsPerEclipseCell);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < eclipseCase->timeStepDates().size(); i++)
|
||||
{
|
||||
// Update time step in export settings
|
||||
exportSettings.timeStep = static_cast<int>(i);
|
||||
|
||||
if (exportSettings.includePerforations)
|
||||
{
|
||||
std::vector<RigCompletionData> completionData = generatePerforationsCompdatValues(wellPath, exportSettings);
|
||||
|
||||
std::copy(completionData.begin(), completionData.end(), std::back_inserter(completionsPerEclipseCell));
|
||||
}
|
||||
|
||||
//virtualPerfTrans->appendCompletionDataForWellPath(wellPath, completionsPerEclipseCell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RigCompletionData> RicWellPathExportCompletionDataFeatureImpl::computeCompletionsForWellPath(
|
||||
RimWellPath* wellPath,
|
||||
const RicExportCompletionDataSettingsUi& exportSettings)
|
||||
{
|
||||
std::vector<RigCompletionData> completionsPerEclipseCell;
|
||||
{
|
||||
// Compute completions that do not change between time steps
|
||||
|
||||
if (exportSettings.includeFishbones)
|
||||
{
|
||||
std::vector<RigCompletionData> completionData =
|
||||
RicFishbonesTransmissibilityCalculationFeatureImp::generateFishboneCompdatValuesUsingAdjustedCellVolume(
|
||||
wellPath, exportSettings);
|
||||
|
||||
std::copy(completionData.begin(), completionData.end(), std::back_inserter(completionsPerEclipseCell));
|
||||
}
|
||||
|
||||
if (exportSettings.includeFractures())
|
||||
{
|
||||
std::vector<RigCompletionData> completionData =
|
||||
RicExportFractureCompletionsImpl::generateCompdatValuesForWellPath(wellPath, exportSettings, nullptr);
|
||||
|
||||
std::copy(completionData.begin(), completionData.end(), std::back_inserter(completionsPerEclipseCell));
|
||||
}
|
||||
|
||||
{
|
||||
/*
|
||||
for (size_t i = 0; i < exportSettings.caseToApply()->timeStepDates().size(); i++)
|
||||
{
|
||||
// Update time step in export settings
|
||||
exportSettings.timeStep = static_cast<int>(i);
|
||||
|
||||
if (exportSettings.includePerforations)
|
||||
{
|
||||
std::vector<RigCompletionData> completionData = generatePerforationsCompdatValues(wellPath, exportSettings);
|
||||
|
||||
std::copy(completionData.begin(), completionData.end(), std::back_inserter(completionsPerEclipseCell));
|
||||
}
|
||||
|
||||
// virtualPerfTrans->appendCompletionDataForWellPath(wellPath, completionsPerEclipseCell);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
return completionsPerEclipseCell;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
@@ -35,6 +35,7 @@ class RimFishbonesMultipleSubs;
|
||||
class RimSimWellInView;
|
||||
class RimWellPath;
|
||||
class RifEclipseDataTableFormatter;
|
||||
class RigVirtualPerforationTransmissibilities;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
@@ -145,6 +146,9 @@ public:
|
||||
const std::vector<RimSimWellInView*>& simWells,
|
||||
const RicExportCompletionDataSettingsUi& exportSettings);
|
||||
|
||||
static std::vector<RigCompletionData> computeCompletionsForWellPath(RimWellPath* wellPath,
|
||||
const RicExportCompletionDataSettingsUi& exportSettings);
|
||||
|
||||
private:
|
||||
static double calculateTransmissibilityAsEclipseDoes(RimEclipseCase* eclipseCase,
|
||||
double skinFactor,
|
||||
|
||||
@@ -1,419 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RigCompletionData.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
|
||||
#include "cvfAssert.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <cmath> // Needed for HUGE_VAL on Linux
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
RigCompletionData::RigCompletionData(const QString wellName, const RigCompletionDataGridCell& cellIndex, double orderingValue)
|
||||
: m_wellName(wellName)
|
||||
, m_cellIndex(cellIndex)
|
||||
, m_saturation(HUGE_VAL)
|
||||
, m_transmissibility(HUGE_VAL)
|
||||
, m_diameter(HUGE_VAL)
|
||||
, m_kh(HUGE_VAL)
|
||||
, m_skinFactor(HUGE_VAL)
|
||||
, m_dFactor(HUGE_VAL)
|
||||
, m_direction(DIR_UNDEF)
|
||||
, m_connectionState(OPEN)
|
||||
, m_count(1)
|
||||
, m_wpimult(HUGE_VAL)
|
||||
, m_isMainBore(false)
|
||||
, m_completionType(CT_UNDEFINED)
|
||||
, m_firstOrderingValue(orderingValue)
|
||||
, m_secondOrderingValue(HUGE_VAL)
|
||||
{
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
RigCompletionData::~RigCompletionData() {}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
RigCompletionData::RigCompletionData(const RigCompletionData& other)
|
||||
{
|
||||
copy(*this, other);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
bool RigCompletionData::operator<(const RigCompletionData& other) const
|
||||
{
|
||||
if (m_wellName != other.m_wellName)
|
||||
{
|
||||
return (m_wellName < other.m_wellName);
|
||||
}
|
||||
|
||||
if (m_completionType != other.m_completionType)
|
||||
{
|
||||
return (m_completionType < other.m_completionType);
|
||||
}
|
||||
|
||||
if (m_firstOrderingValue != other.m_firstOrderingValue)
|
||||
{
|
||||
return (m_firstOrderingValue < other.m_firstOrderingValue);
|
||||
}
|
||||
|
||||
if (m_secondOrderingValue != other.m_secondOrderingValue)
|
||||
{
|
||||
return (m_secondOrderingValue < other.m_secondOrderingValue);
|
||||
}
|
||||
|
||||
return m_cellIndex < other.m_cellIndex;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
RigCompletionData& RigCompletionData::operator=(const RigCompletionData& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
copy(*this, other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
void RigCompletionData::setFromFracture(double transmissibility, double skinFactor, double diameter)
|
||||
{
|
||||
m_completionType = FRACTURE;
|
||||
m_transmissibility = transmissibility;
|
||||
m_skinFactor = skinFactor;
|
||||
m_diameter = diameter;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigCompletionData::setSecondOrderingValue(double orderingValue)
|
||||
{
|
||||
m_secondOrderingValue = orderingValue;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigCompletionData::setDiameter(double diameter)
|
||||
{
|
||||
m_diameter = diameter;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
void RigCompletionData::setTransAndWPImultBackgroundDataFromFishbone(double transmissibility,
|
||||
double skinFactor,
|
||||
double diameter,
|
||||
CellDirection direction,
|
||||
bool isMainBore)
|
||||
{
|
||||
m_completionType = FISHBONES;
|
||||
m_transmissibility = transmissibility;
|
||||
m_skinFactor = skinFactor;
|
||||
m_diameter = diameter;
|
||||
m_direction = direction;
|
||||
m_isMainBore = isMainBore;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
void RigCompletionData::setTransAndWPImultBackgroundDataFromPerforation(double transmissibility,
|
||||
double skinFactor,
|
||||
double diameter,
|
||||
CellDirection direction)
|
||||
{
|
||||
m_completionType = PERFORATION;
|
||||
m_transmissibility = transmissibility;
|
||||
m_skinFactor = skinFactor;
|
||||
m_diameter = diameter;
|
||||
m_direction = direction;
|
||||
m_isMainBore = true;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
void RigCompletionData::setCombinedValuesExplicitTrans(double transmissibility, CompletionType completionType)
|
||||
{
|
||||
m_completionType = completionType;
|
||||
m_transmissibility = transmissibility;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
void RigCompletionData::setCombinedValuesImplicitTransWPImult(double wpimult,
|
||||
CellDirection celldirection,
|
||||
double skinFactor,
|
||||
double wellDiameter,
|
||||
CompletionType completionType)
|
||||
{
|
||||
m_wpimult = wpimult;
|
||||
m_direction = celldirection;
|
||||
m_completionType = completionType;
|
||||
m_skinFactor = skinFactor;
|
||||
m_diameter = wellDiameter;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigCompletionData::isNonDarcyFlow() const
|
||||
{
|
||||
if (!isDefaultValue(m_kh)) return true;
|
||||
if (!isDefaultValue(m_dFactor)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigCompletionData::setDFactor(double dFactor)
|
||||
{
|
||||
m_dFactor = dFactor;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigCompletionData::setKh(double kh)
|
||||
{
|
||||
m_kh = kh;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
void RigCompletionData::addMetadata(const QString& name, const QString& comment)
|
||||
{
|
||||
m_metadata.push_back(RigCompletionMetaData(name, comment));
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
bool RigCompletionData::isDefaultValue(double val)
|
||||
{
|
||||
return val == HUGE_VAL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<RigCompletionMetaData>& RigCompletionData::metadata() const
|
||||
{
|
||||
return m_metadata;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const QString& RigCompletionData::wellName() const
|
||||
{
|
||||
return m_wellName;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const RigCompletionDataGridCell& RigCompletionData::completionDataGridCell() const
|
||||
{
|
||||
return m_cellIndex;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
WellConnectionState RigCompletionData::connectionState() const
|
||||
{
|
||||
return m_connectionState;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigCompletionData::saturation() const
|
||||
{
|
||||
return m_saturation;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigCompletionData::transmissibility() const
|
||||
{
|
||||
return m_transmissibility;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigCompletionData::diameter() const
|
||||
{
|
||||
return m_diameter;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigCompletionData::kh() const
|
||||
{
|
||||
return m_kh;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigCompletionData::skinFactor() const
|
||||
{
|
||||
return m_skinFactor;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigCompletionData::dFactor() const
|
||||
{
|
||||
return m_dFactor;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
CellDirection RigCompletionData::direction() const
|
||||
{
|
||||
return m_direction;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RigCompletionData::count() const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigCompletionData::wpimult() const
|
||||
{
|
||||
return m_wpimult;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigCompletionData::CompletionType RigCompletionData::completionType() const
|
||||
{
|
||||
return m_completionType;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigCompletionData::isMainBore() const
|
||||
{
|
||||
return m_isMainBore;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigCompletionData::firstOrderingValue() const
|
||||
{
|
||||
return m_firstOrderingValue;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigCompletionData::secondOrderingValue() const
|
||||
{
|
||||
return m_secondOrderingValue;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
bool RigCompletionData::onlyOneIsDefaulted(double first, double second)
|
||||
{
|
||||
if (first == HUGE_VAL)
|
||||
{
|
||||
if (second == HUGE_VAL)
|
||||
{
|
||||
// Both have default values
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// First has default value, second does not
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (second == HUGE_VAL)
|
||||
{
|
||||
// Second has default value, first does not
|
||||
return true;
|
||||
}
|
||||
|
||||
// Neither has default values
|
||||
return false;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
void RigCompletionData::copy(RigCompletionData& target, const RigCompletionData& from)
|
||||
{
|
||||
target.m_metadata = from.m_metadata;
|
||||
target.m_wellName = from.m_wellName;
|
||||
target.m_cellIndex = from.m_cellIndex;
|
||||
target.m_connectionState = from.m_connectionState;
|
||||
target.m_saturation = from.m_saturation;
|
||||
target.m_transmissibility = from.m_transmissibility;
|
||||
target.m_diameter = from.m_diameter;
|
||||
target.m_kh = from.m_kh;
|
||||
target.m_skinFactor = from.m_skinFactor;
|
||||
target.m_dFactor = from.m_dFactor;
|
||||
target.m_direction = from.m_direction;
|
||||
target.m_isMainBore = from.m_isMainBore;
|
||||
target.m_count = from.m_count;
|
||||
target.m_wpimult = from.m_wpimult;
|
||||
target.m_completionType = from.m_completionType;
|
||||
target.m_firstOrderingValue = from.m_firstOrderingValue;
|
||||
target.m_secondOrderingValue = from.m_secondOrderingValue;
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RigCompletionDataGridCell.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimEclipseCase;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
enum WellConnectionState {
|
||||
OPEN,
|
||||
SHUT,
|
||||
AUTO,
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
enum CellDirection {
|
||||
DIR_I,
|
||||
DIR_J,
|
||||
DIR_K,
|
||||
DIR_UNDEF,
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
struct RigCompletionMetaData {
|
||||
RigCompletionMetaData(const QString& name, const QString& comment) : name(name), comment(comment) {}
|
||||
|
||||
QString name;
|
||||
QString comment;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RigCompletionData
|
||||
{
|
||||
public:
|
||||
enum CompletionType {
|
||||
FISHBONES,
|
||||
FRACTURE,
|
||||
PERFORATION,
|
||||
CT_UNDEFINED
|
||||
};
|
||||
|
||||
RigCompletionData(const QString wellName, const RigCompletionDataGridCell& cellIndex, double orderingValue);
|
||||
~RigCompletionData();
|
||||
RigCompletionData(const RigCompletionData& other);
|
||||
|
||||
bool operator<(const RigCompletionData& other) const;
|
||||
RigCompletionData& operator=(const RigCompletionData& other);
|
||||
|
||||
void setFromFracture(double transmissibility, double skinFactor, double diameter);
|
||||
void setSecondOrderingValue(double orderingValue);
|
||||
void setDiameter(double diameter);
|
||||
|
||||
void setTransAndWPImultBackgroundDataFromFishbone(double transmissibility,
|
||||
double skinFactor,
|
||||
double diameter,
|
||||
CellDirection direction,
|
||||
bool isMainBore);
|
||||
|
||||
void setTransAndWPImultBackgroundDataFromPerforation(double transmissibility,
|
||||
double skinFactor,
|
||||
double diameter,
|
||||
CellDirection direction);
|
||||
|
||||
void setCombinedValuesExplicitTrans(double transmissibility, CompletionType completionType);
|
||||
|
||||
void setCombinedValuesImplicitTransWPImult(double wpimult,
|
||||
CellDirection celldirection,
|
||||
double skinFactor,
|
||||
double wellDiameter,
|
||||
CompletionType completionType);
|
||||
|
||||
bool isNonDarcyFlow() const;
|
||||
void setDFactor(double dFactor);
|
||||
void setKh(double kh);
|
||||
|
||||
void addMetadata(const QString& name, const QString& comment);
|
||||
static bool isDefaultValue(double val);
|
||||
|
||||
const std::vector<RigCompletionMetaData>& metadata() const;
|
||||
const QString& wellName() const;
|
||||
const RigCompletionDataGridCell& completionDataGridCell() const;
|
||||
WellConnectionState connectionState() const;
|
||||
double saturation() const;
|
||||
double transmissibility() const;
|
||||
double diameter() const; //TODO: should be ft or m
|
||||
double kh() const;
|
||||
double skinFactor() const;
|
||||
double dFactor() const;
|
||||
CellDirection direction() const;
|
||||
size_t count() const;
|
||||
double wpimult() const;
|
||||
CompletionType completionType() const;
|
||||
bool isMainBore() const;
|
||||
|
||||
double firstOrderingValue() const;
|
||||
double secondOrderingValue() const;
|
||||
|
||||
std::vector<RigCompletionMetaData> m_metadata;
|
||||
|
||||
private:
|
||||
QString m_wellName;
|
||||
RigCompletionDataGridCell m_cellIndex;
|
||||
WellConnectionState m_connectionState;
|
||||
double m_saturation; //TODO: remove, always use default in Eclipse?
|
||||
double m_transmissibility;
|
||||
double m_diameter;
|
||||
double m_kh; //TODO: Remove, always use default in Eclipse?
|
||||
double m_skinFactor;
|
||||
double m_dFactor; //TODO: Remove, always use default in Eclipse?
|
||||
CellDirection m_direction;
|
||||
|
||||
bool m_isMainBore; //to use mainbore for Eclipse calculation
|
||||
|
||||
size_t m_count; //TODO: Remove, usage replaced by WPImult
|
||||
double m_wpimult;
|
||||
|
||||
CompletionType m_completionType;
|
||||
|
||||
double m_firstOrderingValue;
|
||||
double m_secondOrderingValue;
|
||||
|
||||
private:
|
||||
static bool onlyOneIsDefaulted(double first, double second);
|
||||
static void copy(RigCompletionData& target, const RigCompletionData& from);
|
||||
};
|
||||
@@ -1,127 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2018 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 "RigCompletionDataGridCell.h"
|
||||
|
||||
#include "RigMainGrid.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigCompletionDataGridCell::RigCompletionDataGridCell() {}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigCompletionDataGridCell::RigCompletionDataGridCell(size_t globalCellIndex, const RigMainGrid* mainGrid)
|
||||
: m_globalCellIndex(globalCellIndex)
|
||||
{
|
||||
if (mainGrid)
|
||||
{
|
||||
const RigCell& cell = mainGrid->globalCellArray()[globalCellIndex];
|
||||
RigGridBase* grid = cell.hostGrid();
|
||||
if (grid)
|
||||
{
|
||||
size_t gridLocalCellIndex = cell.gridLocalCellIndex();
|
||||
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
size_t k = 0;
|
||||
grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k);
|
||||
|
||||
m_localCellIndexI = i;
|
||||
m_localCellIndexJ = j;
|
||||
m_localCellIndexK = k;
|
||||
|
||||
if (grid != mainGrid)
|
||||
{
|
||||
m_lgrName = QString::fromStdString(grid->gridName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigCompletionDataGridCell::operator==(const RigCompletionDataGridCell& other) const
|
||||
{
|
||||
return m_globalCellIndex == other.m_globalCellIndex;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigCompletionDataGridCell::operator<(const RigCompletionDataGridCell& other) const
|
||||
{
|
||||
if (m_localCellIndexI != other.m_localCellIndexI) return m_localCellIndexI < other.m_localCellIndexI;
|
||||
if (m_localCellIndexJ != other.m_localCellIndexJ) return m_localCellIndexJ < other.m_localCellIndexJ;
|
||||
if (m_localCellIndexK != other.m_localCellIndexK) return m_localCellIndexK < other.m_localCellIndexK;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RigCompletionDataGridCell::globalCellIndex() const
|
||||
{
|
||||
return m_globalCellIndex;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RigCompletionDataGridCell::localCellIndexI() const
|
||||
{
|
||||
return m_localCellIndexI;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RigCompletionDataGridCell::localCellIndexJ() const
|
||||
{
|
||||
return m_localCellIndexJ;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RigCompletionDataGridCell::localCellIndexK() const
|
||||
{
|
||||
return m_localCellIndexK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RigCompletionDataGridCell::oneBasedLocalCellIndexString() const
|
||||
{
|
||||
QString text = QString("[%1, %2, %3]").arg(m_localCellIndexI + 1).arg(m_localCellIndexJ + 1).arg(m_localCellIndexK + 1);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RigCompletionDataGridCell::lgrName() const
|
||||
{
|
||||
return m_lgrName;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2018 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
class RigMainGrid;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RigCompletionDataGridCell
|
||||
{
|
||||
public:
|
||||
RigCompletionDataGridCell();
|
||||
|
||||
RigCompletionDataGridCell(size_t globalCellIndex, const RigMainGrid* mainGrid);
|
||||
|
||||
bool operator==(const RigCompletionDataGridCell& other) const;
|
||||
|
||||
bool operator<(const RigCompletionDataGridCell& other) const;
|
||||
|
||||
size_t globalCellIndex() const;
|
||||
|
||||
size_t localCellIndexI() const;
|
||||
size_t localCellIndexJ() const;
|
||||
size_t localCellIndexK() const;
|
||||
|
||||
QString oneBasedLocalCellIndexString() const;
|
||||
|
||||
QString lgrName() const;
|
||||
|
||||
private:
|
||||
size_t m_globalCellIndex;
|
||||
QString m_lgrName;
|
||||
|
||||
size_t m_localCellIndexI;
|
||||
size_t m_localCellIndexJ;
|
||||
size_t m_localCellIndexK;
|
||||
};
|
||||
@@ -1,247 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RigEclipseToStimPlanCellTransmissibilityCalculator.h"
|
||||
|
||||
#include "RigActiveCellInfo.h"
|
||||
#include "RigCaseCellResultsData.h"
|
||||
#include "RigCellGeometryTools.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigFractureCell.h"
|
||||
#include "RigFractureTransmissibilityEquations.h"
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigResultAccessorFactory.h"
|
||||
#include "RigHexIntersectionTools.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
|
||||
#include "cvfGeometryTools.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigEclipseToStimPlanCellTransmissibilityCalculator::RigEclipseToStimPlanCellTransmissibilityCalculator(RimEclipseCase* caseToApply,
|
||||
cvf::Mat4d fractureTransform,
|
||||
double skinFactor,
|
||||
double cDarcy,
|
||||
const RigFractureCell& stimPlanCell)
|
||||
: m_case(caseToApply),
|
||||
m_fractureTransform(fractureTransform),
|
||||
m_fractureSkinFactor(skinFactor),
|
||||
m_cDarcy(cDarcy),
|
||||
m_stimPlanCell(stimPlanCell)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<size_t>& RigEclipseToStimPlanCellTransmissibilityCalculator::globalIndeciesToContributingEclipseCells()
|
||||
{
|
||||
if (m_globalIndeciesToContributingEclipseCells.size() < 1)
|
||||
{
|
||||
calculateStimPlanCellsMatrixTransmissibility();
|
||||
}
|
||||
|
||||
return m_globalIndeciesToContributingEclipseCells;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>& RigEclipseToStimPlanCellTransmissibilityCalculator::contributingEclipseCellTransmissibilities()
|
||||
{
|
||||
if (m_globalIndeciesToContributingEclipseCells.size() < 1)
|
||||
{
|
||||
calculateStimPlanCellsMatrixTransmissibility();
|
||||
}
|
||||
|
||||
return m_contributingEclipseCellTransmissibilities;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigEclipseToStimPlanCellTransmissibilityCalculator::calculateStimPlanCellsMatrixTransmissibility()
|
||||
{
|
||||
// Not calculating flow into fracture if stimPlan cell cond value is 0 (assumed to be outside the fracture):
|
||||
if (m_stimPlanCell.getConductivtyValue() < 1e-7) return;
|
||||
|
||||
const RigEclipseCaseData* eclipseCaseData = m_case->eclipseCaseData();
|
||||
|
||||
RiaDefines::PorosityModelType porosityModel = RiaDefines::MATRIX_MODEL;
|
||||
|
||||
cvf::ref<RigResultAccessor> dataAccessObjectDx = loadResultAndCreateResultAccessor(m_case, porosityModel, "DX");
|
||||
cvf::ref<RigResultAccessor> dataAccessObjectDy = loadResultAndCreateResultAccessor(m_case, porosityModel, "DY");
|
||||
cvf::ref<RigResultAccessor> dataAccessObjectDz = loadResultAndCreateResultAccessor(m_case, porosityModel, "DZ");
|
||||
cvf::ref<RigResultAccessor> dataAccessObjectPermX = loadResultAndCreateResultAccessor(m_case, porosityModel, "PERMX");
|
||||
cvf::ref<RigResultAccessor> dataAccessObjectPermY = loadResultAndCreateResultAccessor(m_case, porosityModel, "PERMY");
|
||||
cvf::ref<RigResultAccessor> dataAccessObjectPermZ = loadResultAndCreateResultAccessor(m_case, porosityModel, "PERMZ");
|
||||
cvf::ref<RigResultAccessor> dataAccessObjectNTG = loadResultAndCreateResultAccessor(m_case, porosityModel, "NTG");
|
||||
|
||||
const RigActiveCellInfo* activeCellInfo = eclipseCaseData->activeCellInfo(porosityModel);
|
||||
|
||||
std::vector<cvf::Vec3d> stimPlanPolygonTransformed;
|
||||
for (cvf::Vec3d v : m_stimPlanCell.getPolygon())
|
||||
{
|
||||
v.transformPoint(m_fractureTransform);
|
||||
stimPlanPolygonTransformed.push_back(v);
|
||||
}
|
||||
|
||||
std::vector<size_t> fracCells = getPotentiallyFracturedCellsForPolygon(stimPlanPolygonTransformed);
|
||||
for (size_t fracCell : fracCells)
|
||||
{
|
||||
bool cellIsActive = activeCellInfo->isActive(fracCell);
|
||||
if (!cellIsActive) continue;
|
||||
|
||||
double permX = dataAccessObjectPermX->cellScalarGlobIdx(fracCell);
|
||||
double permY = dataAccessObjectPermY->cellScalarGlobIdx(fracCell);
|
||||
double permZ = dataAccessObjectPermZ->cellScalarGlobIdx(fracCell);
|
||||
|
||||
double dx = dataAccessObjectDx->cellScalarGlobIdx(fracCell);
|
||||
double dy = dataAccessObjectDy->cellScalarGlobIdx(fracCell);
|
||||
double dz = dataAccessObjectDz->cellScalarGlobIdx(fracCell);
|
||||
|
||||
double NTG = 1.0;
|
||||
if (dataAccessObjectNTG.notNull())
|
||||
{
|
||||
NTG = dataAccessObjectNTG->cellScalarGlobIdx(fracCell);
|
||||
}
|
||||
|
||||
const RigMainGrid* mainGrid = m_case->eclipseCaseData()->mainGrid();
|
||||
std::array<cvf::Vec3d, 8> hexCorners;
|
||||
mainGrid->cellCornerVertices(fracCell, hexCorners.data());
|
||||
|
||||
std::vector<std::vector<cvf::Vec3d> > planeCellPolygons;
|
||||
bool isPlanIntersected = RigHexIntersectionTools::planeHexIntersectionPolygons(hexCorners, m_fractureTransform, planeCellPolygons);
|
||||
if (!isPlanIntersected || planeCellPolygons.size() == 0) continue;
|
||||
|
||||
cvf::Vec3d localX;
|
||||
cvf::Vec3d localY;
|
||||
cvf::Vec3d localZ;
|
||||
RigCellGeometryTools::findCellLocalXYZ(hexCorners, localX, localY, localZ);
|
||||
|
||||
//Transform planCell polygon(s) and averageZdirection to x/y coordinate system (where fracturePolygon already is located)
|
||||
cvf::Mat4d invertedTransMatrix = m_fractureTransform.getInverted();
|
||||
for (std::vector<cvf::Vec3d> & planeCellPolygon : planeCellPolygons)
|
||||
{
|
||||
for (cvf::Vec3d& v : planeCellPolygon)
|
||||
{
|
||||
v.transformPoint(invertedTransMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::vector<cvf::Vec3d> > polygonsForStimPlanCellInEclipseCell;
|
||||
cvf::Vec3d areaVector;
|
||||
std::vector<cvf::Vec3d> stimPlanPolygon = m_stimPlanCell.getPolygon();
|
||||
|
||||
for (std::vector<cvf::Vec3d> planeCellPolygon : planeCellPolygons)
|
||||
{
|
||||
std::vector<std::vector<cvf::Vec3d> >clippedPolygons = RigCellGeometryTools::intersectPolygons(planeCellPolygon, stimPlanPolygon);
|
||||
for (std::vector<cvf::Vec3d> clippedPolygon : clippedPolygons)
|
||||
{
|
||||
polygonsForStimPlanCellInEclipseCell.push_back(clippedPolygon);
|
||||
}
|
||||
}
|
||||
|
||||
if (polygonsForStimPlanCellInEclipseCell.size() == 0) continue;
|
||||
|
||||
double area;
|
||||
std::vector<double> areaOfFractureParts;
|
||||
double length;
|
||||
std::vector<double> lengthXareaOfFractureParts;
|
||||
double Ax = 0.0, Ay = 0.0, Az = 0.0;
|
||||
|
||||
for (std::vector<cvf::Vec3d> fracturePartPolygon : polygonsForStimPlanCellInEclipseCell)
|
||||
{
|
||||
areaVector = cvf::GeometryTools::polygonAreaNormal3D(fracturePartPolygon);
|
||||
area = areaVector.length();
|
||||
areaOfFractureParts.push_back(area);
|
||||
|
||||
length = RigCellGeometryTools::polygonLengthInLocalXdirWeightedByArea(fracturePartPolygon);
|
||||
lengthXareaOfFractureParts.push_back(length * area);
|
||||
|
||||
cvf::Plane fracturePlane;
|
||||
fracturePlane.setFromPointAndNormal(static_cast<cvf::Vec3d>(m_fractureTransform.translation()),
|
||||
static_cast<cvf::Vec3d>(m_fractureTransform.col(2)));
|
||||
|
||||
Ax += fabs(area*(fracturePlane.normal().dot(localY)));
|
||||
Ay += fabs(area*(fracturePlane.normal().dot(localX)));
|
||||
Az += fabs(area*(fracturePlane.normal().dot(localZ)));
|
||||
}
|
||||
|
||||
double fractureArea = 0.0;
|
||||
for (double area : areaOfFractureParts) fractureArea += area;
|
||||
|
||||
double totalAreaXLength = 0.0;
|
||||
for (double lengtXarea : lengthXareaOfFractureParts) totalAreaXLength += lengtXarea;
|
||||
|
||||
double fractureAreaWeightedlength = totalAreaXLength / fractureArea;
|
||||
|
||||
double transmissibility_X = RigFractureTransmissibilityEquations::matrixToFractureTrans(permY, NTG, Ay, dx, m_fractureSkinFactor, fractureAreaWeightedlength, m_cDarcy);
|
||||
double transmissibility_Y = RigFractureTransmissibilityEquations::matrixToFractureTrans(permX, NTG, Ax, dy, m_fractureSkinFactor, fractureAreaWeightedlength, m_cDarcy);
|
||||
double transmissibility_Z = RigFractureTransmissibilityEquations::matrixToFractureTrans(permZ, 1.0, Az, dz, m_fractureSkinFactor, fractureAreaWeightedlength, m_cDarcy);
|
||||
|
||||
double transmissibility = sqrt(transmissibility_X * transmissibility_X
|
||||
+ transmissibility_Y * transmissibility_Y
|
||||
+ transmissibility_Z * transmissibility_Z);
|
||||
|
||||
|
||||
m_globalIndeciesToContributingEclipseCells.push_back(fracCell);
|
||||
m_contributingEclipseCellTransmissibilities.push_back(transmissibility);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<size_t> RigEclipseToStimPlanCellTransmissibilityCalculator::getPotentiallyFracturedCellsForPolygon(std::vector<cvf::Vec3d> polygon)
|
||||
{
|
||||
std::vector<size_t> cellIndices;
|
||||
|
||||
const RigMainGrid* mainGrid = m_case->eclipseCaseData()->mainGrid();
|
||||
if (!mainGrid) return cellIndices;
|
||||
|
||||
cvf::BoundingBox polygonBBox;
|
||||
for (cvf::Vec3d nodeCoord : polygon) polygonBBox.add(nodeCoord);
|
||||
|
||||
mainGrid->findIntersectingCells(polygonBBox, &cellIndices);
|
||||
|
||||
return cellIndices;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::ref<RigResultAccessor> RigEclipseToStimPlanCellTransmissibilityCalculator::loadResultAndCreateResultAccessor(
|
||||
RimEclipseCase* eclipseCase,
|
||||
RiaDefines::PorosityModelType porosityModel,
|
||||
const QString& uiResultName)
|
||||
{
|
||||
CVF_ASSERT(eclipseCase);
|
||||
|
||||
RigCaseCellResultsData* gridCellResults = eclipseCase->results(porosityModel);
|
||||
|
||||
// Calling this function will force loading of result from file
|
||||
gridCellResults->findOrLoadScalarResult(RiaDefines::STATIC_NATIVE, uiResultName);
|
||||
|
||||
const RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
|
||||
|
||||
// Create result accessor object for main grid at time step zero (static result date is always at first time step
|
||||
return RigResultAccessorFactory::createFromUiResultName(eclipseCaseData, 0, porosityModel, 0, uiResultName);
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RiaPorosityModel.h"
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfObject.h"
|
||||
#include "cvfMatrix4.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class QString;
|
||||
|
||||
class RimEclipseCase;
|
||||
class RigFractureCell;
|
||||
class RigEclipseCaseData;
|
||||
class RigResultAccessor;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
class RigEclipseToStimPlanCellTransmissibilityCalculator
|
||||
{
|
||||
public:
|
||||
explicit RigEclipseToStimPlanCellTransmissibilityCalculator(RimEclipseCase* caseToApply,
|
||||
cvf::Mat4d fractureTransform,
|
||||
double skinFactor,
|
||||
double cDarcy,
|
||||
const RigFractureCell& stimPlanCell);
|
||||
|
||||
const std::vector<size_t>& globalIndeciesToContributingEclipseCells();
|
||||
const std::vector<double>& contributingEclipseCellTransmissibilities();
|
||||
|
||||
private:
|
||||
void calculateStimPlanCellsMatrixTransmissibility();
|
||||
std::vector<size_t> getPotentiallyFracturedCellsForPolygon(std::vector<cvf::Vec3d> polygon);
|
||||
|
||||
static cvf::ref<RigResultAccessor>
|
||||
loadResultAndCreateResultAccessor(RimEclipseCase* eclipseCase,
|
||||
RiaDefines::PorosityModelType porosityModel,
|
||||
const QString& uiResultName);
|
||||
|
||||
private:
|
||||
RimEclipseCase* m_case;
|
||||
double m_cDarcy;
|
||||
double m_fractureSkinFactor;
|
||||
cvf::Mat4d m_fractureTransform;
|
||||
const RigFractureCell& m_stimPlanCell;
|
||||
std::vector<size_t> m_globalIndeciesToContributingEclipseCells;
|
||||
std::vector<double> m_contributingEclipseCellTransmissibilities;
|
||||
};
|
||||
@@ -1,135 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RigFractureTransmissibilityEquations.h"
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfMath.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigFractureTransmissibilityEquations::centerToCenterFractureCellTrans(double conductivityCell1,
|
||||
double sideLengthParallellTransCell1,
|
||||
double sideLengthNormalTransCell1,
|
||||
double conductivityCell2,
|
||||
double sideLengthParallellTransCell2,
|
||||
double sideLengthNormalTransCell2,
|
||||
double cDarcyForRelevantUnit)
|
||||
{
|
||||
double transCell1 = centerToEdgeFractureCellTrans(conductivityCell1, sideLengthParallellTransCell1, sideLengthNormalTransCell1, cDarcyForRelevantUnit);
|
||||
double transCell2 = centerToEdgeFractureCellTrans(conductivityCell2, sideLengthParallellTransCell2, sideLengthNormalTransCell2, cDarcyForRelevantUnit);
|
||||
|
||||
double totalTrans = 1 / ( (1 / transCell1) + (1 / transCell2));
|
||||
|
||||
return totalTrans;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigFractureTransmissibilityEquations::fractureCellToWellRadialTrans(double fractureCellConductivity,
|
||||
double fractureCellSizeX,
|
||||
double fractureCellSizeZ,
|
||||
double wellRadius,
|
||||
double skinFactor,
|
||||
double cDarcyForRelevantUnit)
|
||||
{
|
||||
double ro = 0.14 * cvf::Math::sqrt(
|
||||
pow(fractureCellSizeX, 2.0) + pow(fractureCellSizeZ, 2));
|
||||
|
||||
if (ro < (wellRadius * 1.01))
|
||||
{
|
||||
ro = wellRadius * 1.01;
|
||||
}
|
||||
|
||||
double Tc = 2 * cvf::PI_D * cDarcyForRelevantUnit * fractureCellConductivity /
|
||||
(log(ro / wellRadius) + skinFactor );
|
||||
|
||||
CVF_TIGHT_ASSERT(Tc > 0);
|
||||
return Tc;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigFractureTransmissibilityEquations::fractureCellToWellLinearTrans(double fractureCellConductivity,
|
||||
double fractureCellSizeX,
|
||||
double fractureCellSizeZ,
|
||||
double perforationLengthVertical,
|
||||
double perforationLengthHorizontal,
|
||||
double perforationEfficiency,
|
||||
double skinfactor,
|
||||
double cDarcyForRelevantUnit)
|
||||
{
|
||||
double TcPrefix = 8 * cDarcyForRelevantUnit * fractureCellConductivity;
|
||||
|
||||
double DzPerf = perforationLengthVertical * perforationEfficiency;
|
||||
double DxPerf = perforationLengthHorizontal * perforationEfficiency;
|
||||
|
||||
double TcZ = TcPrefix * DzPerf /
|
||||
(fractureCellSizeX + skinfactor * DzPerf / cvf::PI_D);
|
||||
|
||||
double TcX = TcPrefix * DxPerf /
|
||||
(fractureCellSizeZ + skinfactor* DxPerf / cvf::PI_D);
|
||||
|
||||
double Tc = cvf::Math::sqrt(pow(TcX, 2) + pow(TcZ, 2));
|
||||
return Tc;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigFractureTransmissibilityEquations::matrixToFractureTrans(double perm,
|
||||
double NTG,
|
||||
double A,
|
||||
double cellSizeLength,
|
||||
double skinfactor,
|
||||
double fractureAreaWeightedlength,
|
||||
double cDarcy)
|
||||
{
|
||||
double transmissibility;
|
||||
|
||||
double slDivPi = 0.0;
|
||||
if ( cvf::Math::abs(skinfactor) > 1e-9)
|
||||
{
|
||||
slDivPi = (skinfactor * fractureAreaWeightedlength) / cvf::PI_D;
|
||||
}
|
||||
|
||||
transmissibility = 8 * cDarcy * (perm * NTG) * A / (cellSizeLength + slDivPi);
|
||||
|
||||
CVF_ASSERT(transmissibility == transmissibility);
|
||||
return transmissibility;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigFractureTransmissibilityEquations::centerToEdgeFractureCellTrans(double conductivity,
|
||||
double sideLengthParallellTrans,
|
||||
double sideLengthNormalTrans,
|
||||
double cDarcyForRelevantUnit)
|
||||
{
|
||||
double transmissibility = cDarcyForRelevantUnit * conductivity * sideLengthNormalTrans / (sideLengthParallellTrans / 2);
|
||||
return transmissibility;
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
class RigFractureTransmissibilityEquations
|
||||
{
|
||||
public:
|
||||
static double centerToCenterFractureCellTrans(double conductivityCell1,
|
||||
double sideLengthParallellTransCell1,
|
||||
double sideLengthNormalTransCell1,
|
||||
double conductivityCell2,
|
||||
double sideLengthParallellTransCell2,
|
||||
double sideLengthNormalTransCell2,
|
||||
double cDarcyForRelevantUnit);
|
||||
|
||||
static double fractureCellToWellRadialTrans(double fractureCellConductivity,
|
||||
double fractureCellSizeX,
|
||||
double fractureCellSizeZ,
|
||||
double wellRadius,
|
||||
double skinFactor,
|
||||
double cDarcyForRelevantUnit);
|
||||
|
||||
static double fractureCellToWellLinearTrans(double fractureConductivity,
|
||||
double fractureCellSizeX,
|
||||
double fractureCellSizeZ,
|
||||
double perforationLengthVertical,
|
||||
double perforationLengthHorizontal,
|
||||
double perforationEfficiency,
|
||||
double skinfactor,
|
||||
double cDarcyForRelevantUnit);
|
||||
|
||||
static double matrixToFractureTrans(double permX,
|
||||
double NTG,
|
||||
double Ay,
|
||||
double dx,
|
||||
double skinfactor,
|
||||
double fractureAreaWeightedlength,
|
||||
double cDarcy);
|
||||
|
||||
private:
|
||||
static double centerToEdgeFractureCellTrans(double conductivity,
|
||||
double sideLengthParallellTrans,
|
||||
double sideLengthNormalTrans,
|
||||
double cDarcyForRelevantUnit);
|
||||
|
||||
|
||||
};
|
||||
@@ -1,271 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RigTransmissibilityCondenser.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/LU>
|
||||
#include <iomanip>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigTransmissibilityCondenser::addNeighborTransmissibility(CellAddress cell1, CellAddress cell2, double transmissibility)
|
||||
{
|
||||
if (transmissibility < 1e-9) return;
|
||||
|
||||
m_condensedTransmissibilities.clear();
|
||||
m_externalCellAddrSet.clear();
|
||||
if ( cell1 < cell2 )
|
||||
m_neighborTransmissibilities[cell1][cell2] += transmissibility;
|
||||
else
|
||||
m_neighborTransmissibilities[cell2][cell1] += transmissibility;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::set<RigTransmissibilityCondenser::CellAddress> RigTransmissibilityCondenser::externalCells()
|
||||
{
|
||||
calculateCondensedTransmissibilitiesIfNeeded();
|
||||
|
||||
return m_externalCellAddrSet;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigTransmissibilityCondenser::condensedTransmissibility(CellAddress externalCell1, CellAddress externalCell2)
|
||||
{
|
||||
CAF_ASSERT(!(externalCell1 == externalCell2));
|
||||
|
||||
calculateCondensedTransmissibilitiesIfNeeded();
|
||||
|
||||
if ( externalCell2 < externalCell1 ) std::swap(externalCell1, externalCell2);
|
||||
|
||||
const auto& adrToAdrTransMapPair = m_condensedTransmissibilities.find(externalCell1);
|
||||
if ( adrToAdrTransMapPair != m_condensedTransmissibilities.end() )
|
||||
{
|
||||
const auto& adrTransPair = adrToAdrTransMapPair->second.find(externalCell2);
|
||||
if ( adrTransPair != adrToAdrTransMapPair->second.end() )
|
||||
{
|
||||
return adrTransPair->second;
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigTransmissibilityCondenser::calculateCondensedTransmissibilitiesIfNeeded()
|
||||
{
|
||||
if (m_condensedTransmissibilities.size()) return;
|
||||
|
||||
// Find all equations, and their total ordering
|
||||
|
||||
union
|
||||
{
|
||||
int idxToFirstExternalEquation;
|
||||
int internalEquationCount;
|
||||
};
|
||||
idxToFirstExternalEquation = -1;
|
||||
int totalEquationCount = -1;
|
||||
|
||||
std::map<CellAddress, int> cellAddressToEqIdxMap;
|
||||
std::vector<CellAddress> eqIdxToCellAddressMapping;
|
||||
{
|
||||
for ( const auto& adrEqIdxPair : m_neighborTransmissibilities )
|
||||
{
|
||||
cellAddressToEqIdxMap.insert({ adrEqIdxPair.first, -1 });
|
||||
for ( const auto& adrTranspair : adrEqIdxPair.second )
|
||||
{
|
||||
cellAddressToEqIdxMap.insert({ adrTranspair.first, -1 });
|
||||
}
|
||||
}
|
||||
|
||||
int currentEqIdx = 0;
|
||||
|
||||
for ( auto& adrEqIdxPair : cellAddressToEqIdxMap)
|
||||
{
|
||||
adrEqIdxPair.second = currentEqIdx;
|
||||
eqIdxToCellAddressMapping.push_back(adrEqIdxPair.first);
|
||||
|
||||
if ( idxToFirstExternalEquation == -1 && adrEqIdxPair.first.m_isExternal )
|
||||
{
|
||||
idxToFirstExternalEquation = currentEqIdx;
|
||||
}
|
||||
++currentEqIdx;
|
||||
}
|
||||
totalEquationCount = currentEqIdx;
|
||||
}
|
||||
|
||||
CAF_ASSERT(idxToFirstExternalEquation != -1);
|
||||
|
||||
using namespace Eigen;
|
||||
|
||||
MatrixXd totalSystem = MatrixXd::Zero(totalEquationCount, totalEquationCount);
|
||||
|
||||
for (const auto& adrToAdrTransMapPair : m_neighborTransmissibilities)
|
||||
{
|
||||
CAF_ASSERT(cellAddressToEqIdxMap.count(adrToAdrTransMapPair.first)); // Remove when stabilized
|
||||
int c1EquationIdx = cellAddressToEqIdxMap[adrToAdrTransMapPair.first];
|
||||
for (const auto& adrTranspair : adrToAdrTransMapPair.second)
|
||||
{
|
||||
CAF_ASSERT(cellAddressToEqIdxMap.count(adrTranspair.first)); // Remove when stabilized
|
||||
|
||||
int c2EquationIdx = cellAddressToEqIdxMap[adrTranspair.first];
|
||||
|
||||
totalSystem(c1EquationIdx, c2EquationIdx) += adrTranspair.second;
|
||||
totalSystem(c2EquationIdx, c1EquationIdx) += adrTranspair.second;
|
||||
totalSystem(c1EquationIdx, c1EquationIdx) -= adrTranspair.second;
|
||||
totalSystem(c2EquationIdx, c2EquationIdx) -= adrTranspair.second;
|
||||
}
|
||||
|
||||
++c1EquationIdx;
|
||||
}
|
||||
|
||||
// std::cout << "T = " << std::endl << totalSystem << std::endl;
|
||||
|
||||
int externalEquationCount = totalEquationCount - internalEquationCount;
|
||||
MatrixXd condensedSystem = totalSystem.bottomRightCorner(externalEquationCount, externalEquationCount)
|
||||
- totalSystem.bottomLeftCorner(externalEquationCount, internalEquationCount)
|
||||
* totalSystem.topLeftCorner(internalEquationCount, internalEquationCount).inverse()
|
||||
* totalSystem.topRightCorner(internalEquationCount, externalEquationCount );
|
||||
|
||||
// std::cout << "Te = " << std::endl << condensedSystem << std::endl << std::endl;
|
||||
|
||||
for (int exEqIdx = 0; exEqIdx < externalEquationCount; ++exEqIdx)
|
||||
{
|
||||
for (int exColIdx = exEqIdx +1; exColIdx < externalEquationCount; ++exColIdx)
|
||||
{
|
||||
double T = condensedSystem(exEqIdx, exColIdx);
|
||||
//if (T != 0.0)
|
||||
{
|
||||
CellAddress cell1 = eqIdxToCellAddressMapping[exEqIdx + internalEquationCount];
|
||||
CellAddress cell2 = eqIdxToCellAddressMapping[exColIdx + internalEquationCount];
|
||||
if (cell1 < cell2) m_condensedTransmissibilities[cell1][cell2] = T;
|
||||
else m_condensedTransmissibilities[cell2][cell1] = T;
|
||||
|
||||
m_externalCellAddrSet.insert(cell1);
|
||||
m_externalCellAddrSet.insert(cell2);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "RimStimPlanFractureTemplate.h"
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigFractureCell.h"
|
||||
|
||||
void printCellAddress(std::stringstream& str,
|
||||
const RigMainGrid* mainGrid,
|
||||
const RigFractureGrid* fractureGrid,
|
||||
RigTransmissibilityCondenser::CellAddress cellAddr)
|
||||
{
|
||||
using CellAddress = RigTransmissibilityCondenser::CellAddress;
|
||||
|
||||
str << (cellAddr.m_isExternal ? "E " : "I ");
|
||||
|
||||
switch (cellAddr.m_cellIndexSpace) {
|
||||
case CellAddress::ECLIPSE:
|
||||
{
|
||||
if (cellAddr.m_globalCellIdx > mainGrid->cellCount())
|
||||
{
|
||||
str << "ECL - LGR CELL ";
|
||||
}
|
||||
else
|
||||
{
|
||||
str << "ECL ";
|
||||
size_t i, j, k;
|
||||
mainGrid->ijkFromCellIndex(cellAddr.m_globalCellIdx, &i, &j, &k);
|
||||
str << std::setw(5) << i+1 << std::setw(5) << j+1 << std::setw(5) << k+1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CellAddress::STIMPLAN:
|
||||
{
|
||||
str << "STP ";
|
||||
const RigFractureCell& stpCell = fractureGrid->cellFromIndex(cellAddr.m_globalCellIdx);
|
||||
str << std::setw(5) << stpCell.getI()+1 << std::setw(5) << stpCell.getJ()+1 << std::setw(5) << " ";
|
||||
}
|
||||
break;
|
||||
|
||||
case CellAddress::WELL:
|
||||
{
|
||||
str << "WEL ";
|
||||
str << std::setw(5) << cellAddr.m_globalCellIdx << std::setw(5) << " " << std::setw(5) << " ";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
str << " ";
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RigTransmissibilityCondenser::neighborTransDebugOutput(const RigMainGrid* mainGrid, const RigFractureGrid* fractureGrid)
|
||||
{
|
||||
std::stringstream debugText;
|
||||
for ( const auto& adrEqIdxPair : m_neighborTransmissibilities )
|
||||
{
|
||||
for (const auto& adrTransPair :adrEqIdxPair.second)
|
||||
{
|
||||
debugText << "-- ";
|
||||
printCellAddress(debugText, mainGrid, fractureGrid, adrEqIdxPair.first);
|
||||
printCellAddress(debugText, mainGrid, fractureGrid, adrTransPair.first);
|
||||
|
||||
debugText << " Trans: " << std::setprecision(10) << std::fixed << adrTransPair.second;
|
||||
debugText << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return debugText.str();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RigTransmissibilityCondenser::condensedTransDebugOutput(const RigMainGrid* mainGrid, const RigFractureGrid* fractureGrid)
|
||||
{
|
||||
std::stringstream debugText;
|
||||
for ( const auto& adrEqIdxPair : m_condensedTransmissibilities )
|
||||
{
|
||||
for (const auto& adrTransPair :adrEqIdxPair.second)
|
||||
{
|
||||
debugText << "-- ";
|
||||
printCellAddress(debugText, mainGrid, fractureGrid, adrEqIdxPair.first);
|
||||
printCellAddress(debugText, mainGrid, fractureGrid, adrTransPair.first);
|
||||
|
||||
debugText << " Trans: " << std::setprecision(10) << std::fixed << adrTransPair.second;
|
||||
debugText << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return debugText.str();
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafAssert.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
class RigMainGrid;
|
||||
class RimStimPlanFractureTemplate;
|
||||
class RigFractureGrid;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
class RigTransmissibilityCondenser
|
||||
{
|
||||
public:
|
||||
class CellAddress
|
||||
{
|
||||
public:
|
||||
enum CellIndexSpace { ECLIPSE, STIMPLAN, WELL};
|
||||
|
||||
CellAddress(): m_isExternal(false),
|
||||
m_cellIndexSpace(STIMPLAN),
|
||||
m_globalCellIdx(-1)
|
||||
{}
|
||||
CellAddress(bool isExternal,
|
||||
CellIndexSpace cellType,
|
||||
size_t globalCellIdx)
|
||||
: m_isExternal(isExternal),
|
||||
m_cellIndexSpace(cellType),
|
||||
m_globalCellIdx(globalCellIdx)
|
||||
{}
|
||||
|
||||
bool m_isExternal;
|
||||
CellIndexSpace m_cellIndexSpace;
|
||||
size_t m_globalCellIdx;
|
||||
|
||||
|
||||
bool operator==(const CellAddress& o)
|
||||
{
|
||||
return (m_isExternal == o.m_isExternal) && (m_cellIndexSpace == o.m_cellIndexSpace) && (m_globalCellIdx == o.m_globalCellIdx);
|
||||
}
|
||||
|
||||
// Ordering external after internal is important for the matrix order internally
|
||||
|
||||
bool operator<(const CellAddress& other) const
|
||||
{
|
||||
if (m_isExternal != other.m_isExternal) return !m_isExternal; // Internal cells < External cells
|
||||
if (m_cellIndexSpace != other.m_cellIndexSpace)return m_cellIndexSpace < other.m_cellIndexSpace; // Eclipse < StimPlan
|
||||
if (m_globalCellIdx != other.m_globalCellIdx) return m_globalCellIdx < other.m_globalCellIdx;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void addNeighborTransmissibility(CellAddress cell1, CellAddress cell2, double transmissibility);
|
||||
|
||||
std::set<CellAddress> externalCells();
|
||||
|
||||
double condensedTransmissibility( CellAddress externalCell1, CellAddress externalCell2);
|
||||
|
||||
std::string neighborTransDebugOutput(const RigMainGrid* mainGrid, const RigFractureGrid* fractureGrid);
|
||||
std::string condensedTransDebugOutput(const RigMainGrid* mainGrid, const RigFractureGrid* fractureGrid);
|
||||
|
||||
private:
|
||||
void calculateCondensedTransmissibilitiesIfNeeded();
|
||||
|
||||
std::map<CellAddress, std::map<CellAddress, double> > m_neighborTransmissibilities;
|
||||
std::map<CellAddress, std::map<CellAddress, double> > m_condensedTransmissibilities;
|
||||
std::set<CellAddress> m_externalCellAddrSet;
|
||||
};
|
||||
@@ -1,226 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RigWellPathStimplanIntersector.h"
|
||||
|
||||
#include "RigCellGeometryTools.h"
|
||||
#include "RigFractureCell.h"
|
||||
#include "RigFractureGrid.h"
|
||||
#include "RigWellPath.h"
|
||||
|
||||
#include "RimFracture.h"
|
||||
#include "RimFractureTemplate.h"
|
||||
#include "RimSimWellFracture.h"
|
||||
#include "RimStimPlanFractureTemplate.h"
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfMath.h"
|
||||
#include "cvfMatrix4.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigWellPathStimplanIntersector::RigWellPathStimplanIntersector(const RigWellPath* wellpathGeom, const RimFracture* rimFracture)
|
||||
{
|
||||
std::vector<cvf::Vec3d> wellPathPoints = wellpathGeom->wellPathPointsIncludingInterpolatedIntersectionPoint(rimFracture->fractureMD());
|
||||
cvf::Mat4d fractureXf = rimFracture->transformMatrix();
|
||||
double wellRadius = rimFracture->wellRadius();
|
||||
std::vector<std::vector<cvf::Vec3d> > stpCellPolygons;
|
||||
{
|
||||
RimFractureTemplate* fractureTemplate = rimFracture->fractureTemplate();
|
||||
|
||||
if(fractureTemplate)
|
||||
{
|
||||
const std::vector<RigFractureCell>& stpCells = fractureTemplate->fractureGrid()->fractureCells();
|
||||
for ( const auto& stpCell: stpCells ) stpCellPolygons.push_back(stpCell.getPolygon());
|
||||
}
|
||||
}
|
||||
double perforationLength = rimFracture->perforationLength();
|
||||
|
||||
calculate(fractureXf, wellPathPoints, wellRadius, perforationLength, stpCellPolygons, m_stimPlanCellIdxToIntersectionInfoMap);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::map<size_t, RigWellPathStimplanIntersector::RigWellPathStimplanIntersector::WellCellIntersection >& RigWellPathStimplanIntersector::intersections() const
|
||||
{
|
||||
return m_stimPlanCellIdxToIntersectionInfoMap;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Todo: Use only the perforated parts of the well path
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigWellPathStimplanIntersector::calculate(const cvf::Mat4d &fractureXf,
|
||||
const std::vector<cvf::Vec3d>& wellPathPointsOrg,
|
||||
double wellRadius,
|
||||
double perforationLength,
|
||||
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
||||
std::map<size_t, WellCellIntersection>& m_stimPlanCellIdxToIntersectionInfoMap)
|
||||
{
|
||||
cvf::Mat4d toFractureXf = fractureXf.getInverted();
|
||||
|
||||
std::vector<cvf::Vec3d> perforationLengthBoundingBoxPolygon;
|
||||
double cicleRadius = perforationLength / 2;
|
||||
int pointsInCirclePolygon = 20;
|
||||
for (int i = 0; i < pointsInCirclePolygon; i++)
|
||||
{
|
||||
double x = cicleRadius * cvf::Math::cos(i * (2 * cvf::PI_D / pointsInCirclePolygon));
|
||||
double y = cicleRadius * cvf::Math::sin(i * (2 * cvf::PI_D / pointsInCirclePolygon));
|
||||
perforationLengthBoundingBoxPolygon.push_back(cvf::Vec3d(x, y, 0));
|
||||
}
|
||||
|
||||
// Convert well path to fracture template system
|
||||
|
||||
std::vector<cvf::Vec3d> fractureRelativeWellPathPoints;
|
||||
for ( auto & wellPPoint : wellPathPointsOrg ) fractureRelativeWellPathPoints.push_back(wellPPoint.getTransformedPoint( toFractureXf));
|
||||
|
||||
// Clip well path to fracture domain
|
||||
|
||||
std::vector<std::vector<cvf::Vec3d> > wellPathPartsWithinFracture =
|
||||
RigCellGeometryTools::clipPolylineByPolygon(fractureRelativeWellPathPoints,
|
||||
perforationLengthBoundingBoxPolygon,
|
||||
RigCellGeometryTools::INTERPOLATE_LINE_Z);
|
||||
|
||||
// Remove the part of the well path that is more than well radius away from the fracture plane
|
||||
|
||||
std::vector< std::vector< cvf::Vec3d > > intersectingWellPathParts;
|
||||
|
||||
for ( const auto& part : wellPathPartsWithinFracture )
|
||||
{
|
||||
std::vector< cvf::Vec3d > currentIntersectingWpPart;
|
||||
for ( size_t vxIdx = 0; vxIdx < part.size() -1; ++vxIdx )
|
||||
{
|
||||
double thisAbsZ = fabs(part[vxIdx].z());
|
||||
double nextAbsZ = fabs(part[vxIdx + 1].z());
|
||||
double thisZ = part[vxIdx].z();
|
||||
double nextZ = part[vxIdx + 1].z();
|
||||
|
||||
if ( thisAbsZ >= wellRadius && nextAbsZ >= wellRadius )
|
||||
{
|
||||
if ( (thisZ >= 0 && nextZ >= 0)
|
||||
|| (thisZ <= 0 && nextZ <= 0 ) )
|
||||
{
|
||||
continue; // Outside
|
||||
}
|
||||
else // In and out
|
||||
{
|
||||
{
|
||||
double wellRadiusDistFromPlane = thisZ > 0 ? wellRadius: -wellRadius;
|
||||
|
||||
double fraction = (wellRadiusDistFromPlane - thisZ)/ (nextZ - thisZ);
|
||||
|
||||
cvf::Vec3d intersectPoint = part[vxIdx] + fraction * (part[vxIdx+1] - part[vxIdx]);
|
||||
currentIntersectingWpPart.push_back(intersectPoint);
|
||||
}
|
||||
{
|
||||
double wellRadiusDistFromPlane = nextZ > 0 ? wellRadius: -wellRadius;
|
||||
|
||||
double fraction = (wellRadiusDistFromPlane - thisZ)/ (nextZ - thisZ);
|
||||
|
||||
cvf::Vec3d intersectPoint = part[vxIdx] + fraction * (part[vxIdx+1] - part[vxIdx]);
|
||||
currentIntersectingWpPart.push_back(intersectPoint);
|
||||
|
||||
intersectingWellPathParts.push_back(currentIntersectingWpPart);
|
||||
currentIntersectingWpPart.clear();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( thisAbsZ < wellRadius && nextAbsZ < wellRadius ) // Inside
|
||||
{
|
||||
currentIntersectingWpPart.push_back(part[vxIdx]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( thisAbsZ < wellRadius && nextAbsZ >= wellRadius ) // Going out
|
||||
{
|
||||
currentIntersectingWpPart.push_back(part[vxIdx]);
|
||||
|
||||
double wellRadiusDistFromPlane = nextZ > 0 ? wellRadius: -wellRadius;
|
||||
|
||||
double fraction = (wellRadiusDistFromPlane - thisZ)/ (nextZ - thisZ);
|
||||
|
||||
cvf::Vec3d intersectPoint = part[vxIdx] + fraction * (part[vxIdx+1] - part[vxIdx]);
|
||||
currentIntersectingWpPart.push_back(intersectPoint);
|
||||
|
||||
intersectingWellPathParts.push_back(currentIntersectingWpPart);
|
||||
currentIntersectingWpPart.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( thisAbsZ >= wellRadius && nextAbsZ < wellRadius ) // Going in
|
||||
{
|
||||
double wellRadiusDistFromPlane = thisZ > 0 ? wellRadius: -wellRadius;
|
||||
|
||||
double fraction = (wellRadiusDistFromPlane - thisZ)/ (nextZ - thisZ);
|
||||
|
||||
cvf::Vec3d intersectPoint = part[vxIdx] + fraction * (part[vxIdx+1] - part[vxIdx]);
|
||||
currentIntersectingWpPart.push_back(intersectPoint);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add last point if it is within the radius
|
||||
|
||||
if (part.size() > 1 && fabs(part.back().z()) < wellRadius)
|
||||
{
|
||||
currentIntersectingWpPart.push_back(part.back());
|
||||
}
|
||||
|
||||
if ( !currentIntersectingWpPart.empty() )
|
||||
{
|
||||
intersectingWellPathParts.push_back(currentIntersectingWpPart);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the StimPlan cells touched by the intersecting well path parts
|
||||
|
||||
for ( size_t cIdx = 0; cIdx < stpCellPolygons.size(); ++ cIdx )
|
||||
{
|
||||
const std::vector<cvf::Vec3d>& cellPolygon = stpCellPolygons[cIdx];
|
||||
for ( const auto& wellpathPart :intersectingWellPathParts )
|
||||
{
|
||||
std::vector<std::vector<cvf::Vec3d> > wellPathPartsInPolygon =
|
||||
RigCellGeometryTools::clipPolylineByPolygon(wellpathPart,
|
||||
cellPolygon,
|
||||
RigCellGeometryTools::USE_HUGEVAL);
|
||||
for ( const auto& wellPathPartInCell: wellPathPartsInPolygon )
|
||||
{
|
||||
if ( !wellPathPartInCell.empty() )
|
||||
{
|
||||
int endpointCount = 0;
|
||||
if ( wellPathPartInCell.front().z() != HUGE_VAL ) ++endpointCount;
|
||||
if ( wellPathPartInCell.back().z() != HUGE_VAL ) ++endpointCount;
|
||||
|
||||
cvf::Vec3d intersectionLength = (wellPathPartInCell.back() - wellPathPartInCell.front());
|
||||
double xLengthInCell = fabs(intersectionLength.x());
|
||||
double yLengthInCell = fabs(intersectionLength.y());
|
||||
|
||||
m_stimPlanCellIdxToIntersectionInfoMap[cIdx].endpointCount += endpointCount;
|
||||
m_stimPlanCellIdxToIntersectionInfoMap[cIdx].hlength += xLengthInCell;
|
||||
m_stimPlanCellIdxToIntersectionInfoMap[cIdx].vlength += yLengthInCell;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfMatrix4.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class RigWellPath;
|
||||
class RimFracture;
|
||||
class RigWellPathStimplanIntersectorTester;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
class RigWellPathStimplanIntersector
|
||||
{
|
||||
public:
|
||||
struct WellCellIntersection
|
||||
{
|
||||
WellCellIntersection():hlength(0.0), vlength(0.0), endpointCount(0) {}
|
||||
double hlength;
|
||||
double vlength;
|
||||
int endpointCount;
|
||||
};
|
||||
|
||||
RigWellPathStimplanIntersector(const RigWellPath* wellpathGeom, const RimFracture* rimFracture);
|
||||
|
||||
const std::map<size_t, WellCellIntersection >& intersections() const;
|
||||
|
||||
private:
|
||||
friend class RigWellPathStimplanIntersectorTester;
|
||||
static void calculate(const cvf::Mat4d& fractureXf,
|
||||
const std::vector<cvf::Vec3d>& wellPathPoints,
|
||||
double wellRadius,
|
||||
double perforationLength,
|
||||
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
||||
std::map<size_t, WellCellIntersection>& stimPlanCellIdxToIntersectionInfoMap);
|
||||
|
||||
std::map<size_t, WellCellIntersection > m_stimPlanCellIdxToIntersectionInfoMap;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
class RigWellPathStimplanIntersectorTester
|
||||
{
|
||||
public:
|
||||
static void testCalculate(const cvf::Mat4d& fractureXf,
|
||||
const std::vector<cvf::Vec3d>& wellPathPoints,
|
||||
double wellRadius,
|
||||
double perforationLength,
|
||||
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
||||
std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection>& stimPlanCellIdxToIntersectionInfoMap)
|
||||
{
|
||||
RigWellPathStimplanIntersector::calculate(fractureXf, wellPathPoints, wellRadius, perforationLength, stpCellPolygons, stimPlanCellIdxToIntersectionInfoMap);
|
||||
}
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user