2017-01-02 07:13:34 -06: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 "RimFracture.h"
2017-01-19 03:43:23 -06:00
# include "RiaApplication.h"
2017-01-30 03:45:18 -06:00
# include "RifReaderInterface.h"
2017-01-31 08:58:13 -06:00
# include "RigActiveCellInfo.h"
2017-01-30 03:45:18 -06:00
# include "RigCaseCellResultsData.h"
2017-01-19 03:43:23 -06:00
# include "RigCell.h"
2017-01-23 08:22:51 -06:00
# include "RigCellGeometryTools.h"
2017-01-30 03:45:18 -06:00
# include "RigEclipseCaseData.h"
2017-01-04 01:10:02 -06:00
# include "RigFracture.h"
2017-01-19 03:43:23 -06:00
# include "RigMainGrid.h"
2017-01-30 03:45:18 -06:00
# include "RigResultAccessor.h"
# include "RigResultAccessorFactory.h"
2017-01-04 01:10:02 -06:00
# include "RigTesselatorTools.h"
2017-01-10 06:37:50 -06:00
2017-01-30 03:45:18 -06:00
# include "RimEclipseCase.h"
# include "RimEclipseCellColors.h"
2017-01-19 03:43:23 -06:00
# include "RimEclipseView.h"
2017-01-12 06:29:18 -06:00
# include "RimEllipseFractureTemplate.h"
2017-02-07 04:08:56 -06:00
# include "RimFractureTemplateCollection.h"
2017-01-19 03:43:23 -06:00
# include "RimOilField.h"
# include "RimProject.h"
2017-01-31 08:58:13 -06:00
# include "RimReservoirCellResultsStorage.h"
2017-02-15 05:16:01 -06:00
# include "RimStimPlanFractureTemplate.h"
2017-01-10 06:37:50 -06:00
# include "RimView.h"
2017-01-19 03:43:23 -06:00
# include "RivWellFracturePartMgr.h"
# include "cafHexGridIntersectionTools/cafHexGridIntersectionTools.h"
2017-02-15 04:29:44 -06:00
# include "cafPdmUiDoubleSliderEditor.h"
# include "cafPdmUiTreeOrdering.h"
2017-01-02 07:13:34 -06:00
2017-01-19 03:43:23 -06:00
# include "cvfBoundingBox.h"
# include "cvfGeometryTools.h"
2017-01-11 07:32:15 -06:00
# include "cvfMath.h"
2017-01-10 06:37:50 -06:00
# include "cvfMatrix4.h"
2017-01-13 08:49:21 -06:00
# include "cvfPlane.h"
2017-01-19 03:43:23 -06:00
2017-01-24 08:39:39 -06:00
# include "clipper/clipper.hpp"
2017-01-30 03:45:18 -06:00
# include <math.h>
2017-02-15 04:29:44 -06:00
2017-02-10 06:29:31 -06:00
# include <QDebug>
2017-02-15 05:16:01 -06:00
# include <QString>
2017-01-02 07:13:34 -06:00
2017-01-04 01:10:02 -06:00
CAF_PDM_XML_ABSTRACT_SOURCE_INIT ( RimFracture , " Fracture " ) ;
2017-01-02 07:13:34 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFracture : : RimFracture ( void )
{
CAF_PDM_InitObject ( " Fracture " , " " , " " , " " ) ;
2017-01-19 03:43:23 -06:00
CAF_PDM_InitFieldNoDefault ( & m_fractureTemplate , " FractureDef " , " Fracture Template " , " " , " " , " " ) ;
CAF_PDM_InitFieldNoDefault ( & m_anchorPosition , " anchorPosition " , " Anchor Position " , " " , " " , " " ) ;
m_anchorPosition . uiCapability ( ) - > setUiHidden ( true ) ;
2017-01-19 06:35:07 -06:00
CAF_PDM_InitFieldNoDefault ( & m_uiAnchorPosition , " ui_positionAtWellpath " , " Fracture Position " , " " , " " , " " ) ;
2017-01-19 03:43:23 -06:00
m_uiAnchorPosition . registerGetMethod ( this , & RimFracture : : fracturePositionForUi ) ;
m_uiAnchorPosition . uiCapability ( ) - > setUiReadOnly ( true ) ;
2017-01-10 03:53:54 -06:00
CAF_PDM_InitField ( & azimuth , " Azimuth " , 0.0 , " Azimuth " , " " , " " , " " ) ;
2017-02-15 05:16:01 -06:00
azimuth . uiCapability ( ) - > setUiEditorTypeName ( caf : : PdmUiDoubleSliderEditor : : uiEditorTypeName ( ) ) ;
2017-02-22 04:52:06 -06:00
CAF_PDM_InitField ( & perforationLength , " PerforationLength " , 0.0 , " Perforation Length " , " " , " " , " " ) ;
2017-01-23 01:54:27 -06:00
2017-02-22 04:52:06 -06:00
CAF_PDM_InitField ( & stimPlanTimeIndexToPlot , " timeIndexToPlot " , 0 , " StimPlan Time Step " , " " , " " , " " ) ;
2017-01-10 03:53:54 -06:00
2017-01-19 03:43:23 -06:00
CAF_PDM_InitField ( & m_i , " I " , 1 , " Fracture location cell I " , " " , " " , " " ) ;
m_i . uiCapability ( ) - > setUiHidden ( true ) ;
CAF_PDM_InitField ( & m_j , " J " , 1 , " Fracture location cell J " , " " , " " , " " ) ;
m_j . uiCapability ( ) - > setUiHidden ( true ) ;
CAF_PDM_InitField ( & m_k , " K " , 1 , " Fracture location cell K " , " " , " " , " " ) ;
m_k . uiCapability ( ) - > setUiHidden ( true ) ;
CAF_PDM_InitFieldNoDefault ( & m_displayIJK , " Cell_IJK " , " Cell IJK " , " " , " " , " " ) ;
m_displayIJK . registerGetMethod ( this , & RimFracture : : createOneBasedIJK ) ;
m_displayIJK . uiCapability ( ) - > setUiReadOnly ( true ) ;
2017-01-04 01:10:02 -06:00
m_rigFracture = new RigFracture ;
2017-01-06 06:13:25 -06:00
m_recomputeGeometry = true ;
2017-01-19 00:28:04 -06:00
m_rivFracture = new RivWellFracturePartMgr ( this ) ;
2017-01-02 07:13:34 -06:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFracture : : ~ RimFracture ( )
{
}
2017-01-04 01:10:02 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-01-12 03:24:01 -06:00
const std : : vector < cvf : : uint > & RimFracture : : triangleIndices ( ) const
2017-01-04 01:10:02 -06:00
{
2017-01-12 03:24:01 -06:00
return m_rigFracture - > triangleIndices ( ) ;
2017-01-04 01:10:02 -06:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std : : vector < cvf : : Vec3f > & RimFracture : : nodeCoords ( ) const
{
return m_rigFracture - > nodeCoords ( ) ;
}
2017-01-12 05:19:52 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : vector < size_t > RimFracture : : getPotentiallyFracturedCells ( )
{
std : : vector < size_t > cellindecies ;
RiaApplication * app = RiaApplication : : instance ( ) ;
RimView * activeView = RiaApplication : : instance ( ) - > activeReservoirView ( ) ;
if ( ! activeView ) return cellindecies ;
RimEclipseView * activeRiv = dynamic_cast < RimEclipseView * > ( activeView ) ;
if ( ! activeRiv ) return cellindecies ;
const RigMainGrid * mainGrid = activeRiv - > mainGrid ( ) ;
if ( ! mainGrid ) return cellindecies ;
const std : : vector < cvf : : Vec3f > & nodeCoordVec = nodeCoords ( ) ;
if ( ! hasValidGeometry ( ) ) computeGeometry ( ) ;
cvf : : BoundingBox polygonBBox ;
for ( cvf : : Vec3f nodeCoord : nodeCoordVec ) polygonBBox . add ( nodeCoord ) ;
mainGrid - > findIntersectingCells ( polygonBBox , & cellindecies ) ;
return cellindecies ;
}
2017-01-10 06:37:50 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture : : fieldChangedByUi ( const caf : : PdmFieldHandle * changedField , const QVariant & oldValue , const QVariant & newValue )
{
2017-01-23 02:46:33 -06:00
if ( changedField = = & m_fractureTemplate )
{
2017-02-07 02:09:00 -06:00
//perforationLength = m_fractureTemplate->perforationLength();
//TODO: Find out if performationLength should be in RimFractureTemplate or in RimEllipseFracTemplate
2017-02-17 02:32:45 -06:00
if ( attachedFractureDefinition ( ) ) azimuth = m_fractureTemplate - > azimuthAngle ( ) ;
else azimuth = 0.0 ;
2017-02-20 08:39:48 -06:00
setAzimuth ( ) ;
2017-01-23 02:46:33 -06:00
}
2017-01-19 03:43:23 -06:00
if ( changedField = = & azimuth | |
2017-02-15 08:49:53 -06:00
changedField = = & m_fractureTemplate | |
changedField = = & stimPlanTimeIndexToPlot )
2017-01-10 06:37:50 -06:00
{
2017-01-23 01:54:27 -06:00
2017-01-19 03:43:23 -06:00
setRecomputeGeometryFlag ( ) ;
2017-01-10 06:37:50 -06:00
RimView * rimView = nullptr ;
this - > firstAncestorOrThisOfType ( rimView ) ;
if ( rimView )
{
rimView - > createDisplayModelAndRedraw ( ) ;
}
2017-01-19 03:43:23 -06:00
else
{
// Can be triggered from well path, find active view
RimView * activeView = RiaApplication : : instance ( ) - > activeReservoirView ( ) ;
if ( activeView )
{
activeView - > createDisplayModelAndRedraw ( ) ;
}
}
2017-01-23 01:54:27 -06:00
2017-01-10 06:37:50 -06:00
}
2017-01-23 01:54:27 -06:00
2017-01-10 06:37:50 -06:00
}
2017-01-19 06:35:07 -06:00
//--------------------------------------------------------------------------------------------------
2017-02-06 04:44:24 -06:00
///
//--------------------------------------------------------------------------------------------------
cvf : : Vec3d RimFracture : : fracturePosition ( ) const
{
return m_anchorPosition ;
}
2017-01-04 01:10:02 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture : : computeGeometry ( )
{
std : : vector < cvf : : Vec3f > nodeCoords ;
2017-02-10 04:32:18 -06:00
std : : vector < cvf : : uint > triangleIndices ;
2017-01-04 01:10:02 -06:00
2017-02-07 02:09:00 -06:00
RimFractureTemplate * fractureDef = attachedFractureDefinition ( ) ;
2017-01-12 06:29:18 -06:00
if ( fractureDef )
2017-01-04 01:10:02 -06:00
{
2017-02-10 04:32:18 -06:00
fractureDef - > fractureGeometry ( & nodeCoords , & triangleIndices ) ;
2017-01-12 03:52:47 -06:00
}
cvf : : Mat4f m = transformMatrix ( ) ;
2017-01-04 01:10:02 -06:00
2017-01-12 03:52:47 -06:00
for ( cvf : : Vec3f & v : nodeCoords )
{
v . transformPoint ( m ) ;
2017-01-04 01:10:02 -06:00
}
2017-02-10 04:32:18 -06:00
m_rigFracture - > setGeometry ( triangleIndices , nodeCoords ) ;
2017-01-12 03:52:47 -06:00
m_recomputeGeometry = false ;
}
2017-01-19 03:43:23 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf : : Vec3d RimFracture : : anchorPosition ( )
{
return m_anchorPosition ( ) ;
}
2017-01-12 03:52:47 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf : : Mat4f RimFracture : : transformMatrix ( )
{
2017-01-19 03:43:23 -06:00
cvf : : Vec3d center = anchorPosition ( ) ;
2017-01-12 03:52:47 -06:00
2017-01-10 06:37:50 -06:00
// Ellipsis geometry is produced in XY-plane, rotate 90 deg around X to get zero azimuth along Y
cvf : : Mat4f rotationFromTesselator = cvf : : Mat4f : : fromRotation ( cvf : : Vec3f : : X_AXIS , cvf : : Math : : toRadians ( 90.0f ) ) ;
2017-02-01 03:49:50 -06:00
2017-01-10 06:37:50 -06:00
// Azimuth rotation
2017-02-02 03:02:27 -06:00
cvf : : Mat4f azimuthRotation = cvf : : Mat4f : : fromRotation ( cvf : : Vec3f : : Z_AXIS , cvf : : Math : : toRadians ( - azimuth ( ) - 90 ) ) ;
2017-01-10 06:37:50 -06:00
cvf : : Mat4f m = azimuthRotation * rotationFromTesselator ;
m . setTranslation ( cvf : : Vec3f ( center ) ) ;
2017-01-12 03:52:47 -06:00
return m ;
}
2017-01-04 01:10:02 -06:00
2017-01-06 06:13:25 -06:00
2017-01-10 08:29:38 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-02-02 01:46:05 -06:00
void RimFracture : : computeTransmissibility ( RimEclipseCase * caseToApply )
2017-01-11 07:32:15 -06:00
{
2017-02-10 06:29:31 -06:00
//TODO: Handle case with finite conductivity in fracture
if ( attachedFractureDefinition ( ) )
{
if ( attachedFractureDefinition ( ) - > fractureConductivity = = RimFractureTemplate : : FINITE_CONDUCTIVITY )
{
qDebug ( ) < < " Transimssibility for finite conductity in fracture not yet implemented. " ;
qDebug ( ) < < " Performing calculation for infinite conductivity instead. " ;
}
}
2017-02-02 01:46:05 -06:00
RigEclipseCaseData * eclipseCaseData = caseToApply - > reservoirData ( ) ;
2017-01-31 05:32:59 -06:00
2017-02-02 01:46:05 -06:00
RifReaderInterface : : PorosityModelResultType porosityModel = RifReaderInterface : : MATRIX_RESULTS ;
RimReservoirCellResultsStorage * gridCellResults = caseToApply - > results ( porosityModel ) ;
2017-01-31 05:32:59 -06: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 ) ;
2017-01-10 08:29:38 -06:00
std : : vector < RigFractureData > fracDataVec ;
2017-01-12 05:19:52 -06:00
std : : vector < size_t > fracCells = getPotentiallyFracturedCells ( ) ;
2017-01-27 03:46:45 -06:00
for ( size_t fracCell : fracCells )
2017-01-10 08:29:38 -06:00
{
2017-01-31 05:26:30 -06:00
bool cellIsActive = activeCellInfo - > isActive ( fracCell ) ;
2017-01-30 03:45:18 -06:00
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 ) ;
2017-02-03 07:56:30 -06:00
double NTG = dataAccessObjectNTG - > cellScalarGlobIdx ( fracCell ) ;
2017-01-16 07:50:25 -06:00
2017-01-24 05:15:26 -06:00
cvf : : Vec3d localX ;
cvf : : Vec3d localY ;
cvf : : Vec3d localZ ;
2017-01-26 02:06:18 -06:00
std : : vector < std : : vector < cvf : : Vec3d > > planeCellPolygons ;
2017-01-24 05:15:26 -06:00
bool isPlanIntersected = planeCellIntersectionPolygons ( fracCell , planeCellPolygons , localX , localY , localZ ) ;
2017-01-16 07:50:25 -06:00
if ( ! isPlanIntersected | | planeCellPolygons . size ( ) = = 0 ) continue ;
2017-01-13 08:49:21 -06:00
2017-01-24 05:15:26 -06:00
//Transform planCell polygon(s) and averageZdirection to x/y coordinate system (where fracturePolygon already is located)
2017-01-23 06:48:19 -06:00
cvf : : Mat4f invertedTransMatrix = transformMatrix ( ) . getInverted ( ) ;
2017-01-23 08:22:51 -06:00
for ( std : : vector < cvf : : Vec3d > & planeCellPolygon : planeCellPolygons )
2017-01-23 06:48:19 -06:00
{
for ( cvf : : Vec3d & v : planeCellPolygon )
{
v . transformPoint ( static_cast < cvf : : Mat4d > ( invertedTransMatrix ) ) ;
}
}
2017-01-26 02:06:18 -06:00
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 ) ) ;
2017-01-27 03:46:45 -06:00
directionOfLength . normalize ( ) ;
2017-01-24 05:15:26 -06:00
2017-01-11 07:32:15 -06:00
RigFractureData fracData ;
2017-01-12 05:19:52 -06:00
fracData . reservoirCellIndex = fracCell ;
2017-01-10 08:29:38 -06:00
2017-01-11 07:32:15 -06:00
double transmissibility ;
2017-01-27 03:46:45 -06:00
double fractureArea = 0.0 ;
double fractureAreaWeightedlength = 0.0 ;
double Ax = 0.0 ;
double Ay = 0.0 ;
double Az = 0.0 ;
2017-01-30 03:45:18 -06:00
double skinfactor = 0.0 ;
2017-01-30 07:47:56 -06:00
double transmissibility_X = 0.0 ;
double transmissibility_Y = 0.0 ;
double transmissibility_Z = 0.0 ;
2017-01-16 07:50:25 -06:00
2017-01-11 07:32:15 -06:00
if ( attachedFractureDefinition ( ) )
{
2017-01-16 07:50:25 -06:00
std : : vector < cvf : : Vec3f > fracPolygon = attachedFractureDefinition ( ) - > fracturePolygon ( ) ;
2017-01-23 06:48:19 -06:00
2017-01-26 03:28:15 -06:00
std : : vector < cvf : : Vec3d > fracPolygonDouble ;
for ( auto v : fracPolygon ) fracPolygonDouble . push_back ( static_cast < cvf : : Vec3d > ( v ) ) ;
2017-01-26 02:06:18 -06:00
2017-01-26 03:28:15 -06:00
std : : vector < std : : vector < cvf : : Vec3d > > polygonsDescribingFractureInCell ;
cvf : : Vec3d areaVector ;
2017-01-26 04:40:50 -06:00
for ( std : : vector < cvf : : Vec3d > planeCellPolygon : planeCellPolygons )
2017-01-26 02:06:18 -06:00
{
2017-01-26 03:28:15 -06:00
std : : vector < std : : vector < cvf : : Vec3d > > clippedPolygons = RigCellGeometryTools : : clipPolygons ( planeCellPolygon , fracPolygonDouble ) ;
2017-01-26 04:40:50 -06:00
for ( std : : vector < cvf : : Vec3d > clippedPolygon : clippedPolygons )
2017-01-26 03:28:15 -06:00
{
polygonsDescribingFractureInCell . push_back ( clippedPolygon ) ;
}
2017-01-26 02:06:18 -06:00
}
2017-01-26 03:28:15 -06:00
double area ;
std : : vector < double > areaOfFractureParts ;
double length ;
std : : vector < double > lengthXareaOfFractureParts ;
2017-01-26 04:40:50 -06:00
for ( std : : vector < cvf : : Vec3d > fracturePartPolygon : polygonsDescribingFractureInCell )
2017-01-26 03:28:15 -06:00
{
areaVector = cvf : : GeometryTools : : polygonAreaNormal3D ( fracturePartPolygon ) ;
area = areaVector . length ( ) ;
areaOfFractureParts . push_back ( area ) ;
length = RigCellGeometryTools : : polygonAreaWeightedLength ( directionOfLength , fracturePartPolygon ) ;
lengthXareaOfFractureParts . push_back ( length * area ) ;
2017-01-27 03:46:45 -06:00
cvf : : Plane fracturePlane ;
cvf : : Mat4f m = transformMatrix ( ) ;
bool isCellIntersected = false ;
2017-01-26 04:40:50 -06:00
2017-01-27 03:46:45 -06:00
fracturePlane . setFromPointAndNormal ( static_cast < cvf : : Vec3d > ( m . translation ( ) ) ,
static_cast < cvf : : Vec3d > ( m . col ( 2 ) ) ) ;
2017-01-26 04:40:50 -06:00
2017-01-27 05:11:24 -06:00
Ax + = abs ( area * ( fracturePlane . normal ( ) . dot ( localY ) ) ) ;
Ay + = abs ( area * ( fracturePlane . normal ( ) . dot ( localX ) ) ) ;
Az + = abs ( area * ( fracturePlane . normal ( ) . dot ( localZ ) ) ) ;
2017-01-30 03:45:18 -06:00
//TODO: resulting values have only been checked for vertical fracture...
2017-01-26 03:28:15 -06:00
}
2017-01-27 03:46:45 -06:00
fractureArea = 0.0 ;
for ( double area : areaOfFractureParts ) fractureArea + = area ;
2017-01-26 03:28:15 -06:00
double totalAreaXLength = 0.0 ;
for ( double lengtXarea : lengthXareaOfFractureParts ) totalAreaXLength + = lengtXarea ;
2017-01-30 07:47:56 -06:00
fractureAreaWeightedlength = totalAreaXLength / fractureArea ;
2017-01-26 02:06:18 -06:00
double c = 0.008527 ; // TODO: Get value with units, is defined in RimReservoirCellResultsStorage
2017-02-03 07:10:33 -06:00
skinfactor = attachedFractureDefinition ( ) - > skinFactor ;
2017-01-27 05:11:24 -06:00
2017-01-30 03:45:18 -06:00
double slDivPi = ( skinfactor * fractureAreaWeightedlength ) / cvf : : PI_D ;
2017-01-27 05:11:24 -06:00
2017-01-30 07:47:56 -06:00
transmissibility_X = 8 * c * ( permY * NTG ) * Ay / ( dx + slDivPi ) ;
transmissibility_Y = 8 * c * ( permX * NTG ) * Ax / ( dy + slDivPi ) ;
transmissibility_Z = 8 * c * permZ * Az / ( dz + slDivPi ) ;
2017-01-30 03:45:18 -06:00
transmissibility = sqrt ( transmissibility_X * transmissibility_X
+ transmissibility_Y * transmissibility_Y
+ transmissibility_Z * transmissibility_Z ) ;
}
else
{
transmissibility = cvf : : UNDEFINED_DOUBLE ;
2017-01-11 07:32:15 -06:00
}
2017-01-30 03:45:18 -06:00
2017-01-27 03:46:45 -06:00
2017-01-11 07:32:15 -06:00
fracData . transmissibility = transmissibility ;
2017-01-30 07:47:56 -06:00
fracData . transmissibilities = cvf : : Vec3d ( transmissibility_X , transmissibility_Y , transmissibility_Z ) ;
2017-01-30 03:45:18 -06:00
2017-01-27 03:46:45 -06:00
fracData . totalArea = fractureArea ;
fracData . projectedAreas = cvf : : Vec3d ( Ax , Ay , Az ) ;
2017-01-27 05:11:24 -06:00
fracData . fractureLenght = fractureAreaWeightedlength ;
2017-01-30 03:45:18 -06:00
fracData . cellSizes = cvf : : Vec3d ( dx , dy , dz ) ;
fracData . permeabilities = cvf : : Vec3d ( permX , permY , permZ ) ;
fracData . NTG = NTG ;
fracData . skinFactor = skinfactor ;
2017-01-31 05:26:30 -06:00
fracData . cellIsActive = cellIsActive ;
2017-01-27 03:46:45 -06:00
2017-01-31 03:31:28 -06:00
//Since we loop over all potentially fractured cells, we only keep FractureData for cells where fracture have an non-zero area.
2017-01-31 05:26:30 -06:00
if ( fractureArea > 1e-5 )
2017-01-31 03:31:28 -06:00
{
fracDataVec . push_back ( fracData ) ;
}
2017-01-20 02:39:44 -06:00
2017-01-10 08:29:38 -06:00
}
m_rigFracture - > setFractureData ( fracDataVec ) ;
}
2017-01-13 08:49:21 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-01-24 05:15:26 -06:00
bool RimFracture : : planeCellIntersectionPolygons ( size_t cellindex , std : : vector < std : : vector < cvf : : Vec3d > > & polygons ,
cvf : : Vec3d & localX , cvf : : Vec3d & localY , cvf : : Vec3d & localZ )
2017-01-13 08:49:21 -06:00
{
2017-01-16 07:50:25 -06:00
2017-01-13 08:49:21 -06:00
cvf : : Plane fracturePlane ;
cvf : : Mat4f m = transformMatrix ( ) ;
bool isCellIntersected = false ;
fracturePlane . setFromPointAndNormal ( static_cast < cvf : : Vec3d > ( m . translation ( ) ) ,
static_cast < cvf : : Vec3d > ( m . col ( 2 ) ) ) ;
RiaApplication * app = RiaApplication : : instance ( ) ;
RimView * activeView = RiaApplication : : instance ( ) - > activeReservoirView ( ) ;
if ( ! activeView ) return isCellIntersected ;
RimEclipseView * activeRiv = dynamic_cast < RimEclipseView * > ( activeView ) ;
if ( ! activeRiv ) return isCellIntersected ;
const RigMainGrid * mainGrid = activeRiv - > mainGrid ( ) ;
if ( ! mainGrid ) return isCellIntersected ;
RigCell cell = mainGrid - > globalCellArray ( ) [ cellindex ] ;
if ( cell . isInvalid ( ) ) return isCellIntersected ;
2017-01-20 02:39:44 -06:00
if ( cellindex = = 186234 )
{
cvf : : Vec3d cellcenter = cell . center ( ) ;
}
2017-01-13 08:49:21 -06:00
//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 ;
2017-01-20 07:31:22 -06:00
2017-01-23 08:22:51 -06:00
isCellIntersected = RigCellGeometryTools : : planeHexCellIntersection ( hexCorners , fracturePlane , intersectionLineSegments ) ;
2017-01-20 07:31:22 -06:00
2017-01-23 08:22:51 -06:00
RigCellGeometryTools : : createPolygonFromLineSegments ( intersectionLineSegments , polygons ) ;
2017-01-20 07:31:22 -06:00
2017-01-24 05:15:26 -06:00
RigCellGeometryTools : : findCellLocalXYZ ( hexCorners , localX , localY , localZ ) ;
2017-01-20 07:31:22 -06:00
return isCellIntersected ;
}
2017-01-06 06:13:25 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture : : setRecomputeGeometryFlag ( )
{
m_recomputeGeometry = true ;
2017-01-19 00:28:04 -06:00
m_rivFracture - > clearGeometryCache ( ) ;
2017-01-06 06:13:25 -06:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFracture : : isRecomputeGeometryFlagSet ( )
{
return m_recomputeGeometry ;
2017-01-04 01:10:02 -06:00
}
2017-01-19 03:43:23 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf : : Vec3d RimFracture : : fracturePositionForUi ( ) const
{
cvf : : Vec3d v = m_anchorPosition ;
v . z ( ) = - v . z ( ) ;
return v ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFracture : : createOneBasedIJK ( ) const
{
2017-01-19 06:35:07 -06:00
return QString ( " Cell : [%1, %2, %3] " ) . arg ( m_i + 1 ) . arg ( m_j + 1 ) . arg ( m_k + 1 ) ;
2017-01-19 03:43:23 -06:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList < caf : : PdmOptionItemInfo > RimFracture : : calculateValueOptions ( const caf : : PdmFieldHandle * fieldNeedingOptions , bool * useOptionsOnly )
{
QList < caf : : PdmOptionItemInfo > options ;
RimProject * proj = RiaApplication : : instance ( ) - > project ( ) ;
CVF_ASSERT ( proj ) ;
RimOilField * oilField = proj - > activeOilField ( ) ;
if ( oilField = = nullptr ) return options ;
if ( fieldNeedingOptions = = & m_fractureTemplate )
{
2017-02-07 04:08:56 -06:00
RimFractureTemplateCollection * fracDefColl = oilField - > fractureDefinitionCollection ( ) ;
2017-01-19 03:43:23 -06:00
if ( fracDefColl = = nullptr ) return options ;
2017-02-07 02:09:00 -06:00
for ( RimFractureTemplate * fracDef : fracDefColl - > fractureDefinitions ( ) )
2017-01-19 03:43:23 -06:00
{
options . push_back ( caf : : PdmOptionItemInfo ( fracDef - > name ( ) , fracDef ) ) ;
}
}
2017-02-15 05:16:01 -06:00
else if ( fieldNeedingOptions = = & stimPlanTimeIndexToPlot )
{
if ( attachedFractureDefinition ( ) )
{
RimFractureTemplate * fracTemplate = attachedFractureDefinition ( ) ;
if ( dynamic_cast < RimStimPlanFractureTemplate * > ( fracTemplate ) )
{
RimStimPlanFractureTemplate * fracTemplateStimPlan = dynamic_cast < RimStimPlanFractureTemplate * > ( fracTemplate ) ;
std : : vector < double > timeValues = fracTemplateStimPlan - > getStimPlanTimeValues ( ) ;
int index = 0 ;
for ( double value : timeValues )
{
options . push_back ( caf : : PdmOptionItemInfo ( QString : : number ( value ) , index ) ) ;
index + + ;
}
}
}
}
2017-01-19 03:43:23 -06:00
return options ;
}
2017-01-10 03:53:54 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture : : defineUiOrdering ( QString uiConfigName , caf : : PdmUiOrdering & uiOrdering )
{
2017-01-19 03:43:23 -06:00
2017-02-15 05:16:01 -06:00
if ( attachedFractureDefinition ( ) )
{
if ( attachedFractureDefinition ( ) - > orientation = = RimFractureTemplate : : ALONG_WELL_PATH
| | attachedFractureDefinition ( ) - > orientation = = RimFractureTemplate : : TRANSVERSE_WELL_PATH )
{
azimuth . uiCapability ( ) - > setUiReadOnly ( true ) ;
}
else if ( attachedFractureDefinition ( ) - > orientation = = RimFractureTemplate : : AZIMUTH )
{
azimuth . uiCapability ( ) - > setUiReadOnly ( false ) ;
}
RimFractureTemplate * fracTemplate = attachedFractureDefinition ( ) ;
if ( dynamic_cast < RimStimPlanFractureTemplate * > ( fracTemplate ) )
{
stimPlanTimeIndexToPlot . uiCapability ( ) - > setUiHidden ( false ) ;
}
else
{
stimPlanTimeIndexToPlot . uiCapability ( ) - > setUiHidden ( true ) ;
}
}
else
{
stimPlanTimeIndexToPlot . uiCapability ( ) - > setUiHidden ( true ) ;
}
2017-01-10 03:53:54 -06:00
}
2017-01-10 06:37:50 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture : : defineEditorAttribute ( const caf : : PdmFieldHandle * field , QString uiConfigName , caf : : PdmUiEditorAttribute * attribute )
{
if ( field = = & azimuth )
{
caf : : PdmUiDoubleSliderEditorAttribute * myAttr = dynamic_cast < caf : : PdmUiDoubleSliderEditorAttribute * > ( attribute ) ;
if ( myAttr )
{
myAttr - > m_minimum = 0 ;
myAttr - > m_maximum = 360 ;
}
}
}
2017-01-19 03:43:23 -06:00
//--------------------------------------------------------------------------------------------------
2017-02-15 04:29:44 -06:00
///
//--------------------------------------------------------------------------------------------------
void RimFracture : : defineUiTreeOrdering ( caf : : PdmUiTreeOrdering & uiTreeOrdering , QString uiConfigName /*= ""*/ )
{
}
//--------------------------------------------------------------------------------------------------
2017-01-19 03:43:23 -06:00
///
//--------------------------------------------------------------------------------------------------
void RimFracture : : setAnchorPosition ( const cvf : : Vec3d & pos )
{
m_anchorPosition = pos ;
setRecomputeGeometryFlag ( ) ;
// Update ijk
{
std : : vector < size_t > cellindecies ;
RiaApplication * app = RiaApplication : : instance ( ) ;
RimView * activeView = RiaApplication : : instance ( ) - > activeReservoirView ( ) ;
if ( ! activeView ) return ;
RimEclipseView * activeRiv = dynamic_cast < RimEclipseView * > ( activeView ) ;
if ( ! activeRiv ) return ;
const RigMainGrid * mainGrid = activeRiv - > mainGrid ( ) ;
if ( ! mainGrid ) return ;
cvf : : BoundingBox polygonBBox ;
polygonBBox . add ( m_anchorPosition ) ;
mainGrid - > findIntersectingCells ( polygonBBox , & cellindecies ) ;
if ( cellindecies . size ( ) > 0 )
{
size_t i = cvf : : UNDEFINED_SIZE_T ;
size_t j = cvf : : UNDEFINED_SIZE_T ;
size_t k = cvf : : UNDEFINED_SIZE_T ;
size_t gridCellIndex = cellindecies [ 0 ] ;
if ( mainGrid - > ijkFromCellIndex ( gridCellIndex , & i , & j , & k ) )
{
m_i = static_cast < int > ( i ) ;
m_j = static_cast < int > ( j ) ;
m_k = static_cast < int > ( k ) ;
}
}
}
}
2017-01-10 08:29:38 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-01-19 00:42:33 -06:00
const RigFracture * RimFracture : : attachedRigFracture ( ) const
2017-01-10 08:29:38 -06:00
{
2017-01-19 00:42:33 -06:00
CVF_ASSERT ( m_rigFracture . notNull ( ) ) ;
return m_rigFracture . p ( ) ;
2017-01-10 08:29:38 -06:00
}
2017-01-19 03:43:23 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-02-07 02:09:00 -06:00
void RimFracture : : setFractureTemplate ( RimFractureTemplate * fractureTemplate )
2017-01-19 03:43:23 -06:00
{
m_fractureTemplate = fractureTemplate ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-02-07 02:09:00 -06:00
RimFractureTemplate * RimFracture : : attachedFractureDefinition ( ) const
2017-01-19 03:43:23 -06:00
{
return m_fractureTemplate ( ) ;
}
2017-01-19 00:28:04 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivWellFracturePartMgr * RimFracture : : fracturePartManager ( )
{
CVF_ASSERT ( m_rivFracture . notNull ( ) ) ;
return m_rivFracture . p ( ) ;
}
2017-02-16 02:15:23 -06:00
2017-01-04 01:10:02 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFracture : : hasValidGeometry ( ) const
{
2017-01-06 06:13:25 -06:00
if ( m_recomputeGeometry ) return false ;
2017-01-12 03:24:01 -06:00
return ( nodeCoords ( ) . size ( ) > 0 & & triangleIndices ( ) . size ( ) > 0 ) ;
2017-01-04 01:10:02 -06:00
}