2016-12-16 03:15:23 -06:00
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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.
//
/////////////////////////////////////////////////////////////////////////////////
2017-01-12 06:29:18 -06:00
# include "RimEllipseFractureTemplate.h"
2016-12-16 03:15:23 -06:00
2018-02-06 05:42:13 -06:00
# include "RiaApplication.h"
2017-06-14 00:25:34 -05:00
# include "RiaEclipseUnitTools.h"
2018-01-25 06:30:36 -06:00
# include "RiaFractureDefines.h"
2017-03-02 03:08:45 -06:00
# include "RiaLogging.h"
2017-06-01 04:31:34 -05:00
# include "RigCellGeometryTools.h"
# include "RigFractureCell.h"
# include "RigFractureGrid.h"
2018-01-19 02:10:30 -06:00
# include "RigStatisticsMath.h"
2017-01-13 01:58:36 -06:00
# include "RigTesselatorTools.h"
2017-02-06 06:22:18 -06:00
2018-02-06 05:42:13 -06:00
# include "RimEclipseView.h"
2017-02-06 06:22:18 -06:00
# include "RimFracture.h"
2017-06-08 15:54:06 -05:00
# include "RimFractureContainment.h"
2017-02-07 02:09:00 -06:00
# include "RimFractureTemplate.h"
2017-02-06 06:22:18 -06:00
# include "RimProject.h"
2018-02-06 05:42:13 -06:00
# include "RimStimPlanColors.h"
2017-02-06 06:22:18 -06:00
# include "cafPdmObject.h"
2017-01-13 01:58:36 -06:00
# include "cvfVector3.h"
2017-06-01 04:31:34 -05:00
# include "cvfGeometryTools.h"
2016-12-16 03:15:23 -06:00
2017-02-07 02:09:00 -06:00
CAF_PDM_SOURCE_INIT ( RimEllipseFractureTemplate , " RimEllipseFractureTemplate " ) ;
2016-12-16 03:15:23 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-01-12 06:29:18 -06:00
RimEllipseFractureTemplate : : RimEllipseFractureTemplate ( void )
2016-12-16 03:15:23 -06:00
{
2017-01-05 07:57:04 -06:00
CAF_PDM_InitObject ( " Fracture Template " , " :/FractureTemplate16x16.png " , " " , " " ) ;
2016-12-16 03:15:23 -06:00
2018-02-16 01:26:36 -06:00
CAF_PDM_InitField ( & m_halfLength , " HalfLength " , 0.0 , " Halflength X<sub>f</sub> " , " " , " " , " " ) ;
CAF_PDM_InitField ( & m_height , " Height " , 0.0 , " Height " , " " , " " , " " ) ;
CAF_PDM_InitField ( & m_width , " Width " , 0.0 , " Width " , " " , " " , " " ) ;
2017-01-23 01:54:27 -06:00
2018-02-16 01:26:36 -06:00
CAF_PDM_InitField ( & m_userDefinedEffectivePermeability , " Permeability " , 0.0 , " Permeability [mD] " , " " , " " , " " ) ;
2017-06-01 04:31:34 -05:00
m_fractureGrid = new RigFractureGrid ( ) ;
2017-06-06 04:24:05 -05:00
setupFractureGridCells ( ) ;
2016-12-16 03:15:23 -06:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-01-12 06:29:18 -06:00
RimEllipseFractureTemplate : : ~ RimEllipseFractureTemplate ( )
2016-12-16 03:15:23 -06:00
{
}
2016-12-19 04:23:02 -06:00
2017-08-04 07:35:16 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate : : loadDataAndUpdate ( )
{
setupFractureGridCells ( ) ;
2018-02-06 05:42:13 -06:00
RimEclipseView * activeView = dynamic_cast < RimEclipseView * > ( RiaApplication : : instance ( ) - > activeReservoirView ( ) ) ;
if ( activeView ) activeView - > loadDataAndUpdate ( ) ;
2017-08-04 07:35:16 -05:00
}
2016-12-19 04:23:02 -06:00
2017-01-06 06:55:26 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-01-12 06:29:18 -06:00
void RimEllipseFractureTemplate : : fieldChangedByUi ( const caf : : PdmFieldHandle * changedField , const QVariant & oldValue , const QVariant & newValue )
2017-01-06 06:55:26 -06:00
{
2017-02-23 02:47:30 -06:00
RimFractureTemplate : : fieldChangedByUi ( changedField , oldValue , newValue ) ;
2017-01-06 06:55:26 -06:00
2018-01-19 02:49:26 -06:00
if ( changedField = = & m_halfLength
| | changedField = = & m_height
| | changedField = = & m_width
2018-02-15 08:38:27 -06:00
| | changedField = = & m_userDefinedEffectivePermeability )
2017-02-02 02:20:58 -06:00
{
//Changes to one of these parameters should change all fractures with this fracture template attached.
2017-01-06 06:55:26 -06:00
RimProject * proj ;
this - > firstAncestorOrThisOfType ( proj ) ;
if ( proj )
{
//Regenerate geometry
2017-02-01 03:49:50 -06:00
proj - > createDisplayModelAndRedrawAllViews ( ) ;
2017-06-01 04:31:34 -05:00
setupFractureGridCells ( ) ;
2017-02-01 03:49:50 -06:00
}
}
2018-02-15 08:38:27 -06:00
if ( changedField = = & m_width | | changedField = = & m_userDefinedEffectivePermeability )
2017-06-01 04:31:34 -05:00
{
setupFractureGridCells ( ) ;
}
2017-01-10 04:57:42 -06:00
}
2017-01-13 01:58:36 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-06-09 10:21:59 -05:00
void RimEllipseFractureTemplate : : fractureTriangleGeometry ( std : : vector < cvf : : Vec3f > * nodeCoords ,
2018-02-21 01:18:55 -06:00
std : : vector < cvf : : uint > * triangleIndices )
2017-01-13 01:58:36 -06:00
{
RigEllipsisTesselator tesselator ( 20 ) ;
2018-02-21 01:18:55 -06:00
float a = m_halfLength ;
float b = m_height / 2.0f ;
2017-03-02 03:08:45 -06:00
2017-02-10 04:32:18 -06:00
tesselator . tesselateEllipsis ( a , b , triangleIndices , nodeCoords ) ;
2017-01-13 01:58:36 -06:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2018-02-21 01:18:55 -06:00
std : : vector < cvf : : Vec3f > RimEllipseFractureTemplate : : fractureBorderPolygon ( )
2017-01-13 01:58:36 -06:00
{
std : : vector < cvf : : Vec3f > polygon ;
std : : vector < cvf : : Vec3f > nodeCoords ;
2017-02-10 04:32:18 -06:00
std : : vector < cvf : : uint > triangleIndices ;
2017-01-13 01:58:36 -06:00
2018-02-21 01:18:55 -06:00
fractureTriangleGeometry ( & nodeCoords , & triangleIndices ) ;
2017-01-13 01:58:36 -06:00
for ( size_t i = 1 ; i < nodeCoords . size ( ) ; i + + )
{
polygon . push_back ( nodeCoords [ i ] ) ;
}
return polygon ;
}
2017-02-14 02:49:14 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate : : changeUnits ( )
{
2018-02-08 06:57:43 -06:00
if ( fractureTemplateUnit ( ) = = RiaEclipseUnitTools : : UNITS_METRIC )
2017-02-14 02:49:14 -06:00
{
2018-02-20 08:15:06 -06:00
convertToUnitSystem ( RiaEclipseUnitTools : : UNITS_FIELD ) ;
2017-02-14 02:49:14 -06:00
}
2018-02-08 06:57:43 -06:00
else if ( fractureTemplateUnit ( ) = = RiaEclipseUnitTools : : UNITS_FIELD )
2017-02-14 02:49:14 -06:00
{
2018-02-20 08:15:06 -06:00
convertToUnitSystem ( RiaEclipseUnitTools : : UNITS_METRIC ) ;
2017-02-14 02:49:14 -06:00
}
this - > updateConnectedEditors ( ) ;
}
2017-06-01 04:31:34 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate : : setupFractureGridCells ( )
{
std : : vector < RigFractureCell > fractureCells ;
std : : pair < size_t , size_t > wellCenterFractureCellIJ = std : : make_pair ( 0 , 0 ) ;
2017-06-23 03:41:31 -05:00
int numberOfCellsX = 35 ;
int numberOfCellsY = 35 ;
2017-06-01 04:31:34 -05:00
2018-01-10 00:44:26 -06:00
double cellSizeX = ( m_halfLength * 2 ) / numberOfCellsX ;
double cellSizeZ = m_height / numberOfCellsY ;
2017-06-01 04:31:34 -05:00
double cellArea = cellSizeX * cellSizeZ ;
double areaTresholdForIncludingCell = 0.5 * cellArea ;
for ( int i = 0 ; i < numberOfCellsX ; i + + )
{
for ( int j = 0 ; j < numberOfCellsX ; j + + )
{
2018-01-10 00:44:26 -06:00
double X1 = - m_halfLength + i * cellSizeX ;
double X2 = - m_halfLength + ( i + 1 ) * cellSizeX ;
double Y1 = - m_height / 2 + j * cellSizeZ ;
double Y2 = - m_height / 2 + ( j + 1 ) * cellSizeZ ;
2017-06-01 04:31:34 -05:00
std : : vector < cvf : : Vec3d > cellPolygon ;
cellPolygon . push_back ( cvf : : Vec3d ( X1 , Y1 , 0.0 ) ) ;
cellPolygon . push_back ( cvf : : Vec3d ( X2 , Y1 , 0.0 ) ) ;
cellPolygon . push_back ( cvf : : Vec3d ( X2 , Y2 , 0.0 ) ) ;
cellPolygon . push_back ( cvf : : Vec3d ( X1 , Y2 , 0.0 ) ) ;
2018-01-15 06:32:13 -06:00
double cond = conductivity ( ) ;
2017-06-01 04:31:34 -05:00
2018-02-21 01:18:55 -06:00
std : : vector < cvf : : Vec3f > ellipseFracPolygon = fractureBorderPolygon ( ) ;
2017-06-01 04:31:34 -05:00
std : : vector < cvf : : Vec3d > ellipseFracPolygonDouble ;
for ( auto v : ellipseFracPolygon ) ellipseFracPolygonDouble . push_back ( static_cast < cvf : : Vec3d > ( v ) ) ;
std : : vector < std : : vector < cvf : : Vec3d > > clippedFracturePolygons = RigCellGeometryTools : : intersectPolygons ( cellPolygon , ellipseFracPolygonDouble ) ;
if ( clippedFracturePolygons . size ( ) > 0 )
{
for ( auto clippedFracturePolygon : clippedFracturePolygons )
{
double areaCutPolygon = cvf : : GeometryTools : : polygonAreaNormal3D ( clippedFracturePolygon ) . length ( ) ;
if ( areaCutPolygon < areaTresholdForIncludingCell ) cond = 0.0 ; //Cell is excluded from calculation, cond is set to zero. Must be included for indexing to be correct
}
}
else cond = 0.0 ;
RigFractureCell fractureCell ( cellPolygon , i , j ) ;
fractureCell . setConductivityValue ( cond ) ;
if ( cellPolygon [ 0 ] . x ( ) < 0.0 & & cellPolygon [ 1 ] . x ( ) > 0.0 )
{
2017-06-06 04:24:05 -05:00
if ( cellPolygon [ 1 ] . y ( ) < 0.0 & & cellPolygon [ 2 ] . y ( ) > 0.0 )
2017-06-01 04:31:34 -05:00
{
wellCenterFractureCellIJ = std : : make_pair ( fractureCell . getI ( ) , fractureCell . getJ ( ) ) ;
2017-06-06 04:24:05 -05:00
RiaLogging : : debug ( QString ( " Setting wellCenterFractureCell at cell %1, %2 " ) .
2017-06-01 04:31:34 -05:00
arg ( QString : : number ( fractureCell . getI ( ) ) , QString : : number ( fractureCell . getJ ( ) ) ) ) ;
}
}
fractureCells . push_back ( fractureCell ) ;
}
}
m_fractureGrid - > setFractureCells ( fractureCells ) ;
m_fractureGrid - > setWellCenterFractureCellIJ ( wellCenterFractureCellIJ ) ;
m_fractureGrid - > setICellCount ( numberOfCellsX ) ;
m_fractureGrid - > setJCellCount ( numberOfCellsY ) ;
}
//--------------------------------------------------------------------------------------------------
2018-02-14 06:35:35 -06:00
///
//--------------------------------------------------------------------------------------------------
FractureWidthAndConductivity RimEllipseFractureTemplate : : widthAndConductivityAtWellPathIntersection ( ) const
{
FractureWidthAndConductivity values ;
values . m_width = m_width ;
2018-02-15 08:38:27 -06:00
values . m_permeability = m_userDefinedEffectivePermeability ;
2018-02-14 06:35:35 -06:00
return values ;
}
//--------------------------------------------------------------------------------------------------
2017-06-01 04:31:34 -05:00
///
//--------------------------------------------------------------------------------------------------
const RigFractureGrid * RimEllipseFractureTemplate : : fractureGrid ( ) const
{
return m_fractureGrid . p ( ) ;
}
2018-01-10 00:34:45 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate : : setDefaultValuesFromUnit ( )
{
2018-02-08 06:57:43 -06:00
if ( fractureTemplateUnit ( ) = = RiaEclipseUnitTools : : UNITS_FIELD )
2018-01-10 00:34:45 -06:00
{
2018-02-16 01:26:36 -06:00
m_width = 0.5 ;
m_userDefinedEffectivePermeability = 80000.0 ;
m_halfLength = 300.0 ;
m_height = 225.0 ;
2018-01-10 00:34:45 -06:00
}
else
{
2018-02-16 01:26:36 -06:00
m_width = 0.01 ;
m_userDefinedEffectivePermeability = 100000.0 ;
m_halfLength = 100.0 ;
m_height = 75.0 ;
2018-01-10 00:34:45 -06:00
}
this - > setDefaultWellDiameterFromUnit ( ) ;
}
2018-01-15 06:32:13 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimEllipseFractureTemplate : : conductivity ( ) const
{
double cond = cvf : : UNDEFINED_DOUBLE ;
2018-02-08 06:57:43 -06:00
if ( fractureTemplateUnit ( ) = = RiaEclipseUnitTools : : UNITS_METRIC )
2018-01-15 06:32:13 -06:00
{
//Conductivity should be md-m, width is in m
2018-02-15 08:38:27 -06:00
cond = m_userDefinedEffectivePermeability * m_width ;
2018-01-15 06:32:13 -06:00
}
2018-02-08 06:57:43 -06:00
else if ( fractureTemplateUnit ( ) = = RiaEclipseUnitTools : : UNITS_FIELD )
2018-01-15 06:32:13 -06:00
{
//Conductivity should be md-ft, but width is in inches
2018-02-15 08:38:27 -06:00
cond = m_userDefinedEffectivePermeability * RiaEclipseUnitTools : : inchToFeet ( m_width ) ;
2018-01-15 06:32:13 -06:00
}
return cond ;
}
2018-01-19 02:10:30 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2018-01-25 06:30:36 -06:00
void RimEllipseFractureTemplate : : appendDataToResultStatistics ( const QString & uiResultName , const QString & unit , MinMaxAccumulator & minMaxAccumulator , PosNegAccumulator & posNegAccumulator ) const
2018-01-19 02:10:30 -06:00
{
2018-01-25 06:30:36 -06:00
if ( uiResultName = = RiaDefines : : conductivityResultName ( ) )
2018-01-19 02:10:30 -06:00
{
minMaxAccumulator . addValue ( conductivity ( ) ) ;
posNegAccumulator . addValue ( conductivity ( ) ) ;
}
}
2018-02-06 05:42:13 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : vector < std : : pair < QString , QString > > RimEllipseFractureTemplate : : uiResultNamesWithUnit ( ) const
{
std : : vector < std : : pair < QString , QString > > propertyNamesAndUnits ;
QString condUnit = RiaDefines : : unitStringConductivity ( fractureTemplateUnit ( ) ) ;
propertyNamesAndUnits . push_back ( std : : make_pair ( RiaDefines : : conductivityResultName ( ) , condUnit ) ) ;
return propertyNamesAndUnits ;
}
2018-02-20 08:15:06 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate : : convertToUnitSystem ( RiaEclipseUnitTools : : UnitSystem neededUnit )
{
if ( neededUnit = = fractureTemplateUnit ( ) )
{
return ;
}
if ( neededUnit = = RiaEclipseUnitTools : : UNITS_FIELD )
{
m_halfLength = RiaEclipseUnitTools : : meterToFeet ( m_halfLength ) ;
m_height = RiaEclipseUnitTools : : meterToFeet ( m_height ) ;
m_width = RiaEclipseUnitTools : : meterToInch ( m_width ) ;
m_wellDiameter = RiaEclipseUnitTools : : meterToInch ( m_wellDiameter ) ;
m_perforationLength = RiaEclipseUnitTools : : meterToFeet ( m_perforationLength ) ;
setFractureTemplateUnit ( RiaEclipseUnitTools : : UNITS_FIELD ) ;
}
else if ( neededUnit = = RiaEclipseUnitTools : : UNITS_METRIC )
{
m_halfLength = RiaEclipseUnitTools : : feetToMeter ( m_halfLength ) ;
m_height = RiaEclipseUnitTools : : feetToMeter ( m_height ) ;
m_width = RiaEclipseUnitTools : : inchToMeter ( m_width ) ;
m_wellDiameter = RiaEclipseUnitTools : : inchToMeter ( m_wellDiameter ) ;
m_perforationLength = RiaEclipseUnitTools : : feetToMeter ( m_perforationLength ) ;
setFractureTemplateUnit ( RiaEclipseUnitTools : : UNITS_METRIC ) ;
}
}
2016-12-19 04:23:02 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-01-12 06:29:18 -06:00
void RimEllipseFractureTemplate : : defineUiOrdering ( QString uiConfigName , caf : : PdmUiOrdering & uiOrdering )
2016-12-19 04:23:02 -06:00
{
2017-02-14 02:49:14 -06:00
2018-02-08 06:57:43 -06:00
if ( fractureTemplateUnit ( ) = = RiaEclipseUnitTools : : UNITS_METRIC )
2017-02-14 02:49:14 -06:00
{
2018-01-10 00:44:26 -06:00
m_halfLength . uiCapability ( ) - > setUiName ( " Halflenght X<sub>f</sub> [m] " ) ;
m_height . uiCapability ( ) - > setUiName ( " Height [m] " ) ;
m_width . uiCapability ( ) - > setUiName ( " Width [m] " ) ;
2018-02-08 04:34:18 -06:00
m_wellDiameter . uiCapability ( ) - > setUiName ( " Well Diameter [m] " ) ;
2017-02-14 02:49:14 -06:00
}
2018-02-08 06:57:43 -06:00
else if ( fractureTemplateUnit ( ) = = RiaEclipseUnitTools : : UNITS_FIELD )
2017-02-14 02:49:14 -06:00
{
2018-01-10 00:44:26 -06:00
m_halfLength . uiCapability ( ) - > setUiName ( " Halflenght X<sub>f</sub> [Ft] " ) ;
m_height . uiCapability ( ) - > setUiName ( " Height [Ft] " ) ;
m_width . uiCapability ( ) - > setUiName ( " Width [inches] " ) ;
2018-02-08 04:34:18 -06:00
m_wellDiameter . uiCapability ( ) - > setUiName ( " Well Diameter [inches] " ) ;
2017-02-14 02:49:14 -06:00
}
2017-02-10 03:33:07 -06:00
2018-02-08 04:34:18 -06:00
if ( conductivityType ( ) = = FINITE_CONDUCTIVITY )
2017-06-26 03:43:14 -05:00
{
2018-02-15 08:38:27 -06:00
m_userDefinedEffectivePermeability . uiCapability ( ) - > setUiHidden ( false ) ;
2018-01-10 00:44:26 -06:00
m_width . uiCapability ( ) - > setUiHidden ( false ) ;
2017-06-26 03:43:14 -05:00
}
2018-02-08 04:34:18 -06:00
else if ( conductivityType ( ) = = INFINITE_CONDUCTIVITY )
2017-06-26 03:43:14 -05:00
{
2018-02-15 08:38:27 -06:00
m_userDefinedEffectivePermeability . uiCapability ( ) - > setUiHidden ( true ) ;
2018-01-10 00:44:26 -06:00
m_width . uiCapability ( ) - > setUiHidden ( true ) ;
2017-06-26 03:43:14 -05:00
}
2017-02-14 02:49:14 -06:00
2018-02-08 06:57:43 -06:00
uiOrdering . add ( & m_name ) ;
2016-12-19 04:23:02 -06:00
2017-02-22 04:52:06 -06:00
caf : : PdmUiGroup * geometryGroup = uiOrdering . addNewGroup ( " Geometry " ) ;
2018-01-10 00:44:26 -06:00
geometryGroup - > add ( & m_halfLength ) ;
geometryGroup - > add ( & m_height ) ;
2018-02-08 06:57:43 -06:00
geometryGroup - > add ( & m_orientationType ) ;
2018-02-08 04:34:18 -06:00
geometryGroup - > add ( & m_azimuthAngle ) ;
2016-12-19 04:23:02 -06:00
2017-06-08 15:54:06 -05:00
caf : : PdmUiGroup * trGr = uiOrdering . addNewGroup ( " Fracture Truncation " ) ;
2017-06-09 10:21:59 -05:00
m_fractureContainment ( ) - > defineUiOrdering ( uiConfigName , * trGr ) ;
2017-06-08 15:54:06 -05:00
2017-02-22 04:52:06 -06:00
caf : : PdmUiGroup * propertyGroup = uiOrdering . addNewGroup ( " Properties " ) ;
2018-02-08 04:34:18 -06:00
propertyGroup - > add ( & m_conductivityType ) ;
2018-02-15 08:38:27 -06:00
propertyGroup - > add ( & m_userDefinedEffectivePermeability ) ;
2018-01-10 00:44:26 -06:00
propertyGroup - > add ( & m_width ) ;
2018-02-08 04:34:18 -06:00
propertyGroup - > add ( & m_skinFactor ) ;
propertyGroup - > add ( & m_perforationLength ) ;
propertyGroup - > add ( & m_perforationEfficiency ) ;
propertyGroup - > add ( & m_wellDiameter ) ;
2017-02-22 04:52:06 -06:00
2018-02-09 00:26:48 -06:00
RimFractureTemplate : : defineUiOrdering ( uiConfigName , uiOrdering ) ;
2016-12-19 04:23:02 -06:00
}
2017-02-14 02:49:14 -06:00