#4736 System python command refactor (#4743)

* Move case loading commands from Commands to project and case
* Major refactor
* Fix problems with Python examples
* Add ability to export snapshot from just one view + fixup
* Case comments and black
* Make all modules pass pylint test
This commit is contained in:
Gaute Lindkvist 2019-09-23 11:50:33 +02:00 committed by GitHub
parent 00eb02ccec
commit a2bad82391
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 1753 additions and 1432 deletions

View File

@ -832,7 +832,7 @@ RiaApplication::ApplicationStatus RiaGuiApplication::handleArguments( cvf::Progr
// 2016-11-09 : Location of snapshot folder was previously located in 'snapshot' folder // 2016-11-09 : Location of snapshot folder was previously located in 'snapshot' folder
// relative to current working folder. Now harmonized to behave as RiuMainWindow::slotSnapshotAllViewsToFile() // relative to current working folder. Now harmonized to behave as RiuMainWindow::slotSnapshotAllViewsToFile()
QString absolutePathToSnapshotDir = createAbsolutePathFromProjectRelativePath( "snapshots" ); QString absolutePathToSnapshotDir = createAbsolutePathFromProjectRelativePath( "snapshots" );
RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder( absolutePathToSnapshotDir ); RicSnapshotAllViewsToFileFeature::exportSnapshotOfViewsIntoFolder( absolutePathToSnapshotDir );
mainWnd->loadWinGeoAndDockToolBarLayout(); mainWnd->loadWinGeoAndDockToolBarLayout();
} }
@ -1799,7 +1799,7 @@ void RiaGuiApplication::runMultiCaseSnapshots( const QString& templateProj
bool loadOk = loadProject( templateProjectFileName, PLA_NONE, &modifier ); bool loadOk = loadProject( templateProjectFileName, PLA_NONE, &modifier );
if ( loadOk ) if ( loadOk )
{ {
RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder( snapshotFolderName ); RicSnapshotAllViewsToFileFeature::exportSnapshotOfViewsIntoFolder( snapshotFolderName );
} }
} }

View File

@ -208,7 +208,7 @@ void RiaRegressionTestRunner::runRegressionTest()
resizePlotWindows(); resizePlotWindows();
QString fullPathGeneratedFolder = testCaseFolder.absoluteFilePath( generatedFolderName ); QString fullPathGeneratedFolder = testCaseFolder.absoluteFilePath( generatedFolderName );
RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder( fullPathGeneratedFolder ); RicSnapshotAllViewsToFileFeature::exportSnapshotOfViewsIntoFolder( fullPathGeneratedFolder );
RicSnapshotAllPlotsToFileFeature::exportSnapshotOfAllPlotsIntoFolder( fullPathGeneratedFolder ); RicSnapshotAllPlotsToFileFeature::exportSnapshotOfAllPlotsIntoFolder( fullPathGeneratedFolder );

View File

@ -135,3 +135,25 @@ RimEclipseView* RicfApplicationTools::viewFromCaseIdAndViewName( int caseId, con
} }
return nullptr; return nullptr;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEclipseView* RicfApplicationTools::viewFromCaseIdAndViewId( int caseId, int viewId )
{
for ( RimEclipseCase* c : RiaApplication::instance()->project()->eclipseCases() )
{
if ( c->caseId() == caseId )
{
for ( auto v : c->views() )
{
auto eclipseView = dynamic_cast<RimEclipseView*>( v );
if ( eclipseView && eclipseView->id() == viewId )
{
return eclipseView;
}
}
}
}
return nullptr;
}

View File

@ -37,6 +37,7 @@ public:
static std::vector<RimWellPath*> wellPathsFromNames( const QStringList& wellPathNames, QStringList* wellsNotFound ); static std::vector<RimWellPath*> wellPathsFromNames( const QStringList& wellPathNames, QStringList* wellsNotFound );
static RimEclipseCase* caseFromId( int caseId ); static RimEclipseCase* caseFromId( int caseId );
static RimEclipseView* viewFromCaseIdAndViewName( int caseId, const QString& viewName ); static RimEclipseView* viewFromCaseIdAndViewName( int caseId, const QString& viewName );
static RimEclipseView* viewFromCaseIdAndViewId( int caseId, int viewId );
static std::vector<QString> toStringVector( const QStringList& stringList ); static std::vector<QString> toStringVector( const QStringList& stringList );
static QStringList toQStringList( const std::vector<QString>& v ); static QStringList toQStringList( const std::vector<QString>& v );

View File

@ -48,6 +48,7 @@ CAF_PDM_SOURCE_INIT( RicfExportPropertyInViews, "exportPropertyInViews" );
RicfExportPropertyInViews::RicfExportPropertyInViews() RicfExportPropertyInViews::RicfExportPropertyInViews()
{ {
RICF_InitField( &m_caseId, "caseId", -1, "Case ID", "", "", "" ); RICF_InitField( &m_caseId, "caseId", -1, "Case ID", "", "", "" );
RICF_InitField( &m_viewIds, "viewIds", std::vector<int>(), "View IDs", "", "", "" );
RICF_InitField( &m_viewNames, "viewNames", std::vector<QString>(), "View Names", "", "", "" ); RICF_InitField( &m_viewNames, "viewNames", std::vector<QString>(), "View Names", "", "", "" );
RICF_InitField( &m_undefinedValue, "undefinedValue", 0.0, "Undefined Value", "", "", "" ); RICF_InitField( &m_undefinedValue, "undefinedValue", 0.0, "Undefined Value", "", "", "" );
} }
@ -74,22 +75,35 @@ RicfCommandResponse RicfExportPropertyInViews::execute()
RimEclipseView* view = dynamic_cast<RimEclipseView*>( v ); RimEclipseView* view = dynamic_cast<RimEclipseView*>( v );
if ( !view ) continue; if ( !view ) continue;
if ( m_viewNames().empty() ) if ( m_viewNames().empty() && m_viewIds().empty() )
{ {
viewsForExport.push_back( view ); viewsForExport.push_back( view );
} }
else else
{ {
bool matchingName = false; bool matchingIdOrName = false;
for ( const auto& viewName : m_viewNames() )
for ( auto viewId : m_viewIds() )
{ {
if ( view->name().compare( viewName, Qt::CaseInsensitive ) == 0 ) if ( view->id() == viewId )
{ {
matchingName = true; matchingIdOrName = true;
break;
} }
} }
if ( matchingName ) if ( !matchingIdOrName )
{
for ( const auto& viewName : m_viewNames() )
{
if ( view->name().compare( viewName, Qt::CaseInsensitive ) == 0 )
{
matchingIdOrName = true;
}
}
}
if ( matchingIdOrName )
{ {
viewsForExport.push_back( view ); viewsForExport.push_back( view );
} }

View File

@ -44,6 +44,7 @@ public:
private: private:
caf::PdmField<int> m_caseId; caf::PdmField<int> m_caseId;
caf::PdmField<std::vector<int>> m_viewIds;
caf::PdmField<std::vector<QString>> m_viewNames; caf::PdmField<std::vector<QString>> m_viewNames;
caf::PdmField<double> m_undefinedValue; caf::PdmField<double> m_undefinedValue;
}; };

View File

