Bubble plot (#5452)

Bubble plot issues #5209 #2285 #5308 

Co-authored-by: Kristian Bendiksen <kristian.bendiksen@gmail.com>
This commit is contained in:
Magne Sjaastad
2020-02-03 12:20:35 +01:00
committed by GitHub
parent cf72ce5989
commit 7148bd73ae
23 changed files with 1828 additions and 64 deletions

View File

@@ -34,6 +34,7 @@
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSimWellInView.h"
#include "RimSimWellInViewTools.h"
#include "RimSummaryCaseMainCollection.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveAppearanceCalculator.h"
@@ -58,7 +59,7 @@ bool RicPlotProductionRateFeature::isCommandEnabled()
for ( RimSimWellInView* well : collection )
{
RimGridSummaryCase* gridSummaryCase = RicPlotProductionRateFeature::gridSummaryCaseForWell( well );
RimGridSummaryCase* gridSummaryCase = RimSimWellInViewTools::gridSummaryCaseForWell( well );
if ( gridSummaryCase )
{
return true;
@@ -90,12 +91,12 @@ void RicPlotProductionRateFeature::onActionTriggered( bool isChecked )
for ( RimSimWellInView* well : collection )
{
RimGridSummaryCase* gridSummaryCase = RicPlotProductionRateFeature::gridSummaryCaseForWell( well );
RimGridSummaryCase* gridSummaryCase = RimSimWellInViewTools::gridSummaryCaseForWell( well );
if ( !gridSummaryCase ) continue;
QString description = "Well Production Rates : ";
if ( isInjector( well ) )
if ( RimSimWellInViewTools::isInjector( well ) )
{
description = "Well Injection Rates : ";
}
@@ -103,7 +104,7 @@ void RicPlotProductionRateFeature::onActionTriggered( bool isChecked )
description += well->name();
RimSummaryPlot* plot = summaryPlotColl->createNamedSummaryPlot( description );
if ( isInjector( well ) )
if ( RimSimWellInViewTools::isInjector( well ) )
{
// Left Axis
@@ -239,63 +240,6 @@ void RicPlotProductionRateFeature::setupActionLook( QAction* actionToSetup )
actionToSetup->setText( "Plot Production Rates" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridSummaryCase* RicPlotProductionRateFeature::gridSummaryCaseForWell( RimSimWellInView* well )
{
RimProject* project = RiaApplication::instance()->project();
if ( !project ) return nullptr;
RimSummaryCaseMainCollection* sumCaseColl = project->activeOilField()
? project->activeOilField()->summaryCaseMainCollection()
: nullptr;
if ( !sumCaseColl ) return nullptr;
RimEclipseResultCase* eclCase = nullptr;
well->firstAncestorOrThisOfType( eclCase );
if ( eclCase )
{
RimGridSummaryCase* gridSummaryCase = dynamic_cast<RimGridSummaryCase*>(
sumCaseColl->findSummaryCaseFromEclipseResultCase( eclCase ) );
if ( gridSummaryCase )
{
return gridSummaryCase;
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicPlotProductionRateFeature::isInjector( RimSimWellInView* well )
{
RigSimWellData* wRes = well->simWellData();
if ( wRes )
{
Rim3dView* rimView = nullptr;
well->firstAncestorOrThisOfTypeAsserted( rimView );
int currentTimeStep = rimView->currentTimeStep();
if ( wRes->hasWellResult( currentTimeStep ) )
{
const RigWellResultFrame& wrf = wRes->wellResultFrame( currentTimeStep );
if ( wrf.m_productionType == RigWellResultFrame::OIL_INJECTOR ||
wrf.m_productionType == RigWellResultFrame::GAS_INJECTOR ||
wrf.m_productionType == RigWellResultFrame::WATER_INJECTOR )
{
return true;
}
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -55,6 +55,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RivPolylinesAnnotationSourceInfo.h
${CMAKE_CURRENT_LIST_DIR}/RivPolylineGenerator.h
${CMAKE_CURRENT_LIST_DIR}/RivMeasurementPartMgr.h
${CMAKE_CURRENT_LIST_DIR}/RivTextLabelSourceInfo.h
${CMAKE_CURRENT_LIST_DIR}/RivDiskGeometryGenerator.h
${CMAKE_CURRENT_LIST_DIR}/RivWellDiskPartMgr.h
)
set (SOURCE_GROUP_SOURCE_FILES
@@ -108,6 +110,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RivPolylinesAnnotationSourceInfo.cpp
${CMAKE_CURRENT_LIST_DIR}/RivPolylineGenerator.cpp
${CMAKE_CURRENT_LIST_DIR}/RivMeasurementPartMgr.cpp
${CMAKE_CURRENT_LIST_DIR}/RivTextLabelSourceInfo.cpp
${CMAKE_CURRENT_LIST_DIR}/RivDiskGeometryGenerator.cpp
${CMAKE_CURRENT_LIST_DIR}/RivWellDiskPartMgr.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@@ -0,0 +1,141 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor 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 "RivDiskGeometryGenerator.h"
#include "cvfArray.h"
#include "cvfBase.h"
#include "cvfMath.h"
#include "cvfGeometryBuilder.h"
#include "cvfGeometryUtils.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivDiskGeometryGenerator::RivDiskGeometryGenerator()
: m_relativeRadius( 0.085f )
, m_relativeLength( 0.25f )
, m_numSlices( 20 )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivDiskGeometryGenerator::setRelativeRadius( float relativeRadius )
{
m_relativeRadius = relativeRadius;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivDiskGeometryGenerator::setRelativeLength( float relativeLength )
{
m_relativeLength = relativeLength;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivDiskGeometryGenerator::setNumSlices( unsigned int numSlices )
{
m_numSlices = numSlices;
}
//--------------------------------------------------------------------------------------------------
/// Create a disc centered at origin with its normal along positive z-axis
///
/// \param radius Outer radius of the disc
/// \param numSlices The number of subdivisions around the z-axis. Must be >= 4
/// \param builder Geometry builder to use when creating geometry
///
/// Creates a disc on the z = 0 plane, centered at origin and with its surface normal pointing
/// along the positive z-axis.
///
/// The disk is subdivided around the z axis into numSlices (as in pizza slices).
///
/// Each slice is a triangle which does not share any vertices with other slices. This
/// is the main different between cvf::GeometryUtils::createDisc. This method generates 3x
/// more vertices, but the result is easier to use if you need to color each slice separately.
///
/// The sourceNodes that will be produced by this method:
///
/// The following triangle connectivities will be produced:
/// (0,1,2) (3,4,5) (6,7,8) ...
//--------------------------------------------------------------------------------------------------
void createDisc( double radius, size_t numSlices, cvf::GeometryBuilder* builder )
{
CVF_ASSERT( numSlices >= 4 );
CVF_ASSERT( builder );
double da = 2 * cvf::PI_D / numSlices;
// Find the start point on the circle for each slice
cvf::Vec3fArray points;
points.reserve( numSlices );
for ( size_t i = 0; i < numSlices; i++ )
{
// Precompute this one (A = i*da;)
double sinA = cvf::Math::sin( i * da );
double cosA = cvf::Math::cos( i * da );
cvf::Vec3f point = cvf::Vec3f::ZERO;
point.x() = static_cast<float>( -sinA * radius );
point.y() = static_cast<float>( cosA * radius );
points.add( point );
}
// Create independent vertices per slice
cvf::Vec3fArray verts;
verts.reserve( numSlices * 3 );
for ( size_t i = 0; i < numSlices; i++ )
{
verts.add( cvf::Vec3f::ZERO );
verts.add( points[i] );
if ( i == numSlices - 1 )
{
// Last slice complete the circle.
verts.add( points[0] );
}
else
verts.add( points[i + 1] );
}
cvf::uint baseNodeIdx = builder->addVertices( verts );
// Build the triangles for each slice
for ( cvf::uint i = 0; i < static_cast<cvf::uint>( numSlices ); i++ )
{
cvf::uint v1 = baseNodeIdx + ( i * 3 ) + 0;
cvf::uint v2 = baseNodeIdx + ( i * 3 ) + 1;
cvf::uint v3 = baseNodeIdx + ( i * 3 ) + 2;
builder->addTriangle( v1, v2, v3 );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivDiskGeometryGenerator::generate( cvf::GeometryBuilder* builder )
{
const unsigned int numPolysZDir = 1;
createDisc( m_relativeRadius, m_numSlices, builder );
}

View File

@@ -0,0 +1,43 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
namespace cvf
{
class GeometryBuilder;
}
class RivDiskGeometryGenerator
{
public:
RivDiskGeometryGenerator();
void setRelativeRadius( float relativeRadius );
void setRelativeLength( float relativeLength );
void setNumSlices( unsigned int numSlices );
void generate( cvf::GeometryBuilder* builder );
private:
float m_relativeRadius;
float m_relativeLength;
unsigned int m_numSlices;
};

View File

@@ -31,6 +31,7 @@
#include "RivSimWellPipesPartMgr.h"
#include "RivWellConnectionsPartMgr.h"
#include "RivWellDiskPartMgr.h"
#include "RivWellHeadPartMgr.h"
#include "RivWellSpheresPartMgr.h"
@@ -63,6 +64,7 @@ void RivReservoirSimWellsPartMgr::clearGeometryCache()
m_wellPipesPartMgrs.clear();
m_wellHeadPartMgrs.clear();
m_wellSpheresPartMgrs.clear();
m_wellDiskPartMgrs.clear();
}
//--------------------------------------------------------------------------------------------------
@@ -112,6 +114,25 @@ void RivReservoirSimWellsPartMgr::appendDynamicGeometryPartsToModel( cvf::ModelB
m_reservoirView->displayCoordTransform().p() );
}
// Well disks
if ( m_reservoirView->wellCollection()->wells.size() != m_wellDiskPartMgrs.size() )
{
clearGeometryCache();
for ( size_t i = 0; i < m_reservoirView->wellCollection()->wells.size(); ++i )
{
RivWellDiskPartMgr* wellDiskMgr = new RivWellDiskPartMgr( m_reservoirView->wellCollection()->wells[i] );
m_wellDiskPartMgrs.push_back( wellDiskMgr );
}
}
for ( size_t wIdx = 0; wIdx != m_wellDiskPartMgrs.size(); ++wIdx )
{
m_wellDiskPartMgrs[wIdx]->appendDynamicGeometryPartsToModel( model,
frameIndex,
m_reservoirView->displayCoordTransform().p() );
}
// Well spheres
if ( m_reservoirView->wellCollection()->wells.size() != m_wellSpheresPartMgrs.size() )

View File

@@ -33,6 +33,7 @@ class RimEclipseView;
class RivSimWellPipesPartMgr;
class RivWellHeadPartMgr;
class RivWellSpheresPartMgr;
class RivWellDiskPartMgr;
class RivWellConnectionsPartMgr;
//--------------------------------------------------------------------------------------------------
@@ -59,5 +60,6 @@ private:
cvf::Collection<RivSimWellPipesPartMgr> m_wellPipesPartMgrs;
cvf::Collection<RivWellHeadPartMgr> m_wellHeadPartMgrs;
cvf::Collection<RivWellSpheresPartMgr> m_wellSpheresPartMgrs;
cvf::Collection<RivWellDiskPartMgr> m_wellDiskPartMgrs;
cvf::Collection<RivWellConnectionsPartMgr> m_wellConnPartMgrs;
};

View File

@@ -0,0 +1,568 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor 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 "RivWellDiskPartMgr.h"
#include "RiaColorTools.h"
#include "RiaGuiApplication.h"
#include "RigActiveCellInfo.h"
#include "RigCell.h"
#include "RigSimWellData.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimSimWellInView.h"
#include "RimSimWellInViewCollection.h"
#include "RivDiskGeometryGenerator.h"
#include "RivPartPriority.h"
#include "RivSectionFlattner.h"
#include "RivSimWellPipeSourceInfo.h"
#include "RivTextLabelSourceInfo.h"
#include "cafDisplayCoordTransform.h"
#include "cafEffectGenerator.h"
#include "cvfDrawableGeo.h"
#include "cvfDrawableText.h"
#include "cvfEffect.h"
#include "cvfGeometryBuilderDrawableGeo.h"
#include "cvfGeometryBuilderFaceList.h"
#include "cvfGeometryBuilderTriangles.h"
#include "cvfGeometryUtils.h"
#include "cvfModelBasicList.h"
#include "cvfPart.h"
#include "cvfRenderState_FF.h"
#include "cvfShaderProgram.h"
#include "cvfShaderProgramGenerator.h"
#include "cvfShaderSourceProvider.h"
#include "cvfShaderSourceRepository.h"
#include "cvfTransform.h"
#include "cvfUniform.h"
#include "cvfqtUtils.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivWellDiskPartMgr::RivWellDiskPartMgr( RimSimWellInView* well )
: m_rimWell( well )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivWellDiskPartMgr::~RivWellDiskPartMgr() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellDiskPartMgr::buildWellDiskParts( size_t frameIndex, const caf::DisplayCoordTransform* displayXf )
{
clearAllGeometry();
if ( !viewWithSettings() ) return;
RimSimWellInView* well = m_rimWell;
double characteristicCellSize = viewWithSettings()->ownerCase()->characteristicCellSize();
cvf::Vec3d whEndPos;
cvf::Vec3d whStartPos;
{
well->wellHeadTopBottomPosition( static_cast<int>( frameIndex ), &whEndPos, &whStartPos );
whEndPos = displayXf->transformToDisplayCoord( whEndPos );
whEndPos.z() += characteristicCellSize;
}
if ( !well->simWellData()->hasWellResult( frameIndex ) ) return;
auto productionType = well->simWellData()->wellResultFrame( frameIndex ).m_productionType;
double pipeRadius = m_rimWell->pipeRadius();
unsigned int numSectors = 100;
// Upper part of simulation well pipe is defined to use branch index 0
cvf::ref<RivSimWellPipeSourceInfo> sourceInfo = new RivSimWellPipeSourceInfo( m_rimWell, 0 );
// Well disk geometry
double arrowLength = characteristicCellSize * simWellInViewCollection()->wellHeadScaleFactor() *
m_rimWell->wellHeadScaleFactor();
cvf::Vec3d diskPosition = whEndPos;
diskPosition.z() += pipeRadius + arrowLength * 2.0;
cvf::Vec3d textPosition = diskPosition;
textPosition.z() += 0.1;
double ijScaleFactor = arrowLength / 6;
cvf::ref<cvf::DrawableGeo> geo1 = new cvf::DrawableGeo;
{
cvf::Mat4f matr;
matr( 0, 0 ) *= ijScaleFactor;
matr( 1, 1 ) *= ijScaleFactor;
matr( 2, 2 ) *= ijScaleFactor;
matr.setTranslation( cvf::Vec3f( diskPosition ) );
cvf::GeometryBuilderFaceList builder;
{
RivDiskGeometryGenerator gen;
gen.setRelativeRadius( 2.5f * ( m_rimWell->diskScale() ) );
gen.setRelativeLength( 0.1f );
gen.setNumSlices( numSectors );
gen.generate( &builder );
}
cvf::ref<cvf::Vec3fArray> vertices = builder.vertices();
cvf::ref<cvf::UIntArray> faceList = builder.faceList();
for ( size_t i = 0; i < vertices->size(); i++ )
{
cvf::Vec3f v = vertices->get( i );
v.transformPoint( matr );
vertices->set( i, v );
}
geo1->setVertexArray( vertices.p() );
geo1->setFromFaceList( *faceList );
geo1->computeNormals();
}
// Create the fixed function effect
{
m_fixedFuncEffect = new cvf::Effect;
cvf::ref<cvf::RenderStateMaterial_FF> mat = new cvf::RenderStateMaterial_FF( cvf::Color3::BLUE );
mat->enableColorMaterial( true );
m_fixedFuncEffect->setRenderState( mat.p() );
cvf::ref<cvf::RenderStateLighting_FF> lighting = new cvf::RenderStateLighting_FF;
m_fixedFuncEffect->setRenderState( lighting.p() );
}
// Create effect with shader program
{
m_shaderEffect = new cvf::Effect;
cvf::ShaderProgramGenerator gen( "PerVertexColor", cvf::ShaderSourceProvider::instance() );
gen.addVertexCode( cvf::ShaderSourceRepository::vs_Standard );
gen.addFragmentCode( cvf::ShaderSourceRepository::src_VaryingColorGlobalAlpha );
gen.addFragmentCode( cvf::ShaderSourceRepository::fs_Unlit );
m_shaderProg = gen.generate();
m_shaderProg->setDefaultUniform( new cvf::UniformFloat( "u_alpha", 1.0f ) );
m_shaderEffect->setShaderProgram( m_shaderProg.p() );
}
cvf::ref<cvf::Effect> effectToUse = RiaGuiApplication::instance()->useShaders() ? m_shaderEffect : m_fixedFuncEffect;
const cvf::Color3ub colorTable[] = {cvf::Color3ub( cvf::Color3::DARK_GREEN ),
cvf::Color3ub( cvf::Color3::DARK_RED ),
cvf::Color3ub( cvf::Color3::DARK_BLUE )};
size_t vertexCount = geo1->vertexCount();
cvf::ref<cvf::Color3ubArray> colorArray = new cvf::Color3ubArray;
colorArray->resize( vertexCount );
colorArray->setAll( cvf::Color3::WHITE );
CVF_ASSERT( vertexCount == numSectors * 3 );
std::vector<std::pair<cvf::String, cvf::Vec3f>> labelsWithPosition;
int numberPrecision = 2;
double accumulatedPropertyValue = 0.0;
QString labelText = m_rimWell->name();
RigWellDiskData diskData = m_rimWell->wellDiskData();
if ( diskData.isSingleProperty() )
{
// Set color for the triangle vertices
for ( size_t i = 0; i < numSectors * 3; i++ )
{
cvf::Color3ub c = cvf::Color3::OLIVE;
colorArray->set( i, c );
}
accumulatedPropertyValue = diskData.singlePropertyValue();
if ( simWellInViewCollection()->showWellDiskQuantityLables() )
{
const double singleProperty = diskData.singlePropertyValue();
labelText += QString( "\n%2" ).arg( singleProperty, 0, 'g', numberPrecision );
}
}
else
{
const double oil = diskData.oil();
const double gas = diskData.gas();
const double water = diskData.water();
const double total = diskData.total();
const double oilFraction = oil / total;
const double gasFraction = gas / total;
const double waterFraction = water / total;
accumulatedPropertyValue = total;
const double threshold = 1e-6;
if ( total > threshold )
{
double aggregatedFraction = 0.0;
{
auto p = createTextAndLocation( oilFraction / 2.0, diskPosition, ijScaleFactor, oil, numberPrecision );
labelsWithPosition.push_back( p );
aggregatedFraction += oilFraction;
}
{
auto p = createTextAndLocation( aggregatedFraction + gasFraction / 2.0,
diskPosition,
ijScaleFactor,
gas,
numberPrecision );
labelsWithPosition.push_back( p );
aggregatedFraction += gasFraction;
}
{
auto p = createTextAndLocation( aggregatedFraction + waterFraction / 2.0,
diskPosition,
ijScaleFactor,
water,
numberPrecision );
labelsWithPosition.push_back( p );
aggregatedFraction += waterFraction;
}
}
for ( size_t i = 0; i < numSectors; i++ )
{
int colorIdx = 0;
// Find the color for this sector
double lim = ( i + 1 ) / static_cast<double>( numSectors );
if ( lim <= oilFraction )
{
colorIdx = 0;
}
else if ( lim <= oilFraction + gasFraction )
{
colorIdx = 1;
}
else
{
colorIdx = 2;
}
// Set color for the triangle vertices
for ( int t = 0; t < 3; t++ )
{
cvf::Color3ub c = colorTable[colorIdx];
colorArray->set( i * 3 + t, c );
}
}
}
geo1->setColorArray( colorArray.p() );
double threshold = 0.1;
if ( accumulatedPropertyValue > threshold )
{
{
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "RivWellDiskPartMgr: disk " + cvfqt::Utils::toString( well->name() ) );
part->setDrawable( geo1.p() );
part->setEffect( effectToUse.p() );
part->setSourceInfo( sourceInfo.p() );
m_wellDiskPart = part;
}
// Add visual indicator for well type: producer or injector
if ( productionType == RigWellResultFrame::PRODUCER )
{
const uint numPolysZDir = 1;
float bottomRadius = 0.5f;
float topRadius = 0.5f;
float height = 0.1f;
float topOffsetX = 0.0f;
float topOffsetY = 0.0f;
cvf::GeometryBuilderFaceList builder;
cvf::GeometryUtils::createObliqueCylinder( bottomRadius,
topRadius,
height,
topOffsetX,
topOffsetY,
20,
true,
true,
true,
numPolysZDir,
&builder );
cvf::ref<cvf::Vec3fArray> vertices = builder.vertices();
cvf::ref<cvf::UIntArray> faceList = builder.faceList();
cvf::Mat4f matr;
matr( 0, 0 ) *= ijScaleFactor;
matr( 1, 1 ) *= ijScaleFactor;
matr( 2, 2 ) *= ijScaleFactor;
matr.setTranslation( cvf::Vec3f( diskPosition ) );
for ( size_t i = 0; i < vertices->size(); i++ )
{
cvf::Vec3f v = vertices->get( i );
v.transformPoint( matr );
vertices->set( i, v );
}
caf::SurfaceEffectGenerator surfaceGen( cvf::Color4f( cvf::Color3::BLACK ), caf::PO_1 );
surfaceGen.enableLighting( false );
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
cvf::ref<cvf::DrawableGeo> injectorGeo = new cvf::DrawableGeo;
injectorGeo->setVertexArray( vertices.p() );
injectorGeo->setFromFaceList( *faceList );
injectorGeo->computeNormals();
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "RivWellDiskPartMgr: producer " + cvfqt::Utils::toString( well->name() ) );
part->setDrawable( injectorGeo.p() );
part->setEffect( eff.p() );
part->setSourceInfo( sourceInfo.p() );
m_wellDiskInjectorPart = part;
}
else if ( productionType == RigWellResultFrame::OIL_INJECTOR ||
productionType == RigWellResultFrame::GAS_INJECTOR ||
productionType == RigWellResultFrame::WATER_INJECTOR )
{
cvf::GeometryBuilderFaceList builder;
cvf::Vec3f pos( 0.0, 0.0, 0.0 );
// Construct a cross using to "bars"
cvf::GeometryUtils::createBox( pos, 0.2f, 0.8f, 0.1f, &builder );
cvf::GeometryUtils::createBox( pos, 0.8f, 0.2f, 0.1f, &builder );
cvf::ref<cvf::Vec3fArray> vertices = builder.vertices();
cvf::ref<cvf::UIntArray> faceList = builder.faceList();
cvf::Mat4f matr;
matr( 0, 0 ) *= ijScaleFactor;
matr( 1, 1 ) *= ijScaleFactor;
matr( 2, 2 ) *= ijScaleFactor;
matr.setTranslation( cvf::Vec3f( diskPosition ) );
for ( size_t i = 0; i < vertices->size(); i++ )
{
cvf::Vec3f v = vertices->get( i );
v.transformPoint( matr );
vertices->set( i, v );
}
cvf::Color4f injectorMarkerColor = getWellInjectionColor( productionType );
caf::SurfaceEffectGenerator surfaceGen( injectorMarkerColor, caf::PO_1 );
surfaceGen.enableLighting( false );
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
cvf::ref<cvf::DrawableGeo> injectorGeo = new cvf::DrawableGeo;
injectorGeo->setVertexArray( vertices.p() );
injectorGeo->setFromFaceList( *faceList );
injectorGeo->computeNormals();
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "RivWellDiskPartMgr: injector " + cvfqt::Utils::toString( well->name() ) );
part->setDrawable( injectorGeo.p() );
part->setEffect( eff.p() );
part->setSourceInfo( sourceInfo.p() );
m_wellDiskInjectorPart = part;
}
}
bool showTextLabels = simWellInViewCollection()->showWellDiskQuantityLables() ||
( well->showWellLabel() && well->showWellDisks() && !well->name().isEmpty() );
if ( showTextLabels )
{
cvf::Font* font = RiaGuiApplication::instance()->defaultWellLabelFont();
cvf::ref<cvf::DrawableText> drawableText = new cvf::DrawableText;
drawableText->setFont( font );
drawableText->setCheckPosVisible( false );
drawableText->setDrawBorder( false );
drawableText->setDrawBackground( simWellInViewCollection()->showWellDiskLabelBackground() );
drawableText->setVerticalAlignment( cvf::TextDrawer::CENTER );
auto textColor = simWellInViewCollection()->wellLabelColor();
drawableText->setTextColor( textColor );
auto bgColor = RiaColorTools::contrastColor( textColor );
drawableText->setBackgroundColor( bgColor );
cvf::String cvfString = cvfqt::Utils::toString( labelText );
cvf::Vec3f textCoord( textPosition );
drawableText->addText( cvfString, textCoord );
if ( simWellInViewCollection()->showWellDiskQuantityLables() )
{
for ( const auto& t : labelsWithPosition )
{
drawableText->addText( t.first, t.second );
}
}
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "RivWellDiskPartMgr: text " + cvfString );
part->setDrawable( drawableText.p() );
cvf::ref<cvf::Effect> eff = new cvf::Effect;
part->setEffect( eff.p() );
part->setPriority( RivPartPriority::PartType::Text );
m_wellDiskLabelPart = part;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<cvf::String, cvf::Vec3f> RivWellDiskPartMgr::createTextAndLocation( const double aggregatedFraction,
cvf::Vec3d diskPosition,
double ijScaleFactor,
const double fraction,
int precision )
{
double sinA = cvf::Math::sin( aggregatedFraction * 2.0 * cvf::PI_F );
double cosA = cvf::Math::cos( aggregatedFraction * 2.0 * cvf::PI_F );
cvf::Vec3f v = cvf::Vec3f( diskPosition );
double radius = 2.5f * ( m_rimWell->diskScale() );
radius *= ijScaleFactor;
radius *= 1.1; // Put label outside the disk
v.x() = v.x() + static_cast<float>( -sinA * radius );
v.y() = v.y() + static_cast<float>( cosA * radius );
auto s = QString::number( fraction, 'g', precision );
cvf::String text = cvf::String( s.toStdString() );
auto p = std::make_pair( text, v );
return p;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellDiskPartMgr::clearAllGeometry()
{
m_wellDiskPart = nullptr;
m_wellDiskLabelPart = nullptr;
m_wellDiskInjectorPart = nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellDiskPartMgr::appendDynamicGeometryPartsToModel( cvf::ModelBasicList* model,
size_t frameIndex,
const caf::DisplayCoordTransform* displayXf )
{
if ( m_rimWell.isNull() ) return;
if ( !viewWithSettings() ) return;
if ( !m_rimWell->isWellPipeVisible( frameIndex ) ) return;
if ( !m_rimWell->isValidDisk() ) return;
buildWellDiskParts( frameIndex, displayXf );
if ( m_rimWell->showWellDisks() && m_wellDiskLabelPart.notNull() )
{
model->addPart( m_wellDiskLabelPart.p() );
}
if ( m_rimWell->showWellDisks() && m_wellDiskPart.notNull() )
{
model->addPart( m_wellDiskPart.p() );
}
if ( m_rimWell->showWellDisks() && m_wellDiskInjectorPart.notNull() )
{
model->addPart( m_wellDiskInjectorPart.p() );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Rim3dView* RivWellDiskPartMgr::viewWithSettings()
{
Rim3dView* view = nullptr;
if ( m_rimWell ) m_rimWell->firstAncestorOrThisOfType( view );
return view;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSimWellInViewCollection* RivWellDiskPartMgr::simWellInViewCollection()
{
RimSimWellInViewCollection* wellCollection = nullptr;
if ( m_rimWell ) m_rimWell->firstAncestorOrThisOfType( wellCollection );
return wellCollection;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color4f RivWellDiskPartMgr::getWellInjectionColor( RigWellResultFrame::WellProductionType productionType )
{
if ( productionType == RigWellResultFrame::OIL_INJECTOR )
{
return cvf::Color4f( cvf::Color3::ORANGE );
}
else if ( productionType == RigWellResultFrame::GAS_INJECTOR )
{
return cvf::Color4f( cvf::Color3::RED );
}
else if ( productionType == RigWellResultFrame::WATER_INJECTOR )
{
return cvf::Color4f( cvf::Color3::BLUE );
}
return cvf::Color4f( cvf::Color3::BLACK );
}

View File

@@ -0,0 +1,81 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019 Equinor 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RigWellResultPoint.h"
#include "cafPdmPointer.h"
#include "cvfObject.h"
#include "cvfString.h"
namespace cvf
{
class Part;
class ModelBasicList;
class Effect;
class ShaderProgram;
class Color4f;
} // namespace cvf
namespace caf
{
class DisplayCoordTransform;
}
class Rim3dView;
class RimSimWellInView;
class RimSimWellInViewCollection;
class RivWellDiskPartMgr : public cvf::Object
{
public:
RivWellDiskPartMgr( RimSimWellInView* well );
~RivWellDiskPartMgr() override;
void appendDynamicGeometryPartsToModel( cvf::ModelBasicList* model,
size_t frameIndex,
const caf::DisplayCoordTransform* displayXf );
private:
void buildWellDiskParts( size_t frameIndex, const caf::DisplayCoordTransform* displayXf );
std::pair<cvf::String, cvf::Vec3f> createTextAndLocation( const double aggregatedFraction,
cvf::Vec3d diskPosition,
double ijScaleFactor,
const double fraction,
int precision );
void clearAllGeometry();
Rim3dView* viewWithSettings();
RimSimWellInViewCollection* simWellInViewCollection();
static cvf::Color4f getWellInjectionColor( RigWellResultFrame::WellProductionType productionType );
private:
caf::PdmPointer<RimSimWellInView> m_rimWell;
cvf::ref<cvf::Part> m_wellDiskPart;
cvf::ref<cvf::Part> m_wellDiskLabelPart;
cvf::ref<cvf::Part> m_wellDiskInjectorPart;
cvf::ref<cvf::ShaderProgram> m_shaderProg;
cvf::ref<cvf::Effect> m_fixedFuncEffect;
cvf::ref<cvf::Effect> m_shaderEffect;
};

View File

@@ -287,7 +287,9 @@ void RivWellHeadPartMgr::buildWellHeadParts( size_t f
m_wellHeadArrowPart = part;
}
if ( well->showWellLabel() && !well->name().isEmpty() )
// Show labels for well heads only when well disks are disabled:
// well disk labels are prefered since they have more info.
if ( well->showWellLabel() && !well->name().isEmpty() && !well->showWellDisks() )
{
cvf::Font* font = RiaGuiApplication::instance()->defaultWellLabelFont();

View File

@@ -23,6 +23,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimEclipseCellColors.h
${CMAKE_CURRENT_LIST_DIR}/RimCellEdgeColors.h
${CMAKE_CURRENT_LIST_DIR}/RimSimWellInView.h
${CMAKE_CURRENT_LIST_DIR}/RimSimWellInViewCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimSimWellInViewTools.h
${CMAKE_CURRENT_LIST_DIR}/RimWellPath.h
${CMAKE_CURRENT_LIST_DIR}/RimFileWellPath.h
${CMAKE_CURRENT_LIST_DIR}/RimModeledWellPath.h
@@ -149,6 +150,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCurve.h
${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementFilter.h
${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementInViewCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementInView.h
${CMAKE_CURRENT_LIST_DIR}/RimWellDiskConfig.h
)
@@ -176,6 +178,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimEclipseCellColors.cpp
${CMAKE_CURRENT_LIST_DIR}/RimCellEdgeColors.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSimWellInView.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSimWellInViewCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSimWellInViewTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellPath.cpp
${CMAKE_CURRENT_LIST_DIR}/RimFileWellPath.cpp
${CMAKE_CURRENT_LIST_DIR}/RimModeledWellPath.cpp
@@ -302,6 +305,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementCurve.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementFilter.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementInViewCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementInView.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellDiskConfig.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@@ -716,6 +716,12 @@ QString Rim3dOverlayInfoConfig::resultInfoText( const HistogramData& histData,
infoText += QString( "%1<br>" ).arg( diffResString );
}
const RimSimWellInViewCollection* wellCollection = eclipseView->wellCollection();
if ( wellCollection && wellCollection->isActive() && wellCollection->isWellDisksVisible() )
{
infoText += QString( "<b>Well Disk Property:</b> %1<br>" ).arg( wellCollection->wellDiskPropertyUiText() );
}
if ( eclipseView->cellResult()->hasDualPorFractureResult() )
{
QString porosityModelText = caf::AppEnum<RiaDefines::PorosityModelType>::uiText(

View File

@@ -633,6 +633,8 @@ void RimEclipseView::onUpdateDisplayModelForCurrentTimeStep()
m_overlayInfoConfig()->update3DInfo();
wellCollection()->updateWellDisks();
// Invisible Wells are marked as read only when "show wells intersecting visible cells" is enabled
// Visibility of wells differ betweeen time steps, so trigger a rebuild of tree state items
wellCollection()->updateConnectedEditors();
@@ -922,6 +924,8 @@ void RimEclipseView::onLoadDataAndUpdate()
this->faultCollection()->syncronizeFaults();
this->m_wellCollection->updateWellDisks();
scheduleReservoirGridGeometryRegen();
m_simWellsPartManager->clearGeometryCache();

View File

@@ -37,6 +37,8 @@
#include "RimSimWellFracture.h"
#include "RimSimWellFractureCollection.h"
#include "RimSimWellInViewCollection.h"
#include "RimSimWellInViewTools.h"
#include "RimWellDiskConfig.h"
#include "RiuMainWindow.h"
@@ -67,6 +69,7 @@ RimSimWellInView::RimSimWellInView()
CAF_PDM_InitField( &showWellHead, "ShowWellHead", true, "Well Head", "", "", "" );
CAF_PDM_InitField( &showWellPipe, "ShowWellPipe", true, "Pipe", "", "", "" );
CAF_PDM_InitField( &showWellSpheres, "ShowWellSpheres", false, "Spheres", "", "", "" );
CAF_PDM_InitField( &showWellDisks, "ShowWellDisks", false, "Disks", "", "", "" );
CAF_PDM_InitField( &wellHeadScaleFactor, "WellHeadScaleFactor", 1.0, "Well Head Scale", "", "", "" );
CAF_PDM_InitField( &pipeScaleFactor, "WellPipeRadiusScale", 1.0, "Pipe Radius Scale", "", "", "" );
@@ -113,7 +116,7 @@ void RimSimWellInView::fieldChangedByUi( const caf::PdmFieldHandle* changedField
if ( reservoirView )
{
if ( &showWellLabel == changedField || &showWellHead == changedField || &showWellPipe == changedField ||
&showWellSpheres == changedField || &wellPipeColor == changedField )
&showWellSpheres == changedField || &showWellDisks == changedField || &wellPipeColor == changedField )
{
reservoirView->scheduleCreateDisplayModelAndRedraw();
schedule2dIntersectionViewUpdate();
@@ -401,6 +404,7 @@ void RimSimWellInView::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderin
appearanceGroup->add( &showWellHead );
appearanceGroup->add( &showWellPipe );
appearanceGroup->add( &showWellSpheres );
appearanceGroup->add( &showWellDisks );
caf::PdmUiGroup* filterGroup = uiOrdering.addNewGroup( "Well Cells and Fence" );
filterGroup->add( &showWellCells );
@@ -580,6 +584,14 @@ bool RimSimWellInView::isUsingCellCenterForPipe() const
return ( wellColl && wellColl->wellPipeCoordType() == RimSimWellInViewCollection::WELLPIPE_CELLCENTER );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigWellDiskData RimSimWellInView::wellDiskData() const
{
return m_wellDiskData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -613,6 +625,128 @@ size_t RimSimWellInView::resultWellIndex() const
return m_resultWellIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSimWellInView::calculateInjectionProductionFractions( const RimWellDiskConfig& wellDiskConfig, bool* isOk )
{
const RimEclipseView* reservoirView = nullptr;
this->firstAncestorOrThisOfType( reservoirView );
if ( !reservoirView ) return false;
size_t timeStep = static_cast<size_t>( reservoirView->currentTimeStep() );
std::vector<QDateTime> caseTimeSteps = reservoirView->eclipseCase()->timeStepDates();
QDateTime currentDate;
if ( timeStep < caseTimeSteps.size() )
{
currentDate = caseTimeSteps[timeStep];
}
else
{
currentDate = caseTimeSteps.back();
}
RimGridSummaryCase* gridSummaryCase = RimSimWellInViewTools::gridSummaryCaseForWell( this );
if ( wellDiskConfig.isSingleProperty() )
{
double singleProperty = RimSimWellInViewTools::extractValueForTimeStep( gridSummaryCase,
name(),
wellDiskConfig.getSingleProperty(),
currentDate,
isOk );
if ( !( *isOk ) )
{
m_isValidDisk = false;
return -1.0;
}
m_wellDiskData.setSinglePropertyValue( singleProperty );
}
else
{
m_isInjector = RimSimWellInViewTools::gridSummaryCaseForWell( this );
double oil = RimSimWellInViewTools::extractValueForTimeStep( gridSummaryCase,
name(),
wellDiskConfig.getOilProperty(),
currentDate,
isOk );
if ( !( *isOk ) )
{
m_isValidDisk = false;
return -1.0;
}
double gas = RimSimWellInViewTools::extractValueForTimeStep( gridSummaryCase,
name(),
wellDiskConfig.getGasProperty(),
currentDate,
isOk ) /
1000.0;
if ( !( *isOk ) )
{
m_isValidDisk = false;
return -1.0;
}
double water = RimSimWellInViewTools::extractValueForTimeStep( gridSummaryCase,
name(),
wellDiskConfig.getWaterProperty(),
currentDate,
isOk );
if ( !( *isOk ) )
{
m_isValidDisk = false;
return -1.0;
}
m_wellDiskData.setOilGasWater( oil, gas, water );
}
m_isValidDisk = true;
return m_wellDiskData.total();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellInView::scaleDisk( double minValue, double maxValue )
{
if ( m_isValidDisk )
{
m_diskScale = 1.0 + ( m_wellDiskData.total() - minValue ) / ( maxValue - minValue );
}
else
{
m_diskScale = 1.0;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSimWellInView::isValidDisk() const
{
return m_isValidDisk;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSimWellInView::diskScale() const
{
if ( m_isValidDisk )
{
return m_diskScale;
}
else
{
return 1.0;
}
}
//--------------------------------------------------------------------------------------------------
/// Internal functions
//--------------------------------------------------------------------------------------------------

View File

@@ -20,6 +20,8 @@
#pragma once
#include "RigWellDiskData.h"
#include "cafAppEnum.h"
#include "cafPdmChildField.h"
#include "cafPdmField.h"
@@ -38,6 +40,7 @@ struct RigWellResultPoint;
class RimSimWellFractureCollection;
class RigWellPath;
class RimWellDiskConfig;
//==================================================================================================
///
@@ -61,6 +64,10 @@ public:
bool isWellSpheresVisible( size_t frameIndex ) const;
bool isUsingCellCenterForPipe() const;
RigWellDiskData wellDiskData() const;
bool isValidDisk() const;
double diskScale() const;
caf::PdmFieldHandle* userDescriptionField() override;
caf::PdmFieldHandle* objectToggleField() override;
@@ -83,6 +90,7 @@ public:
caf::PdmField<bool> showWellHead;
caf::PdmField<bool> showWellPipe;
caf::PdmField<bool> showWellSpheres;
caf::PdmField<bool> showWellDisks;
caf::PdmField<double> wellHeadScaleFactor;
caf::PdmField<double> pipeScaleFactor;
@@ -94,6 +102,9 @@ public:
caf::PdmChildField<RimSimWellFractureCollection*> simwellFractureCollection;
double calculateInjectionProductionFractions( const RimWellDiskConfig& wellDiskConfig, bool* isOk );
void scaleDisk( double minValue, double maxValue );
protected:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
@@ -110,4 +121,9 @@ private:
private:
cvf::ref<RigSimWellData> m_simWellData;
size_t m_resultWellIndex;
bool m_isInjector;
RigWellDiskData m_wellDiskData;
bool m_isValidDisk;
double m_diskScale;
};

View File

@@ -32,19 +32,28 @@
#include "RimEclipseContourMapView.h"
#include "RimEclipseResultCase.h"
#include "RimEclipseView.h"
#include "RimGridSummaryCase.h"
#include "RimIntersectionCollection.h"
#include "RimProject.h"
#include "RimSimWellFractureCollection.h"
#include "RimSimWellInView.h"
#include "RimSimWellInViewTools.h"
#include "RimWellAllocationPlot.h"
#include "RimWellDiskConfig.h"
#include "RifSummaryReaderInterface.h"
#include "RiuMainWindow.h"
#include "RiuSummaryQuantityNameInfoProvider.h"
#include "RivReservoirViewPartMgr.h"
#include "cafPdmUiCheckBoxTristateEditor.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiPushButtonEditor.h"
#include <set>
namespace caf
{
// OBSOLETE enum
@@ -117,6 +126,30 @@ void RimSimWellInViewCollection::WellPipeColorsEnum::setUp()
}
} // namespace caf
namespace caf
{
template <>
void AppEnum<RimSimWellInViewCollection::WellDiskPropertyType>::setUp()
{
addItem( RimSimWellInViewCollection::PROPERTY_TYPE_PREDEFINED, " PROPERTY_TYPE_PREDEFINED", "Predefined" );
addItem( RimSimWellInViewCollection::PROPERTY_TYPE_SINGLE, "ANY_SINGLE_PROPERTY", "Single Property" );
setDefault( RimSimWellInViewCollection::PROPERTY_TYPE_PREDEFINED );
}
} // namespace caf
namespace caf
{
template <>
void AppEnum<RimSimWellInViewCollection::WellDiskPropertyConfigType>::setUp()
{
addItem( RimSimWellInViewCollection::PRODUCTION_RATES, "PRODUCTION_RATES", "Production Rates" );
addItem( RimSimWellInViewCollection::INJECTION_RATES, "INJECTION_RATES", "Injection Rates" );
addItem( RimSimWellInViewCollection::CUMULATIVE_PRODUCTION_RATES, "CUMULATIVE_PRODUCTION_RATES", "Production Total" );
addItem( RimSimWellInViewCollection::CUMULATIVE_INJECTION_RATES, "CUMULATIVE_INJECTION_RATES", "Injection Total" );
setDefault( RimSimWellInViewCollection::PRODUCTION_RATES );
}
} // namespace caf
CAF_PDM_SOURCE_INIT( RimSimWellInViewCollection, "Wells" );
//--------------------------------------------------------------------------------------------------
@@ -146,6 +179,7 @@ RimSimWellInViewCollection::RimSimWellInViewCollection()
CAF_PDM_InitFieldNoDefault( &m_showWellLabel, "ShowWellLabelTristate", "Label", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_showWellPipe, "ShowWellPipe", "Pipe", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_showWellSpheres, "ShowWellSpheres", "Spheres", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_showWellDisks, "ShowWellDisks", "Disks", "", "", "" );
m_showWellHead.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxTristateEditor::uiEditorTypeName() );
m_showWellHead.xmlCapability()->disableIO();
@@ -159,6 +193,9 @@ RimSimWellInViewCollection::RimSimWellInViewCollection()
m_showWellSpheres.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxTristateEditor::uiEditorTypeName() );
m_showWellSpheres.xmlCapability()->disableIO();
m_showWellDisks.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxTristateEditor::uiEditorTypeName() );
m_showWellDisks.xmlCapability()->disableIO();
// Scaling
CAF_PDM_InitField( &wellHeadScaleFactor, "WellHeadScale", 1.0, "Well Head Scale", "", "", "" );
CAF_PDM_InitField( &pipeScaleFactor, "WellPipeRadiusScale", 0.1, "Pipe Radius Scale ", "", "", "" );
@@ -220,6 +257,27 @@ RimSimWellInViewCollection::RimSimWellInViewCollection()
m_showWellCellFence.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxTristateEditor::uiEditorTypeName() );
m_showWellCellFence.xmlCapability()->disableIO();
CAF_PDM_InitField( &m_wellDiskQuantity, "WellDiskQuantity", QString( "WOPT" ), "Disk Quantity", "", "", "" );
m_wellDiskQuantity.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
m_wellDiskQuantity.uiCapability()->setAutoAddingOptionFromValue( false );
CAF_PDM_InitFieldNoDefault( &m_wellDiskPropertyType, "WellDiskPropertyType", "Property Type", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_wellDiskPropertyConfigType,
"WellDiskPropertyConfigType",
"Property Config Type",
"",
"",
"" );
CAF_PDM_InitField( &m_wellDiskShowQuantityLabels, "WellDiskShowQuantityLabels", true, "Show Quantity Labels", "", "", "" );
CAF_PDM_InitField( &m_wellDiskshowLabelsBackground,
"WellDiskShowLabelsBackground",
false,
"Show Label Background",
"",
"",
"" );
CAF_PDM_InitField( &obsoleteField_wellPipeVisibility,
"GlobalWellPipeVisibility",
WellVisibilityEnum( PIPES_INDIVIDUALLY ),
@@ -405,6 +463,15 @@ void RimSimWellInViewCollection::fieldChangedByUi( const caf::PdmFieldHandle* ch
}
}
if ( &m_showWellDisks == changedField )
{
for ( RimSimWellInView* w : wells )
{
w->showWellDisks = !( m_showWellDisks().isFalse() );
w->updateConnectedEditors();
}
}
if ( &m_showWellCells == changedField )
{
for ( RimSimWellInView* w : wells )
@@ -435,8 +502,16 @@ void RimSimWellInViewCollection::fieldChangedByUi( const caf::PdmFieldHandle* ch
{
m_reservoirView->scheduleCreateDisplayModelAndRedraw();
}
else if ( &m_wellDiskQuantity == changedField || &m_wellDiskPropertyType == changedField ||
&m_wellDiskPropertyConfigType == changedField || &m_wellDiskshowLabelsBackground == changedField ||
&m_wellDiskShowQuantityLabels == changedField )
{
RimWellDiskConfig wellDiskConfig = getActiveWellDiskConfig();
updateWellDisks( wellDiskConfig );
m_reservoirView->updateDisplayModelForCurrentTimeStepAndRedraw();
}
else if ( &spheresScaleFactor == changedField || &m_showWellSpheres == changedField ||
&showConnectionStatusColors == changedField )
&m_showWellDisks == changedField || &showConnectionStatusColors == changedField )
{
m_reservoirView->scheduleSimWellGeometryRegen();
m_reservoirView->scheduleCreateDisplayModelAndRedraw();
@@ -505,6 +580,64 @@ void RimSimWellInViewCollection::fieldChangedByUi( const caf::PdmFieldHandle* ch
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo>
RimSimWellInViewCollection::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly )
{
if ( fieldNeedingOptions == &m_wellDiskQuantity )
{
QList<caf::PdmOptionItemInfo> options;
if ( !wells.empty() )
{
// Assume that the wells share the grid summary case
RimGridSummaryCase* summaryCase = RimSimWellInViewTools::gridSummaryCaseForWell( wells[0] );
std::set<std::string> summaries;
if ( summaryCase )
{
auto addresses = summaryCase->summaryReader()->allResultAddresses();
for ( auto addr : addresses )
{
if ( addr.category() == RifEclipseSummaryAddress::SUMMARY_WELL )
{
summaries.insert( addr.quantityName() );
}
}
}
for ( const auto& itemName : summaries )
{
QString displayName;
std::string longVectorName = RiuSummaryQuantityNameInfoProvider::instance()->longNameFromQuantityName(
itemName );
if ( longVectorName.empty() )
{
displayName = QString::fromStdString( itemName );
}
else
{
displayName = QString::fromStdString( longVectorName );
displayName += QString( " (%1)" ).arg( QString::fromStdString( itemName ) );
}
auto optionItem = caf::PdmOptionItemInfo( displayName, QString::fromStdString( itemName ) );
options.push_back( optionItem );
}
}
if ( useOptionsOnly ) *useOptionsOnly = true;
return options;
}
return QList<caf::PdmOptionItemInfo>();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -567,6 +700,7 @@ void RimSimWellInViewCollection::defineUiOrdering( QString uiConfigName, caf::Pd
appearanceGroup->add( &m_showWellHead );
appearanceGroup->add( &m_showWellPipe );
appearanceGroup->add( &m_showWellSpheres );
appearanceGroup->add( &m_showWellDisks );
appearanceGroup->add( &m_showWellCommunicationLines );
if ( !isContourMap )
@@ -604,6 +738,19 @@ void RimSimWellInViewCollection::defineUiOrdering( QString uiConfigName, caf::Pd
advancedGroup->add( &wellHeadPosition );
}
caf::PdmUiGroup* wellDiskGroup = uiOrdering.addNewGroup( "Well Disk" );
wellDiskGroup->add( &m_wellDiskPropertyType );
if ( m_wellDiskPropertyType() == PROPERTY_TYPE_PREDEFINED )
{
wellDiskGroup->add( &m_wellDiskPropertyConfigType );
}
else
{
wellDiskGroup->add( &m_wellDiskQuantity );
}
wellDiskGroup->add( &m_wellDiskShowQuantityLabels );
wellDiskGroup->add( &m_wellDiskshowLabelsBackground );
RimEclipseResultCase* ownerCase = nullptr;
firstAncestorOrThisOfType( ownerCase );
if ( ownerCase )
@@ -626,6 +773,7 @@ void RimSimWellInViewCollection::updateStateForVisibilityCheckboxes()
size_t showWellHeadCount = 0;
size_t showPipeCount = 0;
size_t showSphereCount = 0;
size_t showDiskCount = 0;
size_t showWellCellsCount = 0;
size_t showWellCellFenceCount = 0;
@@ -635,6 +783,7 @@ void RimSimWellInViewCollection::updateStateForVisibilityCheckboxes()
if ( w->showWellHead() ) showWellHeadCount++;
if ( w->showWellPipe() ) showPipeCount++;
if ( w->showWellSpheres() ) showSphereCount++;
if ( w->showWellDisks() ) showDiskCount++;
if ( w->showWellCells() ) showWellCellsCount++;
if ( w->showWellCellFence() ) showWellCellFenceCount++;
}
@@ -643,6 +792,7 @@ void RimSimWellInViewCollection::updateStateForVisibilityCheckboxes()
updateStateFromEnabledChildCount( showWellHeadCount, &m_showWellHead );
updateStateFromEnabledChildCount( showPipeCount, &m_showWellPipe );
updateStateFromEnabledChildCount( showSphereCount, &m_showWellSpheres );
updateStateFromEnabledChildCount( showDiskCount, &m_showWellDisks );
updateStateFromEnabledChildCount( showWellCellsCount, &m_showWellCells );
updateStateFromEnabledChildCount( showWellCellFenceCount, &m_showWellCellFence );
}
@@ -805,3 +955,119 @@ void RimSimWellInViewCollection::sortWellsByName()
{
std::sort( wells.begin(), wells.end(), lessEclipseWell );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSimWellInViewCollection::wellDiskPropertyUiText() const
{
if ( m_wellDiskPropertyType() == RimSimWellInViewCollection::PROPERTY_TYPE_PREDEFINED )
{
return m_wellDiskPropertyConfigType().uiText();
}
return m_wellDiskQuantity;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSimWellInViewCollection::isWellDisksVisible() const
{
return m_showWellDisks.v().isTrue() || m_showWellDisks.v().isPartiallyTrue();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSimWellInViewCollection::showWellDiskLabelBackground() const
{
return m_wellDiskshowLabelsBackground();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSimWellInViewCollection::showWellDiskQuantityLables() const
{
return m_wellDiskShowQuantityLabels();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellInViewCollection::updateWellDisks()
{
RimWellDiskConfig wellDiskConfig = getActiveWellDiskConfig();
updateWellDisks( wellDiskConfig );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellInViewCollection::updateWellDisks( const RimWellDiskConfig& wellDiskConfig )
{
double minValue = std::numeric_limits<double>::max();
double maxValue = -minValue;
for ( RimSimWellInView* w : wells )
{
bool isOk = true;
double value = w->calculateInjectionProductionFractions( wellDiskConfig, &isOk );
if ( isOk )
{
minValue = std::min( minValue, value );
maxValue = std::max( maxValue, value );
}
}
if ( maxValue > minValue )
{
for ( RimSimWellInView* w : wells )
{
w->scaleDisk( minValue, maxValue );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellDiskConfig RimSimWellInViewCollection::getActiveWellDiskConfig() const
{
RimWellDiskConfig wellDiskConfig;
if ( m_wellDiskPropertyType() == RimSimWellInViewCollection::PROPERTY_TYPE_PREDEFINED )
{
WellDiskPropertyConfigType configType = m_wellDiskPropertyConfigType();
if ( configType == PRODUCTION_RATES )
{
wellDiskConfig.setOilProperty( "WOPR" );
wellDiskConfig.setGasProperty( "WGPR" );
wellDiskConfig.setWaterProperty( "WWPR" );
}
else if ( configType == INJECTION_RATES )
{
wellDiskConfig.setOilProperty( "" );
wellDiskConfig.setGasProperty( "WGIR" );
wellDiskConfig.setWaterProperty( "WWIR" );
}
else if ( configType == CUMULATIVE_PRODUCTION_RATES )
{
wellDiskConfig.setOilProperty( "WOPT" );
wellDiskConfig.setGasProperty( "WGPT" );
wellDiskConfig.setWaterProperty( "WWPT" );
}
else if ( configType == CUMULATIVE_INJECTION_RATES )
{
wellDiskConfig.setOilProperty( "" );
wellDiskConfig.setGasProperty( "WGIT" );
wellDiskConfig.setWaterProperty( "WWIT" );
}
}
else
{
wellDiskConfig.setSingleProperty( m_wellDiskQuantity.v().toStdString() );
}
return wellDiskConfig;
}

View File

@@ -30,6 +30,7 @@
class RimEclipseView;
class RimSimWellInView;
class RimWellDiskConfig;
//==================================================================================================
///
@@ -91,6 +92,20 @@ public:
WELLPIPE_COLOR_UNIFORM
};
enum WellDiskPropertyType
{
PROPERTY_TYPE_PREDEFINED,
PROPERTY_TYPE_SINGLE
};
enum WellDiskPropertyConfigType
{
PRODUCTION_RATES,
INJECTION_RATES,
CUMULATIVE_PRODUCTION_RATES,
CUMULATIVE_INJECTION_RATES
};
typedef caf::AppEnum<RimSimWellInViewCollection::WellPipeColors> WellPipeColorsEnum;
caf::PdmField<bool> isActive;
@@ -121,6 +136,11 @@ public:
caf::PdmField<bool> isAutoDetectingBranches;
QString wellDiskPropertyUiText() const;
bool isWellDisksVisible() const;
bool showWellDiskLabelBackground() const;
bool showWellDiskQuantityLables() const;
caf::PdmChildArrayField<RimSimWellInView*> wells;
RimSimWellInView* findWell( QString name );
@@ -136,6 +156,8 @@ public:
static void updateWellAllocationPlots();
void updateWellDisks();
protected:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
@@ -143,12 +165,17 @@ protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly );
caf::PdmFieldHandle* objectToggleField() override;
void initAfterRead() override;
private:
void calculateWellGeometryVisibility( size_t frameIndex );
void updateStateFromEnabledChildCount( size_t showLabelCount, caf::PdmField<caf::Tristate>* fieldToUpdate );
void updateWellDisks( const RimWellDiskConfig& wellDiskConfig );
RimWellDiskConfig getActiveWellDiskConfig() const;
private:
RimEclipseView* m_reservoirView;
@@ -162,11 +189,19 @@ private:
caf::PdmField<caf::Tristate> m_showWellHead;
caf::PdmField<caf::Tristate> m_showWellPipe;
caf::PdmField<caf::Tristate> m_showWellSpheres;
caf::PdmField<caf::Tristate> m_showWellDisks;
caf::PdmField<caf::Tristate> m_showWellCells;
caf::PdmField<caf::Tristate> m_showWellCellFence;
caf::PdmField<bool> m_showWellCommunicationLines;
// Well Discs
caf::PdmField<caf::AppEnum<WellDiskPropertyType>> m_wellDiskPropertyType;
caf::PdmField<caf::AppEnum<WellDiskPropertyConfigType>> m_wellDiskPropertyConfigType;
caf::PdmField<QString> m_wellDiskQuantity;
caf::PdmField<bool> m_wellDiskShowQuantityLabels;
caf::PdmField<bool> m_wellDiskshowLabelsBackground;
// Obsolete fields
caf::PdmField<WellVisibilityEnum> obsoleteField_wellPipeVisibility;
caf::PdmField<WellCellsRangeFilterEnum> obsoleteField_wellCellsToRangeFilterMode;

View File

@@ -0,0 +1,167 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor 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 "RimSimWellInViewTools.h"
#include "RiaApplication.h"
#include "RiaSummaryTools.h"
#include "RiaTimeHistoryCurveResampler.h"
#include "RifEclipseSummaryAddress.h"
#include "RifSummaryReaderInterface.h"
#include "RigSimWellData.h"
#include "Rim3dView.h"
#include "RimEclipseResultCase.h"
#include "RimGridSummaryCase.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSimWellInView.h"
#include "RimSimWellInViewCollection.h"
#include "RimSummaryCaseMainCollection.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridSummaryCase* RimSimWellInViewTools::gridSummaryCaseForWell( RimSimWellInView* well )
{
RimProject* project = RiaApplication::instance()->project();
if ( !project ) return nullptr;
RimSummaryCaseMainCollection* sumCaseColl = project->activeOilField()
? project->activeOilField()->summaryCaseMainCollection()
: nullptr;
if ( !sumCaseColl ) return nullptr;
RimEclipseResultCase* eclCase = nullptr;
well->firstAncestorOrThisOfType( eclCase );
if ( eclCase )
{
RimGridSummaryCase* gridSummaryCase = dynamic_cast<RimGridSummaryCase*>(
sumCaseColl->findSummaryCaseFromEclipseResultCase( eclCase ) );
if ( gridSummaryCase )
{
return gridSummaryCase;
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSimWellInViewTools::isInjector( RimSimWellInView* well )
{
RigSimWellData* wRes = well->simWellData();
if ( wRes )
{
Rim3dView* rimView = nullptr;
well->firstAncestorOrThisOfTypeAsserted( rimView );
int currentTimeStep = rimView->currentTimeStep();
if ( wRes->hasWellResult( currentTimeStep ) )
{
const RigWellResultFrame& wrf = wRes->wellResultFrame( currentTimeStep );
if ( wrf.m_productionType == RigWellResultFrame::OIL_INJECTOR ||
wrf.m_productionType == RigWellResultFrame::GAS_INJECTOR ||
wrf.m_productionType == RigWellResultFrame::WATER_INJECTOR )
{
return true;
}
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSimWellInViewTools::extractValueForTimeStep( RimGridSummaryCase* gridSummaryCase,
const QString& wellName,
const std::string& vectorName,
const QDateTime& currentDate,
bool* isOk )
{
if ( vectorName.empty() )
{
*isOk = true;
return 0.0;
}
RifEclipseSummaryAddress addr( RifEclipseSummaryAddress::SUMMARY_WELL,
vectorName,
-1,
-1,
"",
wellName.toStdString(),
-1,
"",
-1,
-1,
-1,
-1,
false,
-1 );
RifSummaryReaderInterface* reader = gridSummaryCase->summaryReader();
if ( !gridSummaryCase->summaryReader()->hasAddress( addr ) )
{
// TODO: better error handling
std::cerr << "ERROR: no address found for well " << wellName.toStdString() << " " << vectorName << std::endl;
*isOk = false;
return 0.0;
}
std::vector<double> values;
reader->values( addr, &values );
std::vector<time_t> timeSteps = reader->timeSteps( addr );
RiaTimeHistoryCurveResampler resampler;
resampler.setCurveData( values, timeSteps );
if ( RiaSummaryTools::hasAccumulatedData( addr ) )
{
resampler.resampleAndComputePeriodEndValues( DateTimePeriod::DAY );
}
else
{
resampler.resampleAndComputeWeightedMeanValues( DateTimePeriod::DAY );
}
// Find the data point which best matches the selected time step
std::vector<time_t> resampledTimeSteps = resampler.resampledTimeSteps();
std::vector<double> resampledValues = resampler.resampledValues();
for ( unsigned int i = 0; i < resampledTimeSteps.size(); i++ )
{
QDateTime t = QDateTime::fromTime_t( resampledTimeSteps[i] );
if ( t > currentDate )
{
*isOk = true;
return resampledValues[i];
}
}
std::cerr << "ERROR: no resampled value found for well " << wellName.toStdString() << " " << vectorName << std::endl;
*isOk = false;
return -1;
}

View File

@@ -0,0 +1,44 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <string>
class QString;
class QDateTime;
class RimSimWellInView;
class RimGridSummaryCase;
//==================================================================================================
///
///
//==================================================================================================
class RimSimWellInViewTools
{
public:
static RimGridSummaryCase* gridSummaryCaseForWell( RimSimWellInView* well );
static bool isInjector( RimSimWellInView* well );
static double extractValueForTimeStep( RimGridSummaryCase* gridSummaryCase,
const QString& wellName,
const std::string& vectorName,
const QDateTime& currentDate,
bool* isOk );
};

View File

@@ -0,0 +1,75 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor 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 "RimWellDiskConfig.h"
RimWellDiskConfig::RimWellDiskConfig()
: m_isSingleProperty( false )
{
}
RimWellDiskConfig::~RimWellDiskConfig() {}
bool RimWellDiskConfig::isSingleProperty() const
{
return m_isSingleProperty;
}
std::string RimWellDiskConfig::getSingleProperty() const
{
return m_singleProperty;
}
void RimWellDiskConfig::setSingleProperty( const std::string& singleProperty )
{
m_isSingleProperty = true;
m_singleProperty = singleProperty;
}
void RimWellDiskConfig::setOilProperty( const std::string& oilProperty )
{
m_isSingleProperty = false;
m_oilProperty = oilProperty;
}
std::string RimWellDiskConfig::getOilProperty() const
{
return m_oilProperty;
}
void RimWellDiskConfig::setGasProperty( const std::string& gasProperty )
{
m_isSingleProperty = false;
m_gasProperty = gasProperty;
}
std::string RimWellDiskConfig::getGasProperty() const
{
return m_gasProperty;
}
void RimWellDiskConfig::setWaterProperty( const std::string& waterProperty )
{
m_isSingleProperty = false;
m_waterProperty = waterProperty;
}
std::string RimWellDiskConfig::getWaterProperty() const
{
return m_waterProperty;
}

View File

@@ -0,0 +1,52 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <string>
//==================================================================================================
///
///
//==================================================================================================
class RimWellDiskConfig
{
public:
RimWellDiskConfig();
~RimWellDiskConfig();
bool isSingleProperty() const;
std::string getSingleProperty() const;
void setSingleProperty( const std::string& singleProperty );
void setOilProperty( const std::string& oilProperty );
std::string getOilProperty() const;
void setGasProperty( const std::string& gasProperty );
std::string getGasProperty() const;
void setWaterProperty( const std::string& waterProperty );
std::string getWaterProperty() const;
private:
bool m_isSingleProperty;
std::string m_singleProperty;
std::string m_oilProperty;
std::string m_gasProperty;
std::string m_waterProperty;
};

View File

@@ -77,6 +77,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RigWbsParameter.h
${CMAKE_CURRENT_LIST_DIR}/RigEclipseAllenFaultsStatCalc.h
${CMAKE_CURRENT_LIST_DIR}/RigCellFaceGeometryTools.h
${CMAKE_CURRENT_LIST_DIR}/RigNncConnection.h
${CMAKE_CURRENT_LIST_DIR}/RigWellDiskData.h
)
@@ -151,6 +152,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RigWbsParameter.cpp
${CMAKE_CURRENT_LIST_DIR}/RigEclipseAllenFaultsStatCalc.cpp
${CMAKE_CURRENT_LIST_DIR}/RigCellFaceGeometryTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RigNncConnection.cpp
${CMAKE_CURRENT_LIST_DIR}/RigWellDiskData.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@@ -0,0 +1,107 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor 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 "RigWellDiskData.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigWellDiskData::RigWellDiskData()
: m_isSingleProperty( false )
, m_singlePropertyValue( 0.0 )
, m_oilValue( 0.0 )
, m_waterValue( 0.0 )
, m_gasValue( 0.0 )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellDiskData::setSinglePropertyValue( double value )
{
m_isSingleProperty = true;
m_singlePropertyValue = value;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellDiskData::setOilGasWater( double oil, double gas, double water )
{
m_isSingleProperty = false;
m_oilValue = oil;
m_gasValue = gas;
m_waterValue = water;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigWellDiskData::total() const
{
if ( m_isSingleProperty )
{
return m_singlePropertyValue;
}
else
{
return m_oilValue + m_gasValue + m_waterValue;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigWellDiskData::oil() const
{
return m_oilValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigWellDiskData::gas() const
{
return m_gasValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigWellDiskData::water() const
{
return m_waterValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigWellDiskData::singlePropertyValue() const
{
return m_singlePropertyValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigWellDiskData::isSingleProperty() const
{
return m_isSingleProperty;
}

View File

@@ -0,0 +1,46 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
//==================================================================================================
///
///
//==================================================================================================
class RigWellDiskData
{
public:
RigWellDiskData();
void setSinglePropertyValue( double value );
void setOilGasWater( double oil, double gas, double water );
double total() const;
double oil() const;
double gas() const;
double water() const;
double singlePropertyValue() const;
bool isSingleProperty() const;
private:
bool m_isSingleProperty;
double m_singlePropertyValue;
double m_oilValue;
double m_waterValue;
double m_gasValue;
};