diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.cpp index d3816570ed..ff05672e8a 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.cpp @@ -774,3 +774,11 @@ void RimThermalFractureTemplate::defineUiOrdering( QString uiConfigName, caf::Pd uiOrdering.add( &m_filterCakePressureDropType ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimThermalFractureTemplate::FilterCakePressureDrop RimThermalFractureTemplate::filterCakePressureDropType() const +{ + return m_filterCakePressureDropType.value(); +} diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.h b/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.h index 4b9cd42db2..a70ace7c55 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.h @@ -111,6 +111,8 @@ public: const RigThermalFractureDefinition* fractureDefinition() const; + FilterCakePressureDrop filterCakePressureDropType() const; + protected: void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/CMakeLists_files.cmake b/ApplicationLibCode/ReservoirDataModel/Completions/CMakeLists_files.cmake index b4ba15d3d4..c11644d6c9 100644 --- a/ApplicationLibCode/ReservoirDataModel/Completions/CMakeLists_files.cmake +++ b/ApplicationLibCode/ReservoirDataModel/Completions/CMakeLists_files.cmake @@ -2,6 +2,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RigCompletionData.h ${CMAKE_CURRENT_LIST_DIR}/RigCompletionDataGridCell.h ${CMAKE_CURRENT_LIST_DIR}/RigEclipseToStimPlanCellTransmissibilityCalculator.h + ${CMAKE_CURRENT_LIST_DIR}/RigEclipseToThermalCellTransmissibilityCalculator.h ${CMAKE_CURRENT_LIST_DIR}/RigTransmissibilityCondenser.h ${CMAKE_CURRENT_LIST_DIR}/RigFractureTransmissibilityEquations.h ${CMAKE_CURRENT_LIST_DIR}/RigWellPathStimplanIntersector.h @@ -14,6 +15,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RigCompletionData.cpp ${CMAKE_CURRENT_LIST_DIR}/RigCompletionDataGridCell.cpp ${CMAKE_CURRENT_LIST_DIR}/RigEclipseToStimPlanCellTransmissibilityCalculator.cpp + ${CMAKE_CURRENT_LIST_DIR}/RigEclipseToThermalCellTransmissibilityCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigTransmissibilityCondenser.cpp ${CMAKE_CURRENT_LIST_DIR}/RigFractureTransmissibilityEquations.cpp ${CMAKE_CURRENT_LIST_DIR}/RigWellPathStimplanIntersector.cpp diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.cpp index 5ba3648097..d1a24bab08 100644 --- a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.cpp @@ -19,11 +19,14 @@ #include "RigEclipseToStimPlanCalculator.h" #include "RiaLogging.h" +#include "RiaWeightedMeanCalculator.h" #include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" #include "RigCellGeometryTools.h" #include "RigEclipseCaseData.h" +#include "RigEclipseToStimPlanCellTransmissibilityCalculator.h" +#include "RigEclipseToThermalCellTransmissibilityCalculator.h" #include "RigFractureCell.h" #include "RigFractureGrid.h" #include "RigFractureTransmissibilityEquations.h" @@ -32,12 +35,12 @@ #include "RigResultAccessorFactory.h" #include "RigTransmissibilityCondenser.h" -#include "RiaWeightedMeanCalculator.h" #include "RimEclipseCase.h" #include "RimEllipseFractureTemplate.h" #include "RimFracture.h" #include "RimFractureContainmentTools.h" #include "RimMeshFractureTemplate.h" +#include "RimThermalFractureTemplate.h" //-------------------------------------------------------------------------------------------------- /// @@ -71,20 +74,68 @@ void RigEclipseToStimPlanCalculator::computeValues() const RigFractureCell& fractureCell = m_fractureGrid.fractureCells()[i]; if ( !fractureCell.hasNonZeroConductivity() ) continue; - RigEclipseToStimPlanCellTransmissibilityCalculator eclToFractureTransCalc( m_case, - m_fractureTransform, - m_fractureSkinFactor, - m_cDarcy, - fractureCell, - reservoirCellIndicesOpenForFlow, - m_fracture ); + std::unique_ptr eclToFractureTransCalc; + if ( dynamic_cast( m_fracture->fractureTemplate() ) != nullptr ) + { + RimThermalFractureTemplate* thermalFractureTemplate = + dynamic_cast( m_fracture->fractureTemplate() ); + + size_t timeStep = thermalFractureTemplate->activeTimeStepIndex(); + int cellI = fractureCell.getI(); + int cellJ = fractureCell.getJ(); + + double injectivityDecline = thermalFractureTemplate->resultValueAtIJ( &m_fractureGrid, + "InjectivityDecline", + "factor", + timeStep, + cellI, + cellJ ); + double viscosity = + thermalFractureTemplate->resultValueAtIJ( &m_fractureGrid, "Viscosity", "mPa.s", timeStep, cellI, cellJ ); + + double filterCakeMobility = thermalFractureTemplate->resultValueAtIJ( &m_fractureGrid, + "FilterCakeMobility", + "m/day/bar", + timeStep, + cellI, + cellJ ); + + // Assumed value + double relativePermeability = 1.0; + + auto filterPressureDropType = thermalFractureTemplate->filterCakePressureDropType(); + eclToFractureTransCalc = + std::make_unique( m_case, + m_fractureTransform, + m_fractureSkinFactor, + m_cDarcy, + fractureCell, + m_fracture, + filterPressureDropType, + injectivityDecline, + filterCakeMobility, + viscosity, + relativePermeability ); + } + else + { + eclToFractureTransCalc = + std::make_unique( m_case, + m_fractureTransform, + m_fractureSkinFactor, + m_cDarcy, + fractureCell, + m_fracture ); + } + + eclToFractureTransCalc->computeValues( reservoirCellIndicesOpenForFlow ); const std::vector& fractureCellContributingEclipseCells = - eclToFractureTransCalc.globalIndiciesToContributingEclipseCells(); + eclToFractureTransCalc->globalIndiciesToContributingEclipseCells(); if ( !fractureCellContributingEclipseCells.empty() ) { - m_singleFractureCellCalculators.emplace( i, eclToFractureTransCalc ); + m_singleFractureCellCalculators.emplace( i, std::move( eclToFractureTransCalc ) ); } } } @@ -100,10 +151,10 @@ void RigEclipseToStimPlanCalculator::appendDataToTransmissibilityCondenser( bool for ( const auto& eclToFractureTransCalc : m_singleFractureCellCalculators ) { const std::vector& fractureCellContributingEclipseCells = - eclToFractureTransCalc.second.globalIndiciesToContributingEclipseCells(); + eclToFractureTransCalc.second->globalIndiciesToContributingEclipseCells(); const std::vector& fractureCellContributingEclipseCellTransmissibilities = - eclToFractureTransCalc.second.contributingEclipseCellTransmissibilities(); + eclToFractureTransCalc.second->contributingEclipseCellTransmissibilities(); size_t stimPlanCellIndex = eclToFractureTransCalc.first; @@ -138,7 +189,7 @@ double RigEclipseToStimPlanCalculator::totalEclipseAreaOpenForFlow() const for ( const auto& singleCellCalc : m_singleFractureCellCalculators ) { - double cellArea = singleCellCalc.second.areaOpenForFlow(); + double cellArea = singleCellCalc.second->areaOpenForFlow(); area += cellArea; } @@ -153,20 +204,16 @@ double RigEclipseToStimPlanCalculator::areaWeightedMatrixPermeability() const { RiaWeightedMeanCalculator calc; + for ( const auto& singleCellCalc : m_singleFractureCellCalculators ) { - for ( const auto& singleCellCalc : m_singleFractureCellCalculators ) + const std::vector& areas = singleCellCalc.second->contributingEclipseCellIntersectionAreas(); + const std::vector& permeabilities = singleCellCalc.second->contributingEclipseCellPermeabilities(); + + if ( areas.size() == permeabilities.size() ) { - const RigEclipseToStimPlanCellTransmissibilityCalculator& calulator = singleCellCalc.second; - - const std::vector& areas = calulator.contributingEclipseCellIntersectionAreas(); - const std::vector& permeabilities = calulator.contributingEclipseCellPermeabilities(); - - if ( areas.size() == permeabilities.size() ) + for ( size_t i = 0; i < areas.size(); i++ ) { - for ( size_t i = 0; i < areas.size(); i++ ) - { - calc.addValueAndWeight( permeabilities[i], areas[i] ); - } + calc.addValueAndWeight( permeabilities[i], areas[i] ); } } } @@ -197,7 +244,7 @@ double RigEclipseToStimPlanCalculator::areaWeightedWidth() const for ( const auto& singleCellCalc : m_singleFractureCellCalculators ) { - double cellArea = singleCellCalc.second.areaOpenForFlow(); + double cellArea = singleCellCalc.second->areaOpenForFlow(); size_t globalStimPlanCellIndex = singleCellCalc.first; double widthValue = widthValues[globalStimPlanCellIndex]; @@ -228,9 +275,9 @@ double RigEclipseToStimPlanCalculator::areaWeightedConductivity() const for ( const auto& singleCellCalc : m_singleFractureCellCalculators ) { - double cellArea = singleCellCalc.second.areaOpenForFlow(); + double cellArea = singleCellCalc.second->areaOpenForFlow(); - double conductivity = singleCellCalc.second.fractureCell().getConductivityValue(); + double conductivity = singleCellCalc.second->fractureCell().getConductivityValue(); if ( !std::isinf( conductivity ) && !std::isnan( conductivity ) ) { calc.addValueAndWeight( conductivity, cellArea ); @@ -260,7 +307,7 @@ double RigEclipseToStimPlanCalculator::longestYSectionOpenForFlow() const auto calculatorForCell = m_singleFractureCellCalculators.find( globalStimPlanCellIndex ); if ( calculatorForCell != m_singleFractureCellCalculators.end() ) { - currentAggregatedDistanceY += calculatorForCell->second.fractureCell().cellSizeZ(); + currentAggregatedDistanceY += calculatorForCell->second->fractureCell().cellSizeZ(); } else { diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.h b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.h index f8d5d7664f..f45d6cb083 100644 --- a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.h +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.h @@ -25,6 +25,7 @@ #include "cvfMatrix4.h" #include +#include class QString; @@ -69,5 +70,5 @@ private: cvf::Mat4d m_fractureTransform; const RigFractureGrid& m_fractureGrid; - std::map m_singleFractureCellCalculators; + std::map> m_singleFractureCellCalculators; }; diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCellTransmissibilityCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCellTransmissibilityCalculator.cpp index d944a05f75..1237baa172 100644 --- a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCellTransmissibilityCalculator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCellTransmissibilityCalculator.cpp @@ -39,19 +39,22 @@ /// //-------------------------------------------------------------------------------------------------- RigEclipseToStimPlanCellTransmissibilityCalculator::RigEclipseToStimPlanCellTransmissibilityCalculator( - const RimEclipseCase* caseToApply, - cvf::Mat4d fractureTransform, - double skinFactor, - double cDarcy, - const RigFractureCell& stimPlanCell, - const std::set& reservoirCellIndicesOpenForFlow, - const RimFracture* fracture ) + const RimEclipseCase* caseToApply, + cvf::Mat4d fractureTransform, + double skinFactor, + double cDarcy, + const RigFractureCell& stimPlanCell, + const RimFracture* fracture ) : m_case( caseToApply ) , m_fractureTransform( fractureTransform ) , m_fractureSkinFactor( skinFactor ) , m_cDarcy( cDarcy ) , m_stimPlanCell( stimPlanCell ) , m_fracture( fracture ) +{ +} + +void RigEclipseToStimPlanCellTransmissibilityCalculator::computeValues( const std::set& reservoirCellIndicesOpenForFlow ) { calculateStimPlanCellsMatrixTransmissibility( reservoirCellIndicesOpenForFlow ); } @@ -328,8 +331,8 @@ void RigEclipseToStimPlanCellTransmissibilityCalculator::calculateStimPlanCellsM fractureAreaWeightedlength, m_cDarcy ); - transmissibility = sqrt( transmissibility_X * transmissibility_X + transmissibility_Y * transmissibility_Y + - transmissibility_Z * transmissibility_Z ); + cvf::Vec3d transmissibilityVector( transmissibility_X, transmissibility_Y, transmissibility_Z ); + transmissibility = calculateTransmissibility( transmissibilityVector, fractureArea ); matrixPermeability = RigFractureTransmissibilityEquations::matrixPermeability( permX, permY, NTG ); } @@ -390,3 +393,12 @@ cvf::ref 0, RigEclipseResultAddress( uiResultName ) ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigEclipseToStimPlanCellTransmissibilityCalculator::calculateTransmissibility( const cvf::Vec3d& transmissibilityVector, + double fractureArea ) +{ + return transmissibilityVector.length(); +} diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCellTransmissibilityCalculator.h b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCellTransmissibilityCalculator.h index 2a612149cd..0d5e792945 100644 --- a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCellTransmissibilityCalculator.h +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCellTransmissibilityCalculator.h @@ -42,13 +42,13 @@ class RimFracture; class RigEclipseToStimPlanCellTransmissibilityCalculator { public: - explicit RigEclipseToStimPlanCellTransmissibilityCalculator( const RimEclipseCase* caseToApply, - cvf::Mat4d fractureTransform, - double skinFactor, - double cDarcy, - const RigFractureCell& stimPlanCell, - const std::set& reservoirCellIndicesOpenForFlow, - const RimFracture* fracture ); + explicit RigEclipseToStimPlanCellTransmissibilityCalculator( const RimEclipseCase* caseToApply, + cvf::Mat4d fractureTransform, + double skinFactor, + double cDarcy, + const RigFractureCell& stimPlanCell, + const RimFracture* fracture ); + void computeValues( const std::set& reservoirCellIndicesOpenForFlow ); // These three vectors have the same size const std::vector& globalIndiciesToContributingEclipseCells() const; @@ -65,12 +65,14 @@ public: private: void calculateStimPlanCellsMatrixTransmissibility( const std::set& reservoirCellIndicesOpenForFlow ); + virtual double calculateTransmissibility( const cvf::Vec3d& transmissibilityVector, double fractureArea ); + std::vector getPotentiallyFracturedCellsForPolygon( const std::vector& polygon ) const; static cvf::ref createResultAccessor( const RimEclipseCase* eclipseCase, const QString& uiResultName ); -private: +protected: const RimEclipseCase* m_case; const RimFracture* m_fracture; diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.cpp new file mode 100644 index 0000000000..634c1e40c0 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.cpp @@ -0,0 +1,70 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022 Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigEclipseToThermalCellTransmissibilityCalculator.h" + +#include "RimEclipseCase.h" +#include "RimFracture.h" +#include "RimThermalFractureTemplate.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigEclipseToThermalCellTransmissibilityCalculator::RigEclipseToThermalCellTransmissibilityCalculator( + const RimEclipseCase* caseToApply, + cvf::Mat4d fractureTransform, + double skinFactor, + double cDarcy, + const RigFractureCell& stimPlanCell, + const RimFracture* fracture, + RimThermalFractureTemplate::FilterCakePressureDrop filterCakePressureDrop, + double injectivityDecline, + double filterCakeMobility, + double viscosity, + double relativePermeability ) + : RigEclipseToStimPlanCellTransmissibilityCalculator( caseToApply, fractureTransform, skinFactor, cDarcy, stimPlanCell, fracture ) + , m_filterCakePressureDrop( filterCakePressureDrop ) + , m_injectivityDecline( injectivityDecline ) + , m_filterCakeMobility( filterCakeMobility ) + , m_viscosity( viscosity ) + , m_relativePermeability( relativePermeability ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigEclipseToThermalCellTransmissibilityCalculator::calculateTransmissibility( const cvf::Vec3d& transmissibilityVector, + double fractureArea ) +{ + double fractureMatrixTransimissibility = transmissibilityVector.length(); + + if ( m_filterCakePressureDrop == RimThermalFractureTemplate::FilterCakePressureDrop::RELATIVE ) + { + return m_injectivityDecline * fractureMatrixTransimissibility; + } + else + { + CAF_ASSERT( m_filterCakePressureDrop == RimThermalFractureTemplate::FilterCakePressureDrop::ABSOLUTE ); + double filterCakeTransmissibility = ( m_viscosity / m_relativePermeability ) * fractureArea * m_filterCakeMobility; + + // Harmonic mean + return ( fractureMatrixTransimissibility * filterCakeTransmissibility ) / + ( fractureMatrixTransimissibility + filterCakeTransmissibility ); + } +} diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.h b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.h new file mode 100644 index 0000000000..27ff7691ba --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.h @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022 Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigEclipseToStimPlanCellTransmissibilityCalculator.h" + +#include "cvfMatrix4.h" +#include "cvfObject.h" + +#include "RimThermalFractureTemplate.h" + +#include + +class QString; + +class RimEclipseCase; +class RigFractureCell; +class RigResultAccessor; +class RimFracture; + +//================================================================================================== +/// +/// Calculator used to compute the intersection areas between one Thermal RigFractureCell and Eclipse cells +/// Both active and inactive Eclipse cells are included. The transmissibility value for inactive cells are set to zero. +/// Eclipse reservoir cells open for flow is defined by reservoirCellIndicesOpenForFlow +/// +//================================================================================================== +class RigEclipseToThermalCellTransmissibilityCalculator : public RigEclipseToStimPlanCellTransmissibilityCalculator +{ +public: + explicit RigEclipseToThermalCellTransmissibilityCalculator( + const RimEclipseCase* caseToApply, + cvf::Mat4d fractureTransform, + double skinFactor, + double cDarcy, + const RigFractureCell& stimPlanCell, + const RimFracture* fracture, + RimThermalFractureTemplate::FilterCakePressureDrop filterCakePressureDrop, + double injectvityDecline, + double filterCakeMobility, + double viscosity, + double relativePermeability ); + +protected: + double calculateTransmissibility( const cvf::Vec3d& transmissibilityVector, double fractureArea ) override; + + RimThermalFractureTemplate::FilterCakePressureDrop m_filterCakePressureDrop; + double m_injectivityDecline; + double m_filterCakeMobility; + double m_viscosity; + double m_relativePermeability; +};