@ -45,6 +45,7 @@ CAF_PDM_SOURCE_INIT( RicfExportSimWellFractureCompletions, "exportSimWellFractur
RicfExportSimWellFractureCompletions::RicfExportSimWellFractureCompletions() RicfExportSimWellFractureCompletions::RicfExportSimWellFractureCompletions()
{ {
RICF_InitField( &m_caseId, "caseId", -1, "Case ID", "", "", "" ); RICF_InitField( &m_caseId, "caseId", -1, "Case ID", "", "", "" );
RICF_InitField( &m_viewId, "viewId", -1, "View ID", "", "", "" );
RICF_InitField( &m_viewName, "viewName", QString( "" ), "View Name", "", "", "" ); RICF_InitField( &m_viewName, "viewName", QString( "" ), "View Name", "", "", "" );
RICF_InitField( &m_timeStep, "timeStep", -1, "Time Step Index", "", "", "" ); RICF_InitField( &m_timeStep, "timeStep", -1, "Time Step Index", "", "", "" );
RICF_InitField( &m_simWellNames, "simulationWellNames", std::vector<QString>(), "Simulation Well Names", "", "", "" ); RICF_InitField( &m_simWellNames, "simulationWellNames", std::vector<QString>(), "Simulation Well Names", "", "", "" );
@ -94,17 +95,19 @@ RicfCommandResponse RicfExportSimWellFractureCompletions::execute()
for ( Rim3dView* v : exportSettings->caseToApply->views() ) for ( Rim3dView* v : exportSettings->caseToApply->views() )
{ {
RimEclipseView* eclipseView = dynamic_cast<RimEclipseView*>( v ); RimEclipseView* eclipseView = dynamic_cast<RimEclipseView*>( v );
if ( eclipseView && eclipseView->name() == m_viewName() ) if ( eclipseView && ( eclipseView->id() == m_viewId() || eclipseView->name() == m_viewName() ) )
{ {
views.push_back( eclipseView ); views.push_back( eclipseView );
} }
} }
if ( views.empty() ) if ( views.empty() )
{ {
QString error = QString( QString error =
"exportSimWellCompletions: Could not find any views named \"%1\" in the case with ID %2" ) QString(
.arg( m_viewName ) "exportSimWellCompletions: Could not find any views with id %1 or named \"%2\" in the case with ID %3" )
.arg( m_caseId() ); .arg( m_viewId )
.arg( m_viewName )
.arg( m_caseId() );
RiaLogging::error( error ); RiaLogging::error( error );
return RicfCommandResponse( RicfCommandResponse::COMMAND_ERROR, error ); return RicfCommandResponse( RicfCommandResponse::COMMAND_ERROR, error );
} }

View File

@ -41,6 +41,7 @@ public:
private: private:
caf::PdmField<int> m_caseId; caf::PdmField<int> m_caseId;
caf::PdmField<int> m_viewId;
caf::PdmField<QString> m_viewName; caf::PdmField<QString> m_viewName;
caf::PdmField<int> m_timeStep; caf::PdmField<int> m_timeStep;
caf::PdmField<std::vector<QString>> m_simWellNames; caf::PdmField<std::vector<QString>> m_simWellNames;

View File

@ -52,6 +52,7 @@ RicfExportSnapshots::RicfExportSnapshots()
RICF_InitField( &m_type, "type", RicfExportSnapshots::SnapshotsTypeEnum(), "Type", "", "", "" ); RICF_InitField( &m_type, "type", RicfExportSnapshots::SnapshotsTypeEnum(), "Type", "", "", "" );
RICF_InitField( &m_prefix, "prefix", QString(), "Prefix", "", "", "" ); RICF_InitField( &m_prefix, "prefix", QString(), "Prefix", "", "", "" );
RICF_InitField( &m_caseId, "caseId", -1, "Case Id", "", "", "" ); RICF_InitField( &m_caseId, "caseId", -1, "Case Id", "", "", "" );
RICF_InitField( &m_viewId, "viewId", -1, "View Id", "", "", "" );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -80,9 +81,10 @@ RicfCommandResponse RicfExportSnapshots::execute()
} }
if ( m_type == RicfExportSnapshots::VIEWS || m_type == RicfExportSnapshots::ALL ) if ( m_type == RicfExportSnapshots::VIEWS || m_type == RicfExportSnapshots::ALL )
{ {
RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder( absolutePathToSnapshotDir, RicSnapshotAllViewsToFileFeature::exportSnapshotOfViewsIntoFolder( absolutePathToSnapshotDir,
m_prefix, m_prefix,
m_caseId() ); m_caseId(),
m_viewId() );
} }
if ( m_type == RicfExportSnapshots::PLOTS || m_type == RicfExportSnapshots::ALL ) if ( m_type == RicfExportSnapshots::PLOTS || m_type == RicfExportSnapshots::ALL )
{ {

View File

@ -51,4 +51,5 @@ private:
caf::PdmField<SnapshotsTypeEnum> m_type; caf::PdmField<SnapshotsTypeEnum> m_type;
caf::PdmField<QString> m_prefix; caf::PdmField<QString> m_prefix;
caf::PdmField<int> m_caseId; caf::PdmField<int> m_caseId;
caf::PdmField<int> m_viewId;
}; };

View File

@ -64,6 +64,7 @@ void AppEnum<RicfExportVisibleCells::ExportKeyword>::setUp()
RicfExportVisibleCells::RicfExportVisibleCells() RicfExportVisibleCells::RicfExportVisibleCells()
{ {
RICF_InitField( &m_caseId, "caseId", -1, "Case ID", "", "", "" ); RICF_InitField( &m_caseId, "caseId", -1, "Case ID", "", "", "" );
RICF_InitField( &m_viewId, "viewId", -1, "View ID", "", "", "" );
RICF_InitField( &m_viewName, "viewName", QString(), "View Name", "", "", "" ); RICF_InitField( &m_viewName, "viewName", QString(), "View Name", "", "", "" );
RICF_InitField( &m_exportKeyword, RICF_InitField( &m_exportKeyword,
"exportKeyword", "exportKeyword",
@ -82,18 +83,27 @@ RicfExportVisibleCells::RicfExportVisibleCells()
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RicfCommandResponse RicfExportVisibleCells::execute() RicfCommandResponse RicfExportVisibleCells::execute()
{ {
if ( m_caseId < 0 || m_viewName().isEmpty() ) if ( m_caseId < 0 || ( m_viewName().isEmpty() && m_viewId() < 0 ) )
{ {
QString error( "exportVisibleCells: CaseId or view name not specified" ); QString error( "exportVisibleCells: CaseId or view name or view id not specified" );
RiaLogging::error( error ); RiaLogging::error( error );
return RicfCommandResponse( RicfCommandResponse::COMMAND_ERROR, error ); return RicfCommandResponse( RicfCommandResponse::COMMAND_ERROR, error );
} }
RimEclipseView* eclipseView = nullptr;
auto eclipseView = RicfApplicationTools::viewFromCaseIdAndViewName( m_caseId, m_viewName ); if ( m_viewId() >= 0 )
{
eclipseView = RicfApplicationTools::viewFromCaseIdAndViewId( m_caseId, m_viewId() );
}
else
{
eclipseView = RicfApplicationTools::viewFromCaseIdAndViewName( m_caseId, m_viewName );
}
if ( !eclipseView ) if ( !eclipseView )
{ {
QString error( QString error( QString( "exportVisibleCells: Could not find view of id %1 or named '%2' in case ID %3" )
QString( "exportVisibleCells: Could not find view '%1' in case ID %2" ).arg( m_viewName ).arg( m_caseId ) ); .arg( m_viewId )
.arg( m_viewName )
.arg( m_caseId ) );
RiaLogging::error( error ); RiaLogging::error( error );
return RicfCommandResponse( RicfCommandResponse::COMMAND_ERROR, error ); return RicfCommandResponse( RicfCommandResponse::COMMAND_ERROR, error );
} }

View File

@ -51,6 +51,7 @@ private:
void buildExportSettings( const QString& exportFolder, RicSaveEclipseInputVisibleCellsUi* exportSettings ); void buildExportSettings( const QString& exportFolder, RicSaveEclipseInputVisibleCellsUi* exportSettings );
caf::PdmField<int> m_caseId; caf::PdmField<int> m_caseId;
caf::PdmField<int> m_viewId;
caf::PdmField<QString> m_viewName; caf::PdmField<QString> m_viewName;
caf::PdmField<caf::AppEnum<ExportKeyword>> m_exportKeyword; caf::PdmField<caf::AppEnum<ExportKeyword>> m_exportKeyword;
caf::PdmField<int> m_visibleActiveCellsValue; caf::PdmField<int> m_visibleActiveCellsValue;

View File

@ -35,6 +35,7 @@ CAF_PDM_SOURCE_INIT( RicfSetTimeStep, "setTimeStep" );
RicfSetTimeStep::RicfSetTimeStep() RicfSetTimeStep::RicfSetTimeStep()
{ {
RICF_InitField( &m_caseId, "caseId", -1, "Case ID", "", "", "" ); RICF_InitField( &m_caseId, "caseId", -1, "Case ID", "", "", "" );
RICF_InitField( &m_viewId, "viewId", -1, "View ID", "", "", "" );
RICF_InitField( &m_timeStepIndex, "timeStep", -1, "Time Step Index", "", "", "" ); RICF_InitField( &m_timeStepIndex, "timeStep", -1, "Time Step Index", "", "", "" );
} }
@ -46,6 +47,14 @@ void RicfSetTimeStep::setCaseId( int caseId )
m_caseId = caseId; m_caseId = caseId;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicfSetTimeStep::setViewId( int viewId )
{
m_viewId = viewId;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -93,8 +102,11 @@ RicfCommandResponse RicfSetTimeStep::execute()
for ( Rim3dView* view : eclipseCase->views() ) for ( Rim3dView* view : eclipseCase->views() )
{ {
view->setCurrentTimeStepAndUpdate( m_timeStepIndex ); if ( m_viewId() == -1 || view->id() == m_viewId() )
view->createDisplayModelAndRedraw(); {
view->setCurrentTimeStepAndUpdate( m_timeStepIndex );
view->createDisplayModelAndRedraw();
}
} }
return RicfCommandResponse(); return RicfCommandResponse();

View File

@ -35,11 +35,13 @@ public:
RicfSetTimeStep(); RicfSetTimeStep();
void setCaseId( int caseId ); void setCaseId( int caseId );
void setViewId( int viewId );
void setTimeStepIndex( int timeStepIndex ); void setTimeStepIndex( int timeStepIndex );
RicfCommandResponse execute() override; RicfCommandResponse execute() override;
private: private:
caf::PdmField<int> m_caseId; caf::PdmField<int> m_caseId;
caf::PdmField<int> m_viewId;
caf::PdmField<int> m_timeStepIndex; caf::PdmField<int> m_timeStepIndex;
}; };

View File

@ -60,18 +60,19 @@ void RicSnapshotAllViewsToFileFeature::saveAllViews()
// Save images in snapshot catalog relative to project directory // Save images in snapshot catalog relative to project directory
QString snapshotFolderName = app->createAbsolutePathFromProjectRelativePath( "snapshots" ); QString snapshotFolderName = app->createAbsolutePathFromProjectRelativePath( "snapshots" );
exportSnapshotOfAllViewsIntoFolder( snapshotFolderName ); exportSnapshotOfViewsIntoFolder( snapshotFolderName );
QString text = QString( "Exported snapshots to folder : \n%1" ).arg( snapshotFolderName ); QString text = QString( "Exported snapshots to folder : \n%1" ).arg( snapshotFolderName );
RiaLogging::info( text ); RiaLogging::info( text );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Export all snapshots of a given case (or caseId == -1 for all cases) /// Export snapshots of a given view (or viewId == -1 for all views) for the given case (or caseId == -1 for all cases)
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder( const QString& snapshotFolderName, void RicSnapshotAllViewsToFileFeature::exportSnapshotOfViewsIntoFolder( const QString& snapshotFolderName,
const QString& prefix /*= ""*/, const QString& prefix /*= ""*/,
int caseId /*= -1*/ ) int caseId /*= -1*/,
int viewId /*= -1*/ )
{ {
RimProject* project = RiaApplication::instance()->project(); RimProject* project = RiaApplication::instance()->project();
@ -104,7 +105,7 @@ void RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder( const
{ {
Rim3dView* riv = views[j]; Rim3dView* riv = views[j];
if ( riv && riv->viewer() ) if ( riv && riv->viewer() && ( viewId == -1 || viewId == riv->id() ) )
{ {
RiaApplication::instance()->setActiveReservoirView( riv ); RiaApplication::instance()->setActiveReservoirView( riv );

View File

@ -32,9 +32,10 @@ class RicSnapshotAllViewsToFileFeature : public caf::CmdFeature
public: public:
static void saveAllViews(); static void saveAllViews();
static void exportSnapshotOfAllViewsIntoFolder( const QString& snapshotFolderName, static void exportSnapshotOfViewsIntoFolder( const QString& snapshotFolderName,
const QString& prefix = "", const QString& prefix = "",
int caseId = -1 ); int caseId = -1,
int viewId = -1 );
protected: protected:
// Overrides // Overrides

View File

@ -85,7 +85,7 @@ set(PROTO_FILES
"Commands" "Commands"
"App" "App"
"Properties" "Properties"
"Grid" "grid"
) )
set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}/Python") set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}/Python")
@ -162,15 +162,13 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE)
list(APPEND GRPC_PYTHON_SOURCES list(APPEND GRPC_PYTHON_SOURCES
"rips/generated/RiaVersionInfo.py" "rips/generated/RiaVersionInfo.py"
"rips/__init__.py" "rips/__init__.py"
"rips/Case.py" "rips/case.py"
"rips/Commands.py" "rips/grid.py"
"rips/Grid.py" "rips/gridcasegroup.py"
"rips/GridCaseGroup.py" "rips/project.py"
"rips/Project.py" "rips/instance.py"
"rips/Properties.py" "rips/pdmobject.py"
"rips/Instance.py" "rips/view.py"
"rips/PdmObject.py"
"rips/View.py"
"rips/PythonExamples/InstanceExample.py" "rips/PythonExamples/InstanceExample.py"
"rips/PythonExamples/CommandExample.py" "rips/PythonExamples/CommandExample.py"
"rips/PythonExamples/CaseGridGroup.py" "rips/PythonExamples/CaseGridGroup.py"
@ -191,7 +189,6 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE)
"rips/PythonExamples/SoilAverageSync.py" "rips/PythonExamples/SoilAverageSync.py"
"rips/PythonExamples/ViewExample.py" "rips/PythonExamples/ViewExample.py"
"rips/tests/test_cases.py" "rips/tests/test_cases.py"
"rips/tests/test_commands.py"
"rips/tests/test_grids.py" "rips/tests/test_grids.py"
"rips/tests/test_properties.py" "rips/tests/test_properties.py"
"rips/tests/test_project.py" "rips/tests/test_project.py"

View File

@ -53,6 +53,7 @@ message ExportSnapshotsRequest
SnapshotType type = 1; SnapshotType type = 1;
string prefix = 2; string prefix = 2;
int32 caseId = 3; int32 caseId = 3;
int32 viewId = 4;
} }
message ExportPropertyRequest message ExportPropertyRequest
@ -67,9 +68,9 @@ message ExportPropertyRequest
message ExportPropertyInViewsRequest message ExportPropertyInViewsRequest
{ {
int32 caseId = 1; int32 caseId = 1;
repeated string viewNames = 2; repeated int32 viewIds = 2;
double undefinedValue = 3; double undefinedValue = 3;
} }
enum CompdatExportSplit enum CompdatExportSplit
@ -89,7 +90,7 @@ enum CompdatExportType
enum CompdatCombinationMode enum CompdatCombinationMode
{ {
INDIVIDUALLY = 0; INDIVIDUALLY = 0;
caCOMBINED = 1; COMBINED = 1;
} }
message ExportWellPathCompRequest message ExportWellPathCompRequest
@ -108,7 +109,7 @@ message ExportWellPathCompRequest
message ExportSimWellPathFracRequest message ExportSimWellPathFracRequest
{ {
int32 caseId = 1; int32 caseId = 1;
string viewName = 2; int32 viewId = 2;
int32 timeStep = 3; int32 timeStep = 3;
repeated string simulationWellNames = 4; repeated string simulationWellNames = 4;
CompdatExportSplit fileSplit = 5; CompdatExportSplit fileSplit = 5;
@ -130,7 +131,7 @@ message ExportWellPathRequest
message ExportVisibleCellsRequest message ExportVisibleCellsRequest
{ {
int32 caseId = 1; int32 caseId = 1;
string viewName = 2; int32 viewId = 2;
string exportKeyword = 3; string exportKeyword = 3;
int32 visibleActiveCellsValue = 4; int32 visibleActiveCellsValue = 4;
int32 hiddenActiveCellsValue = 5; int32 hiddenActiveCellsValue = 5;
@ -175,7 +176,8 @@ message ComputeCaseGroupStatRequest
message SetTimeStepParams message SetTimeStepParams
{ {
int32 caseId = 1; int32 caseId = 1;
int32 timeStep = 2; int32 viewId = 2;
int32 timeStep = 3;
} }
message ScaleFractureTemplateRequest message ScaleFractureTemplateRequest

View File

@ -1,188 +0,0 @@
import grpc
import os
import sys
from rips.Commands import Commands
from rips.Grid import Grid
from rips.Properties import Properties
from rips.PdmObject import PdmObject
from rips.View import View
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
import Case_pb2
import Case_pb2_grpc
import PdmObject_pb2
class Case (PdmObject):
"""ResInsight case class
Operate on a ResInsight case specified by a Case Id integer.
Not meant to be constructed separately but created by one of the following
methods in Project: loadCase, case, allCases, selectedCases
Attributes:
id (int): Case Id corresponding to case Id in ResInsight project.
name (str): Case name
groupId (int): Case Group id
"""
def __init__(self, channel, id):
self.channel = channel
self.stub = Case_pb2_grpc.CaseStub(channel)
self.id = id
info = self.stub.GetCaseInfo(Case_pb2.CaseRequest(id=self.id))
self.name = info.name
self.group_id = info.group_id
self.type = info.type
self.properties = Properties(self)
self.request = Case_pb2.CaseRequest(id=self.id)
PdmObject.__init__(self, self.stub.GetPdmObject(self.request), self.channel)
def grid_count(self):
"""Get number of grids in the case"""
try:
return self.stub.GetGridCount(self.request).count
except grpc.RpcError as e:
if e.code() == grpc.StatusCode.NOT_FOUND:
return 0
print("ERROR: ", e)
return 0
def grid_path(self):
return self.get_value("CaseFileName")
def grid(self, index):
"""Get Grid of a given index. Returns a rips Grid object
Arguments:
index (int): The grid index
Returns: Grid object
"""
return Grid(index, self)
def grids(self):
"""Get a list of all rips Grid objects in the case"""
grid_list = []
for i in range(0, self.grid_count()):
grid_list.append(Grid(i, self))
return grid_list
def cell_count(self, porosity_model='MATRIX_MODEL'):
"""Get a cell count object containing number of active cells and
total number of cells
Arguments:
porosity_model (str): String representing an enum.
must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
Returns:
Cell Count object with the following integer attributes:
active_cell_count: number of active cells
reservoir_cell_count: total number of reservoir cells
"""
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Case_pb2.CellInfoRequest(case_request=self.request,
porosity_model=porosity_model_enum)
return self.stub.GetCellCount(request)
def cell_info_for_active_cells_async(self, porosity_model='MATRIX_MODEL'):
"""Get Stream of cell info objects for current case
Arguments:
porosity_model(str): String representing an enum.
must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
Returns:
Stream of **CellInfo** objects
See cell_info_for_active_cells() for detalis on the **CellInfo** class.
"""
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Case_pb2.CellInfoRequest(case_request=self.request,
porosity_model=porosity_model_enum)
return self.stub.GetCellInfoForActiveCells(request)
def cell_info_for_active_cells(self, porosity_model='MATRIX_MODEL'):
"""Get list of cell info objects for current case
Arguments:
porosity_model(str): String representing an enum.
must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
Returns:
List of **CellInfo** objects
### CellInfo class description
Parameter | Description | Type
------------------------- | --------------------------------------------- | -----
grid_index | Index to grid | Integer
parent_grid_index | Index to parent grid | Integer
coarsening_box_index | Index to coarsening box | Integer
local_ijk | Cell index in IJK directions of local grid | Vec3i
parent_ijk | Cell index in IJK directions of parent grid | Vec3i
### Vec3i class description
Parameter | Description | Type
---------------- | -------------------------------------------- | -----
i | I grid index | Integer
j | J grid index | Integer
k | K grid index | Integer
"""
active_cell_info_chunks = self.cell_info_for_active_cells_async()
received_active_cells = []
for active_cell_chunk in active_cell_info_chunks:
for active_cell in active_cell_chunk.data:
received_active_cells.append(active_cell)
return received_active_cells
def time_steps(self):
"""Get a list containing all time steps
The time steps are defined by the class **TimeStepDate** :
Type | Name
--------- | ----------
int | year
int | month
int | day
int | hour
int | minute
int | second
"""
return self.stub.GetTimeSteps(self.request).dates
def days_since_start(self):
"""Get a list of decimal values representing days since the start of the simulation"""
return self.stub.GetDaysSinceStart(self.request).day_decimals
def views(self):
"""Get a list of views belonging to a case"""
pdm_objects = self.children("ReservoirViews")
view_list = []
for pdm_object in pdm_objects:
view_list.append(View(pdm_object))
return view_list
def view(self, id):
"""Get a particular view belonging to a case by providing view id
Arguments:
id(int): view id
Returns: a view object
"""
views = self.views()
for view_object in views:
if view_object.id == id:
return view_object
return None
def create_view(self):
"""Create a new view in the current case"""
view_id = Commands(self.channel).create_view(self.id)
return self.view(view_id)

View File

@ -1,311 +0,0 @@
import grpc
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
from Definitions_pb2 import Empty
import Commands_pb2 as Cmd
import Commands_pb2_grpc as CmdRpc
import rips.Case
class Commands:
"""Command executor which can run ResInsight Command File commands nearly verbatim. See
[ Command File Interface ]({{< ref "commandfile.md" >}})
The differences are:
- Enum values have to be provided as strings. I.e. "ALL" instead of ALL.
- Booleans have to be specified as correct Python. True instead of true.
"""
def __init__(self, channel):
self.channel = channel
self.commands = CmdRpc.CommandsStub(channel)
def __execute(self, **command_params):
return self.commands.Execute(Cmd.CommandParams(**command_params))
########################
# Case Control Commands
########################
def open_project(self, path):
"""Open a project
Arguments:
path (str): path to project file
"""
return self.__execute(openProject=Cmd.FilePathRequest(path=path))
def close_project(self):
"""Close the current project (and reopen empty one)"""
return self.__execute(closeProject=Empty())
def set_start_dir(self, path):
"""Set current start directory
Arguments:
path (str): path to directory
"""
return self.__execute(setStartDir=Cmd.FilePathRequest(path=path))
def load_case(self, path):
"""Load a case
Arguments:
path (str): path to EGRID file
Returns:
A Case object
"""
command_reply = self.__execute(loadCase=Cmd.FilePathRequest(path=path))
return rips.Case(self.channel, command_reply.loadCaseResult.id)
def replace_case(self, new_grid_file, case_id=0):
"""Replace the given case with a new case loaded from file
Arguments:
new_grid_file (str): path to EGRID file
case_id (int): case Id to replace
"""
return self.__execute(replaceCase=Cmd.ReplaceCaseRequest(newGridFile=new_grid_file,
caseId=case_id))
def replace_source_cases(self, grid_list_file, case_group_id=0):
"""Replace all source cases within a case group
Arguments:
grid_list_file (str): path to file containing a list of cases
case_group_id (int): id of the case group to replace
"""
return self.__execute(replaceSourceCases=Cmd.ReplaceSourceCasesRequest(gridListFile=grid_list_file,
caseGroupId=case_group_id))
def create_grid_case_group(self, case_paths):
"""Create a Grid Case Group from a list of cases
Arguments:
case_paths (list): list of file path strings
Returns:
A case group id and name
"""
commandReply = self.__execute(createGridCaseGroup=Cmd.CreateGridCaseGroupRequest(casePaths=case_paths))
return (commandReply.createGridCaseGroupResult.groupId, commandReply.createGridCaseGroupResult.groupName)
def create_statistics_case(self, case_group_id):
"""Create a Statistics case in a Grid Case Group
Arguments:
case_group_id (int): id of the case group
Returns:
A case id for the new case
"""
commandReply = self.__execute(createStatisticsCase=Cmd.CreateStatisticsCaseRequest(caseGroupId=case_group_id))
return commandReply.createStatisticsCaseResult.caseId
##################
# Export Commands
##################
def export_multi_case_snapshots(self, grid_list_file):
"""Export snapshots for a set of cases
Arguments:
grid_list_file (str): Path to a file containing a list of grids to export snapshot for
"""
return self.__execute(exportMultiCaseSnapshot=Cmd.ExportMultiCaseRequest(gridListFile=grid_list_file))
def export_snapshots(self, type = 'ALL', prefix='', case_id = -1):
""" Export snapshots of a given type
Arguments:
type (str): Enum string ('ALL', 'VIEWS' or 'PLOTS')
prefix (str): Exported file name prefix
case_id (int): the case Id to export for. The default of -1 will export all cases
"""
return self.__execute(exportSnapshots=Cmd.ExportSnapshotsRequest(type=type,
prefix=prefix,
caseId=case_id))
def export_property(self, case_id, time_step, property, eclipse_keyword=property, undefined_value=0.0, export_file=property):
""" Export an Eclipse property
Arguments:
case_id (int): case id
time_step (int): time step index
property (str): property to export
eclipse_keyword (str): Eclipse keyword used as text in export header. Defaults to the value of property parameter.
undefined_value (double): Value to use for undefined values. Defaults to 0.0
export_file (str): File name for export. Defaults to the value of property parameter
"""
return self.__execute(exportProperty=Cmd.ExportPropertyRequest(caseId=case_id,
timeStep=time_step,
property=property,
eclipseKeyword=eclipse_keyword,
undefinedValue=undefined_value,
exportFile=export_file))
def export_property_in_views(self, case_id, view_names, undefined_value):
""" Export the current Eclipse property from the given views
Arguments:
case_id (int): case id
view_names (list): list of views
undefined_value (double): Value to use for undefined values. Defaults to 0.0
"""
if isinstance(view_names, str):
view_names = [view_names]
return self.__execute(exportPropertyInViews=Cmd.ExportPropertyInViewsRequest(caseId=case_id,
viewNames=view_names,
undefinedValue=undefined_value))
def export_well_path_completions(self, case_id, time_step, well_path_names, file_split,
compdat_export, include_perforations, include_fishbones,
exclude_main_bore_for_fishbones, combination_mode):
if (isinstance(well_path_names, str)):
well_path_names = [well_path_names]
return self.__execute(exportWellPathCompletions=Cmd.ExportWellPathCompRequest(caseId=case_id,
timeStep=time_step,
wellPathNames=well_path_names,
fileSplit=file_split,
compdatExport=compdat_export,
includePerforations=include_perforations,
includeFishbones=include_fishbones,
excludeMainBoreForFishbones=exclude_main_bore_for_fishbones,
combinationMode=combination_mode))
def export_sim_well_fracture_completions(self, case_id, view_name, time_step, simulation_well_names, file_split, compdat_export):
if(isinstance(simulation_well_names, str)):
simulation_well_names = [simulation_well_names]
return self.__execute(exportSimWellFractureCompletions=Cmd.ExportSimWellPathFraqRequest(caseId=case_id,
viewName=view_name,
timeStep=time_step,
simulationWellNames=simulation_well_names,
fileSplit=file_split,
compdatExport=compdat_export))
def export_msw(self, case_id, well_path):
return self.__execute(exportMsw=Cmd.ExportMswRequest(caseId=case_id,
wellPath=well_path))
def export_well_paths(self, well_paths=[], md_step_size=5.0):
if isinstance(well_paths, str):
well_paths = [well_paths]
return self.__execute(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=well_paths, mdStepSize=md_step_size))
def export_visible_cells(self, case_id, view_name, export_keyword='FLUXNUM', visible_active_cells_value=1, hidden_active_cells_value=0, inactive_cells_value=0):
return self.__execute(exportVisibleCells=Cmd.ExportVisibleCellsRequest(caseId=case_id,
viewName=view_name,
exportKeyword=export_keyword,
visibleActiveCellsValue=visible_active_cells_value,
hiddenActiveCellsValue=hidden_active_cells_value,
inactiveCellsValue=inactive_cells_value))
def set_export_folder(self, type, path, create_folder=False):
return self.__execute(setExportFolder=Cmd.SetExportFolderRequest(type=type,
path=path,
createFolder=create_folder))
def run_octave_script(self, path, cases):
caseIds = []
for case in cases:
caseIds.append(case.id)
return self.__execute(runOctaveScript=Cmd.RunOctaveScriptRequest(path=path,
caseIds=caseIds))
def set_main_window_size(self, width, height):
return self.__execute(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height))
def compute_case_group_statistics(self, case_ids = [], case_group_id = -1):
return self.__execute(computeCaseGroupStatistics=Cmd.ComputeCaseGroupStatRequest(caseIds=case_ids,
caseGroupId=case_group_id))
def set_time_step(self, case_id, time_step):
return self.__execute(setTimeStep=Cmd.SetTimeStepParams(caseId=case_id, timeStep=time_step))
def scale_fracture_template(self, id, half_length, height, dfactor, conductivity):
return self.__execute(scaleFractureTemplate=Cmd.ScaleFractureTemplateRequest(id=id,
halfLength=half_length,
height=height,
dFactor=dfactor,
conductivity=conductivity))
def set_fracture_containment(self, id, top_layer, base_layer):
return self.__execute(setFractureContainment=Cmd.SetFracContainmentRequest(id=id,
topLayer=top_layer,
baseLayer=base_layer))
def create_multiple_fractures(self, case_id, template_id, well_path_names, min_dist_from_well_td,
max_fractures_per_well, top_layer, base_layer, spacing, action):
if isinstance(well_path_names, str):
well_path_names = [well_path_names]
return self.__execute(createMultipleFractures=Cmd.MultipleFracAction(caseId=case_id,
templateId=template_id,
wellPathNames=well_path_names,
minDistFromWellTd=min_dist_from_well_td,
maxFracturesPerWell=max_fractures_per_well,
topLayer=top_layer,
baseLayer=base_layer,
spacing=spacing,
action=action))
def create_lgr_for_completion(self, case_id, time_step, well_path_names, refinement_i, refinement_j, refinement_k, split_type):
if isinstance(well_path_names, str):
well_path_names = [well_path_names]
return self.__execute(createLgrForCompletions=Cmd.CreateLgrForCompRequest(caseId=case_id,
timeStep=time_step,
wellPathNames=well_path_names,
refinementI=refinement_i,
refinementJ=refinement_j,
refinementK=refinement_k,
splitType=split_type))
def create_saturation_pressure_plots(self, case_ids):
if isinstance(case_ids, int):
case_ids = [case_ids]
return self.__execute(createSaturationPressurePlots=Cmd.CreateSatPressPlotRequest(caseIds=case_ids))
def export_flow_characteristics(self, case_id, time_steps, injectors, producers, file_name, minimum_communication=0.0, aquifer_cell_threshold=0.1):
""" Export Flow Characteristics data to text file in CSV format
Parameter | Description | Type
------------------------- | --------------------------------------------- | -----
case_id | ID of case | Integer
time_steps | Time step indices | List of Integer
injectors | Injector names | List of Strings
producers | Producer names | List of Strings
file_name | Export file name | Integer
minimum_communication | Minimum Communication, defaults to 0.0 | Integer
aquifer_cell_threshold | Aquifer Cell Threshold, defaults to 0.1 | Integer
"""
if isinstance(time_steps, int):
time_steps = [time_steps]
if isinstance(injectors, str):
injectors = [injectors]
if isinstance(producers, str):
producers = [producers]
return self.__execute(exportFlowCharacteristics=Cmd.ExportFlowInfoRequest(caseId=case_id,
timeSteps=time_steps,
injectors=injectors,
producers=producers,
fileName=file_name,
minimumCommunication = minimum_communication,
aquiferCellThreshold = aquifer_cell_threshold))
def create_view(self, case_id):
return self.__execute(createView=Cmd.CreateViewRequest(caseId=case_id)).createViewResult.viewId
def clone_view(self, view_id):
return self.__execute(cloneView=Cmd.CloneViewRequest(viewId=view_id)).createViewResult.viewId

View File

@ -1,27 +0,0 @@
import grpc
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
import Grid_pb2
import Grid_pb2_grpc
class Grid:
"""Grid Information. Not meant to be constructed separately
Create Grid objects using mathods on Case: Grid() and Grids()
"""
def __init__(self, index, case):
self.case = case
self.index = index
self.stub = Grid_pb2_grpc.GridStub(self.case.channel)
def dimensions(self):
"""The dimensions in i, j, k direction
Returns:
Vec3i: class with integer attributes i, j, k representing the extent in all three dimensions.
"""
return self.stub.GetDimensions(Grid_pb2.GridRequest(case_request = self.case.request, grid_index = self.index)).dimensions

View File

@ -1,48 +0,0 @@
import grpc
import os
import sys
from rips.PdmObject import PdmObject
from rips.View import View
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
import PdmObject_pb2
class GridCaseGroup (PdmObject):
"""ResInsight Grid Case Group class
Operate on a ResInsight case group specified by a Case Group Id integer.
Attributes:
group_id (int): Grid Case Group Id corresponding to case group Id in ResInsight project.
"""
def __init__(self, pdm_object):
self.group_id = pdm_object.get_value("GroupId")
PdmObject.__init__(self, pdm_object.pb2Object, pdm_object.channel)
def statistics_cases(self):
"""Get a list of all statistics cases in the Grid Case Group"""
stat_case_collection = self.children("StatisticsCaseCollection")[0]
return stat_case_collection.children("Reservoirs")
def views(self):
"""Get a list of views belonging to a grid case group"""
pdm_objects = self.descendants("ReservoirView")
view_list = []
for pdm_object in pdm_objects:
view_list.append(View(pdm_object))
return view_list
def view(self, id):
"""Get a particular view belonging to a case group by providing view id
Arguments:
id(int): view id
Returns: a view object
"""
views = self.views()
for view_object in views:
if view_object.id == id:
return view_object
return None

View File

@ -1,196 +0,0 @@
import grpc
import os
import sys
import socket
import logging
import time
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
import App_pb2
import App_pb2_grpc
from Definitions_pb2 import Empty
import RiaVersionInfo
from rips.Commands import Commands
from rips.Project import Project
class Instance:
"""The ResInsight Instance class. Use to launch or find existing ResInsight instances
Attributes:
launched (bool): Tells us whether the application was launched as a new process.
If the application was launched we may need to close it when exiting the script.
commands (Commands): Command executor. Set when creating an instance.
project (Project): Current project in ResInsight.
Set when creating an instance and updated when opening/closing projects.
"""
@staticmethod
def __is_port_in_use(port):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(0.2)
return s.connect_ex(('localhost', port)) == 0
@staticmethod
def launch(resinsight_executable = '', console = False, launch_port = -1, command_line_parameters=[]):
""" Launch a new Instance of ResInsight. This requires the environment variable
RESINSIGHT_EXECUTABLE to be set or the parameter resinsight_executable to be provided.
The RESINSIGHT_GRPC_PORT environment variable can be set to an alternative port number.
Args:
resinsight_executable (str): Path to a valid ResInsight executable. If set
will take precedence over what is provided in the RESINSIGHT_EXECUTABLE
environment variable.
console (bool): If True, launch as console application, without GUI.
launch_port(int): If -1 will use the default port of 50051 or look for RESINSIGHT_GRPC_PORT
if anything else, ResInsight will try to launch with this port
command_line_parameters(list): Additional command line parameters as string entries in the list.
Returns:
Instance: an instance object if it worked. None if not.
"""
port = 50051
port_env = os.environ.get('RESINSIGHT_GRPC_PORT')
if port_env:
port = int(port_env)
if launch_port is not -1:
port = launch_port
if not resinsight_executable:
resinsight_executable = os.environ.get('RESINSIGHT_EXECUTABLE')
if not resinsight_executable:
print('ERROR: Could not launch ResInsight because the environment variable'
' RESINSIGHT_EXECUTABLE is not set')
return None
while Instance.__is_port_in_use(port):
port += 1
print('Port ' + str(port))
print('Trying to launch', resinsight_executable)
if isinstance(command_line_parameters, str):
command_line_parameters = [str]
parameters = ["ResInsight", "--server", str(port)] + command_line_parameters
if console:
print("Launching as console app")
parameters.append("--console")
# Stringify all parameters
for i in range(0, len(parameters)):
parameters[i] = str(parameters[i])
pid = os.spawnv(os.P_NOWAIT, resinsight_executable, parameters)
if pid:
instance = Instance(port=port, launched=True)
return instance
return None
@staticmethod
def find(start_port = 50051, end_port = 50071):
""" Search for an existing Instance of ResInsight by testing ports.
By default we search from port 50051 to 50071 or if the environment
variable RESINSIGHT_GRPC_PORT is set we search
RESINSIGHT_GRPC_PORT to RESINSIGHT_GRPC_PORT+20
Args:
start_port (int): start searching from this port
end_port (int): search up to but not including this port
"""
port_env = os.environ.get('RESINSIGHT_GRPC_PORT')
if port_env:
start_port = int(port_env)
end_port = start_port + 20
for try_port in range(start_port, end_port):
if Instance.__is_port_in_use(try_port):
return Instance(port=try_port)
print('Error: Could not find any ResInsight instances responding between ports ' + str(start_port) + ' and ' + str(end_port))
return None
def __check_version(self):
try:
major_version_ok = self.major_version() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION)
minor_version_ok = self.minor_version() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION)
return True, major_version_ok and minor_version_ok
except:
return False, False
def __init__(self, port = 50051, launched = False):
""" Attempts to connect to ResInsight at aa specific port on localhost
Args:
port(int): port number
"""
logging.basicConfig()
location = "localhost:" + str(port)
self.channel = grpc.insecure_channel(location, options=[('grpc.enable_http_proxy', False)])
self.launched = launched
# Main version check package
self.app = self.app = App_pb2_grpc.AppStub(self.channel)
connection_ok = False
version_ok = False
if self.launched:
for i in range(0, 10):
connection_ok, version_ok = self.__check_version()
if connection_ok:
break
time.sleep(1.0)
else:
connection_ok, version_ok = self.__check_version()
if not connection_ok:
if self.launched:
raise Exception('Error: Could not connect to resinsight at ', location, ' after trying 10 times with 1 second apart')
else:
raise Exception('Error: Could not connect to resinsight at ', location)
exit(1)
if not version_ok:
raise Exception('Error: Wrong Version of ResInsight at ', location)
# Service packages
self.commands = Commands(self.channel)
self.project = Project(self.channel)
path = os.getcwd()
self.commands.set_start_dir(path=path)
def __version_message(self):
return self.app.GetVersion(Empty())
def major_version(self):
"""Get an integer with the major version number"""
return self.__version_message().major_version
def minor_version(self):
"""Get an integer with the minor version number"""
return self.__version_message().minor_version
def patch_version(self):
"""Get an integer with the patch version number"""
return self.__version_message().patch_version
def version_string(self):
"""Get a full version string, i.e. 2019.04.01"""
return str(self.major_version()) + "." + str(self.minor_version()) + "." + str(self.patch_version())
def exit(self):
"""Tell ResInsight instance to quit"""
print("Telling ResInsight to Exit")
return self.app.Exit(Empty())
def is_console(self):
"""Returns true if the connected ResInsight instance is a console app"""
return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('CONSOLE_APPLICATION')
def is_gui(self):
"""Returns true if the connected ResInsight instance is a GUI app"""
return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('GUI_APPLICATION')

View File

@ -1,149 +0,0 @@
import grpc
import os
import sys
from rips.Case import Case
from rips.Commands import Commands
from rips.GridCaseGroup import GridCaseGroup
from rips.PdmObject import PdmObject
from rips.View import View
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
from Definitions_pb2 import Empty
import Project_pb2
import Project_pb2_grpc
class Project (PdmObject):
"""ResInsight project. Not intended to be created separately.
Automatically created and assigned to Instance.
"""
def __init__(self, channel):
self.channel = channel
self.project = Project_pb2_grpc.ProjectStub(channel)
PdmObject.__init__(self, self.project.GetPdmObject(Empty()), self.channel)
def open(self, path):
"""Open a new project from the given path
Arguments:
path(str): path to project file
"""
Commands(self.channel).open_project(path)
return self
def close(self):
"""Close the current project (and open new blank project)"""
Commands(self.channel).close_project()
def selected_cases(self):
"""Get a list of all cases selected in the project tree
Returns:
A list of rips Case objects
"""
case_infos = self.project.GetSelectedCases(Empty())
cases = []
for case_info in case_infos.data:
cases.append(Case(self.channel, case_info.id))
return cases
def cases(self):
"""Get a list of all cases in the project
Returns:
A list of rips Case objects
"""
try:
case_infos = self.project.GetAllCases(Empty())
cases = []
for case_info in case_infos.data:
cases.append(Case(self.channel, case_info.id))
return cases
except grpc.RpcError as e:
if e.code() == grpc.StatusCode.NOT_FOUND:
return []
else:
print("ERROR: ", e)
return []
def case(self, id):
"""Get a specific case from the provided case Id
Arguments:
id(int): case id
Returns:
A rips Case object
"""
try:
case = Case(self.channel, id)
return case
except grpc.RpcError as e:
return None
def load_case(self, path):
"""Load a new case from the given file path
Arguments:
path(str): file path to case
Returns:
A rips Case object
"""
return Commands(self.channel).load_case(path)
def views(self):
"""Get a list of views belonging to a project"""
pdm_objects = self.descendants("ReservoirView")
view_list = []
for pdm_object in pdm_objects:
view_list.append(View(pdm_object))
return view_list
def view(self, id):
"""Get a particular view belonging to a case by providing view id
Arguments:
id(int): view id
Returns: a view object
"""
views = self.views()
for view_object in views:
if view_object.id == id:
return view_object
return None
def grid_case_groups(self):
"""Get a list of all grid case groups in the project"""
case_groups = self.descendants("RimIdenticalGridCaseGroup")
case_group_list = []
for pdm_group in case_groups:
case_group_list.append(GridCaseGroup(pdm_group))
return case_group_list
def grid_case_group(self, group_id):
"""Get a particular grid case group belonging to a project
Arguments:
groupId(int): group id
Returns: a grid case group object
"""
case_groups = self.grid_case_groups()
for case_group in case_groups:
if case_group.groupId == group_id:
return case_group
return None
def create_grid_case_group(self, case_paths):
"""Create a new grid case group from the provided case paths
Arguments:
casePaths(list): a list of paths to the cases to be loaded and included in the group
Returns:
A new grid case group object
"""
group_id, group_name = Commands(self.channel).create_grid_case_group(case_paths)
return self.grid_case_group(group_id)

View File

@ -1,239 +0,0 @@
import grpc
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
import Properties_pb2
import Properties_pb2_grpc
import Case_pb2
import Case_pb2_grpc
from Definitions_pb2 import ClientToServerStreamReply
class Properties:
""" Class for streaming properties to and from ResInsight
Attributes:
chunkSize(int): The size of each chunk during value streaming.
A good chunk size is 64KiB = 65536B.
Meaning the ideal number of doubles would be 8192.
However we need overhead space, so the default is 8160.
This leaves 256B for overhead.
"""
def __init__(self, case):
"""
Arguments:
case(Case): A rips case to handle properties for
"""
self.case = case
self._properties_stub = Properties_pb2_grpc.PropertiesStub(self.case.channel)
self.chunk_size = 8160
def __generate_property_input_iterator(self, values_iterator, parameters):
chunk = Properties_pb2.PropertyInputChunk()
chunk.params.CopyFrom(parameters)
yield chunk
for values in values_iterator:
valmsg = Properties_pb2.PropertyChunk(values = values)
chunk.values.CopyFrom(valmsg)
yield chunk
def __generate_property_input_chunks(self, array, parameters):
index = -1
while index < len(array):
chunk = Properties_pb2.PropertyInputChunk()
if index is -1:
chunk.params.CopyFrom(parameters)
index += 1
else:
actual_chunk_size = min(len(array) - index + 1, self.chunk_size)
chunk.values.CopyFrom(Properties_pb2.PropertyChunk(values = array[index:index+actual_chunk_size]))
index += actual_chunk_size
yield chunk
# Final empty message to signal completion
chunk = Properties_pb2.PropertyInputChunk()
yield chunk
def available(self, property_type, porosity_model = 'MATRIX_MODEL'):
"""Get a list of available properties
Arguments:
property_type (str): string corresponding to property_type enum. Can be one of the following:
- DYNAMIC_NATIVE
- STATIC_NATIVE
- SOURSIMRL
- GENERATED
- INPUT_PROPERTY
- FORMATION_NAMES
- FLOW_DIAGNOSTICS
- INJECTION_FLOODING
porosity_model(str): 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.AvailablePropertiesRequest (case_request = Case_pb2.CaseRequest(id=self.case.id),
property_type = property_type_enum,
porosity_model = porosity_model_enum)
return self._properties_stub.GetAvailableProperties(request).property_names
def active_cell_property_async(self, property_type, property_name, time_step, porosity_model = 'MATRIX_MODEL'):
"""Get a cell property for all active cells. Async, so returns an iterator
Arguments:
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
porosity_model(str): string enum. See available()
Returns:
An iterator to a chunk object containing an array of double values
You first loop through the chunks and then the values within the chunk to get all values.
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.PropertyRequest(case_request = Case_pb2.CaseRequest(id=self.case.id),
property_type = property_type_enum,
property_name = property_name,
time_step = time_step,
porosity_model = porosity_model_enum)
for chunk in self._properties_stub.GetActiveCellProperty(request):
yield chunk
def active_cell_property(self, property_type, property_name, time_step, porosity_model = 'MATRIX_MODEL'):
"""Get a cell property for all active cells. Sync, so returns a list
Arguments:
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
porosity_model(str): string enum. See available()
Returns:
A list containing double values
You first loop through the chunks and then the values within the chunk to get all values.
"""
all_values = []
generator = self.active_cell_property_async(property_type, property_name, time_step, porosity_model)
for chunk in generator:
for value in chunk.values:
all_values.append(value)
return all_values
def grid_property_async(self, property_type, property_name, time_step, gridIndex = 0, porosity_model = 'MATRIX_MODEL'):
"""Get a cell property for all grid cells. Async, so returns an iterator
Arguments:
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
gridIndex(int): index to the grid we're getting values for
porosity_model(str): string enum. See available()
Returns:
An iterator to a chunk object containing an array of double values
You first loop through the chunks and then the values within the chunk to get all values.
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.PropertyRequest(case_request = self.case.request,
property_type = property_type_enum,
property_name = property_name,
time_step = time_step,
grid_index = gridIndex,
porosity_model = porosity_model_enum)
for chunk in self._properties_stub.GetGridProperty(request):
yield chunk
def grid_property(self, property_type, property_name, time_step, grid_index = 0, porosity_model = 'MATRIX_MODEL'):
"""Get a cell property for all grid cells. Synchronous, so returns a list
Arguments:
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
grid_index(int): index to the grid we're getting values for
porosity_model(str): string enum. See available()
Returns:
A list of double values
"""
all_values = []
generator = self.grid_property_async(property_type, property_name, time_step, grid_index, porosity_model)
for chunk in generator:
for value in chunk.values:
all_values.append(value)
return all_values
def set_active_cell_property_async(self, values_iterator, property_type, property_name, time_step, porosity_model = 'MATRIX_MODEL'):
"""Set a cell property for all active cells. Async, and so takes an iterator to the input values
Arguments:
values_iterator(iterator): an iterator to the properties to be set
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
porosity_model(str): string enum. See available()
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.PropertyRequest(case_request = self.case.request,
property_type = property_type_enum,
property_name = property_name,
time_step = time_step,
porosity_model = porosity_model_enum)
request_iterator = self.__generate_property_input_iterator(values_iterator, request)
self._properties_stub.SetActiveCellProperty(request_iterator)
def set_active_cell_property(self, values, property_type, property_name, time_step, porosity_model = 'MATRIX_MODEL'):
"""Set a cell property for all active cells.
Arguments:
values(list): a list of double precision floating point numbers
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
porosity_model(str): string enum. See available()
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.PropertyRequest(case_request = self.case.request,
property_type = property_type_enum,
property_name = property_name,
time_step = time_step,
porosity_model = porosity_model_enum)
request_iterator = self.__generate_property_input_chunks(values, request)
reply = self._properties_stub.SetActiveCellProperty(request_iterator)
if reply.accepted_value_count < len(values):
raise IndexError
def set_grid_property(self, values, property_type, property_name, time_step, grid_index = 0, porosity_model = 'MATRIX_MODEL'):
"""Set a cell property for all grid cells.
Arguments:
values(list): a list of double precision floating point numbers
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
grid_index(int): index to the grid we're setting values for
porosity_model(str): string enum. See available()
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.PropertyRequest(case_request = self.case.request,
property_type = property_type_enum,
property_name = property_name,
time_step = time_step,
grid_index = grid_index,
porosity_model = porosity_model_enum)
request_iterator = self.__generate_property_input_chunks(values, request)
reply = self._properties_stub.SetGridProperty(request_iterator)
if reply.accepted_value_count < len(values):
raise IndexError

View File

@ -6,8 +6,8 @@ resinsight = rips.Instance.find()
case_paths = [] case_paths = []
case_paths.append("C:/Users/lindk/source/repos/ResInsight/TestModels/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") case_paths.append("C:/Users/lindk/source/repos/ResInsight/TestModels/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID")
case_paths.append("C:/Users/lindk/source/repos/ResInsight/TestModels/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") case_paths.append("C:/Users/lindk/source/repos/ResInsight/TestModels/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID")
for casePath in case_paths: for case_path in case_paths:
assert os.path.exists(casePath), "You need to set valid case paths for this script to work" assert os.path.exists(case_path), "You need to set valid case paths for this script to work"
case_group = resinsight.project.create_grid_case_group(case_paths=case_paths) case_group = resinsight.project.create_grid_case_group(case_paths=case_paths)
@ -20,7 +20,7 @@ case_group.print_object_info()
# stat_case.update() # stat_case.update()
# case_ids.append(stat_case.get_value("CaseId")) # case_ids.append(stat_case.get_value("CaseId"))
resinsight.commands.compute_case_group_statistics(case_group_id=case_group.group_id) case_group.compute_statistics()
view = case_group.views()[0] view = case_group.views()[0]
cell_result = view.set_cell_result() cell_result = view.set_cell_result()

View File

@ -9,7 +9,7 @@ import rips
resinsight = rips.Instance.find() resinsight = rips.Instance.find()
# Get the case with id == 0. This will fail if your project doesn't have a case with id == 0 # Get the case with id == 0. This will fail if your project doesn't have a case with id == 0
case = resinsight.project.case(id = 0) case = resinsight.project.case(id=0)
# Get the cell count object # Get the cell count object
cell_counts = case.cell_count() cell_counts = case.cell_count()

View File

@ -1,7 +1,5 @@
############################################################################### ###############################################################################
# This example will run a few ResInsight command file commands # This example will show setting time step, window size and export snapshots and properties
# .. which are exposed in the Python interface.
# Including setting time step, window size and export snapshots and properties
############################################################################### ###############################################################################
import os import os
import tempfile import tempfile
@ -10,9 +8,24 @@ import rips
# Load instance # Load instance
resinsight = rips.Instance.find() resinsight = rips.Instance.find()
# Run a couple of commands # Set window size
resinsight.commands.set_time_step(case_id=0, time_step=3) resinsight.set_main_window_size(width=800, height=500)
resinsight.commands.set_main_window_size(width=800, height=500)
# Retrieve first case
case = resinsight.project.cases()[0]
# Get a view
view1 = case.view(view_id=0)
# Clone the view
view2 = view1.clone()
# Set the time step for view1 only
view1.set_time_step(time_step=2)
# Set cell result to SOIL
view1.apply_cell_result(result_type='DYNAMIC_NATIVE', result_variable='SOIL')
# Create a temporary directory which will disappear at the end of this script # Create a temporary directory which will disappear at the end of this script
# If you want to keep the files, provide a good path name instead of tmpdirname # If you want to keep the files, provide a good path name instead of tmpdirname
@ -20,23 +33,23 @@ with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
print("Temporary folder: ", tmpdirname) print("Temporary folder: ", tmpdirname)
# Set export folder for snapshots and properties # Set export folder for snapshots and properties
resinsight.commands.set_export_folder(type='SNAPSHOTS', path=tmpdirname) resinsight.set_export_folder(export_type='SNAPSHOTS', path=tmpdirname)
resinsight.commands.set_export_folder(type='PROPERTIES', path=tmpdirname) resinsight.set_export_folder(export_type='PROPERTIES', path=tmpdirname)
# Export snapshots
resinsight.commands.export_snapshots()
# Print contents of temporary folder
print(os.listdir(tmpdirname))
# Export all snapshots
resinsight.project.export_snapshots()
assert(len(os.listdir(tmpdirname)) > 0) assert(len(os.listdir(tmpdirname)) > 0)
case = resinsight.project.case(id=0)
# Export properties in the view # Export properties in the view
resinsight.commands.export_property_in_views(0, "3D View", 0) view1.export_property()
# Check that the exported file exists # Check that the exported file exists
expected_file_name = case.name + "-" + str("3D_View") + "-" + "T3" + "-SOIL" expected_file_name = case.name + "-" + str("3D_View") + "-" + "T2" + "-SOIL"
full_path = tmpdirname + "/" + expected_file_name full_path = tmpdirname + "/" + expected_file_name
# Print contents of temporary folder
print(os.listdir(tmpdirname))
assert(os.path.exists(full_path)) assert(os.path.exists(full_path))

View File

@ -16,14 +16,14 @@ try:
except grpc.RpcError as e: except grpc.RpcError as e:
print("Expected Server Exception Received: ", e) print("Expected Server Exception Received: ", e)
case = resinsight.project.case(id=0) case = resinsight.project.case(case_id=0)
if case is not None: if case is not None:
results = case.properties.active_cell_property('STATIC_NATIVE', 'PORO', 0) results = case.active_cell_property('STATIC_NATIVE', 'PORO', 0)
active_cell_count = len(results) active_cell_count = len(results)
# Send the results back to ResInsight inside try / except construct # Send the results back to ResInsight inside try / except construct
try: try:
case.properties.set_active_cell_property(results, 'GENERATED', 'POROAPPENDED', 0) case.set_active_cell_property(results, 'GENERATED', 'POROAPPENDED', 0)
print("Everything went well as expected") print("Everything went well as expected")
except: # Match any exception, but it should not happen except: # Match any exception, but it should not happen
print("Ooops!") print("Ooops!")
@ -33,7 +33,7 @@ if case is not None:
# This time we should get a grpc.RpcError exception, which is a server side error. # This time we should get a grpc.RpcError exception, which is a server side error.
try: try:
case.properties.set_active_cell_property(results, 'GENERATED', 'POROAPPENDED', 0) case.set_active_cell_property(results, 'GENERATED', 'POROAPPENDED', 0)
print("Everything went well??") print("Everything went well??")
except grpc.RpcError as e: except grpc.RpcError as e:
print("Expected Server Exception Received: ", e) print("Expected Server Exception Received: ", e)
@ -43,10 +43,10 @@ if case is not None:
# With a chunk size exactly matching the active cell count the server will not # With a chunk size exactly matching the active cell count the server will not
# be able to see any error as it will successfully close the stream after receiving # be able to see any error as it will successfully close the stream after receiving
# the correct number of values, even if the python client has more chunks to send # the correct number of values, even if the python client has more chunks to send
case.properties.chunk_size = active_cell_count case.chunk_size = active_cell_count
try: try:
case.properties.set_active_cell_property(results, 'GENERATED', 'POROAPPENDED', 0) case.set_active_cell_property(results, 'GENERATED', 'POROAPPENDED', 0)
print("Everything went well??") print("Everything went well??")
except grpc.RpcError as e: except grpc.RpcError as e:
print("Got unexpected server exception", e, "This should not happen now") print("Got unexpected server exception", e, "This should not happen now")

View File

@ -10,13 +10,15 @@ resinsight = rips.Instance.find()
cases = resinsight.project.cases() cases = resinsight.project.cases()
# Set main window size # Set main window size
resinsight.commands.set_main_window_size(width=800, height=500) resinsight.set_main_window_size(width=800, height=500)
n = 5 # every n-th time_step for snapshot n = 5 # every n-th time_step for snapshot
property_list = ['SOIL', 'PRESSURE'] # list of parameter for snapshot property_list = ['SOIL', 'PRESSURE'] # list of parameter for snapshot
print ("Looping through cases") print ("Looping through cases")
for case in cases: for case in cases:
print("Case name: ", case.name)
print("Case id: ", case.case_id)
# Get grid path and its folder name # Get grid path and its folder name
case_path = case.grid_path() case_path = case.grid_path()
folder_name = os.path.dirname(case_path) folder_name = os.path.dirname(case_path)
@ -28,16 +30,14 @@ for case in cases:
os.mkdir(dirname) os.mkdir(dirname)
print ("Exporting to folder: " + dirname) print ("Exporting to folder: " + dirname)
resinsight.commands.set_export_folder(type='SNAPSHOTS', path=dirname) resinsight.set_export_folder(export_type='SNAPSHOTS', path=dirname)
time_steps = case.time_steps() time_steps = case.time_steps()
tss_snapshot = range(0, len(time_steps), n) print('Number of time_steps: ' + str(len(time_steps)))
print(case.name, case.id, 'Number of time_steps: ' + str(len(time_steps)))
print('Number of time_steps for snapshoting: ' + str(len(tss_snapshot)))
view = case.views()[0] view = case.views()[0]
for property in property_list: for property in property_list:
view.apply_cell_result(result_type='DYNAMIC_NATIVE', result_variable=property) view.apply_cell_result(result_type='DYNAMIC_NATIVE', result_variable=property)
for ts_snapshot in tss_snapshot: for time_step in range(0, len(time_steps), 10):
resinsight.commands.set_time_step(case_id = case.id, time_step = ts_snapshot) view.set_time_step(time_step = time_step)
resinsight.commands.export_snapshots(type='VIEWS', case_id=case.id) # ALL, VIEWS or PLOTS default is 'ALL' view.export_snapshot()

View File

@ -19,17 +19,17 @@ def create_result(poro_chunks, permx_chunks):
resinsight = rips.Instance.find() resinsight = rips.Instance.find()
start = time.time() start = time.time()
case = resinsight.project.case(id=0) case = resinsight.project.case(case_id=0)
# Get a generator for the poro results. The generator will provide a chunk each time it is iterated # Get a generator for the poro results. The generator will provide a chunk each time it is iterated
poro_chunks = case.properties.active_cell_property_async('STATIC_NATIVE', 'PORO', 0) poro_chunks = case.active_cell_property_async('STATIC_NATIVE', 'PORO', 0)
# Get a generator for the permx results. The generator will provide a chunk each time it is iterated # Get a generator for the permx results. The generator will provide a chunk each time it is iterated
permx_chunks = case.properties.active_cell_property_async('STATIC_NATIVE', 'PERMX', 0) permx_chunks = case.active_cell_property_async('STATIC_NATIVE', 'PERMX', 0)
# Send back the result with the result provided by a generator object. # Send back the result with the result provided by a generator object.
# Iterating the result generator will cause the script to read from the poro and permx generators # Iterating the result generator will cause the script to read from the poro and permx generators
# And return the result of each iteration # And return the result of each iteration
case.properties.set_active_cell_property_async(create_result(poro_chunks, permx_chunks), case.set_active_cell_property_async(create_result(poro_chunks, permx_chunks),
'GENERATED', 'POROPERMXAS', 0) 'GENERATED', 'POROPERMXAS', 0)
end = time.time() end = time.time()

View File

@ -9,12 +9,12 @@ import grpc
resinsight = rips.Instance.find() resinsight = rips.Instance.find()
start = time.time() start = time.time()
case = resinsight.project.case(id=0) case = resinsight.project.case(case_id=0)
# Read poro result into list # Read poro result into list
poro_results = case.properties.active_cell_property('STATIC_NATIVE', 'PORO', 0) poro_results = case.active_cell_property('STATIC_NATIVE', 'PORO', 0)
# Read permx result into list # Read permx result into list
permx_results = case.properties.active_cell_property('STATIC_NATIVE', 'PERMX', 0) permx_results = case.active_cell_property('STATIC_NATIVE', 'PERMX', 0)
# Generate output result # Generate output result
results = [] results = []
@ -23,7 +23,7 @@ for (poro, permx) in zip(poro_results, permx_results):
try: try:
# Send back output result # Send back output result
case.properties.set_active_cell_property(results, 'GENERATED', 'POROPERMXSY', 0) case.set_active_cell_property(results, 'GENERATED', 'POROPERMXSY', 0)
except grpc.RpcError as e: except grpc.RpcError as e:
print("Exception Received: ", e) print("Exception Received: ", e)

View File

@ -14,7 +14,7 @@ if resinsight is not None:
print ("Got " + str(len(cases)) + " cases: ") print ("Got " + str(len(cases)) + " cases: ")
for case in cases: for case in cases:
print(case.name) print(case.name)
for property in case.properties.available('DYNAMIC_NATIVE'): for property in case.available_properties('DYNAMIC_NATIVE'):
print(property) print(property)

View File

@ -5,5 +5,5 @@ import rips
resinsight = rips.Instance.find() resinsight = rips.Instance.find()
view = resinsight.project.view(0) view = resinsight.project.view(view_id=0)
view.apply_cell_result(resultType='STATIC_NATIVE', resultVariable='DX') view.apply_cell_result(result_type='STATIC_NATIVE', result_variable='DX')

View File

@ -7,7 +7,7 @@ import rips
# Connect to ResInsight instance # Connect to ResInsight instance
resinsight = rips.Instance.find() resinsight = rips.Instance.find()
view = resinsight.project.view(0) view = resinsight.project.view(view_id=0)
#view.apply_flow_diagnostics_cell_result(result_variable='Fraction', #view.apply_flow_diagnostics_cell_result(result_variable='Fraction',
# selection_mode='FLOW_TR_INJ_AND_PROD') # selection_mode='FLOW_TR_INJ_AND_PROD')

View File

@ -5,7 +5,7 @@ import rips
resinsight = rips.Instance.find() resinsight = rips.Instance.find()
case = resinsight.project.case(id=0) case = resinsight.project.case(case_id=0)
total_cell_count = case.cell_count().reservoir_cell_count total_cell_count = case.cell_count().reservoir_cell_count
values = [] values = []
@ -13,5 +13,5 @@ for i in range(0, total_cell_count):
values.append(i % 2 * 0.75); values.append(i % 2 * 0.75);
print("Applying values to full grid") print("Applying values to full grid")
case.properties.set_grid_property(values, 'DYNAMIC_NATIVE', 'SOIL', 0) case.set_grid_property(values, 'DYNAMIC_NATIVE', 'SOIL', 0)

View File

@ -11,7 +11,7 @@ resinsight = rips.Instance.find()
start = time.time() start = time.time()
# Get the case with case id 0 # Get the case with case id 0
case = resinsight.project.case(id=0) case = resinsight.project.case(case_id=0)
# Get a list of all time steps # Get a list of all time steps
timeSteps = case.time_steps() timeSteps = case.time_steps()
@ -20,7 +20,7 @@ averages = []
for i in range(0, len(timeSteps)): for i in range(0, len(timeSteps)):
# Get the results from time step i asynchronously # Get the results from time step i asynchronously
# It actually returns a generator object almost immediately # It actually returns a generator object almost immediately
result_chunks = case.properties.active_cell_property_async('DYNAMIC_NATIVE', 'SOIL', i) result_chunks = case.active_cell_property_async('DYNAMIC_NATIVE', 'SOIL', i)
mysum = 0.0 mysum = 0.0
count = 0 count = 0
# Loop through and append the average. each time we loop resultChunks # Loop through and append the average. each time we loop resultChunks

View File

@ -8,10 +8,9 @@ import time
resinsight = rips.Instance.find() resinsight = rips.Instance.find()
start = time.time() start = time.time()
case = resinsight.project.case(id=0)
# Get the case with case id 0 # Get the case with case id 0
case = resinsight.project.case(id=0) case = resinsight.project.case(case_id=0)
# Get a list of all time steps # Get a list of all time steps
time_steps = case.time_steps() time_steps = case.time_steps()
@ -19,7 +18,7 @@ time_steps = case.time_steps()
averages = [] averages = []
for i in range(0, len(time_steps)): for i in range(0, len(time_steps)):
# Get a list of all the results for time step i # Get a list of all the results for time step i
results = case.properties.active_cell_property('DYNAMIC_NATIVE', 'SOIL', i) results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', i)
mysum = sum(results) mysum = sum(results)
averages.append(mysum/len(results)) averages.append(mysum/len(results))

View File

@ -18,11 +18,11 @@ def create_result(soil_chunks, porv_chunks):
resinsight = rips.Instance.find() resinsight = rips.Instance.find()
start = time.time() start = time.time()
case = resinsight.project.case(id=0) case = resinsight.project.case(case_id=0)
timeStepInfo = case.time_steps() timeStepInfo = case.time_steps()
# Get a generator for the porv results. The generator will provide a chunk each time it is iterated # Get a generator for the porv results. The generator will provide a chunk each time it is iterated
porv_chunks = case.properties.active_cell_property_async('STATIC_NATIVE', 'PORV', 0) porv_chunks = case.active_cell_property_async('STATIC_NATIVE', 'PORV', 0)
# Read the static result into an array, so we don't have to transfer it for each iteration # Read the static result into an array, so we don't have to transfer it for each iteration
# Note we use the async method even if we synchronise here, because we need the values chunked # Note we use the async method even if we synchronise here, because we need the values chunked
@ -33,11 +33,11 @@ for porv_chunk in porv_chunks:
for i in range (0, len(timeStepInfo)): for i in range (0, len(timeStepInfo)):
# Get a generator object for the SOIL property for time step i # Get a generator object for the SOIL property for time step i
soil_chunks = case.properties.active_cell_property_async('DYNAMIC_NATIVE', 'SOIL', i) soil_chunks = case.active_cell_property_async('DYNAMIC_NATIVE', 'SOIL', i)
# Create the generator object for the SOIL * PORV derived result # Create the generator object for the SOIL * PORV derived result
result_generator = create_result(soil_chunks, iter(porv_array)) result_generator = create_result(soil_chunks, iter(porv_array))
# Send back the result asynchronously with a generator object # Send back the result asynchronously with a generator object
case.properties.set_active_cell_property_async(result_generator, 'GENERATED', 'SOILPORVAsync', i) case.set_active_cell_property_async(result_generator, 'GENERATED', 'SOILPORVAsync', i)
end = time.time() end = time.time()
print("Time elapsed: ", end - start) print("Time elapsed: ", end - start)

View File

@ -7,15 +7,15 @@ import time
resinsight = rips.Instance.find() resinsight = rips.Instance.find()
start = time.time() start = time.time()
case = resinsight.project.case(id=0) case = resinsight.project.case(case_id=0)
# Read the full porv result # Read the full porv result
porv_results = case.properties.active_cell_property('STATIC_NATIVE', 'PORV', 0) porv_results = case.active_cell_property('STATIC_NATIVE', 'PORV', 0)
time_step_info = case.time_steps() time_step_info = case.time_steps()
for i in range (0, len(time_step_info)): for i in range (0, len(time_step_info)):
# Read the full SOIl result for time step i # Read the full SOIl result for time step i
soil_results = case.properties.active_cell_property('DYNAMIC_NATIVE', 'SOIL', i) soil_results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', i)
# Generate the result by looping through both lists in order # Generate the result by looping through both lists in order
results = [] results = []
@ -23,7 +23,7 @@ for i in range (0, len(time_step_info)):
results.append(soil * porv) results.append(soil * porv)
# Send back result # Send back result
case.properties.set_active_cell_property(results, 'GENERATED', 'SOILPORVSync', i) case.set_active_cell_property(results, 'GENERATED', 'SOILPORVSync', i)
end = time.time() end = time.time()
print("Time elapsed: ", end - start) print("Time elapsed: ", end - start)

View File

@ -1,9 +1,12 @@
name = "rips" name = "rips"
from rips.Case import Case
from rips.Grid import Grid import os
from rips.Properties import Properties import sys
from rips.Instance import Instance sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
from rips.Commands import Commands
from rips.PdmObject import PdmObject from rips.case import Case
from rips.View import View from rips.grid import Grid
from rips.Project import Project from rips.instance import Instance
from rips.pdmobject import PdmObject
from rips.view import View
from rips.project import Project

View File

@ -0,0 +1,719 @@
# pylint: disable=no-member
# pylint: disable=too-many-arguments
# pylint: disable=too-many-public-methods
# pylint: disable=no-self-use
"""
Module containing the Case class
"""
import grpc
import rips.generated.Case_pb2 as Case_pb2
import rips.generated.Case_pb2_grpc as Case_pb2_grpc
import rips.generated.Commands_pb2 as Cmd
import rips.generated.Properties_pb2 as Properties_pb2
import rips.generated.Properties_pb2_grpc as Properties_pb2_grpc
from rips.grid import Grid
from rips.pdmobject import PdmObject
from rips.view import View
class Case(PdmObject):
"""ResInsight case class
Operate on a ResInsight case specified by a Case Id integer.
Not meant to be constructed separately but created by one of the following
methods in Project: loadCase, case, allCases, selectedCasesq
Attributes:
id (int): Case Id corresponding to case Id in ResInsight project.
name (str): Case name
group_id (int): Case Group id
chunkSize(int): The size of each chunk during value streaming.
A good chunk size is 64KiB = 65536B.
Meaning the ideal number of doubles would be 8192.
However we need overhead space, so the default is 8160.
This leaves 256B for overhead.
"""
def __init__(self, channel, case_id):
# Private properties
self.__channel = channel
self.__case_stub = Case_pb2_grpc.CaseStub(channel)
self.__request = Case_pb2.CaseRequest(id=case_id)
info = self.__case_stub.GetCaseInfo(self.__request)
self.__properties_stub = Properties_pb2_grpc.PropertiesStub(
self.__channel)
PdmObject.__init__(self, self.__case_stub.GetPdmObject(self.__request),
self.__channel)
# Public properties
self.case_id = case_id
self.name = info.name
self.chunk_size = 8160
def __grid_count(self):
"""Get number of grids in the case"""
try:
return self.__case_stub.GetGridCount(self.__request).count
except grpc.RpcError as exception:
if exception.code() == grpc.StatusCode.NOT_FOUND:
return 0
print("ERROR: ", exception)
return 0
def __generate_property_input_iterator(self, values_iterator, parameters):
chunk = Properties_pb2.PropertyInputChunk()
chunk.params.CopyFrom(parameters)
yield chunk
for values in values_iterator:
valmsg = Properties_pb2.PropertyChunk(values=values)
chunk.values.CopyFrom(valmsg)
yield chunk
def __generate_property_input_chunks(self, array, parameters):
index = -1
while index < len(array):
chunk = Properties_pb2.PropertyInputChunk()
if index is -1:
chunk.params.CopyFrom(parameters)
index += 1
else:
actual_chunk_size = min(len(array) - index + 1, self.chunk_size)
chunk.values.CopyFrom(
Properties_pb2.PropertyChunk(values=array[index:index +
actual_chunk_size]))
index += actual_chunk_size
yield chunk
# Final empty message to signal completion
chunk = Properties_pb2.PropertyInputChunk()
yield chunk
def grid_path(self):
"""Get path of the current grid case
Returns: path string
"""
return self.get_value("CaseFileName")
def grid(self, index):
"""Get Grid of a given index. Returns a rips Grid object
Arguments:
index (int): The grid index
Returns: Grid object
"""
return Grid(index, self, self.__channel)
def grids(self):
"""Get a list of all rips Grid objects in the case"""
grid_list = []
for i in range(0, self.__grid_count()):
grid_list.append(Grid(i, self, self.__channel))
return grid_list
def replace(self, new_grid_file):
"""Replace the current case grid with a new grid loaded from file
Arguments:
new_egrid_file (str): path to EGRID file
"""
self._execute_command(replaceCase=Cmd.ReplaceCaseRequest(
newGridFile=new_grid_file, caseId=self.case_id))
self.__init__(self.__channel, self.case_id)
def cell_count(self, porosity_model="MATRIX_MODEL"):
"""Get a cell count object containing number of active cells and
total number of cells
Arguments:
porosity_model (str): String representing an enum.
must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
Returns:
Cell Count object with the following integer attributes:
active_cell_count: number of active cells
reservoir_cell_count: total number of reservoir cells
"""
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Case_pb2.CellInfoRequest(case_request=self.__request,
porosity_model=porosity_model_enum)
return self.__case_stub.GetCellCount(request)
def cell_info_for_active_cells_async(self, porosity_model="MATRIX_MODEL"):
"""Get Stream of cell info objects for current case
Arguments:
porosity_model(str): String representing an enum.
must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
Returns:
Stream of **CellInfo** objects
See cell_info_for_active_cells() for detalis on the **CellInfo** class.
"""
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Case_pb2.CellInfoRequest(case_request=self.__request,
porosity_model=porosity_model_enum)
return self.__case_stub.GetCellInfoForActiveCells(request)
def cell_info_for_active_cells(self, porosity_model="MATRIX_MODEL"):
"""Get list of cell info objects for current case
Arguments:
porosity_model(str): String representing an enum.
must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
Returns:
List of **CellInfo** objects
### CellInfo class description
Parameter | Description | Type
------------------------- | --------------------------------------------- | -----
grid_index | Index to grid | Integer
parent_grid_index | Index to parent grid | Integer
coarsening_box_index | Index to coarsening box | Integer
local_ijk | Cell index in IJK directions of local grid | Vec3i
parent_ijk | Cell index in IJK directions of parent grid | Vec3i
### Vec3i class description
Parameter | Description | Type
---------------- | -------------------------------------------- | -----
i | I grid index | Integer
j | J grid index | Integer
k | K grid index | Integer
"""
active_cell_info_chunks = self.cell_info_for_active_cells_async(
porosity_model=porosity_model)
received_active_cells = []
for active_cell_chunk in active_cell_info_chunks:
for active_cell in active_cell_chunk.data:
received_active_cells.append(active_cell)
return received_active_cells
def time_steps(self):
"""Get a list containing all time steps
The time steps are defined by the class **TimeStepDate** :
Type | Name
--------- | ----------
int | year
int | month
int | day
int | hour
int | minute
int | second
"""
return self.__case_stub.GetTimeSteps(self.__request).dates
def days_since_start(self):
"""Get a list of decimal values representing days since the start of the simulation"""
return self.__case_stub.GetDaysSinceStart(self.__request).day_decimals
def views(self):
"""Get a list of views belonging to a case"""
pdm_objects = self.children("ReservoirViews")
view_list = []
for pdm_object in pdm_objects:
view_list.append(View(pdm_object))
return view_list
def view(self, view_id):
"""Get a particular view belonging to a case by providing view id
Arguments:
view_id(int): view id
Returns: a view object
"""
views = self.views()
for view_object in views:
if view_object.view_id == view_id:
return view_object
return None
def create_view(self):
"""Create a new view in the current case"""
return self.view(
self._execute_command(createView=Cmd.CreateViewRequest(
caseId=self.case_id)).createViewResult.viewId)
def export_snapshots_of_all_views(self, prefix=""):
""" Export snapshots for all views in the case
Arguments:
prefix (str): Exported file name prefix
"""
return self._execute_command(
exportSnapshots=Cmd.ExportSnapshotsRequest(
type="VIEWS", prefix=prefix, caseId=self.case_id, viewId=-1))
def export_well_path_completions(
self,
time_step,
well_path_names,
file_split,
compdat_export="TRANSMISSIBILITIES",
include_perforations=True,
include_fishbones=True,
fishbones_exclude_main_bore=True,
combination_mode="INDIVIDUALLY",
):
"""
Export well path completions for the current case to file
Parameter | Description | Type
----------------------------| ------------------------------------------------ | -----
time_step | Time step to export for | Integer
well_path_names | List of well path names | List
file_split | Split type:
<ul>
<li>'UNIFIED_FILE'</li>
<li>'SPLIT_ON_WELL'</li>
<li>'SPLIT_ON_WELL_AND_COMPLETION_TYPE'</li>
</ul> | String enum
compdat_export | Compdat export type:
<ul>
<li>'TRANSMISSIBILITIES'</li>
<li>'WPIMULT_AND_DEFAULT_CONNECTION_FACTORS'</li>
</ul> | String enum
include_perforations | Export perforations? | bool
include_fishbones | Export fishbones? | bool
fishbones_exclude_main_bore | Exclude main bore when exporting fishbones? | bool
combination_mode | Combination mode:
<ul>
<li>'INDIVIDUALLY'</li>
<li>'COMBINED'</li>
</ul> | String enum
"""
if isinstance(well_path_names, str):
well_path_names = [well_path_names]
return self._execute_command(
exportWellPathCompletions=Cmd.ExportWellPathCompRequest(
caseId=self.case_id,
timeStep=time_step,
wellPathNames=well_path_names,
fileSplit=file_split,
compdatExport=compdat_export,
includePerforations=include_perforations,
includeFishbones=include_fishbones,
excludeMainBoreForFishbones=fishbones_exclude_main_bore,
combinationMode=combination_mode,
))
def export_msw(self, well_path):
"""
Export Eclipse Multi-segment-well model to file
Arguments:
well_path(str): Well path name
"""
return self._execute_command(exportMsw=Cmd.ExportMswRequest(
caseId=self.case_id, wellPath=well_path))
def create_multiple_fractures(
self,
template_id,
well_path_names,
min_dist_from_well_td,
max_fractures_per_well,
top_layer,
base_layer,
spacing,
action,
):
"""
Create Multiple Fractures in one go
Parameter | Description | Type
-----------------------| ---------------------------------- -| -----
template_id | Id of the template | Integer
well_path_names | List of well path names | List of Strings
min_dist_from_well_td | Minimum distance from well TD | Double
max_fractures_per_well | Max number of fractures per well | Integer
top_layer | Top grid k-level for fractures | Integer
base_layer | Base grid k-level for fractures | Integer
spacing | Spacing between fractures | Double
action | 'APPEND_FRACTURES' or 'REPLACE_FRACTURES' | String enum
"""
if isinstance(well_path_names, str):
well_path_names = [well_path_names]
return self._execute_command(
createMultipleFractures=Cmd.MultipleFracRequest(
caseId=self.case_id,
templateId=template_id,
wellPathNames=well_path_names,
minDistFromWellTd=min_dist_from_well_td,
maxFracturesPerWell=max_fractures_per_well,
topLayer=top_layer,
baseLayer=base_layer,
spacing=spacing,
action=action,
))
def create_lgr_for_completion(
self,
time_step,
well_path_names,
refinement_i,
refinement_j,
refinement_k,
split_type,
):
"""
Create a local grid refinement for the completions on the given well paths
Parameter | Description | Type
--------------- | -------------------------------------- | -----
time_steps | Time step index | Integer
well_path_names | List of well path names | List of Strings
refinement_i | Refinment in x-direction | Integer
refinement_j | Refinment in y-direction | Integer
refinement_k | Refinment in z-direction | Integer
split_type | Type of LGR split:
<ul>
<li>'LGR_PER_CELL'</li>
<li>'LGR_PER_COMPLETION'</li>
<li>'LGR_PER_WELL'</li>
</ul> | String enum
"""
if isinstance(well_path_names, str):
well_path_names = [well_path_names]
return self._execute_command(
createLgrForCompletions=Cmd.CreateLgrForCompRequest(
caseId=self.case_id,
timeStep=time_step,
wellPathNames=well_path_names,
refinementI=refinement_i,
refinementJ=refinement_j,
refinementK=refinement_k,
splitType=split_type,
))
def create_saturation_pressure_plots(self):
"""
Create saturation pressure plots for the current case
"""
case_ids = [self.case_id]
return self._execute_command(
createSaturationPressurePlots=Cmd.CreateSatPressPlotRequest(
caseIds=case_ids))
def export_flow_characteristics(
self,
time_steps,
injectors,
producers,
file_name,
minimum_communication=0.0,
aquifer_cell_threshold=0.1,
):
""" Export Flow Characteristics data to text file in CSV format
Parameter | Description | Type
------------------------- | --------------------------------------------- | -----
time_steps | Time step indices | List of Integer
injectors | Injector names | List of Strings
producers | Producer names | List of Strings
file_name | Export file name | Integer
minimum_communication | Minimum Communication, defaults to 0.0 | Integer
aquifer_cell_threshold | Aquifer Cell Threshold, defaults to 0.1 | Integer
"""
if isinstance(time_steps, int):
time_steps = [time_steps]
if isinstance(injectors, str):
injectors = [injectors]
if isinstance(producers, str):
producers = [producers]
return self._execute_command(
exportFlowCharacteristics=Cmd.ExportFlowInfoRequest(
caseId=self.case_id,
timeSteps=time_steps,
injectors=injectors,
producers=producers,
fileName=file_name,
minimumCommunication=minimum_communication,
aquiferCellThreshold=aquifer_cell_threshold,
))
def available_properties(self,
property_type,
porosity_model="MATRIX_MODEL"):
"""Get a list of available properties
Arguments:
property_type (str): string corresponding to property_type enum. Choices:
- DYNAMIC_NATIVE
- STATIC_NATIVE
- SOURSIMRL
- GENERATED
- INPUT_PROPERTY
- FORMATION_NAMES
- FLOW_DIAGNOSTICS
- INJECTION_FLOODING
porosity_model(str): 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.AvailablePropertiesRequest(
case_request=self.__request,
property_type=property_type_enum,
porosity_model=porosity_model_enum,
)
return self.__properties_stub.GetAvailableProperties(
request).property_names
def active_cell_property_async(self,
property_type,
property_name,
time_step,
porosity_model="MATRIX_MODEL"):
"""Get a cell property for all active cells. Async, so returns an iterator
Arguments:
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
porosity_model(str): string enum. See available()
Returns:
An iterator to a chunk object containing an array of double values
Loop through the chunks and then the values within the chunk to get all values.
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.PropertyRequest(
case_request=self.__request,
property_type=property_type_enum,
property_name=property_name,
time_step=time_step,
porosity_model=porosity_model_enum,
)
for chunk in self.__properties_stub.GetActiveCellProperty(request):
yield chunk
def active_cell_property(self,
property_type,
property_name,
time_step,
porosity_model="MATRIX_MODEL"):
"""Get a cell property for all active cells. Sync, so returns a list
Arguments:
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
porosity_model(str): string enum. See available()
Returns:
A list containing double values
Loop through the chunks and then the values within the chunk to get all values.
"""
all_values = []
generator = self.active_cell_property_async(property_type,
property_name, time_step,
porosity_model)
for chunk in generator:
for value in chunk.values:
all_values.append(value)
return all_values
def grid_property_async(
self,
property_type,
property_name,
time_step,
grid_index=0,
porosity_model="MATRIX_MODEL",
):
"""Get a cell property for all grid cells. Async, so returns an iterator
Arguments:
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
gridIndex(int): index to the grid we're getting values for
porosity_model(str): string enum. See available()
Returns:
An iterator to a chunk object containing an array of double values
Loop through the chunks and then the values within the chunk to get all values.
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.PropertyRequest(
case_request=self.__request,
property_type=property_type_enum,
property_name=property_name,
time_step=time_step,
grid_index=grid_index,
porosity_model=porosity_model_enum,
)
for chunk in self.__properties_stub.GetGridProperty(request):
yield chunk
def grid_property(
self,
property_type,
property_name,
time_step,
grid_index=0,
porosity_model="MATRIX_MODEL",
):
"""Get a cell property for all grid cells. Synchronous, so returns a list
Arguments:
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
grid_index(int): index to the grid we're getting values for
porosity_model(str): string enum. See available()
Returns:
A list of double values
"""
all_values = []
generator = self.grid_property_async(property_type, property_name,
time_step, grid_index,
porosity_model)
for chunk in generator:
for value in chunk.values:
all_values.append(value)
return all_values
def set_active_cell_property_async(
self,
values_iterator,
property_type,
property_name,
time_step,
porosity_model="MATRIX_MODEL",
):
"""Set cell property for all active cells Async. Takes an iterator to the input values
Arguments:
values_iterator(iterator): an iterator to the properties to be set
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
porosity_model(str): string enum. See available()
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.PropertyRequest(
case_request=self.__request,
property_type=property_type_enum,
property_name=property_name,
time_step=time_step,
porosity_model=porosity_model_enum,
)
request_iterator = self.__generate_property_input_iterator(
values_iterator, request)
self.__properties_stub.SetActiveCellProperty(request_iterator)
def set_active_cell_property(
self,
values,
property_type,
property_name,
time_step,
porosity_model="MATRIX_MODEL",
):
"""Set a cell property for all active cells.
Arguments:
values(list): a list of double precision floating point numbers
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
porosity_model(str): string enum. See available()
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.PropertyRequest(
case_request=self.__request,
property_type=property_type_enum,
property_name=property_name,
time_step=time_step,
porosity_model=porosity_model_enum,
)
request_iterator = self.__generate_property_input_chunks(
values, request)
reply = self.__properties_stub.SetActiveCellProperty(request_iterator)
if reply.accepted_value_count < len(values):
raise IndexError
def set_grid_property(
self,
values,
property_type,
property_name,
time_step,
grid_index=0,
porosity_model="MATRIX_MODEL",
):
"""Set a cell property for all grid cells.
Arguments:
values(list): a list of double precision floating point numbers
property_type(str): string enum. See available()
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
grid_index(int): index to the grid we're setting values for
porosity_model(str): string enum. See available()
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
request = Properties_pb2.PropertyRequest(
case_request=self.__request,
property_type=property_type_enum,
property_name=property_name,
time_step=time_step,
grid_index=grid_index,
porosity_model=porosity_model_enum,
)
request_iterator = self.__generate_property_input_chunks(
values, request)
reply = self.__properties_stub.SetGridProperty(request_iterator)
if reply.accepted_value_count < len(values):
raise IndexError
def export_property(
self,
time_step,
property_name,
eclipse_keyword=property,
undefined_value=0.0,
export_file=property,
):
""" Export an Eclipse property
Arguments:
time_step (int): time step index
property_name (str): property to export
eclipse_keyword (str): Keyword used in export header. Defaults: value of property
undefined_value (double): Value to use for undefined values. Defaults to 0.0
export_file (str): File name for export. Defaults to the value of property parameter
"""
return self._execute_command(exportProperty=Cmd.ExportPropertyRequest(
caseId=self.case_id,
timeStep=time_step,
property=property_name,
eclipseKeyword=eclipse_keyword,
undefinedValue=undefined_value,
exportFile=export_file,
))

View File

@ -0,0 +1,33 @@
# pylint: disable=too-few-public-methods
"""
Module containing the Grid class, containing information
about Case grids.
"""
import rips.generated.Case_pb2 as Case_pb2
import rips.generated.Grid_pb2 as Grid_pb2
import rips.generated.Grid_pb2_grpc as Grid_pb2_grpc
class Grid:
"""Grid Information. Not meant to be constructed separately
Create Grid objects using mathods on Case: Grid() and Grids()
"""
def __init__(self, index, case, channel):
self.__channel = channel
self.__stub = Grid_pb2_grpc.GridStub(self.__channel)
self.case = case
self.index = index
def dimensions(self):
"""The dimensions in i, j, k direction
Returns:
Vec3i: class with integer attributes i, j, k giving extent in all three dimensions.
"""
case_request = Case_pb2.CaseRequest(id=self.case.case_id)
return self.__stub.GetDimensions(
Grid_pb2.GridRequest(case_request=case_request,
grid_index=self.index)).dimensions

View File

@ -0,0 +1,73 @@
"""
Grid Case Group statistics module
"""
from rips.pdmobject import PdmObject
from rips.view import View
from rips.case import Case
import rips.generated.Commands_pb2 as Cmd
class GridCaseGroup(PdmObject):
"""ResInsight Grid Case Group class
Operate on a ResInsight case group specified by a Case Group Id integer.
Attributes:
group_id (int): Grid Case Group Id corresponding to case group Id in ResInsight project.
"""
def __init__(self, pdm_object):
self.group_id = pdm_object.get_value("GroupId")
PdmObject.__init__(self, pdm_object._pb2_object, pdm_object._channel)
def create_statistics_case(self):
"""Create a Statistics case in the Grid Case Group
Returns:
A new Case
"""
command_reply = self._execute_command(
createStatisticsCase=Cmd.CreateStatisticsCaseRequest(
caseGroupId=self.group_id))
return Case(self.channel,
command_reply.createStatisticsCaseResult.caseId)
def statistics_cases(self):
"""Get a list of all statistics cases in the Grid Case Group"""
stat_case_collection = self.children("StatisticsCaseCollection")[0]
return stat_case_collection.children("Reservoirs")
def views(self):
"""Get a list of views belonging to a grid case group"""
pdm_objects = self.descendants("ReservoirView")
view_list = []
for pdm_object in pdm_objects:
view_list.append(View(pdm_object))
return view_list
def view(self, view_id):
"""Get a particular view belonging to a case group by providing view id
Arguments:
id(int): view id
Returns: a view object
"""
views = self.views()
for view_object in views:
if view_object.id == view_id:
return view_object
return None
def compute_statistics(self, case_ids=None):
""" Compute statistics for the given case ids
Arguments:
case_ids(list): list of case ids. If this is None all cases in group are included
"""
if case_ids is None:
case_ids = []
return self._execute_command(
computeCaseGroupStatistics=Cmd.ComputeCaseGroupStatRequest(
caseIds=case_ids, caseGroupId=self.group_id))

View File

@ -0,0 +1,269 @@
# pylint: disable=no-self-use
"""
The main entry point for ResInsight connections
The Instance class contained have static methods launch and find for
creating connections to ResInsight
"""
import os
import socket
import logging
import time
import grpc
import rips.generated.App_pb2 as App_pb2
import rips.generated.App_pb2_grpc as App_pb2_grpc
import rips.generated.Commands_pb2 as Cmd
import rips.generated.Commands_pb2_grpc as CmdRpc
from rips.generated.Definitions_pb2 import Empty
import rips.generated.RiaVersionInfo as RiaVersionInfo
from rips.project import Project
class Instance:
"""The ResInsight Instance class. Use to launch or find existing ResInsight instances
Attributes:
launched (bool): Tells us whether the application was launched as a new process.
If the application was launched we may need to close it when exiting the script.
commands (Commands): Command executor. Set when creating an instance.
project (Project): Current project in ResInsight.
Set when creating an instance and updated when opening/closing projects.
"""
@staticmethod
def __is_port_in_use(port):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as my_socket:
my_socket.settimeout(0.2)
return my_socket.connect_ex(('localhost', port)) == 0
@staticmethod
def launch(resinsight_executable='',
console=False,
launch_port=-1,
command_line_parameters=None):
""" Launch a new Instance of ResInsight. This requires the environment variable
RESINSIGHT_EXECUTABLE to be set or the parameter resinsight_executable to be provided.
The RESINSIGHT_GRPC_PORT environment variable can be set to an alternative port number.
Args:
resinsight_executable (str): Path to a valid ResInsight executable. If set
will take precedence over what is provided in the RESINSIGHT_EXECUTABLE
environment variable.
console (bool): If True, launch as console application, without GUI.
launch_port(int): If -1 will use the default port 50051 or RESINSIGHT_GRPC_PORT
if anything else, ResInsight will try to launch with this port
command_line_parameters(list): Additional parameters as string entries in the list.
Returns:
Instance: an instance object if it worked. None if not.
"""
port = 50051
port_env = os.environ.get('RESINSIGHT_GRPC_PORT')
if port_env:
port = int(port_env)
if launch_port is not -1:
port = launch_port
if not resinsight_executable:
resinsight_executable = os.environ.get('RESINSIGHT_EXECUTABLE')
if not resinsight_executable:
print(
'ERROR: Could not launch ResInsight because the environment variable'
' RESINSIGHT_EXECUTABLE is not set')
return None
while Instance.__is_port_in_use(port):
port += 1
print('Port ' + str(port))
print('Trying to launch', resinsight_executable)
if command_line_parameters is None:
command_line_parameters = []
elif isinstance(command_line_parameters, str):
command_line_parameters = [str]
parameters = ["ResInsight", "--server",
str(port)] + command_line_parameters
if console:
print("Launching as console app")
parameters.append("--console")
# Stringify all parameters
for i in enumerate(parameters):
parameters[i] = str(parameters[i])
pid = os.spawnv(os.P_NOWAIT, resinsight_executable, parameters)
if pid:
instance = Instance(port=port, launched=True)
return instance
return None
@staticmethod
def find(start_port=50051, end_port=50071):
""" Search for an existing Instance of ResInsight by testing ports.
By default we search from port 50051 to 50071 or if the environment
variable RESINSIGHT_GRPC_PORT is set we search
RESINSIGHT_GRPC_PORT to RESINSIGHT_GRPC_PORT+20
Args:
start_port (int): start searching from this port
end_port (int): search up to but not including this port
"""
port_env = os.environ.get('RESINSIGHT_GRPC_PORT')
if port_env:
start_port = int(port_env)
end_port = start_port + 20
for try_port in range(start_port, end_port):
if Instance.__is_port_in_use(try_port):
return Instance(port=try_port)
print(
'Error: Could not find any ResInsight instances responding between ports '
+ str(start_port) + ' and ' + str(end_port))
return None
def __execute_command(self, **command_params):
return self.commands.Execute(Cmd.CommandParams(**command_params))
def __check_version(self):
try:
major_version_ok = self.major_version() == int(
RiaVersionInfo.RESINSIGHT_MAJOR_VERSION)
minor_version_ok = self.minor_version() == int(
RiaVersionInfo.RESINSIGHT_MINOR_VERSION)
return True, major_version_ok and minor_version_ok
except grpc.RpcError:
return False, False
def __init__(self, port=50051, launched=False):
""" Attempts to connect to ResInsight at aa specific port on localhost
Args:
port(int): port number
"""
logging.basicConfig()
location = "localhost:" + str(port)
self.channel = grpc.insecure_channel(location,
options=[
('grpc.enable_http_proxy',
False)
])
self.launched = launched
self.commands = CmdRpc.CommandsStub(self.channel)
# Main version check package
self.app = self.app = App_pb2_grpc.AppStub(self.channel)
connection_ok = False
version_ok = False
if self.launched:
for _ in range(0, 10):
connection_ok, version_ok = self.__check_version()
if connection_ok:
break
time.sleep(1.0)
else:
connection_ok, version_ok = self.__check_version()
if not connection_ok:
if self.launched:
raise Exception('Error: Could not connect to resinsight at ',
location,
' after trying 10 times with 1 second apart')
raise Exception('Error: Could not connect to resinsight at ', location)
if not version_ok:
raise Exception('Error: Wrong Version of ResInsight at ', location,
self.version_string(), " ",
self.client_version_string())
# Service packages
self.project = Project(self.channel)
path = os.getcwd()
self.set_start_dir(path=path)
def __version_message(self):
return self.app.GetVersion(Empty())
def set_start_dir(self, path):
"""Set current start directory
Arguments:
path (str): path to directory
"""
return self.__execute_command(setStartDir=Cmd.FilePathRequest(path=path))
def set_export_folder(self, export_type, path, create_folder=False):
"""
Set the export folder used for all export functions
Parameter | Description | Type
---------------- | -------------------------------------------- | -----
export_type | Type of export: 'COMPLETIONS', 'SNAPSHOTS'
'PROPERTIES' or 'STATISTICS' | String
path | Path to folder | String
create_folder | Create folder if it doesn't exist? | Boolean
"""
return self.__execute_command(setExportFolder=Cmd.SetExportFolderRequest(
type=export_type, path=path, createFolder=create_folder))
def set_main_window_size(self, width, height):
"""
Set the main window size in pixels
Parameter | Description | Type
--------- | ---------------- | -----
width | Width in pixels | Integer
height | Height in pixels | Integer
"""
return self.__execute_command(setMainWindowSize=Cmd.SetMainWindowSizeParams(
width=width, height=height))
def major_version(self):
"""Get an integer with the major version number"""
return self.__version_message().major_version
def minor_version(self):
"""Get an integer with the minor version number"""
return self.__version_message().minor_version
def patch_version(self):
"""Get an integer with the patch version number"""
return self.__version_message().patch_version
def version_string(self):
"""Get a full version string, i.e. 2019.04.01"""
return str(self.major_version()) + "." + str(
self.minor_version()) + "." + str(self.patch_version())
def client_version_string(self):
"""Get a full version string, i.e. 2019.04.01"""
version_string = RiaVersionInfo.RESINSIGHT_MAJOR_VERSION + "."
version_string += RiaVersionInfo.RESINSIGHT_MINOR_VERSION + "."
version_string += RiaVersionInfo.RESINSIGHT_PATCH_VERSION
return version_string
def exit(self):
"""Tell ResInsight instance to quit"""
print("Telling ResInsight to Exit")
return self.app.Exit(Empty())
def is_console(self):
"""Returns true if the connected ResInsight instance is a console app"""
return self.app.GetRuntimeInfo(
Empty()).app_type == App_pb2.ApplicationTypeEnum.Value(
'CONSOLE_APPLICATION')
def is_gui(self):
"""Returns true if the connected ResInsight instance is a GUI app"""
return self.app.GetRuntimeInfo(
Empty()).app_type == App_pb2.ApplicationTypeEnum.Value(
'GUI_APPLICATION')

View File

@ -1,87 +1,95 @@
import grpc # pylint: disable=no-self-use
import os """
import sys ResInsight caf::PdmObject connection module
"""
import rips.generated.PdmObject_pb2 as PdmObject_pb2
import rips.generated.PdmObject_pb2_grpc as PdmObject_pb2_grpc
import rips.generated.Commands_pb2 as Cmd
import rips.generated.Commands_pb2_grpc as CmdRpc
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
from Definitions_pb2 import Empty
import PdmObject_pb2
import PdmObject_pb2_grpc
class PdmObject: class PdmObject:
"""
Generic ResInsight object. Corresponds to items in the Project Tree
"""
def _execute_command(self, **command_params):
return self._commands.Execute(Cmd.CommandParams(**command_params))
def __init__(self, pb2_object, channel): def __init__(self, pb2_object, channel):
self.pb2_object = pb2_object self._pb2_object = pb2_object
self.channel = channel self._channel = channel
self.pdm_object_stub = PdmObject_pb2_grpc.PdmObjectServiceStub(self.channel) self._pdm_object_stub = PdmObject_pb2_grpc.PdmObjectServiceStub(
self._channel)
self._commands = CmdRpc.CommandsStub(channel)
def address(self): def address(self):
"""Get the unique address of the PdmObject """Get the unique address of the PdmObject
Returns: Returns:
A 64-bit unsigned integer address A 64-bit unsigned integer address
""" """
return self.pb2_object.address return self._pb2_object.address
def class_keyword(self): def class_keyword(self):
"""Get the class keyword in the ResInsight Data Model for the given PdmObject""" """Get the class keyword in the ResInsight Data Model for the given PdmObject"""
return self.pb2_object.class_keyword return self._pb2_object.class_keyword
def keywords(self): def keywords(self):
"""Get a list of all parameter keywords available in the object""" """Get a list of all parameter keywords available in the object"""
list_of_keywords = [] list_of_keywords = []
for keyword in self.pb2_object.parameters: for keyword in self._pb2_object.parameters:
list_of_keywords.append(keyword) list_of_keywords.append(keyword)
return list_of_keywords return list_of_keywords
def print_object_info(self): def print_object_info(self):
"""Print the structure and data content of the PdmObject""" """Print the structure and data content of the PdmObject"""
print ("Class Keyword: " + self.class_keyword()) print("Class Keyword: " + self.class_keyword())
for keyword in self.keywords(): for keyword in self.keywords():
print(keyword + " [" + type(self.get_value(keyword)).__name__ + "]: " + str(self.get_value(keyword))) print(keyword + " [" + type(self.get_value(keyword)).__name__ +
"]: " + str(self.get_value(keyword)))
def __to_value(self, value): def __to_value(self, value):
if value.lower() == 'false': if value.lower() == 'false':
return False return False
elif value.lower() == 'true': if value.lower() == 'true':
return True return True
else: try:
int_val = int(value)
return int_val
except ValueError:
try: try:
int_val = int(value) float_val = float(value)
return int_val return float_val
except ValueError: except ValueError:
try: # We may have a string. Strip internal start and end quotes
float_val = float(value) value = value.strip('\"')
return float_val if self.__islist(value):
except ValueError: return self.__makelist(value)
# We may have a string. Strip internal start and end quotes return value
value = value.strip('\"')
if self.__islist(value):
return self.__makelist(value)
return value
def __from_value(self, value): def __from_value(self, value):
if isinstance(value, bool): if isinstance(value, bool):
if value: if value:
return "true" return "true"
else: return "false"
return "false" if isinstance(value, list):
elif isinstance(value, list):
list_of_strings = [] list_of_strings = []
for val in value: for val in value:
list_of_strings.append(self.__from_value('\"' + val + '\"')) list_of_strings.append(self.__from_value('\"' + val + '\"'))
return "[" + ", ".join(list_of_strings) + "]" return "[" + ", ".join(list_of_strings) + "]"
else: return str(value)
return str(value)
def get_value(self, keyword): def get_value(self, keyword):
"""Get the value associated with the provided keyword """Get the value associated with the provided keyword
Arguments: Arguments:
keyword(str): A string containing the parameter keyword keyword(str): A string containing the parameter keyword
Returns: Returns:
The value of the parameter. Can be int, str or list. The value of the parameter. Can be int, str or list.
""" """
value = self.pb2_object.parameters[keyword] value = self._pb2_object.parameters[keyword]
return self.__to_value(value) return self.__to_value(value)
def __islist(self, value): def __islist(self, value):
@ -104,7 +112,7 @@ class PdmObject:
See keyword documentation and/or print_object_info() to find See keyword documentation and/or print_object_info() to find
the correct data type. the correct data type.
""" """
self.pb2_object.parameters[keyword] = self.__from_value(value) self._pb2_object.parameters[keyword] = self.__from_value(value)
def descendants(self, class_keyword): def descendants(self, class_keyword):
"""Get a list of all project tree descendants matching the class keyword """Get a list of all project tree descendants matching the class keyword
@ -114,11 +122,13 @@ class PdmObject:
Returns: Returns:
A list of PdmObjects matching the keyword provided A list of PdmObjects matching the keyword provided
""" """
request = PdmObject_pb2.PdmDescendantObjectRequest(object=self.pb2_object, child_keyword=class_keyword) request = PdmObject_pb2.PdmDescendantObjectRequest(
object_list = self.pdm_object_stub.GetDescendantPdmObjects(request).objects object=self._pb2_object, child_keyword=class_keyword)
object_list = self._pdm_object_stub.GetDescendantPdmObjects(
request).objects
child_list = [] child_list = []
for object in object_list: for pdm_object in object_list:
child_list.append(PdmObject(object, self.channel)) child_list.append(PdmObject(pdm_object, self._channel))
return child_list return child_list
def children(self, child_field): def children(self, child_field):
@ -128,11 +138,12 @@ class PdmObject:
Returns: Returns:
A list of PdmObjects inside the child_field A list of PdmObjects inside the child_field
""" """
request = PdmObject_pb2.PdmChildObjectRequest(object=self.pb2_object, child_field=child_field) request = PdmObject_pb2.PdmChildObjectRequest(object=self._pb2_object,
object_list = self.pdm_object_stub.GetChildPdmObjects(request).objects child_field=child_field)
object_list = self._pdm_object_stub.GetChildPdmObjects(request).objects
child_list = [] child_list = []
for object in object_list: for pdm_object in object_list:
child_list.append(PdmObject(object, self.channel)) child_list.append(PdmObject(pdm_object, self._channel))
return child_list return child_list
def ancestor(self, class_keyword): def ancestor(self, class_keyword):
@ -140,13 +151,11 @@ class PdmObject:
Arguments: Arguments:
class_keyword[str]: A class keyword matching the type of class wanted class_keyword[str]: A class keyword matching the type of class wanted
""" """
request = PdmObject_pb2.PdmParentObjectRequest(object=self.pb2_object, parent_keyword=class_keyword) request = PdmObject_pb2.PdmParentObjectRequest(
return PdmObject(self.pdm_object_stub.GetAncestorPdmObject(request), self.channel) object=self._pb2_object, parent_keyword=class_keyword)
return PdmObject(self._pdm_object_stub.GetAncestorPdmObject(request),
self._channel)
def update(self): def update(self):
"""Sync all fields from the Python Object to ResInsight""" """Sync all fields from the Python Object to ResInsight"""
self.pdm_object_stub.UpdateExistingPdmObject(self.pb2_object) self._pdm_object_stub.UpdateExistingPdmObject(self._pb2_object)
# def createChild(self, child_field, childClassKeyword):
# childRequest = PdmObject_pb2.CreatePdmChildObjectRequest(object=self.pb2Object, child_field=child_field, child_class=childClassKeyword)
# return PdmObject(self.pdmObjectStub.CreateChildPdmObject(childRequest), self.channel)

View File

@ -0,0 +1,209 @@
# pylint: disable=too-many-arguments
# pylint: disable=no-member
"""
The ResInsight project module
"""
import grpc
from rips.case import Case
from rips.gridcasegroup import GridCaseGroup
from rips.pdmobject import PdmObject
from rips.view import View
import rips.generated.Commands_pb2 as Cmd
from rips.generated.Definitions_pb2 import Empty
import rips.generated.Project_pb2_grpc as Project_pb2_grpc
class Project(PdmObject):
"""ResInsight project. Not intended to be created separately.
Automatically created and assigned to Instance.
"""
def __init__(self, channel):
self._project_stub = Project_pb2_grpc.ProjectStub(channel)
PdmObject.__init__(self, self._project_stub.GetPdmObject(Empty()),
channel)
def open(self, path):
"""Open a new project from the given path
Arguments:
path(str): path to project file
"""
self._execute_command(openProject=Cmd.FilePathRequest(path=path))
return self
def close(self):
"""Close the current project (and open new blank project)"""
self._execute_command(closeProject=Empty())
def load_case(self, path):
"""Load a new case from the given file path
Arguments:
path(str): file path to case
Returns:
A rips Case object
"""
command_reply = self._execute_command(loadCase=Cmd.FilePathRequest(
path=path))
return Case(self._channel, command_reply.loadCaseResult.id)
def selected_cases(self):
"""Get a list of all cases selected in the project tree
Returns:
A list of rips Case objects
"""
case_infos = self._project_stub.GetSelectedCases(Empty())
cases = []
for case_info in case_infos.data:
cases.append(Case(self._channel, case_info.id))
return cases
def cases(self):
"""Get a list of all cases in the project
Returns:
A list of rips Case objects
"""
try:
case_infos = self._project_stub.GetAllCases(Empty())
cases = []
for case_info in case_infos.data:
cases.append(Case(self._channel, case_info.id))
return cases
except grpc.RpcError as rpc_error:
if rpc_error.code() == grpc.StatusCode.NOT_FOUND:
return []
print("ERROR: ", rpc_error)
return []
def case(self, case_id):
"""Get a specific case from the provided case Id
Arguments:
id(int): case id
Returns:
A rips Case object
"""
try:
case = Case(self._channel, case_id)
return case
except grpc.RpcError:
return None
def replace_source_cases(self, grid_list_file, case_group_id=0):
"""Replace all source cases within a case group
Arguments:
grid_list_file (str): path to file containing a list of cases
case_group_id (int): id of the case group to replace
"""
return self._execute_command(
replaceSourceCases=Cmd.ReplaceSourceCasesRequest(
gridListFile=grid_list_file, caseGroupId=case_group_id))
def create_grid_case_group(self, case_paths):
"""Create a Grid Case Group from a list of cases
Arguments:
case_paths (list): list of file path strings
Returns:
A case group id and name
"""
command_reply = self._execute_command(
createGridCaseGroup=Cmd.CreateGridCaseGroupRequest(
casePaths=case_paths))
return self.grid_case_group(
command_reply.createGridCaseGroupResult.groupId)
def views(self):
"""Get a list of views belonging to a project"""
pdm_objects = self.descendants("ReservoirView")
view_list = []
for pdm_object in pdm_objects:
view_list.append(View(pdm_object))
return view_list
def view(self, view_id):
"""Get a particular view belonging to a case by providing view id
Arguments:
id(int): view id
Returns: a view object
"""
views = self.views()
for view_object in views:
if view_object.view_id == view_id:
return view_object
return None
def grid_case_groups(self):
"""Get a list of all grid case groups in the project"""
case_groups = self.descendants("RimIdenticalGridCaseGroup")
case_group_list = []
for pdm_group in case_groups:
case_group_list.append(GridCaseGroup(pdm_group))
return case_group_list
def grid_case_group(self, group_id):
"""Get a particular grid case group belonging to a project
Arguments:
groupId(int): group id
Returns: a grid case group object
"""
case_groups = self.grid_case_groups()
for case_group in case_groups:
if case_group.group_id == group_id:
return case_group
return None
def export_multi_case_snapshots(self, grid_list_file):
"""Export snapshots for a set of cases
Arguments:
grid_list_file (str): Path to a file containing a list of grids to export snapshot for
"""
return self._execute_command(
exportMultiCaseSnapshot=Cmd.ExportMultiCaseRequest(
gridListFile=grid_list_file))
def export_snapshots(self, snapshot_type='ALL', prefix=''):
""" Export all snapshots of a given type
Arguments:
snapshot_type (str): Enum string ('ALL', 'VIEWS' or 'PLOTS')
prefix (str): Exported file name prefix
"""
return self._execute_command(
exportSnapshots=Cmd.ExportSnapshotsRequest(
type=snapshot_type, prefix=prefix, caseId=-1))
def export_well_paths(self, well_paths=None, md_step_size=5.0):
""" Export a set of well paths
Arguments:
well_paths(list): List of strings of well paths. If none, export all.
md_step_size(double): resolution of the exported well path
"""
if well_paths is None:
well_paths = []
elif isinstance(well_paths, str):
well_paths = [well_paths]
return self._execute_command(exportWellPaths=Cmd.ExportWellPathRequest(
wellPathNames=well_paths, mdStepSize=md_step_size))
def scale_fracture_template(self, template_id, half_length, height, dfactor,
conductivity):
return self._execute_command(
scaleFractureTemplate=Cmd.ScaleFractureTemplateRequest(
id=template_id,
halfLength=half_length,
height=height,
dFactor=dfactor,
conductivity=conductivity))
def set_fracture_containment(self, fracture_id, top_layer, base_layer):
return self._execute_command(
setFractureContainment=Cmd.SetFracContainmentRequest(
id=fracture_id, topLayer=top_layer, baseLayer=base_layer))

View File

@ -1,6 +1,8 @@
import sys import sys
import os import os
import pytest import pytest
import grpc
import tempfile
sys.path.insert(1, os.path.join(sys.path[0], '../../')) sys.path.insert(1, os.path.join(sys.path[0], '../../'))
import rips import rips
@ -17,7 +19,7 @@ def test_EmptyProject(rips_instance, initialize_test):
def test_OneCase(rips_instance, initialize_test): def test_OneCase(rips_instance, initialize_test):
case = rips_instance.project.load_case(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") case = rips_instance.project.load_case(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID")
assert(case.name == "TEST10K_FLT_LGR_NNC") assert(case.name == "TEST10K_FLT_LGR_NNC")
assert(case.id == 0) assert(case.case_id == 0)
cases = rips_instance.project.cases() cases = rips_instance.project.cases()
assert(len(cases) is 1) assert(len(cases) is 1)
@ -41,7 +43,7 @@ def test_MultipleCases(rips_instance, initialize_test):
def test_10k(rips_instance, initialize_test): def test_10k(rips_instance, initialize_test):
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=case_path) case = rips_instance.project.load_case(path=case_path)
assert(case.grid_count() == 2) assert(len(case.grids()) == 2)
cell_count_info = case.cell_count() cell_count_info = case.cell_count()
assert(cell_count_info.active_cell_count == 11125) assert(cell_count_info.active_cell_count == 11125)
assert(cell_count_info.reservoir_cell_count == 316224) assert(cell_count_info.reservoir_cell_count == 316224)
@ -53,17 +55,17 @@ def test_10k(rips_instance, initialize_test):
def test_PdmObject(rips_instance, initialize_test): def test_PdmObject(rips_instance, initialize_test):
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=case_path) case = rips_instance.project.load_case(path=case_path)
assert(case.id == 0) assert(case.case_id == 0)
assert(case.address() is not 0) assert(case.address() is not 0)
assert(case.class_keyword() == "EclipseCase") assert(case.class_keyword() == "EclipseCase")
case_id = case.get_value('CaseId') case_id = case.get_value('CaseId')
assert(case_id == case.id) assert(case_id == case.case_id)
@pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux") @pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux")
def test_brugge_0010(rips_instance, initialize_test): def test_brugge_0010(rips_instance, initialize_test):
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID" case_path = dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID"
case = rips_instance.project.load_case(path=case_path) case = rips_instance.project.load_case(path=case_path)
assert(case.grid_count() == 1) assert(len(case.grids()) == 1)
cellCountInfo = case.cell_count() cellCountInfo = case.cell_count()
assert(cellCountInfo.active_cell_count == 43374) assert(cellCountInfo.active_cell_count == 43374)
assert(cellCountInfo.reservoir_cell_count == 60048) assert(cellCountInfo.reservoir_cell_count == 60048)
@ -76,16 +78,36 @@ def test_brugge_0010(rips_instance, initialize_test):
def test_replaceCase(rips_instance, initialize_test): def test_replaceCase(rips_instance, initialize_test):
project = rips_instance.project.open(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp") project = rips_instance.project.open(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp")
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID" case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
case = project.case(id=0) case = project.case(case_id=0)
assert(case is not None) assert(case is not None)
assert(case.name == "TEST10K_FLT_LGR_NNC") assert(case.name == "TEST10K_FLT_LGR_NNC")
assert(case.id == 0) assert(case.case_id == 0)
cases = rips_instance.project.cases() cases = rips_instance.project.cases()
assert(len(cases) is 1) assert(len(cases) is 1)
rips_instance.commands.replace_case(new_grid_file=case_path, case_id=case.id) case.replace(new_grid_file=case_path)
# Check that the case object has been changed
assert(case.name == "Real0--BRUGGE_0000.EGRID")
assert(case.case_id == 0)
cases = rips_instance.project.cases() cases = rips_instance.project.cases()
assert(len(cases) is 1) assert(len(cases) is 1)
case = project.case(id=0) # Check that retrieving the case object again will yield the changed object
case = project.case(case_id=0)
assert(case.name == "Real0--BRUGGE_0000.EGRID") assert(case.name == "Real0--BRUGGE_0000.EGRID")
assert(case.id == 0) assert(case.case_id == 0)
def test_loadNonExistingCase(rips_instance, initialize_test):
case_path = "Nonsense/Nonsense/Nonsense"
with pytest.raises(grpc.RpcError):
assert rips_instance.project.load_case(case_path)
@pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux")
def test_exportFlowCharacteristics(rips_instance, initialize_test):
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
case = rips_instance.project.load_case(case_path)
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
print("Temporary folder: ", tmpdirname)
file_name = tmpdirname + "/exportFlowChar.txt"
case.export_flow_characteristics(time_steps=8, producers=[], injectors = "I01", file_name = file_name)

View File

@ -9,50 +9,3 @@ import rips
import dataroot import dataroot
def test_exportSnapshots(rips_instance, initialize_test):
if not rips_instance.is_gui():
pytest.skip("Cannot run test without a GUI")
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
rips_instance.project.load_case(case_path)
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
print("Temporary folder: ", tmpdirname)
rips_instance.commands.set_export_folder(type='SNAPSHOTS', path=tmpdirname)
rips_instance.commands.export_snapshots()
print(os.listdir(tmpdirname))
assert(len(os.listdir(tmpdirname)) > 0)
for fileName in os.listdir(tmpdirname):
assert(os.path.splitext(fileName)[1] == '.png')
def test_exportPropertyInView(rips_instance, initialize_test):
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
rips_instance.project.load_case(case_path)
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
print("Temporary folder: ", tmpdirname)
rips_instance.commands.set_export_folder(type='PROPERTIES', path=tmpdirname)
case = rips_instance.project.case(id=0)
rips_instance.commands.export_property_in_views(0, "3D View", 0)
expected_file_name = case.name + "-" + str("3D_View") + "-" + "T0" + "-SOIL"
full_path = tmpdirname + "/" + expected_file_name
assert(os.path.exists(full_path))
@pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux")
def test_loadGridCaseGroup(rips_instance, initialize_test):
case_paths = []
case_paths.append(dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID")
case_paths.append(dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID")
group_id, group_name = rips_instance.commands.create_grid_case_group(case_paths=case_paths)
print(group_id, group_name)
def test_exportFlowCharacteristics(rips_instance, initialize_test):
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
rips_instance.project.load_case(case_path)
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
print("Temporary folder: ", tmpdirname)
file_name = tmpdirname + "/exportFlowChar.txt"
rips_instance.commands.export_flow_characteristics(case_id=0, time_steps=8, producers=[], injectors = "I01", file_name = file_name)
def test_loadNonExistingCase(rips_instance, initialize_test):
case_path = "Nonsense/Nonsense/Nonsense"
with pytest.raises(grpc.RpcError):
assert rips_instance.project.load_case(case_path)

View File

@ -9,7 +9,7 @@ import dataroot
def test_10k(rips_instance, initialize_test): def test_10k(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath) case = rips_instance.project.load_case(path=casePath)
assert(case.grid_count() == 2) assert(len(case.grids()) == 2)
grid = case.grid(index=0) grid = case.grid(index=0)
dimensions = grid.dimensions() dimensions = grid.dimensions()
assert(dimensions.i == 90) assert(dimensions.i == 90)

View File

@ -1,6 +1,8 @@
import sys import sys
import os import os
import pytest import pytest
import grpc
import tempfile
sys.path.insert(1, os.path.join(sys.path[0], '../../')) sys.path.insert(1, os.path.join(sys.path[0], '../../'))
import rips import rips
@ -9,9 +11,32 @@ import dataroot
def test_loadProject(rips_instance, initialize_test): def test_loadProject(rips_instance, initialize_test):
project = rips_instance.project.open(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp") project = rips_instance.project.open(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp")
case = project.case(id=0) case = project.case(case_id=0)
assert(case is not None) assert(case is not None)
assert(case.name == "TEST10K_FLT_LGR_NNC") assert(case.name == "TEST10K_FLT_LGR_NNC")
assert(case.id == 0) assert(case.case_id == 0)
cases = rips_instance.project.cases() cases = rips_instance.project.cases()
assert(len(cases) is 1) assert(len(cases) is 1)
@pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux")
def test_loadGridCaseGroup(rips_instance, initialize_test):
case_paths = []
case_paths.append(dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID")
case_paths.append(dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID")
grid_case_group = rips_instance.project.create_grid_case_group(case_paths=case_paths)
assert(grid_case_group is not None and grid_case_group.group_id == 0)
def test_exportSnapshots(rips_instance, initialize_test):
if not rips_instance.is_gui():
pytest.skip("Cannot run test without a GUI")
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
rips_instance.project.load_case(case_path)
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
print("Temporary folder: ", tmpdirname)
rips_instance.set_export_folder(export_type='SNAPSHOTS', path=tmpdirname)
rips_instance.project.export_snapshots()
print(os.listdir(tmpdirname))
assert(len(os.listdir(tmpdirname)) > 0)
for fileName in os.listdir(tmpdirname):
assert(os.path.splitext(fileName)[1] == '.png')

View File

@ -2,6 +2,7 @@ import sys
import os import os
import grpc import grpc
import pytest import pytest
import tempfile
sys.path.insert(1, os.path.join(sys.path[0], '../../')) sys.path.insert(1, os.path.join(sys.path[0], '../../'))
import rips import rips
@ -12,7 +13,7 @@ def test_10kAsync(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath) case = rips_instance.project.load_case(path=casePath)
resultChunks = case.properties.active_cell_property_async('DYNAMIC_NATIVE', 'SOIL', 1) resultChunks = case.active_cell_property_async('DYNAMIC_NATIVE', 'SOIL', 1)
mysum = 0.0 mysum = 0.0
count = 0 count = 0
for chunk in resultChunks: for chunk in resultChunks:
@ -27,7 +28,7 @@ def test_10kSync(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath) case = rips_instance.project.load_case(path=casePath)
results = case.properties.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1) results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1)
mysum = sum(results) mysum = sum(results)
average = mysum / len(results) average = mysum / len(results)
assert(mysum == pytest.approx(621.768, abs=0.001)) assert(mysum == pytest.approx(621.768, abs=0.001))
@ -38,27 +39,27 @@ def test_10k_set(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath) case = rips_instance.project.load_case(path=casePath)
results = case.properties.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1) results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1)
case.properties.set_active_cell_property(results, 'GENERATED', 'SOIL', 1) case.set_active_cell_property(results, 'GENERATED', 'SOIL', 1)
def test_10k_set_out_of_bounds(rips_instance, initialize_test): def test_10k_set_out_of_bounds(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath) case = rips_instance.project.load_case(path=casePath)
results = case.properties.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1) results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1)
results.append(5.0) results.append(5.0)
with pytest.raises(grpc.RpcError): with pytest.raises(grpc.RpcError):
assert case.properties.set_active_cell_property(results, 'GENERATED', 'SOIL', 1) assert case.set_active_cell_property(results, 'GENERATED', 'SOIL', 1)
def test_10k_set_out_of_bounds_client(rips_instance, initialize_test): def test_10k_set_out_of_bounds_client(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath) case = rips_instance.project.load_case(path=casePath)
results = case.properties.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1) results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1)
case.properties.chunk_size = len(results) case.chunk_size = len(results)
results.append(5.0) results.append(5.0)
with pytest.raises(IndexError): with pytest.raises(IndexError):
assert case.properties.set_active_cell_property(results, 'GENERATED', 'SOIL', 1) assert case.set_active_cell_property(results, 'GENERATED', 'SOIL', 1)
def createResult(poroChunks, permxChunks): def createResult(poroChunks, permxChunks):
for (poroChunk, permxChunk) in zip(poroChunks, permxChunks): for (poroChunk, permxChunk) in zip(poroChunks, permxChunks):
@ -76,16 +77,26 @@ def test_10k_PoroPermX(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath) case = rips_instance.project.load_case(path=casePath)
poroChunks = case.properties.active_cell_property_async('STATIC_NATIVE', 'PORO', 0) poroChunks = case.active_cell_property_async('STATIC_NATIVE', 'PORO', 0)
permxChunks = case.properties.active_cell_property_async('STATIC_NATIVE', 'PERMX', 0) permxChunks = case.active_cell_property_async('STATIC_NATIVE', 'PERMX', 0)
case.properties.set_active_cell_property_async(createResult(poroChunks, permxChunks), 'GENERATED', 'POROPERMXAS', 0) case.set_active_cell_property_async(createResult(poroChunks, permxChunks), 'GENERATED', 'POROPERMXAS', 0)
poro = case.properties.active_cell_property('STATIC_NATIVE', 'PORO', 0) poro = case.active_cell_property('STATIC_NATIVE', 'PORO', 0)
permx = case.properties.active_cell_property('STATIC_NATIVE', 'PERMX', 0) permx = case.active_cell_property('STATIC_NATIVE', 'PERMX', 0)
poroPermX = case.properties.active_cell_property('GENERATED', 'POROPERMXAS', 0) poroPermX = case.active_cell_property('GENERATED', 'POROPERMXAS', 0)
checkResults(poro, permx, poroPermX) checkResults(poro, permx, poroPermX)
def test_exportPropertyInView(rips_instance, initialize_test):
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
rips_instance.project.load_case(case_path)
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
print("Temporary folder: ", tmpdirname)
rips_instance.set_export_folder(export_type='PROPERTIES', path=tmpdirname)
case = rips_instance.project.case(case_id=0)
view = case.view(view_id=0)
view.export_property()
expected_file_name = case.name + "-" + str("3D_View") + "-" + "T0" + "-SOIL"
full_path = tmpdirname + "/" + expected_file_name
assert(os.path.exists(full_path))

View File

@ -1,8 +1,13 @@
import rips.Case # Circular import of Case, which already imports View. Use full name. """
from rips.Commands import Commands ResInsight 3d view module
from rips.PdmObject import PdmObject """
import rips.generated.Commands_pb2 as Cmd
class View (PdmObject): import rips.case # Circular import of Case, which already imports View. Use full name.
from rips.pdmobject import PdmObject
class View(PdmObject):
"""ResInsight view class """ResInsight view class
Attributes: Attributes:
@ -10,9 +15,9 @@ class View (PdmObject):
""" """
def __init__(self, pdm_object): def __init__(self, pdm_object):
self.id = pdm_object.get_value("ViewId") self.view_id = pdm_object.get_value("ViewId")
PdmObject.__init__(self, pdm_object.pb2_object, pdm_object.channel) PdmObject.__init__(self, pdm_object._pb2_object, pdm_object._channel)
def show_grid_box(self): def show_grid_box(self):
"""Check if the grid box is meant to be shown in the view""" """Check if the grid box is meant to be shown in the view"""
@ -36,7 +41,7 @@ class View (PdmObject):
def apply_cell_result(self, result_type, result_variable): def apply_cell_result(self, result_type, result_variable):
"""Apply a regular cell result """Apply a regular cell result
Arguments: Arguments:
result_type (str): String representing the result category. The valid values are result_type (str): String representing the result category. The valid values are
- DYNAMIC_NATIVE - DYNAMIC_NATIVE
@ -54,11 +59,12 @@ class View (PdmObject):
cell_result.set_value("ResultVariable", result_variable) cell_result.set_value("ResultVariable", result_variable)
cell_result.update() cell_result.update()
def apply_flow_diagnostics_cell_result(self, def apply_flow_diagnostics_cell_result(
result_variable = 'TOF', self,
selection_mode = 'FLOW_TR_BY_SELECTION', result_variable='TOF',
injectors = [], selection_mode='FLOW_TR_BY_SELECTION',
producers = []): injectors=None,
producers=None):
"""Apply a flow diagnostics cell result """Apply a flow diagnostics cell result
Arguments: Arguments:
@ -66,7 +72,7 @@ class View (PdmObject):
The valid values are 'TOF', 'Fraction', 'MaxFractionTracer' and 'Communication'. The valid values are 'TOF', 'Fraction', 'MaxFractionTracer' and 'Communication'.
selection_mode (str): String specifying which tracers to select. selection_mode (str): String specifying which tracers to select.
The valid values are The valid values are
- FLOW_TR_INJ_AND_PROD (all injector and producer tracers), - FLOW_TR_INJ_AND_PROD (all injector and producer tracers),
- FLOW_TR_PRODUCERS (all producers) - FLOW_TR_PRODUCERS (all producers)
- FLOW_TR_INJECTORS (all injectors), - FLOW_TR_INJECTORS (all injectors),
- FLOW_TR_BY_SELECTION (specify individual tracers in the - FLOW_TR_BY_SELECTION (specify individual tracers in the
@ -76,6 +82,10 @@ class View (PdmObject):
producers (list): List of producer tracers (strings) to select. producers (list): List of producer tracers (strings) to select.
Requires selection_mode to be 'FLOW_TR_BY_SELECTION'. Requires selection_mode to be 'FLOW_TR_BY_SELECTION'.
""" """
if injectors is None:
injectors = []
if producers is None:
producers = []
cell_result = self.set_cell_result() cell_result = self.set_cell_result()
cell_result.set_value("ResultType", "FLOW_DIAGNOSTICS") cell_result.set_value("ResultType", "FLOW_DIAGNOSTICS")
cell_result.set_value("ResultVariable", result_variable) cell_result.set_value("ResultVariable", result_variable)
@ -92,9 +102,69 @@ class View (PdmObject):
pdm_case = self.ancestor("ResInsightGeoMechCase") pdm_case = self.ancestor("ResInsightGeoMechCase")
if pdm_case is None: if pdm_case is None:
return None return None
return rips.Case(self.channel, pdm_case.get_value("CaseId")) return rips.case.Case(self._channel, pdm_case.get_value("CaseId"))
def clone(self): def clone(self):
"""Clone the current view""" """Clone the current view"""
view_id = Commands(self.channel).clone_view(self.id) view_id = self._execute_command(cloneView=Cmd.CloneViewRequest(
viewId=self.view_id)).createViewResult.viewId
return self.case().view(view_id) return self.case().view(view_id)
def set_time_step(self, time_step):
case_id = self.case().case_id
return self._execute_command(setTimeStep=Cmd.SetTimeStepParams(
caseId=case_id, viewId=self.view_id, timeStep=time_step))
def export_sim_well_fracture_completions(self, time_step,
simulation_well_names, file_split,
compdat_export):
if isinstance(simulation_well_names, str):
simulation_well_names = [simulation_well_names]
case_id = self.case().case_id
return self._execute_command(
exportSimWellFractureCompletions=Cmd.ExportSimWellPathFracRequest(
caseId=case_id,
viewId=self.view_id,
timeStep=time_step,
simulationWellNames=simulation_well_names,
fileSplit=file_split,
compdatExport=compdat_export))
def export_visible_cells(self,
export_keyword='FLUXNUM',
visible_active_cells_value=1,
hidden_active_cells_value=0,
inactive_cells_value=0):
case_id = self.case().case_id
return self._execute_command(
exportVisibleCells=Cmd.ExportVisibleCellsRequest(
caseId=case_id,
viewId=self.view_id,
exportKeyword=export_keyword,
visibleActiveCellsValue=visible_active_cells_value,
hiddenActiveCellsValue=hidden_active_cells_value,
inactiveCellsValue=inactive_cells_value))
def export_property(self, undefined_value=0.0):
""" Export the current Eclipse property from the view
Arguments:
undefined_value (double): Value to use for undefined values. Defaults to 0.0
"""
case_id = self.case().case_id
return self._execute_command(
exportPropertyInViews=Cmd.ExportPropertyInViewsRequest(
caseId=case_id,
viewIds=[self.view_id],
undefinedValue=undefined_value))
def export_snapshot(self, prefix=''):
""" Export snapshot for the current view
Arguments:
prefix (str): Exported file name prefix
"""
case_id = self.case().case_id
return self._execute_command(
exportSnapshots=Cmd.ExportSnapshotsRequest(
type='VIEWS', prefix=prefix, caseId=case_id, viewId=self.view_id))

View File

@ -1506,7 +1506,7 @@ void RiuMainWindow::slotSnapshotAllViewsToFile()
// Save images in snapshot catalog relative to project directory // Save images in snapshot catalog relative to project directory
QString absolutePathToSnapshotDir = app->createAbsolutePathFromProjectRelativePath( "snapshots" ); QString absolutePathToSnapshotDir = app->createAbsolutePathFromProjectRelativePath( "snapshots" );
RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder( absolutePathToSnapshotDir ); RicSnapshotAllViewsToFileFeature::exportSnapshotOfViewsIntoFolder( absolutePathToSnapshotDir );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------