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
2017-06-14 00:25:34 -05:00
# include "RiaEclipseUnitTools.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"
2017-01-13 01:58:36 -06:00
# include "RigTesselatorTools.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"
# 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
2017-02-22 04:52:06 -06:00
CAF_PDM_InitField ( & halfLength , " HalfLength " , 650.0f , " Halflength X<sub>f</sub> " , " " , " " , " " ) ;
2017-01-04 04:28:16 -06:00
CAF_PDM_InitField ( & height , " Height " , 75.0f , " Height " , " " , " " , " " ) ;
CAF_PDM_InitField ( & width , " Width " , 1.0f , " Width " , " " , " " , " " ) ;
2017-01-23 01:54:27 -06:00
2017-02-16 08:22:03 -06:00
CAF_PDM_InitField ( & permeability , " Permeability " , 22000.f , " 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 ( ) ;
}
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
2017-04-19 04:00:52 -05:00
if ( changedField = = & halfLength | | changedField = = & height )
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
std : : vector < RimFracture * > fractures ;
proj - > descendantsIncludingThisOfType ( fractures ) ;
for ( RimFracture * fracture : fractures )
{
2017-06-09 10:21:59 -05:00
if ( fracture - > fractureTemplate ( ) = = this )
2017-01-06 06:55:26 -06:00
{
2017-06-12 05:45:09 -05:00
fracture - > clearDisplayGeometryCache ( ) ;
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
}
}
2017-06-01 04:31:34 -05:00
if ( changedField = = & width | | changedField = = & permeability )
{
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 ,
std : : vector < cvf : : uint > * triangleIndices ,
2017-06-14 00:25:34 -05:00
RiaEclipseUnitTools : : UnitSystem neededUnit )
2017-01-13 01:58:36 -06:00
{
RigEllipsisTesselator tesselator ( 20 ) ;
2017-03-02 03:08:45 -06:00
float a = cvf : : UNDEFINED_FLOAT ;
float b = cvf : : UNDEFINED_FLOAT ;
2017-06-09 10:21:59 -05:00
if ( neededUnit = = fractureTemplateUnit ( ) )
2017-03-02 03:08:45 -06:00
{
a = halfLength ;
b = height / 2.0f ;
}
2017-06-14 00:25:34 -05:00
else if ( fractureTemplateUnit ( ) = = RiaEclipseUnitTools : : UNITS_METRIC & & neededUnit = = RiaEclipseUnitTools : : UNITS_FIELD )
2017-03-02 03:08:45 -06:00
{
RiaLogging : : info ( QString ( " Converting fracture template geometry from metric to field " ) ) ;
2017-06-14 00:25:34 -05:00
a = RiaEclipseUnitTools : : meterToFeet ( halfLength ) ;
b = RiaEclipseUnitTools : : meterToFeet ( height / 2.0f ) ;
2017-03-02 03:08:45 -06:00
}
2017-06-14 00:25:34 -05:00
else if ( fractureTemplateUnit ( ) = = RiaEclipseUnitTools : : UNITS_FIELD & & neededUnit = = RiaEclipseUnitTools : : UNITS_METRIC )
2017-03-02 03:08:45 -06:00
{
RiaLogging : : info ( QString ( " Converting fracture template geometry from field to metric " ) ) ;
2017-06-14 00:25:34 -05:00
a = RiaEclipseUnitTools : : feetToMeter ( halfLength ) ;
b = RiaEclipseUnitTools : : feetToMeter ( height / 2.0f ) ;
2017-03-02 03:08:45 -06:00
}
else
{
//Should never get here...
RiaLogging : : error ( QString ( " Error: Could not convert units for fracture / fracture template " ) ) ;
return ;
}
2017-02-10 04:32:18 -06:00
tesselator . tesselateEllipsis ( a , b , triangleIndices , nodeCoords ) ;
2017-01-13 01:58:36 -06:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-06-14 00:25:34 -05:00
std : : vector < cvf : : Vec3f > RimEllipseFractureTemplate : : fractureBorderPolygon ( RiaEclipseUnitTools : : UnitSystem neededUnit )
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
2017-06-09 10:21:59 -05:00
fractureTriangleGeometry ( & nodeCoords , & triangleIndices , neededUnit ) ;
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 ( )
{
2017-06-14 00:25:34 -05:00
if ( fractureTemplateUnit = = RiaEclipseUnitTools : : UNITS_METRIC )
2017-02-14 02:49:14 -06:00
{
2017-06-14 00:25:34 -05:00
halfLength = RiaEclipseUnitTools : : meterToFeet ( halfLength ) ;
height = RiaEclipseUnitTools : : meterToFeet ( height ) ;
width = RiaEclipseUnitTools : : meterToInch ( width ) ;
wellDiameter = RiaEclipseUnitTools : : meterToInch ( wellDiameter ) ;
perforationLength = RiaEclipseUnitTools : : meterToFeet ( perforationLength ) ;
fractureTemplateUnit = RiaEclipseUnitTools : : UNITS_FIELD ;
2017-02-14 02:49:14 -06:00
}
2017-06-14 00:25:34 -05:00
else if ( fractureTemplateUnit = = RiaEclipseUnitTools : : UNITS_FIELD )
2017-02-14 02:49:14 -06:00
{
2017-06-14 00:25:34 -05:00
halfLength = RiaEclipseUnitTools : : feetToMeter ( halfLength ) ;
height = RiaEclipseUnitTools : : feetToMeter ( height ) ;
width = RiaEclipseUnitTools : : inchToMeter ( width ) ;
wellDiameter = RiaEclipseUnitTools : : inchToMeter ( wellDiameter ) ;
perforationLength = RiaEclipseUnitTools : : feetToMeter ( perforationLength ) ;
fractureTemplateUnit = 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
double cellSizeX = ( halfLength * 2 ) / numberOfCellsX ;
double cellSizeZ = height / numberOfCellsY ;
double cellArea = cellSizeX * cellSizeZ ;
double areaTresholdForIncludingCell = 0.5 * cellArea ;
for ( int i = 0 ; i < numberOfCellsX ; i + + )
{
for ( int j = 0 ; j < numberOfCellsX ; j + + )
{
double X1 = - halfLength + i * cellSizeX ;
double X2 = - halfLength + ( i + 1 ) * cellSizeX ;
double Y1 = - height / 2 + j * cellSizeZ ;
double Y2 = - height / 2 + ( j + 1 ) * cellSizeZ ;
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 ) ) ;
double cond = cvf : : UNDEFINED_DOUBLE ;
2017-06-14 00:25:34 -05:00
if ( fractureTemplateUnit = = RiaEclipseUnitTools : : UNITS_METRIC )
2017-06-01 04:31:34 -05:00
{
//Conductivity should be md-m, width is in m
cond = permeability * width ;
}
2017-06-14 00:25:34 -05:00
else if ( fractureTemplateUnit = = RiaEclipseUnitTools : : UNITS_FIELD )
2017-06-01 04:31:34 -05:00
{
//Conductivity should be md-ft, but width is in inches
2017-06-14 00:25:34 -05:00
cond = permeability * RiaEclipseUnitTools : : inchToFeet ( width ) ;
2017-06-01 04:31:34 -05:00
}
2017-06-09 10:21:59 -05:00
std : : vector < cvf : : Vec3f > ellipseFracPolygon = fractureBorderPolygon ( fractureTemplateUnit ( ) ) ;
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 ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RigFractureGrid * RimEllipseFractureTemplate : : fractureGrid ( ) const
{
return m_fractureGrid . p ( ) ;
}
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-10 03:33:07 -06:00
RimFractureTemplate : : defineUiOrdering ( uiConfigName , uiOrdering ) ;
2017-02-14 02:49:14 -06:00
2017-06-14 00:25:34 -05:00
if ( fractureTemplateUnit = = RiaEclipseUnitTools : : UNITS_METRIC )
2017-02-14 02:49:14 -06:00
{
2017-02-22 04:52:06 -06:00
halfLength . uiCapability ( ) - > setUiName ( " Halflenght X<sub>f</sub> [m] " ) ;
2017-02-14 02:49:14 -06:00
height . uiCapability ( ) - > setUiName ( " Height [m] " ) ;
width . uiCapability ( ) - > setUiName ( " Width [m] " ) ;
2017-06-08 02:15:50 -05:00
wellDiameter . uiCapability ( ) - > setUiName ( " Well Diameter [m] " ) ;
2017-02-14 02:49:14 -06:00
}
2017-06-14 00:25:34 -05:00
else if ( fractureTemplateUnit = = RiaEclipseUnitTools : : UNITS_FIELD )
2017-02-14 02:49:14 -06:00
{
2017-02-22 04:52:06 -06:00
halfLength . uiCapability ( ) - > setUiName ( " Halflenght X<sub>f</sub> [Ft] " ) ;
2017-02-14 02:49:14 -06:00
height . uiCapability ( ) - > setUiName ( " Height [Ft] " ) ;
width . uiCapability ( ) - > setUiName ( " Width [inches] " ) ;
2017-06-08 02:15:50 -05:00
wellDiameter . uiCapability ( ) - > setUiName ( " Well Diameter [inches] " ) ;
2017-02-14 02:49:14 -06:00
}
2017-02-10 03:33:07 -06:00
2017-06-26 03:43:14 -05:00
if ( conductivityType = = FINITE_CONDUCTIVITY )
{
permeability . uiCapability ( ) - > setUiHidden ( false ) ;
width . uiCapability ( ) - > setUiHidden ( false ) ;
}
else if ( conductivityType = = INFINITE_CONDUCTIVITY )
{
permeability . uiCapability ( ) - > setUiHidden ( true ) ;
width . uiCapability ( ) - > setUiHidden ( true ) ;
}
2017-02-14 02:49:14 -06:00
2016-12-19 04:23:02 -06:00
uiOrdering . add ( & name ) ;
2017-02-22 04:52:06 -06:00
caf : : PdmUiGroup * geometryGroup = uiOrdering . addNewGroup ( " Geometry " ) ;
2016-12-19 04:23:02 -06:00
geometryGroup - > add ( & halfLength ) ;
geometryGroup - > add ( & height ) ;
2017-06-09 10:21:59 -05:00
geometryGroup - > add ( & orientationType ) ;
2017-01-23 01:54:27 -06:00
geometryGroup - > add ( & 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 " ) ;
2017-06-09 10:21:59 -05:00
propertyGroup - > add ( & conductivityType ) ;
2017-06-26 03:43:14 -05:00
propertyGroup - > add ( & permeability ) ;
propertyGroup - > add ( & width ) ;
2017-02-06 06:51:13 -06:00
propertyGroup - > add ( & skinFactor ) ;
propertyGroup - > add ( & perforationLength ) ;
2017-04-19 04:00:52 -05:00
propertyGroup - > add ( & perforationEfficiency ) ;
2017-06-08 02:15:50 -05:00
propertyGroup - > add ( & wellDiameter ) ;
2017-02-22 04:52:06 -06:00
uiOrdering . add ( & fractureTemplateUnit ) ;
2017-04-03 00:34:56 -05:00
uiOrdering . skipRemainingFields ( true ) ;
2016-12-19 04:23:02 -06:00
}
2017-02-14 02:49:14 -06:00