2017-03-21 13:43:44 +01:00
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigFractureTransCalc.h"
# include "RimFractureTemplate.h"
# include "RigEclipseCaseData.h"
# include "RimEclipseCase.h"
# include "RiaLogging.h"
# include "QString"
# include "RimReservoirCellResultsStorage.h"
# include "RigResultAccessorFactory.h"
# include "RimFracture.h"
# include "RigFracture.h"
# include "cvfGeometryTools.h"
# include "RigCellGeometryTools.h"
# include "RigActiveCellInfo.h"
2017-04-06 11:47:50 +02:00
# include "RigFracture.h"
2017-03-21 13:43:44 +01:00
# include "RimStimPlanFractureTemplate.h"
# include <QString>
# include "RimEllipseFractureTemplate.h"
# include "cafAppEnum.h"
2017-03-21 15:29:22 +01:00
# include "RigCell.h"
# include "RigMainGrid.h"
2017-03-27 10:06:14 +02:00
# include "cvfMath.h"
# include "RimDefines.h"
2017-03-29 10:18:14 +02:00
# include "RigStimPlanCell.h"
2017-04-19 14:12:47 +02:00
# include <cmath> //Used for log
2017-03-21 13:43:44 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-03-21 15:29:22 +01:00
RigFractureTransCalc : : RigFractureTransCalc ( RimEclipseCase * caseToApply , RimFracture * fracture )
2017-03-21 13:43:44 +01:00
{
2017-03-21 15:29:22 +01:00
m_case = caseToApply ;
m_fracture = fracture ;
2017-03-21 13:43:44 +01:00
2017-03-21 15:29:22 +01:00
//Set correct unit system:
RigEclipseCaseData : : UnitsType caseUnit = m_case - > eclipseCaseData ( ) - > unitsType ( ) ;
2017-03-21 13:43:44 +01:00
if ( caseUnit = = RigEclipseCaseData : : UNITS_METRIC )
{
RiaLogging : : debug ( QString ( " Calculating transmissibilities in metric units " ) ) ;
2017-03-21 15:29:22 +01:00
m_unitForCalculation = RimDefines : : UNITS_METRIC ;
2017-03-21 13:43:44 +01:00
}
else if ( caseUnit = = RigEclipseCaseData : : UNITS_FIELD )
{
RiaLogging : : debug ( QString ( " Calculating transmissibilities in field units " ) ) ;
2017-03-21 15:29:22 +01:00
m_unitForCalculation = RimDefines : : UNITS_FIELD ;
2017-03-21 13:43:44 +01:00
}
else
{
2017-03-21 15:29:22 +01:00
//TODO: How to handle lab units for eclipse case?
2017-03-21 13:43:44 +01:00
RiaLogging : : error ( QString ( " Unit system for case not supported for fracture export. " ) ) ;
2017-03-21 15:29:22 +01:00
RiaLogging : : error ( QString ( " Export will be in metric units, but results might be wrong. " ) ) ;
m_unitForCalculation = RimDefines : : UNITS_METRIC ;
2017-03-21 13:43:44 +01:00
}
2017-03-21 15:29:22 +01:00
}
//--------------------------------------------------------------------------------------------------
2017-04-03 14:33:14 +02:00
/// TODO: Document equation
2017-03-21 15:29:22 +01:00
//--------------------------------------------------------------------------------------------------
2017-04-25 16:08:44 +02:00
void RigFractureTransCalc : : computeTransmissibilityFromPolygonWithInfiniteConductivityInFracture ( )
2017-03-21 15:29:22 +01:00
{
if ( m_fracture - > attachedFractureDefinition ( ) - > fractureConductivity = = RimFractureTemplate : : FINITE_CONDUCTIVITY )
2017-03-21 13:43:44 +01:00
{
RiaLogging : : warning ( QString ( " Transimssibility for finite conductity in fracture not yet implemented. " ) ) ;
RiaLogging : : warning ( QString ( " Performing calculation for infinite conductivity instead. " ) ) ;
}
2017-03-21 15:29:22 +01:00
RigEclipseCaseData * eclipseCaseData = m_case - > eclipseCaseData ( ) ;
2017-03-21 13:43:44 +01:00
RifReaderInterface : : PorosityModelResultType porosityModel = RifReaderInterface : : MATRIX_RESULTS ;
2017-03-21 15:29:22 +01:00
RimReservoirCellResultsStorage * gridCellResults = m_case - > results ( porosityModel ) ;
2017-03-21 13:43:44 +01:00
size_t scalarSetIndex ;
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " DX " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectDx = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " DX " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " DY " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectDy = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " DY " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " DZ " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectDz = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " DZ " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " PERMX " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectPermX = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " PERMX " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " PERMY " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectPermY = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " PERMY " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " PERMZ " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectPermZ = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " PERMZ " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " NTG " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectNTG = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " NTG " ) ; //assuming 0 time step and main grid (so grid index =0)
RigActiveCellInfo * activeCellInfo = eclipseCaseData - > activeCellInfo ( porosityModel ) ;
std : : vector < RigFractureData > fracDataVec ;
2017-03-21 15:29:22 +01:00
std : : vector < size_t > fracCells = m_fracture - > getPotentiallyFracturedCells ( ) ;
2017-03-21 13:43:44 +01:00
for ( size_t fracCell : fracCells )
{
bool cellIsActive = activeCellInfo - > isActive ( fracCell ) ;
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 = dataAccessObjectNTG - > cellScalarGlobIdx ( fracCell ) ;
cvf : : Vec3d localX ;
cvf : : Vec3d localY ;
cvf : : Vec3d localZ ;
std : : vector < std : : vector < cvf : : Vec3d > > planeCellPolygons ;
2017-03-21 15:29:22 +01:00
bool isPlanIntersected = planeCellIntersectionPolygons ( fracCell , planeCellPolygons , localX , localY , localZ ) ;
2017-03-21 13:43:44 +01:00
if ( ! isPlanIntersected | | planeCellPolygons . size ( ) = = 0 ) continue ;
//Transform planCell polygon(s) and averageZdirection to x/y coordinate system (where fracturePolygon already is located)
2017-03-21 15:29:22 +01:00
cvf : : Mat4f invertedTransMatrix = m_fracture - > transformMatrix ( ) . getInverted ( ) ;
2017-03-21 13:43:44 +01:00
for ( std : : vector < cvf : : Vec3d > & planeCellPolygon : planeCellPolygons )
{
for ( cvf : : Vec3d & v : planeCellPolygon )
{
v . transformPoint ( static_cast < cvf : : Mat4d > ( invertedTransMatrix ) ) ;
}
}
cvf : : Vec3d localZinFracPlane ;
localZinFracPlane = localZ ;
localZinFracPlane . transformVector ( static_cast < cvf : : Mat4d > ( invertedTransMatrix ) ) ;
cvf : : Vec3d directionOfLength = cvf : : Vec3d : : ZERO ;
directionOfLength . cross ( localZinFracPlane , cvf : : Vec3d ( 0 , 0 , 1 ) ) ;
directionOfLength . normalize ( ) ;
RigFractureData fracData ;
fracData . reservoirCellIndex = fracCell ;
2017-03-21 15:29:22 +01:00
std : : vector < cvf : : Vec3f > fracPolygon = m_fracture - > attachedFractureDefinition ( ) - > fracturePolygon ( m_unitForCalculation ) ;
2017-03-21 13:43:44 +01:00
std : : vector < cvf : : Vec3d > fracPolygonDouble ;
for ( auto v : fracPolygon ) fracPolygonDouble . push_back ( static_cast < cvf : : Vec3d > ( v ) ) ;
std : : vector < std : : vector < cvf : : Vec3d > > polygonsDescribingFractureInCell ;
cvf : : Vec3d areaVector ;
for ( std : : vector < cvf : : Vec3d > planeCellPolygon : planeCellPolygons )
{
std : : vector < std : : vector < cvf : : Vec3d > > clippedPolygons = RigCellGeometryTools : : clipPolygons ( planeCellPolygon , fracPolygonDouble ) ;
for ( std : : vector < cvf : : Vec3d > clippedPolygon : clippedPolygons )
{
polygonsDescribingFractureInCell . push_back ( clippedPolygon ) ;
}
}
double area ;
std : : vector < double > areaOfFractureParts ;
double length ;
std : : vector < double > lengthXareaOfFractureParts ;
2017-04-05 14:40:54 +02:00
double Ax = 0.0 ;
double Ay = 0.0 ;
double Az = 0.0 ;
2017-03-21 13:43:44 +01:00
for ( std : : vector < cvf : : Vec3d > fracturePartPolygon : polygonsDescribingFractureInCell )
{
areaVector = cvf : : GeometryTools : : polygonAreaNormal3D ( fracturePartPolygon ) ;
area = areaVector . length ( ) ;
areaOfFractureParts . push_back ( area ) ;
length = RigCellGeometryTools : : polygonAreaWeightedLength ( directionOfLength , fracturePartPolygon ) ;
lengthXareaOfFractureParts . push_back ( length * area ) ;
cvf : : Plane fracturePlane ;
2017-03-21 15:29:22 +01:00
cvf : : Mat4f m = m_fracture - > transformMatrix ( ) ;
2017-03-21 13:43:44 +01:00
bool isCellIntersected = false ;
fracturePlane . setFromPointAndNormal ( static_cast < cvf : : Vec3d > ( m . translation ( ) ) ,
static_cast < cvf : : Vec3d > ( m . col ( 2 ) ) ) ;
Ax + = abs ( area * ( fracturePlane . normal ( ) . dot ( localY ) ) ) ;
Ay + = abs ( area * ( fracturePlane . normal ( ) . dot ( localX ) ) ) ;
Az + = abs ( area * ( fracturePlane . normal ( ) . dot ( localZ ) ) ) ;
//TODO: resulting values have only been checked for vertical fracture...
}
2017-04-05 14:40:54 +02:00
double fractureArea = 0.0 ;
2017-03-21 13:43:44 +01:00
for ( double area : areaOfFractureParts ) fractureArea + = area ;
double totalAreaXLength = 0.0 ;
for ( double lengtXarea : lengthXareaOfFractureParts ) totalAreaXLength + = lengtXarea ;
2017-04-05 14:40:54 +02:00
double fractureAreaWeightedlength = totalAreaXLength / fractureArea ;
double skinfactor = m_fracture - > attachedFractureDefinition ( ) - > skinFactor ;
2017-03-21 13:43:44 +01:00
2017-04-05 14:40:54 +02:00
double transmissibility_X = calculateMatrixTransmissibility ( permY , NTG , Ay , dx , skinfactor , fractureAreaWeightedlength ) ;
double transmissibility_Y = calculateMatrixTransmissibility ( permX , NTG , Ax , dy , skinfactor , fractureAreaWeightedlength ) ;
double transmissibility_Z = calculateMatrixTransmissibility ( permZ , 1.0 , Az , dz , skinfactor , fractureAreaWeightedlength ) ;
2017-03-21 13:43:44 +01:00
2017-04-05 14:40:54 +02:00
double transmissibility = sqrt ( transmissibility_X * transmissibility_X
2017-03-21 13:43:44 +01:00
+ transmissibility_Y * transmissibility_Y
+ transmissibility_Z * transmissibility_Z ) ;
fracData . transmissibility = transmissibility ;
fracData . transmissibilities = cvf : : Vec3d ( transmissibility_X , transmissibility_Y , transmissibility_Z ) ;
fracData . totalArea = fractureArea ;
fracData . projectedAreas = cvf : : Vec3d ( Ax , Ay , Az ) ;
fracData . fractureLenght = fractureAreaWeightedlength ;
fracData . cellSizes = cvf : : Vec3d ( dx , dy , dz ) ;
fracData . permeabilities = cvf : : Vec3d ( permX , permY , permZ ) ;
fracData . NTG = NTG ;
fracData . skinFactor = skinfactor ;
fracData . cellIsActive = cellIsActive ;
//Since we loop over all potentially fractured cells, we only keep FractureData for cells where fracture have an non-zero area.
if ( fractureArea > 1e-5 )
{
fracDataVec . push_back ( fracData ) ;
}
}
2017-03-21 15:29:22 +01:00
m_fracture - > setFractureData ( fracDataVec ) ;
}
2017-04-05 14:40:54 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-04-06 11:47:50 +02:00
void RigFractureTransCalc : : calculateStimPlanCellsMatrixTransmissibility ( RigStimPlanCell * stimPlanCell , RigFractureStimPlanCellData * fracStimPlanCellData )
2017-04-05 14:40:54 +02:00
{
2017-04-06 11:47:50 +02:00
//Not calculating flow into fracture if stimPlan cell cond value is 0 (assumed to be outside the fracture):
if ( stimPlanCell - > getConductivtyValue ( ) < 1e-7 ) return ;
2017-04-05 14:40:54 +02:00
RigEclipseCaseData * eclipseCaseData = m_case - > eclipseCaseData ( ) ;
RifReaderInterface : : PorosityModelResultType porosityModel = RifReaderInterface : : MATRIX_RESULTS ;
RimReservoirCellResultsStorage * gridCellResults = m_case - > results ( porosityModel ) ;
size_t scalarSetIndex ;
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " DX " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectDx = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " DX " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " DY " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectDy = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " DY " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " DZ " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectDz = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " DZ " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " PERMX " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectPermX = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " PERMX " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " PERMY " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectPermY = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " PERMY " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " PERMZ " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectPermZ = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " PERMZ " ) ; //assuming 0 time step and main grid (so grid index =0)
scalarSetIndex = gridCellResults - > findOrLoadScalarResult ( RimDefines : : STATIC_NATIVE , " NTG " ) ;
cvf : : ref < RigResultAccessor > dataAccessObjectNTG = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , porosityModel , 0 , " NTG " ) ; //assuming 0 time step and main grid (so grid index =0)
RigActiveCellInfo * activeCellInfo = eclipseCaseData - > activeCellInfo ( porosityModel ) ;
std : : vector < cvf : : Vec3d > stimPlanPolygon = stimPlanCell - > getPolygon ( ) ;
std : : vector < size_t > fracCells = m_fracture - > getPotentiallyFracturedCells ( ) ;
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 = dataAccessObjectNTG - > cellScalarGlobIdx ( fracCell ) ;
cvf : : Vec3d localX ;
cvf : : Vec3d localY ;
cvf : : Vec3d localZ ;
std : : vector < std : : vector < cvf : : Vec3d > > planeCellPolygons ;
bool isPlanIntersected = planeCellIntersectionPolygons ( fracCell , planeCellPolygons , localX , localY , localZ ) ;
if ( ! isPlanIntersected | | planeCellPolygons . size ( ) = = 0 ) continue ;
//Transform planCell polygon(s) and averageZdirection to x/y coordinate system (where fracturePolygon already is located)
cvf : : Mat4f invertedTransMatrix = m_fracture - > transformMatrix ( ) . getInverted ( ) ;
for ( std : : vector < cvf : : Vec3d > & planeCellPolygon : planeCellPolygons )
{
for ( cvf : : Vec3d & v : planeCellPolygon )
{
v . transformPoint ( static_cast < cvf : : Mat4d > ( invertedTransMatrix ) ) ;
}
}
cvf : : Vec3d localZinFracPlane ;
localZinFracPlane = localZ ;
localZinFracPlane . transformVector ( static_cast < cvf : : Mat4d > ( invertedTransMatrix ) ) ;
cvf : : Vec3d directionOfLength = cvf : : Vec3d : : ZERO ;
directionOfLength . cross ( localZinFracPlane , cvf : : Vec3d ( 0 , 0 , 1 ) ) ;
directionOfLength . normalize ( ) ;
std : : vector < std : : vector < cvf : : Vec3d > > polygonsForStimPlanCellInEclipseCell ;
cvf : : Vec3d areaVector ;
for ( std : : vector < cvf : : Vec3d > planeCellPolygon : planeCellPolygons )
{
std : : vector < std : : vector < cvf : : Vec3d > > clippedPolygons = RigCellGeometryTools : : clipPolygons ( 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 ) ;
//TODO: the l in the sl/pi term in the denominator of the Tmj expression should be the length of the full Eclipse cell
//In the current form the implementation gives correct result only if s=0 (fracture templte skin factor).
length = RigCellGeometryTools : : polygonAreaWeightedLength ( directionOfLength , fracturePartPolygon ) ;
lengthXareaOfFractureParts . push_back ( length * area ) ;
cvf : : Plane fracturePlane ;
cvf : : Mat4f m = m_fracture - > transformMatrix ( ) ;
bool isCellIntersected = false ;
fracturePlane . setFromPointAndNormal ( static_cast < cvf : : Vec3d > ( m . translation ( ) ) ,
static_cast < cvf : : Vec3d > ( m . col ( 2 ) ) ) ;
Ax + = abs ( area * ( fracturePlane . normal ( ) . dot ( localY ) ) ) ;
Ay + = abs ( area * ( fracturePlane . normal ( ) . dot ( localX ) ) ) ;
Az + = abs ( 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 skinfactor = m_fracture - > attachedFractureDefinition ( ) - > skinFactor ;
double transmissibility_X = calculateMatrixTransmissibility ( permY , NTG , Ay , dx , skinfactor , fractureAreaWeightedlength ) ;
double transmissibility_Y = calculateMatrixTransmissibility ( permX , NTG , Ax , dy , skinfactor , fractureAreaWeightedlength ) ;
double transmissibility_Z = calculateMatrixTransmissibility ( permZ , 1.0 , Az , dz , skinfactor , fractureAreaWeightedlength ) ;
double transmissibility = sqrt ( transmissibility_X * transmissibility_X
+ transmissibility_Y * transmissibility_Y
+ transmissibility_Z * transmissibility_Z ) ;
2017-04-06 11:47:50 +02:00
fracStimPlanCellData - > addContributingEclipseCell ( fracCell , transmissibility ) ;
}
2017-04-05 14:40:54 +02:00
}
2017-03-21 15:29:22 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigFractureTransCalc : : planeCellIntersectionPolygons ( size_t cellindex , std : : vector < std : : vector < cvf : : Vec3d > > & polygons ,
cvf : : Vec3d & localX , cvf : : Vec3d & localY , cvf : : Vec3d & localZ )
{
cvf : : Plane fracturePlane ;
cvf : : Mat4f m = m_fracture - > transformMatrix ( ) ;
bool isCellIntersected = false ;
fracturePlane . setFromPointAndNormal ( static_cast < cvf : : Vec3d > ( m . translation ( ) ) ,
static_cast < cvf : : Vec3d > ( m . col ( 2 ) ) ) ;
const RigMainGrid * mainGrid = m_case - > eclipseCaseData ( ) - > mainGrid ( ) ;
if ( ! mainGrid ) return false ;
RigCell cell = mainGrid - > globalCellArray ( ) [ cellindex ] ;
if ( cell . isInvalid ( ) ) return mainGrid ;
if ( cellindex = = 186234 )
{
cvf : : Vec3d cellcenter = cell . center ( ) ;
}
//Copied (and adapted) from RigEclipseWellLogExtractor
cvf : : Vec3d hexCorners [ 8 ] ;
const std : : vector < cvf : : Vec3d > & nodeCoords = mainGrid - > nodes ( ) ;
const caf : : SizeTArray8 & cornerIndices = cell . cornerIndices ( ) ;
hexCorners [ 0 ] = nodeCoords [ cornerIndices [ 0 ] ] ;
hexCorners [ 1 ] = nodeCoords [ cornerIndices [ 1 ] ] ;
hexCorners [ 2 ] = nodeCoords [ cornerIndices [ 2 ] ] ;
hexCorners [ 3 ] = nodeCoords [ cornerIndices [ 3 ] ] ;
hexCorners [ 4 ] = nodeCoords [ cornerIndices [ 4 ] ] ;
hexCorners [ 5 ] = nodeCoords [ cornerIndices [ 5 ] ] ;
hexCorners [ 6 ] = nodeCoords [ cornerIndices [ 6 ] ] ;
hexCorners [ 7 ] = nodeCoords [ cornerIndices [ 7 ] ] ;
//Find line-segments where cell and fracture plane intersects
std : : list < std : : pair < cvf : : Vec3d , cvf : : Vec3d > > intersectionLineSegments ;
isCellIntersected = RigCellGeometryTools : : planeHexCellIntersection ( hexCorners , fracturePlane , intersectionLineSegments ) ;
RigCellGeometryTools : : createPolygonFromLineSegments ( intersectionLineSegments , polygons ) ;
RigCellGeometryTools : : findCellLocalXYZ ( hexCorners , localX , localY , localZ ) ;
return isCellIntersected ;
2017-03-21 13:43:44 +01:00
}
2017-03-28 13:49:03 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-03-29 09:13:07 +02:00
std : : pair < double , double > RigFractureTransCalc : : flowAcrossLayersUpscaling ( QString resultName , QString resultUnit , size_t timeStepIndex , RimDefines : : UnitSystem unitSystem , size_t eclipseCellIndex )
2017-03-28 13:49:03 +02:00
{
RimStimPlanFractureTemplate * fracTemplateStimPlan ;
if ( dynamic_cast < RimStimPlanFractureTemplate * > ( m_fracture - > attachedFractureDefinition ( ) ) )
{
fracTemplateStimPlan = dynamic_cast < RimStimPlanFractureTemplate * > ( m_fracture - > attachedFractureDefinition ( ) ) ;
}
2017-03-29 09:13:07 +02:00
else return std : : make_pair ( cvf : : UNDEFINED_DOUBLE , cvf : : UNDEFINED_DOUBLE ) ;
2017-03-28 13:49:03 +02:00
2017-04-06 09:34:38 +02:00
std : : vector < RigStimPlanCell > stimPlanCells = fracTemplateStimPlan - > getStimPlanCells ( ) ;
2017-03-28 13:49:03 +02:00
2017-04-03 14:33:14 +02:00
cvf : : Vec3d localX , localY , localZ ; //Not used in calculation here, but needed for function to find planCellPolygons
2017-03-28 13:49:03 +02:00
std : : vector < std : : vector < cvf : : Vec3d > > planeCellPolygons ;
bool isPlanIntersected = planeCellIntersectionPolygons ( eclipseCellIndex , planeCellPolygons , localX , localY , localZ ) ;
2017-03-29 09:13:07 +02:00
if ( ! isPlanIntersected | | planeCellPolygons . size ( ) = = 0 ) return std : : make_pair ( cvf : : UNDEFINED_DOUBLE , cvf : : UNDEFINED_DOUBLE ) ;
2017-03-28 13:49:03 +02:00
//Transform planCell polygon(s) and averageZdirection to x/y coordinate system (where fracturePolygon/stimPlan mesh already is located)
cvf : : Mat4f invertedTransMatrix = m_fracture - > transformMatrix ( ) . getInverted ( ) ;
for ( std : : vector < cvf : : Vec3d > & planeCellPolygon : planeCellPolygons )
{
for ( cvf : : Vec3d & v : planeCellPolygon )
{
v . transformPoint ( static_cast < cvf : : Mat4d > ( invertedTransMatrix ) ) ;
}
}
cvf : : Vec3d directionAcrossLayers ;
cvf : : Vec3d directionAlongLayers ;
2017-03-31 10:25:24 +02:00
directionAcrossLayers = cvf : : Vec3d ( 0.0 , - 1.0 , 0.0 ) ;
directionAlongLayers = cvf : : Vec3d ( 1.0 , 0.0 , 0.0 ) ;
2017-03-28 13:49:03 +02:00
std : : vector < cvf : : Vec3f > fracPolygon = m_fracture - > attachedFractureDefinition ( ) - > fracturePolygon ( unitSystem ) ;
std : : vector < std : : vector < cvf : : Vec3d > > polygonsDescribingFractureInCell ;
2017-03-29 09:13:07 +02:00
std : : vector < double > upscaledConductivitiesHA ;
std : : vector < double > upscaledConductivitiesAH ;
2017-03-28 13:49:03 +02:00
for ( std : : vector < cvf : : Vec3d > planeCellPolygon : planeCellPolygons )
{
2017-03-31 13:59:30 +02:00
// //For debug only, to compare with results in Excel:
// std::vector<cvf::Vec3d> planeCellPolygonHacked;
// if (eclipseCellIndex == 134039)
// {
// planeCellPolygonHacked.push_back(cvf::Vec3d(-12.0, -3.5, 0.0));
// planeCellPolygonHacked.push_back(cvf::Vec3d(12.0, -3.5, 0.0));
// planeCellPolygonHacked.push_back(cvf::Vec3d(12.0, 19.0, 0.0));
// planeCellPolygonHacked.push_back(cvf::Vec3d(-12.0, 19.0, 0.0));
// planeCellPolygon = planeCellPolygonHacked;
// }
2017-03-29 09:13:07 +02:00
double condHA = computeHAupscale ( fracTemplateStimPlan , stimPlanCells , planeCellPolygon , directionAlongLayers , directionAcrossLayers ) ;
upscaledConductivitiesHA . push_back ( condHA ) ;
double condAH = computeAHupscale ( fracTemplateStimPlan , stimPlanCells , planeCellPolygon , directionAlongLayers , directionAcrossLayers ) ;
upscaledConductivitiesAH . push_back ( condAH ) ;
}
return std : : make_pair ( arithmeticAverage ( upscaledConductivitiesHA ) , arithmeticAverage ( upscaledConductivitiesAH ) ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-04-06 09:34:38 +02:00
double RigFractureTransCalc : : computeHAupscale ( RimStimPlanFractureTemplate * fracTemplateStimPlan , std : : vector < RigStimPlanCell > stimPlanCells , std : : vector < cvf : : Vec3d > planeCellPolygon , cvf : : Vec3d directionAlongLayers , cvf : : Vec3d directionAcrossLayers )
2017-03-29 09:13:07 +02:00
{
std : : vector < double > DcolSum ;
std : : vector < double > lavgCol ;
std : : vector < double > CondHarmCol ;
for ( size_t j = 0 ; j < fracTemplateStimPlan - > stimPlanGridNumberOfColums ( ) ; j + + )
{
std : : vector < double > conductivitiesInStimPlanCells ;
std : : vector < double > lengthsLiOfStimPlanCol ;
std : : vector < double > heightsDiOfStimPlanCells ;
2017-03-28 13:49:03 +02:00
2017-03-29 10:18:14 +02:00
std : : vector < RigStimPlanCell * > stimPlanCellsCol = getColOfStimPlanCells ( stimPlanCells , j ) ;
for ( RigStimPlanCell * stimPlanCell : stimPlanCellsCol )
2017-03-29 09:13:07 +02:00
{
2017-04-06 09:34:38 +02:00
if ( stimPlanCell - > getConductivtyValue ( ) > 1e-7 )
2017-03-28 13:49:03 +02:00
{
2017-03-29 09:13:07 +02:00
std : : vector < std : : vector < cvf : : Vec3d > > clippedStimPlanPolygons = RigCellGeometryTools : : clipPolygons ( stimPlanCell - > getPolygon ( ) , planeCellPolygon ) ;
if ( clippedStimPlanPolygons . size ( ) > 0 )
2017-03-28 13:49:03 +02:00
{
2017-03-29 09:13:07 +02:00
for ( auto clippedStimPlanPolygon : clippedStimPlanPolygons )
2017-03-28 13:49:03 +02:00
{
2017-04-06 09:34:38 +02:00
conductivitiesInStimPlanCells . push_back ( stimPlanCell - > getConductivtyValue ( ) ) ;
2017-03-29 09:13:07 +02:00
lengthsLiOfStimPlanCol . push_back ( RigCellGeometryTools : : polygonAreaWeightedLength ( directionAlongLayers , clippedStimPlanPolygon ) ) ;
heightsDiOfStimPlanCells . push_back ( RigCellGeometryTools : : polygonAreaWeightedLength ( directionAcrossLayers , clippedStimPlanPolygon ) ) ;
2017-03-28 13:49:03 +02:00
}
}
}
2017-03-29 09:13:07 +02:00
}
//Regne ut average
double sumDiDivCondLi = 0.0 ;
double sumDi = 0.0 ;
double sumLiDi = 0.0 ;
for ( int i = 0 ; i < conductivitiesInStimPlanCells . size ( ) ; i + + )
{
sumDiDivCondLi + = heightsDiOfStimPlanCells [ i ] / ( conductivitiesInStimPlanCells [ i ] * lengthsLiOfStimPlanCol [ i ] ) ;
sumDi + = heightsDiOfStimPlanCells [ i ] ;
sumLiDi + = heightsDiOfStimPlanCells [ i ] * lengthsLiOfStimPlanCol [ i ] ;
}
2017-03-28 13:49:03 +02:00
2017-03-29 09:13:07 +02:00
if ( sumDiDivCondLi ! = 0 )
{
DcolSum . push_back ( sumDi ) ;
double lAvgValue = sumLiDi / sumDi ;
lavgCol . push_back ( lAvgValue ) ;
2017-03-31 10:25:24 +02:00
double harmMeanForCol = ( sumDi / lAvgValue ) * ( 1 / sumDiDivCondLi ) ;
CondHarmCol . push_back ( harmMeanForCol ) ;
2017-03-29 09:13:07 +02:00
}
}
//Do arithmetic upscaling based on harmonic upscaled values for coloums
double sumCondHLiDivDi = 0.0 ;
double sumLi = 0.0 ;
double sumDiLi = 0.0 ;
for ( int i = 0 ; i < CondHarmCol . size ( ) ; i + + )
{
sumLi + = lavgCol [ i ] ;
sumDiLi + = DcolSum [ i ] * lavgCol [ i ] ;
sumCondHLiDivDi + = CondHarmCol [ i ] * lavgCol [ i ] / DcolSum [ i ] ;
}
double Davg = sumDiLi / sumLi ;
double condHA = ( Davg / sumLi ) * sumCondHLiDivDi ;
return condHA ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-04-06 09:34:38 +02:00
double RigFractureTransCalc : : computeAHupscale ( RimStimPlanFractureTemplate * fracTemplateStimPlan , std : : vector < RigStimPlanCell > stimPlanCells , std : : vector < cvf : : Vec3d > planeCellPolygon , cvf : : Vec3d directionAlongLayers , cvf : : Vec3d directionAcrossLayers )
2017-03-29 09:13:07 +02:00
{
2017-03-31 13:59:30 +02:00
std : : vector < double > DrowAvg ;
std : : vector < double > liRowSum ;
std : : vector < double > CondAritRow ;
2017-03-29 09:13:07 +02:00
2017-03-31 13:59:30 +02:00
for ( size_t j = 0 ; j < fracTemplateStimPlan - > stimPlanGridNumberOfRows ( ) ; j + + )
2017-03-29 09:13:07 +02:00
{
std : : vector < double > conductivitiesInStimPlanCells ;
std : : vector < double > lengthsLiOfStimPlanCol ;
std : : vector < double > heightsDiOfStimPlanCells ;
2017-03-31 13:59:30 +02:00
std : : vector < RigStimPlanCell * > stimPlanCellsCol = getRowOfStimPlanCells ( stimPlanCells , j ) ;
2017-03-29 10:18:14 +02:00
for ( RigStimPlanCell * stimPlanCell : stimPlanCellsCol )
2017-03-29 09:13:07 +02:00
{
2017-04-06 09:34:38 +02:00
if ( stimPlanCell - > getConductivtyValue ( ) > 1e-7 )
2017-03-28 13:49:03 +02:00
{
2017-03-29 09:13:07 +02:00
std : : vector < std : : vector < cvf : : Vec3d > > clippedStimPlanPolygons = RigCellGeometryTools : : clipPolygons ( stimPlanCell - > getPolygon ( ) , planeCellPolygon ) ;
if ( clippedStimPlanPolygons . size ( ) > 0 )
{
for ( auto clippedStimPlanPolygon : clippedStimPlanPolygons )
{
2017-04-06 09:34:38 +02:00
conductivitiesInStimPlanCells . push_back ( stimPlanCell - > getConductivtyValue ( ) ) ;
2017-03-29 09:13:07 +02:00
lengthsLiOfStimPlanCol . push_back ( RigCellGeometryTools : : polygonAreaWeightedLength ( directionAlongLayers , clippedStimPlanPolygon ) ) ;
heightsDiOfStimPlanCells . push_back ( RigCellGeometryTools : : polygonAreaWeightedLength ( directionAcrossLayers , clippedStimPlanPolygon ) ) ;
}
}
2017-03-28 13:49:03 +02:00
}
}
2017-03-29 09:13:07 +02:00
//Calculate sums needed for (arithmetic) average for coloum
double sumCondLiDivDi = 0.0 ;
double sumDi = 0.0 ;
double sumLiDi = 0.0 ;
2017-03-28 13:49:03 +02:00
double sumLi = 0.0 ;
2017-03-29 09:13:07 +02:00
for ( int i = 0 ; i < conductivitiesInStimPlanCells . size ( ) ; i + + )
2017-03-28 13:49:03 +02:00
{
2017-03-29 09:13:07 +02:00
sumCondLiDivDi + = ( conductivitiesInStimPlanCells [ i ] * lengthsLiOfStimPlanCol [ i ] ) / heightsDiOfStimPlanCells [ i ] ;
sumDi + = heightsDiOfStimPlanCells [ i ] ;
sumLiDi + = heightsDiOfStimPlanCells [ i ] * lengthsLiOfStimPlanCol [ i ] ;
sumLi + = lengthsLiOfStimPlanCol [ i ] ;
2017-03-28 13:49:03 +02:00
}
2017-03-29 09:13:07 +02:00
if ( sumCondLiDivDi ! = 0 )
{
//Calculating art avg
double dAvg = sumLiDi / sumLi ;
2017-03-31 13:59:30 +02:00
DrowAvg . push_back ( dAvg ) ;
liRowSum . push_back ( sumLi ) ;
CondAritRow . push_back ( dAvg / sumLi * sumCondLiDivDi ) ;
2017-03-29 09:13:07 +02:00
}
}
//Do harmonic upscaling based on arithmetric upscaled values for coloums
double sumDiDivCondALi = 0.0 ;
double sumDi = 0.0 ;
double sumDiLi = 0.0 ;
2017-03-31 13:59:30 +02:00
for ( int i = 0 ; i < CondAritRow . size ( ) ; i + + )
2017-03-29 09:13:07 +02:00
{
2017-03-31 13:59:30 +02:00
sumDi + = DrowAvg [ i ] ;
sumDiLi + = DrowAvg [ i ] * liRowSum [ i ] ;
sumDiDivCondALi + = DrowAvg [ i ] / ( CondAritRow [ i ] * liRowSum [ i ] ) ;
2017-03-28 13:49:03 +02:00
}
2017-03-29 09:13:07 +02:00
double Lavg = sumDiLi / sumDi ;
double condAH = ( sumDi / Lavg ) * ( 1 / sumDiDivCondALi ) ;
return condAH ;
2017-03-28 13:49:03 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFractureTransCalc : : arithmeticAverage ( std : : vector < double > values )
{
if ( values . size ( ) = = 0 ) return cvf : : UNDEFINED_DOUBLE ;
double sumValue = 0.0 ;
size_t numberOfValues = 0 ;
for ( double value : values )
{
sumValue + = value ;
numberOfValues + + ;
}
return sumValue / numberOfValues ;
}
2017-03-21 13:43:44 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-03-21 15:29:22 +01:00
void RigFractureTransCalc : : computeUpscaledPropertyFromStimPlan ( QString resultName , QString resultUnit , size_t timeStepIndex )
2017-03-21 13:43:44 +01:00
{
RimStimPlanFractureTemplate * fracTemplateStimPlan ;
2017-03-21 15:29:22 +01:00
if ( dynamic_cast < RimStimPlanFractureTemplate * > ( m_fracture - > attachedFractureDefinition ( ) ) )
2017-03-21 13:43:44 +01:00
{
2017-03-21 15:29:22 +01:00
fracTemplateStimPlan = dynamic_cast < RimStimPlanFractureTemplate * > ( m_fracture - > attachedFractureDefinition ( ) ) ;
2017-03-21 13:43:44 +01:00
}
else return ;
std : : vector < std : : vector < cvf : : Vec3d > > stimPlanCellsAsPolygons ;
std : : vector < double > stimPlanParameterValues ;
fracTemplateStimPlan - > getStimPlanDataAsPolygonsAndValues ( stimPlanCellsAsPolygons , stimPlanParameterValues , resultName , resultUnit , timeStepIndex ) ;
//TODO: A lot of common code with function above... Can be cleaned up...?
2017-03-21 15:29:22 +01:00
std : : vector < size_t > fracCells = m_fracture - > getPotentiallyFracturedCells ( ) ;
2017-03-21 13:43:44 +01:00
2017-03-21 15:29:22 +01:00
RigEclipseCaseData * eclipseCaseData = m_case - > eclipseCaseData ( ) ;
2017-03-21 13:43:44 +01:00
RifReaderInterface : : PorosityModelResultType porosityModel = RifReaderInterface : : MATRIX_RESULTS ;
2017-03-21 15:29:22 +01:00
RimReservoirCellResultsStorage * gridCellResults = m_case - > results ( porosityModel ) ;
2017-03-21 13:43:44 +01:00
RigActiveCellInfo * activeCellInfo = eclipseCaseData - > activeCellInfo ( porosityModel ) ;
std : : vector < RigFractureData > fracDataVec ;
for ( size_t fracCell : fracCells )
{
RigFractureData fracData ;
fracData . reservoirCellIndex = fracCell ;
2017-03-29 09:43:36 +02:00
std : : pair < double , double > upscaledCondFlowAcrossLayers = flowAcrossLayersUpscaling ( resultName , resultUnit , timeStepIndex , m_unitForCalculation , fracCell ) ;
2017-03-31 10:25:24 +02:00
double upscaledStimPlanValueHA = upscaledCondFlowAcrossLayers . first ;
double upscaledStimPlanValueAH = upscaledCondFlowAcrossLayers . second ;
2017-03-29 09:43:36 +02:00
2017-03-31 10:25:24 +02:00
if ( upscaledStimPlanValueHA ! = cvf : : UNDEFINED_DOUBLE )
2017-03-21 13:43:44 +01:00
{
2017-03-31 10:25:24 +02:00
fracData . upscaledStimPlanValueHA = upscaledStimPlanValueHA ;
fracData . upscaledStimPlanValueAH = upscaledStimPlanValueAH ;
2017-03-21 13:43:44 +01:00
fracDataVec . push_back ( fracData ) ;
}
}
2017-04-03 14:33:14 +02:00
//TODO: Hvis fracture allerede har en s<> nn vektor, trenger vi vel ikke en til for RigFractureTransCalc...?
//Trenger bare funksjoner for <20> sette / hente ut data for en gitt Eclipse celle...
2017-03-21 15:29:22 +01:00
m_fracture - > setFractureData ( fracDataVec ) ;
2017-03-21 13:43:44 +01:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-04-25 16:08:44 +02:00
void RigFractureTransCalc : : computeStimPlanCellTransmissibilityInFracture ( const RigStimPlanCell & stimPlanCell )
2017-03-21 13:43:44 +01:00
{
2017-04-25 16:08:44 +02:00
double verticalSideLength = stimPlanCell . cellSizeX ( ) ;
double horisontalSideLength = stimPlanCell . cellSizeZ ( ) ;
2017-03-21 13:43:44 +01:00
2017-04-25 16:08:44 +02:00
double verticalTrans = stimPlanCell . getConductivtyValue ( ) * verticalSideLength / ( horisontalSideLength / 2 ) ;
double horizontalTrans = stimPlanCell . getConductivtyValue ( ) * horisontalSideLength / ( verticalSideLength / 2 ) ;
2017-03-21 13:43:44 +01:00
2017-04-25 16:08:44 +02:00
//TODO: Ta bort const???
// stimPlanCell.setTransmissibilityInFracture(verticalTrans, horizontalTrans);
2017-03-21 13:43:44 +01:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-04-25 16:08:44 +02:00
double RigFractureTransCalc : : computeRadialTransmissibilityToWellinStimPlanCell ( const RigStimPlanCell & stimPlanCell )
2017-03-21 13:43:44 +01:00
{
2017-04-19 14:12:47 +02:00
if ( m_fracture - > attachedFractureDefinition ( ) - > orientation = = RimFractureTemplate : : ALONG_WELL_PATH ) return cvf : : UNDEFINED_DOUBLE ;
2017-03-21 13:43:44 +01:00
2017-03-27 10:06:14 +02:00
double areaScalingFactor = 1.0 ;
2017-03-21 15:29:22 +01:00
if ( m_fracture - > attachedFractureDefinition ( ) - > orientation = = RimFractureTemplate : : AZIMUTH )
2017-03-21 13:43:44 +01:00
{
2017-03-27 10:06:14 +02:00
areaScalingFactor = 1 / cvf : : Math : : cos ( ( m_fracture - > azimuth ( ) - ( m_fracture - > wellAzimuthAtFracturePosition ( ) - 90 ) ) ) ;
}
2017-03-21 13:43:44 +01:00
2017-04-19 14:12:47 +02:00
double ro = 0.14 * cvf : : Math : : sqrt (
2017-04-25 16:08:44 +02:00
pow ( stimPlanCell . cellSizeX ( ) , 2.0 ) + pow ( stimPlanCell . cellSizeZ ( ) , 2 ) ) ;
2017-04-19 14:12:47 +02:00
2017-04-25 16:08:44 +02:00
double Tc = 2 * cvf : : PI_D * cDarcy ( ) * stimPlanCell . getConductivtyValue ( ) /
2017-04-19 14:12:47 +02:00
( log ( ro / m_fracture - > wellRadius ( ) ) + m_fracture - > attachedFractureDefinition ( ) - > skinFactor ( ) ) ;
Tc = Tc * areaScalingFactor ;
return Tc ;
}
2017-04-19 14:50:55 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-04-25 16:08:44 +02:00
double RigFractureTransCalc : : computeLinearTransmissibilityToWellinStimPlanCell ( const RigStimPlanCell & stimPlanCell , double perforationLengthVertical , double perforationLengthHorizontal )
2017-04-19 14:50:55 +02:00
{
2017-04-25 16:08:44 +02:00
double TcPrefix = 8 * cDarcy ( ) * stimPlanCell . getConductivtyValue ( ) ;
2017-04-19 14:50:55 +02:00
double DzPerf = perforationLengthVertical * m_fracture - > perforationEfficiency ( ) ;
double DxPerf = perforationLengthHorizontal * m_fracture - > perforationEfficiency ( ) ;
double TcZ = TcPrefix * DzPerf /
2017-04-25 16:08:44 +02:00
( stimPlanCell . cellSizeX ( ) + m_fracture - > attachedFractureDefinition ( ) - > skinFactor ( ) * DzPerf / cvf : : PI_D ) ;
2017-04-19 14:50:55 +02:00
double TcX = TcPrefix * DxPerf /
2017-04-25 16:08:44 +02:00
( stimPlanCell . cellSizeZ ( ) + m_fracture - > attachedFractureDefinition ( ) - > skinFactor ( ) * DxPerf / cvf : : PI_D ) ;
2017-04-19 14:50:55 +02:00
double Tc = cvf : : Math : : sqrt ( pow ( TcX , 2 ) + pow ( TcZ , 2 ) ) ;
return Tc ;
}
2017-04-19 14:12:47 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFractureTransCalc : : cDarcy ( )
{
double c = cvf : : UNDEFINED_DOUBLE ;
if ( m_unitForCalculation = = RimDefines : : UNITS_METRIC ) c = 0.00852702 ;
if ( m_unitForCalculation = = RimDefines : : UNITS_FIELD ) c = 0.00112712 ;
// TODO: Use value from RimReservoirCellResultsStorage?
return c ;
2017-03-27 10:06:14 +02:00
}
2017-03-21 13:43:44 +01:00
2017-03-28 13:49:03 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-04-20 12:16:13 +02:00
std : : vector < RigStimPlanCell * > RigFractureTransCalc : : getRowOfStimPlanCells ( std : : vector < RigStimPlanCell > & allStimPlanCells , size_t i )
2017-03-28 13:49:03 +02:00
{
2017-03-29 10:18:14 +02:00
std : : vector < RigStimPlanCell * > stimPlanCellRow ;
2017-03-28 13:49:03 +02:00
2017-04-06 09:34:38 +02:00
for ( RigStimPlanCell stimPlanCell : allStimPlanCells )
2017-03-28 13:49:03 +02:00
{
2017-04-06 09:34:38 +02:00
if ( stimPlanCell . getI ( ) = = i )
2017-03-28 13:49:03 +02:00
{
2017-04-06 09:34:38 +02:00
stimPlanCellRow . push_back ( & stimPlanCell ) ;
2017-03-28 13:49:03 +02:00
}
}
return stimPlanCellRow ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-04-20 12:16:13 +02:00
std : : vector < RigStimPlanCell * > RigFractureTransCalc : : getColOfStimPlanCells ( std : : vector < RigStimPlanCell > & allStimPlanCells , size_t j )
2017-03-28 13:49:03 +02:00
{
2017-03-29 10:18:14 +02:00
std : : vector < RigStimPlanCell * > stimPlanCellCol ;
2017-03-28 13:49:03 +02:00
2017-04-06 09:34:38 +02:00
for ( RigStimPlanCell stimPlanCell : allStimPlanCells )
2017-03-28 13:49:03 +02:00
{
2017-04-06 09:34:38 +02:00
if ( stimPlanCell . getJ ( ) = = j )
2017-03-28 13:49:03 +02:00
{
2017-04-06 09:34:38 +02:00
stimPlanCellCol . push_back ( & stimPlanCell ) ;
2017-03-28 13:49:03 +02:00
}
}
return stimPlanCellCol ;
}
2017-03-27 10:06:14 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFractureTransCalc : : convertConductivtyValue ( double Kw , RimDefines : : UnitSystem fromUnit , RimDefines : : UnitSystem toUnit )
{
if ( fromUnit = = toUnit ) return Kw ;
else if ( fromUnit = = RimDefines : : UNITS_METRIC & & toUnit = = RimDefines : : UNITS_FIELD )
{
return RimDefines : : meterToFeet ( Kw ) ;
}
else if ( fromUnit = = RimDefines : : UNITS_METRIC & & toUnit = = RimDefines : : UNITS_FIELD )
{
return RimDefines : : feetToMeter ( Kw ) ;
}
2017-03-21 13:43:44 +01:00
2017-03-27 10:06:14 +02:00
return cvf : : UNDEFINED_DOUBLE ;
2017-03-21 13:43:44 +01:00
}
2017-04-05 14:40:54 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFractureTransCalc : : calculateMatrixTransmissibility ( double perm , double NTG , double A , double cellSizeLength , double skinfactor , double fractureAreaWeightedlength )
{
double transmissibility ;
double slDivPi = ( skinfactor * fractureAreaWeightedlength ) / cvf : : PI_D ;
2017-04-19 14:12:47 +02:00
transmissibility = 8 * cDarcy ( ) * ( perm * NTG ) * A / ( cellSizeLength + slDivPi ) ;
2017-04-05 14:40:54 +02:00
return transmissibility ;
}