mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#4550 Add python method to get simulation wells with status and cells info.
This commit is contained in:
parent
2788c7a6c1
commit
f7af2ed83e
@ -6,6 +6,7 @@ set ( SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.inl
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCaseService.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcSimulationWellService.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridService.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectService.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.h
|
||||
@ -18,6 +19,7 @@ set ( SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCaseService.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcSimulationWellService.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridService.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectService.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.cpp
|
||||
@ -81,6 +83,7 @@ set(PROTO_FILES
|
||||
"Definitions"
|
||||
"PdmObject"
|
||||
"Case"
|
||||
"SimulationWell"
|
||||
"Project"
|
||||
"Commands"
|
||||
"App"
|
||||
|
@ -1,6 +1,7 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "PdmObject.proto";
|
||||
import "Definitions.proto";
|
||||
|
||||
package rips;
|
||||
|
||||
@ -60,12 +61,6 @@ message GridCount
|
||||
int32 count = 1;
|
||||
}
|
||||
|
||||
message Vec3i {
|
||||
int32 i = 1;
|
||||
int32 j = 2;
|
||||
int32 k = 3;
|
||||
}
|
||||
|
||||
message CellCount
|
||||
{
|
||||
int32 active_cell_count = 1;
|
||||
|
@ -10,3 +10,10 @@ message ClientToServerStreamReply
|
||||
{
|
||||
int64 accepted_value_count = 1;
|
||||
}
|
||||
|
||||
message Vec3i {
|
||||
int32 i = 1;
|
||||
int32 j = 2;
|
||||
int32 k = 3;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ syntax = "proto3";
|
||||
|
||||
package rips;
|
||||
|
||||
import "Definitions.proto";
|
||||
import "Case.proto";
|
||||
|
||||
service Grid
|
||||
|
@ -0,0 +1,37 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "Definitions.proto";
|
||||
|
||||
package rips;
|
||||
|
||||
service SimulationWell
|
||||
{
|
||||
rpc GetSimulationWellStatus(SimulationWellRequest) returns (SimulationWellStatus) {}
|
||||
rpc GetSimulationWellCells(SimulationWellRequest) returns (SimulationWellCellInfoArray) {}
|
||||
}
|
||||
|
||||
message SimulationWellRequest {
|
||||
int32 case_id = 1;
|
||||
string well_name = 2;
|
||||
int32 timestep = 3;
|
||||
}
|
||||
|
||||
message SimulationWellStatus
|
||||
{
|
||||
string well_type = 1;
|
||||
bool is_open = 2;
|
||||
}
|
||||
|
||||
message SimulationWellCellInfo {
|
||||
Vec3i ijk = 1;
|
||||
int32 grid_index = 2;
|
||||
bool is_open = 3;
|
||||
int32 branch_id = 4;
|
||||
int32 segment_id = 5;
|
||||
}
|
||||
|
||||
message SimulationWellCellInfoArray
|
||||
{
|
||||
repeated SimulationWellCellInfo data = 1;
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
###################################################################################
|
||||
# This example will connect to ResInsight, retrieve a list of
|
||||
# simulation wells and print info
|
||||
###################################################################################
|
||||
|
||||
# Import the ResInsight Processing Server Module
|
||||
import rips
|
||||
|
||||
# Connect to ResInsight
|
||||
resinsight = rips.Instance.find()
|
||||
if resinsight is not None:
|
||||
# Get a list of all wells
|
||||
cases = resinsight.project.cases()
|
||||
|
||||
for case in cases:
|
||||
print("Case id: " + str(case.case_id))
|
||||
print("Case name: " + case.name)
|
||||
|
||||
timesteps = case.time_steps()
|
||||
sim_wells = case.simulation_wells()
|
||||
for sim_well in sim_wells:
|
||||
print("Simulation well: " + sim_well.name)
|
||||
|
||||
for (tidx, timestep) in enumerate(timesteps):
|
||||
status = sim_well.status(tidx)
|
||||
cells = sim_well.cells(tidx)
|
||||
print("timestep: " + str(tidx) + " type: " + status.well_type + " open: " + str(status.is_open) + " cells:" + str(len(cells)))
|
@ -17,12 +17,12 @@ import rips.generated.PdmObject_pb2 as PdmObject_pb2
|
||||
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
|
||||
from rips.contour_map import ContourMap, ContourMapType
|
||||
from rips.well_bore_stability_plot import WellBoreStabilityPlot, WbsParameters
|
||||
from rips.simulation_well import SimulationWell
|
||||
|
||||
class Case(PdmObject):
|
||||
"""ResInsight case class
|
||||
@ -808,3 +808,15 @@ class Case(PdmObject):
|
||||
|
||||
res = self._execute_command(importFormationNames=Cmd.ImportFormationNamesRequest(formationFiles=formation_files,
|
||||
applyToCaseId=self.case_id))
|
||||
|
||||
def simulation_wells(self):
|
||||
"""Get a list of all simulation wells for a case
|
||||
|
||||
Returns:
|
||||
A list of rips SimulationWell objects
|
||||
"""
|
||||
pdm_objects = self.descendants("Well")
|
||||
wells = []
|
||||
for pdm_object in pdm_objects:
|
||||
wells.append(SimulationWell(pdm_object.get_value("WellName"), self.case_id, pdm_object))
|
||||
return wells
|
||||
|
39
ApplicationCode/GrpcInterface/Python/rips/simulation_well.py
Normal file
39
ApplicationCode/GrpcInterface/Python/rips/simulation_well.py
Normal file
@ -0,0 +1,39 @@
|
||||
"""
|
||||
ResInsight SimulationWell
|
||||
"""
|
||||
import grpc
|
||||
|
||||
import rips.generated.SimulationWell_pb2 as SimulationWell_pb2
|
||||
import rips.generated.SimulationWell_pb2_grpc as SimulationWell_pb2_grpc
|
||||
|
||||
import rips.generated.Properties_pb2 as Properties_pb2
|
||||
import rips.generated.Properties_pb2_grpc as Properties_pb2_grpc
|
||||
|
||||
import rips.generated.Commands_pb2 as Cmd
|
||||
|
||||
from rips.pdmobject import PdmObject
|
||||
|
||||
class SimulationWell(PdmObject):
|
||||
"""ResInsight simulation well class
|
||||
|
||||
Attributes:
|
||||
name(string): Name of the well.
|
||||
|
||||
"""
|
||||
def __init__(self, name, case_id, pdm_object):
|
||||
PdmObject.__init__(self, pdm_object.pb2_object(), pdm_object.channel(), pdm_object.project())
|
||||
self._simulation_well_stub = SimulationWell_pb2_grpc.SimulationWellStub(pdm_object.channel())
|
||||
self.name = name
|
||||
self.case_id = case_id
|
||||
|
||||
def status(self, timestep):
|
||||
sim_well_request = SimulationWell_pb2.SimulationWellRequest(case_id=self.case_id,
|
||||
well_name=self.name,
|
||||
timestep=timestep)
|
||||
return self._simulation_well_stub.GetSimulationWellStatus(sim_well_request)
|
||||
|
||||
def cells(self, timestep):
|
||||
sim_well_request = SimulationWell_pb2.SimulationWellRequest(case_id=self.case_id,
|
||||
well_name=self.name,
|
||||
timestep=timestep)
|
||||
return self._simulation_well_stub.GetSimulationWellCells(sim_well_request).data
|
@ -0,0 +1,49 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../../'))
|
||||
import rips
|
||||
|
||||
import dataroot
|
||||
|
||||
def test_10k(rips_instance, initialize_test):
|
||||
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=case_path)
|
||||
assert(len(case.grids()) == 2)
|
||||
cell_count_info = case.cell_count()
|
||||
|
||||
sim_wells = case.simulation_wells()
|
||||
assert(len(sim_wells) == 3)
|
||||
|
||||
assert(sim_wells[0].name == "GI1")
|
||||
assert(sim_wells[1].name == "GP1")
|
||||
assert(sim_wells[2].name == "GP2")
|
||||
|
||||
timesteps = case.time_steps()
|
||||
|
||||
# On time step 0 all simulation wells are undefined
|
||||
for sim_well in sim_wells:
|
||||
status = sim_well.status(0)
|
||||
assert(status.well_type == "NotDefined")
|
||||
|
||||
# On time step 3 all wells are producing
|
||||
for sim_well in sim_wells:
|
||||
status = sim_well.status(3)
|
||||
assert(status.well_type == "Producer")
|
||||
|
||||
# On time step 0 all simulation wells have no cells
|
||||
for sim_well in sim_wells:
|
||||
cells = sim_well.cells(0)
|
||||
assert(len(cells) == 0)
|
||||
|
||||
# On the other time steps there should be cells
|
||||
expected_cell_count = {}
|
||||
expected_cell_count["GP1"] = 105
|
||||
expected_cell_count["GI1"] = 38
|
||||
expected_cell_count["GP2"] = 18
|
||||
for sim_well in sim_wells:
|
||||
for (tidx, timestep) in enumerate(timesteps):
|
||||
if (tidx > 0):
|
||||
cells = sim_well.cells(tidx)
|
||||
print("well: " + sim_well.name + " timestep: " + str(tidx) + " cells:" + str(len(cells)))
|
||||
assert(len(cells) == expected_cell_count[sim_well.name])
|
185
ApplicationCode/GrpcInterface/RiaGrpcSimulationWellService.cpp
Normal file
185
ApplicationCode/GrpcInterface/RiaGrpcSimulationWellService.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#include "RiaGrpcSimulationWellService.h"
|
||||
|
||||
#include "RiaGrpcCallbacks.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigGridBase.h"
|
||||
#include "RigSimWellData.h"
|
||||
|
||||
#include "RimCase.h"
|
||||
#include "RimEclipseCase.h"
|
||||
|
||||
#include "cvfCollection.h"
|
||||
|
||||
using namespace rips;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcSimulationWellService::GetSimulationWellStatus( grpc::ServerContext* context,
|
||||
const rips::SimulationWellRequest* request,
|
||||
rips::SimulationWellStatus* reply )
|
||||
|
||||
{
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( findCase( request->case_id() ) );
|
||||
if ( !eclipseCase )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Case not found" );
|
||||
}
|
||||
|
||||
// First find the well result for the correct well
|
||||
cvf::ref<RigSimWellData> currentWellResult = findWellResult( eclipseCase, request->well_name() );
|
||||
if ( currentWellResult.isNull() )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Well not found" );
|
||||
}
|
||||
|
||||
size_t tsIdx = static_cast<size_t>( request->timestep() );
|
||||
|
||||
QString wellType = "NotDefined";
|
||||
bool wellStatus = false;
|
||||
if ( currentWellResult->hasWellResult( tsIdx ) )
|
||||
{
|
||||
switch ( currentWellResult->wellResultFrame( tsIdx ).m_productionType )
|
||||
{
|
||||
case RigWellResultFrame::PRODUCER:
|
||||
wellType = "Producer";
|
||||
break;
|
||||
case RigWellResultFrame::OIL_INJECTOR:
|
||||
wellType = "OilInjector";
|
||||
break;
|
||||
case RigWellResultFrame::WATER_INJECTOR:
|
||||
wellType = "WaterInjector";
|
||||
break;
|
||||
case RigWellResultFrame::GAS_INJECTOR:
|
||||
wellType = "GasInjector";
|
||||
break;
|
||||
}
|
||||
|
||||
wellStatus = currentWellResult->wellResultFrame( tsIdx ).m_isOpen;
|
||||
}
|
||||
|
||||
reply->set_well_type( wellType.toStdString() );
|
||||
reply->set_is_open( wellStatus );
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcSimulationWellService::GetSimulationWellCells( grpc::ServerContext* context,
|
||||
const rips::SimulationWellRequest* request,
|
||||
rips::SimulationWellCellInfoArray* reply )
|
||||
{
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( findCase( request->case_id() ) );
|
||||
if ( !eclipseCase )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Case not found" );
|
||||
}
|
||||
|
||||
// First find the well result for the correct well
|
||||
cvf::ref<RigSimWellData> currentWellResult = findWellResult( eclipseCase, request->well_name() );
|
||||
if ( currentWellResult.isNull() )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Well not found" );
|
||||
}
|
||||
|
||||
size_t tsIdx = static_cast<size_t>( request->timestep() );
|
||||
if ( currentWellResult->hasWellResult( tsIdx ) )
|
||||
{
|
||||
// Fetch results
|
||||
const RigWellResultFrame& wellResFrame = currentWellResult->wellResultFrame( tsIdx );
|
||||
std::vector<RigGridBase*> grids;
|
||||
eclipseCase->eclipseCaseData()->allGrids( &grids );
|
||||
|
||||
for ( size_t bIdx = 0; bIdx < wellResFrame.m_wellResultBranches.size(); ++bIdx )
|
||||
{
|
||||
const std::vector<RigWellResultPoint>& branchResPoints =
|
||||
wellResFrame.m_wellResultBranches[bIdx].m_branchResultPoints;
|
||||
for ( size_t rpIdx = 0; rpIdx < branchResPoints.size(); ++rpIdx )
|
||||
{
|
||||
const RigWellResultPoint& resPoint = branchResPoints[rpIdx];
|
||||
|
||||
if ( resPoint.isCell() )
|
||||
{
|
||||
rips::SimulationWellCellInfo* cellInfo = reply->add_data();
|
||||
size_t i;
|
||||
size_t j;
|
||||
size_t k;
|
||||
size_t gridIdx = resPoint.m_gridIndex;
|
||||
grids[gridIdx]->ijkFromCellIndex( resPoint.m_gridCellIndex, &i, &j, &k );
|
||||
|
||||
Vec3i* ijk = new Vec3i;
|
||||
ijk->set_i( i );
|
||||
ijk->set_j( j );
|
||||
ijk->set_k( k );
|
||||
|
||||
cellInfo->set_allocated_ijk( ijk );
|
||||
cellInfo->set_grid_index( gridIdx );
|
||||
cellInfo->set_is_open( resPoint.m_isOpen );
|
||||
cellInfo->set_branch_id( resPoint.m_ertBranchId );
|
||||
cellInfo->set_segment_id( resPoint.m_ertSegmentId );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::ref<RigSimWellData> RiaGrpcSimulationWellService::findWellResult( const RimEclipseCase* eclipseCase,
|
||||
const std::string& wellName )
|
||||
{
|
||||
const cvf::Collection<RigSimWellData>& allWellRes = eclipseCase->eclipseCaseData()->wellResults();
|
||||
for ( size_t tsIdx = 0; tsIdx < allWellRes.size(); ++tsIdx )
|
||||
{
|
||||
if ( allWellRes[tsIdx]->m_wellName.toStdString() == wellName )
|
||||
{
|
||||
return allWellRes[tsIdx];
|
||||
}
|
||||
}
|
||||
|
||||
return cvf::ref<RigSimWellData>();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaGrpcCallbackInterface*> RiaGrpcSimulationWellService::createCallbacks()
|
||||
{
|
||||
typedef RiaGrpcSimulationWellService Self;
|
||||
|
||||
return {
|
||||
new RiaGrpcUnaryCallback<Self, SimulationWellRequest, SimulationWellStatus>( this,
|
||||
&Self::GetSimulationWellStatus,
|
||||
&Self::RequestGetSimulationWellStatus ),
|
||||
new RiaGrpcUnaryCallback<Self, SimulationWellRequest, SimulationWellCellInfoArray>( this,
|
||||
&Self::GetSimulationWellCells,
|
||||
&Self::RequestGetSimulationWellCells ),
|
||||
};
|
||||
}
|
||||
|
||||
static bool RiaGrpcSimulationWellService_init =
|
||||
RiaGrpcServiceFactory::instance()->registerCreator<RiaGrpcSimulationWellService>(
|
||||
typeid( RiaGrpcSimulationWellService ).hash_code() );
|
60
ApplicationCode/GrpcInterface/RiaGrpcSimulationWellService.h
Normal file
60
ApplicationCode/GrpcInterface/RiaGrpcSimulationWellService.h
Normal file
@ -0,0 +1,60 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "SimulationWell.grpc.pb.h"
|
||||
|
||||
#include "RiaGrpcServiceInterface.h"
|
||||
|
||||
#include "cvfObject.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace rips
|
||||
{
|
||||
class SimulationWellRequest;
|
||||
class SimulationWellStatus;
|
||||
} // namespace rips
|
||||
|
||||
class RiaGrpcCallbackInterface;
|
||||
|
||||
class RimEclipseCase;
|
||||
class RigSimWellData;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// gRPC-service answering requests about grid information for a simulation wells
|
||||
//
|
||||
//==================================================================================================
|
||||
class RiaGrpcSimulationWellService final : public rips::SimulationWell::AsyncService, public RiaGrpcServiceInterface
|
||||
{
|
||||
public:
|
||||
grpc::Status GetSimulationWellStatus( grpc::ServerContext* context,
|
||||
const rips::SimulationWellRequest* request,
|
||||
rips::SimulationWellStatus* reply );
|
||||
|
||||
grpc::Status GetSimulationWellCells( grpc::ServerContext* context,
|
||||
const rips::SimulationWellRequest* request,
|
||||
rips::SimulationWellCellInfoArray* reply );
|
||||
|
||||
std::vector<RiaGrpcCallbackInterface*> createCallbacks() override;
|
||||
|
||||
private:
|
||||
static cvf::ref<RigSimWellData> findWellResult( const RimEclipseCase* eclipseCase, const std::string& wellName );
|
||||
};
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "RimSimWellInView.h"
|
||||
|
||||
#include "RicfCommandObject.h"
|
||||
|
||||
#include "RigActiveCellInfo.h"
|
||||
#include "RigCell.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
@ -62,7 +64,7 @@ RimSimWellInView::RimSimWellInView()
|
||||
{
|
||||
CAF_PDM_InitObject( "Well", ":/Well.png", "", "" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &name, "WellName", "Name", "", "", "" );
|
||||
RICF_InitFieldNoDefault( &name, "WellName", "Name", "", "", "" );
|
||||
|
||||
CAF_PDM_InitField( &showWell, "ShowWell", true, "Show well ", "", "", "" );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user