mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Move GrpcInterface into top level
This commit is contained in:
335
GrpcInterface/CMakeLists.txt
Normal file
335
GrpcInterface/CMakeLists.txt
Normal file
@@ -0,0 +1,335 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
project(GrpcInterface)
|
||||
|
||||
message(STATUS "GRPC enabled")
|
||||
add_definitions(-DENABLE_GRPC)
|
||||
|
||||
if(VCPKG_AUTO_INSTALL)
|
||||
vcpkg_install(grpc)
|
||||
endif()
|
||||
|
||||
set(CMAKE_UNITY_BUILD false)
|
||||
set(RESINSIGHT_GRPC_PYTHON_EXECUTABLE
|
||||
""
|
||||
CACHE
|
||||
FILEPATH
|
||||
"gRPC : Path to Python 3 executable, required to build the Python client library"
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_WIN32_WINNT=0x600)
|
||||
endif()
|
||||
|
||||
add_definitions(-D_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING)
|
||||
|
||||
set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcHelper.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.h
|
||||
${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
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppService.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcNNCPropertiesService.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPdmObjectService.h)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcHelper.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
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppService.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcNNCPropertiesService.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPdmObjectService.cpp)
|
||||
|
||||
# Find Protobuf installation Looks for protobuf-config.cmake file installed by
|
||||
# Protobuf's cmake installation.
|
||||
set(protobuf_MODULE_COMPATIBLE ON)
|
||||
find_package(Protobuf CONFIG 3.0 QUIET)
|
||||
|
||||
if(Protobuf_FOUND)
|
||||
message(STATUS "Using protobuf ${protobuf_VERSION}")
|
||||
|
||||
# Find gRPC installation Looks for gRPCConfig.cmake file installed by gRPC's
|
||||
# cmake installation.
|
||||
find_package(gRPC CONFIG REQUIRED)
|
||||
message(STATUS "Using gRPC ${gRPC_VERSION}")
|
||||
|
||||
set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
|
||||
set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
|
||||
|
||||
set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure gRPC::grpc_unsecure gRPC::gpr)
|
||||
set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)
|
||||
set(GRPC_LIBRARIES ${_GRPC_GRPCPP_UNSECURE} ${_PROTOBUF_LIBPROTOBUF})
|
||||
|
||||
set_target_properties(
|
||||
${GRPC_LIBRARIES} PROPERTIES MAP_IMPORTED_CONFIG_MINSIZEREL RELEASE
|
||||
MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE)
|
||||
set(RESINSIGHT_GRPC_LIBRARIES ${GRPC_LIBRARIES} PARENT_SCOPE)
|
||||
else()
|
||||
message(STATUS "Using RESINSIGHT_GRPC_INSTALL_PREFIX=${RESINSIGHT_GRPC_INSTALL_PREFIX}")
|
||||
set(RESINSIGHT_GRPC_INSTALL_PREFIX
|
||||
""
|
||||
CACHE PATH "gRPC : Install prefix for gRPC")
|
||||
if(NOT DEFINED RESINSIGHT_GRPC_INSTALL_PREFIX
|
||||
OR NOT EXISTS ${RESINSIGHT_GRPC_INSTALL_PREFIX})
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"You need a valid RESINSIGHT_GRPC_INSTALL_PREFIX set to build with gRPC"
|
||||
)
|
||||
endif()
|
||||
set(ENV{PKG_CONFIG_PATH} "${RESINSIGHT_GRPC_INSTALL_PREFIX}/lib/pkgconfig")
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GRPC REQUIRED grpc grpc++_unsecure>=1.20 grpc_unsecure gpr
|
||||
protobuf libcares)
|
||||
if(EXISTS "${RESINSIGHT_GRPC_INSTALL_PREFIX}/bin/protoc")
|
||||
set(_PROTOBUF_PROTOC "${RESINSIGHT_GRPC_INSTALL_PREFIX}/bin/protoc")
|
||||
elseif(EXISTS "${RESINSIGHT_GRPC_INSTALL_PREFIX}/tools/protobuf/protoc")
|
||||
set(_PROTOBUF_PROTOC
|
||||
"${RESINSIGHT_GRPC_INSTALL_PREFIX}/tools/protobuf/protoc")
|
||||
else()
|
||||
message(FATAL_ERROR "Could not find the protobuf compiler (protoc)")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${RESINSIGHT_GRPC_INSTALL_PREFIX}/bin/grpc_cpp_plugin")
|
||||
set(_GRPC_CPP_PLUGIN_EXECUTABLE
|
||||
"${RESINSIGHT_GRPC_INSTALL_PREFIX}/bin/grpc_cpp_plugin")
|
||||
elseif(EXISTS "${RESINSIGHT_GRPC_INSTALL_PREFIX}/tools/grpc/grpc_cpp_plugin")
|
||||
set(_GRPC_CPP_PLUGIN_EXECUTABLE
|
||||
"${RESINSIGHT_GRPC_INSTALL_PREFIX}/tools/grpc/grpc_cpp_plugin")
|
||||
endif()
|
||||
include_directories(AFTER ${GRPC_INCLUDE_DIRS})
|
||||
set(RESINSIGHT_GRPC_LIBRARIES ${GRPC_LINK_LIBRARIES} PARENT_SCOPE)
|
||||
#list(APPEND RESINSIGHT_GRPC_LIBRARIES upb)
|
||||
endif()
|
||||
|
||||
set(_LINK_LIBRARIES
|
||||
${QT_LIBRARIES}
|
||||
LibCore
|
||||
cafCommand
|
||||
cafPdmCvf
|
||||
cafPdmScripting
|
||||
cafTensor
|
||||
cafViewer
|
||||
cafVizExtensions
|
||||
ecl
|
||||
nightcharts
|
||||
qwt)
|
||||
|
||||
# Proto files
|
||||
set(PROTO_FILES
|
||||
"Definitions"
|
||||
"PdmObject"
|
||||
"Case"
|
||||
"SimulationWell"
|
||||
"Project"
|
||||
"Commands"
|
||||
"NNCProperties"
|
||||
"App"
|
||||
"Properties"
|
||||
"Grid")
|
||||
|
||||
set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}/Python")
|
||||
|
||||
add_custom_target(PipInstall)
|
||||
|
||||
foreach(proto_file ${PROTO_FILES})
|
||||
get_filename_component(
|
||||
rips_proto "${CMAKE_CURRENT_LIST_DIR}/GrpcProtos/${proto_file}.proto"
|
||||
ABSOLUTE)
|
||||
get_filename_component(rips_proto_path "${rips_proto}" PATH)
|
||||
|
||||
list(APPEND GRPC_PROTO_FILES_FULL_PATH ${rips_proto})
|
||||
|
||||
set(rips_proto_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.cc")
|
||||
set(rips_proto_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.h")
|
||||
set(rips_grpc_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.cc")
|
||||
set(rips_grpc_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.h")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${rips_proto_srcs}" "${rips_proto_hdrs}" "${rips_grpc_srcs}"
|
||||
"${rips_grpc_hdrs}"
|
||||
COMMAND
|
||||
${_PROTOBUF_PROTOC} ARGS --grpc_out "${CMAKE_BINARY_DIR}/Generated"
|
||||
--cpp_out "${CMAKE_BINARY_DIR}/Generated" -I "${rips_proto_path}"
|
||||
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" "${rips_proto}"
|
||||
DEPENDS "${rips_proto}")
|
||||
|
||||
set(rips_proto_python "rips/generated/${proto_file}_pb2.py")
|
||||
set(rips_grpc_python "rips/generated/${proto_file}_pb2_grpc.py")
|
||||
|
||||
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE)
|
||||
message(
|
||||
STATUS "Using Python Executable: ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}")
|
||||
add_custom_command(
|
||||
OUTPUT "${GRPC_PYTHON_SOURCE_PATH}/${rips_proto_python}"
|
||||
"${GRPC_PYTHON_SOURCE_PATH}/${rips_grpc_python}"
|
||||
COMMAND
|
||||
${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} ARGS -m grpc_tools.protoc -I
|
||||
"${rips_proto_path}" --python_out
|
||||
"${GRPC_PYTHON_SOURCE_PATH}/rips/generated" --grpc_python_out
|
||||
"${GRPC_PYTHON_SOURCE_PATH}/rips/generated" "${rips_proto}"
|
||||
DEPENDS "${rips_proto}"
|
||||
COMMENT "Generating ${rips_proto_python} and ${rips_grpc_python}"
|
||||
VERBATIM)
|
||||
list(APPEND GRPC_PYTHON_GENERATED_SOURCES ${rips_proto_python}
|
||||
${rips_grpc_python})
|
||||
else()
|
||||
message(
|
||||
STATUS
|
||||
"RESINSIGHT_GRPC_PYTHON_EXECUTABLE not specified. Will not install Python client code"
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND GRPC_HEADER_FILES ${rips_proto_hdrs} ${rips_grpc_hdrs})
|
||||
|
||||
list(APPEND GRPC_CPP_SOURCES ${rips_proto_srcs} ${rips_grpc_srcs})
|
||||
|
||||
endforeach(proto_file)
|
||||
|
||||
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake
|
||||
${GRPC_PYTHON_SOURCE_PATH}/rips/generated/RiaVersionInfo.py)
|
||||
configure_file(${GRPC_PYTHON_SOURCE_PATH}/setup.py.cmake
|
||||
${GRPC_PYTHON_SOURCE_PATH}/setup.py)
|
||||
endif()
|
||||
|
||||
list(
|
||||
APPEND
|
||||
GRPC_PYTHON_SOURCES
|
||||
"rips/generated/RiaVersionInfo.py"
|
||||
"rips/__init__.py"
|
||||
"rips/case.py"
|
||||
"rips/contour_map.py"
|
||||
"rips/grid.py"
|
||||
"rips/gridcasegroup.py"
|
||||
"rips/instance.py"
|
||||
"rips/pdmobject.py"
|
||||
"rips/plot.py"
|
||||
"rips/project.py"
|
||||
"rips/simulation_well.py"
|
||||
"rips/view.py"
|
||||
"rips/well_log_plot.py"
|
||||
"rips/PythonExamples/instance_example.py"
|
||||
"rips/PythonExamples/command_example.py"
|
||||
"rips/PythonExamples/case_grid_group.py"
|
||||
"rips/PythonExamples/case_info_streaming_example.py"
|
||||
"rips/PythonExamples/create_wbs_plot.py"
|
||||
"rips/PythonExamples/export_plots.py"
|
||||
"rips/PythonExamples/export_snapshots.py"
|
||||
"rips/PythonExamples/error_handling.py"
|
||||
"rips/PythonExamples/import_well_paths_and_logs.py"
|
||||
"rips/PythonExamples/soil_porv_async.py"
|
||||
"rips/PythonExamples/soil_porv_sync.py"
|
||||
"rips/PythonExamples/selected_cases.py"
|
||||
"rips/PythonExamples/all_cases.py"
|
||||
"rips/PythonExamples/replace_case.py"
|
||||
"rips/PythonExamples/set_grid_properties.py"
|
||||
"rips/PythonExamples/set_cell_result.py"
|
||||
"rips/PythonExamples/set_flow_diagnostics_result.py"
|
||||
"rips/PythonExamples/grid_information.py"
|
||||
"rips/PythonExamples/input_prop_test_sync.py"
|
||||
"rips/PythonExamples/input_prop_test_async.py"
|
||||
"rips/PythonExamples/soil_average_async.py"
|
||||
"rips/PythonExamples/soil_average_sync.py"
|
||||
"rips/PythonExamples/view_example.py"
|
||||
"rips/tests/test_cases.py"
|
||||
"rips/tests/test_grids.py"
|
||||
"rips/tests/test_properties.py"
|
||||
"rips/tests/test_project.py"
|
||||
"rips/tests/conftest.py"
|
||||
"rips/tests/dataroot.py"
|
||||
"rips/tests/test_nnc_properties.py"
|
||||
"rips/tests/test_simulation_wells.py"
|
||||
"rips/tests/test_summary_cases.py"
|
||||
"rips/tests/test_wells.py"
|
||||
"requirements.txt"
|
||||
"setup.py"
|
||||
"README.md"
|
||||
"LICENSE")
|
||||
|
||||
list(APPEND GRPC_PYTHON_SOURCES ${GRPC_PYTHON_GENERATED_SOURCES})
|
||||
|
||||
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE)
|
||||
foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES})
|
||||
list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH
|
||||
"${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
${PROJECT_NAME} OBJECT
|
||||
${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES}
|
||||
${GRPC_HEADER_FILES} ${GRPC_CPP_SOURCES})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${GRPC_INCLUDE_DIRS})
|
||||
target_link_directories(${PROJECT_NAME} PUBLIC ${GRPC_LIBRARY_DIRS})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${_LINK_LIBRARIES})
|
||||
|
||||
if(MSVC)
|
||||
# GRPC generates a lot of harmless warnings on MSVC
|
||||
set_target_properties(
|
||||
${PROJECT_NAME}
|
||||
PROPERTIES COMPILE_FLAGS "/wd4251 /wd4702 /wd4005 /wd4244 /wd4125 /wd4267")
|
||||
else()
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS
|
||||
"-Wno-overloaded-virtual")
|
||||
endif()
|
||||
|
||||
# install gRPC Python files
|
||||
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE AND RESINSIGHT_GRPC_DOWNLOAD_PYTHON_MODULE)
|
||||
message(STATUS "Installing Python modules")
|
||||
add_custom_command(
|
||||
TARGET PipInstall
|
||||
COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} ARGS -m pip install --user
|
||||
wheel setuptools pytest
|
||||
COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} ARGS -m pip install --user
|
||||
grpcio-tools)
|
||||
endif()
|
||||
|
||||
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE AND RESINSIGHT_GRPC_BUNDLE_PYTHON_MODULE)
|
||||
message(STATUS "Bundling Python GRPC modules")
|
||||
add_custom_command(
|
||||
TARGET PipInstall
|
||||
COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} ARGS -m pip install --user
|
||||
--target=${GRPC_PYTHON_SOURCE_PATH} grpcio-tools)
|
||||
endif()
|
||||
|
||||
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE)
|
||||
add_custom_target(GeneratedPythonSources ALL
|
||||
DEPENDS ${GRPC_PYTHON_SOURCES_FULL_PATH})
|
||||
add_dependencies(${PROJECT_NAME} GeneratedPythonSources)
|
||||
|
||||
if(RESINSIGHT_GRPC_DOWNLOAD_PYTHON_MODULE)
|
||||
add_dependencies(${PROJECT_NAME} PipInstall)
|
||||
add_dependencies(GeneratedPythonSources PipInstall)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE)
|
||||
install(DIRECTORY ${GRPC_PYTHON_SOURCE_PATH}/
|
||||
DESTINATION ${RESINSIGHT_INSTALL_FOLDER}/Python)
|
||||
endif()
|
||||
|
||||
source_group(
|
||||
"GrpcInterface"
|
||||
FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/CMakeLists.cmake)
|
||||
source_group("GrpcInterface\\GrpcProtos" FILES ${GRPC_PROTO_FILES_FULL_PATH})
|
||||
if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE)
|
||||
source_group(
|
||||
TREE ${GRPC_PYTHON_SOURCE_PATH}
|
||||
FILES ${GRPC_PYTHON_SOURCES_FULL_PATH}
|
||||
PREFIX "GrpcInterface\\Python")
|
||||
endif()
|
||||
28
GrpcInterface/GrpcProtos/App.proto
Normal file
28
GrpcInterface/GrpcProtos/App.proto
Normal file
@@ -0,0 +1,28 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package rips;
|
||||
|
||||
import "Definitions.proto";
|
||||
|
||||
service App {
|
||||
rpc GetVersion(Empty) returns (Version) {}
|
||||
rpc Exit(Empty) returns (Empty) {}
|
||||
rpc GetRuntimeInfo(Empty) returns (RuntimeInfo) {}
|
||||
}
|
||||
|
||||
message Version {
|
||||
int32 major_version = 1;
|
||||
int32 minor_version = 2;
|
||||
int32 patch_version = 3;
|
||||
}
|
||||
|
||||
enum ApplicationTypeEnum
|
||||
{
|
||||
GUI_APPLICATION = 0;
|
||||
CONSOLE_APPLICATION = 1;
|
||||
}
|
||||
|
||||
message RuntimeInfo
|
||||
{
|
||||
ApplicationTypeEnum app_type = 1;
|
||||
}
|
||||
140
GrpcInterface/GrpcProtos/Case.proto
Normal file
140
GrpcInterface/GrpcProtos/Case.proto
Normal file
@@ -0,0 +1,140 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "PdmObject.proto";
|
||||
import "Definitions.proto";
|
||||
|
||||
package rips;
|
||||
|
||||
service Case
|
||||
{
|
||||
rpc GetGridCount(CaseRequest) returns(GridCount) {}
|
||||
rpc GetCellCount(CellInfoRequest) returns (CellCount) {}
|
||||
rpc GetCellInfoForActiveCells(CellInfoRequest) returns (stream CellInfoArray) {}
|
||||
rpc GetCellCenterForActiveCells(CellInfoRequest) returns (stream CellCenters) {}
|
||||
rpc GetCellCornersForActiveCells(CellInfoRequest) returns (stream CellCornersArray) {}
|
||||
rpc GetCoarseningInfoArray(CaseRequest) returns (CoarseningInfoArray) {}
|
||||
rpc GetTimeSteps(CaseRequest) returns (TimeStepDates) {}
|
||||
rpc GetSelectedCells(CaseRequest) returns (stream SelectedCells) {}
|
||||
rpc GetDaysSinceStart(CaseRequest) returns (DaysSinceStart) {}
|
||||
rpc GetCaseInfo(CaseRequest) returns (CaseInfo) {}
|
||||
rpc GetPdmObject(CaseRequest) returns (PdmObject) {}
|
||||
rpc GetReservoirBoundingBox(CaseRequest) returns (BoundingBox) {}
|
||||
}
|
||||
|
||||
message CaseRequest {
|
||||
int32 id = 1;
|
||||
}
|
||||
|
||||
message CaseInfo
|
||||
{
|
||||
int32 id = 1;
|
||||
int32 group_id = 2;
|
||||
string name = 3;
|
||||
string type = 4;
|
||||
}
|
||||
|
||||
message CaseInfoArray
|
||||
{
|
||||
repeated CaseInfo data = 1;
|
||||
}
|
||||
|
||||
message BoundingBox
|
||||
{
|
||||
double min_x = 1;
|
||||
double max_x = 2;
|
||||
double min_y = 3;
|
||||
double max_y = 4;
|
||||
double min_z = 5;
|
||||
double max_z = 6;
|
||||
}
|
||||
|
||||
message CaseGroup
|
||||
{
|
||||
int32 id = 1;
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
message CaseGroups
|
||||
{
|
||||
repeated CaseGroup case_groups = 1;
|
||||
}
|
||||
|
||||
message GridCount
|
||||
{
|
||||
int32 count = 1;
|
||||
}
|
||||
|
||||
message CellCount
|
||||
{
|
||||
int32 active_cell_count = 1;
|
||||
int32 reservoir_cell_count = 2;
|
||||
}
|
||||
|
||||
enum PorosityModelType
|
||||
{
|
||||
MATRIX_MODEL = 0;
|
||||
FRACTURE_MODEL = 1;
|
||||
}
|
||||
|
||||
message CellInfoRequest
|
||||
{
|
||||
CaseRequest case_request = 1;
|
||||
PorosityModelType porosity_model = 2;
|
||||
}
|
||||
|
||||
message CellInfoArray
|
||||
{
|
||||
repeated CellInfo data = 1;
|
||||
}
|
||||
|
||||
message CellInfo
|
||||
{
|
||||
int32 grid_index = 1;
|
||||
int32 parent_grid_index = 2;
|
||||
int32 coarsening_box_index = 3;
|
||||
Vec3i local_ijk = 4;
|
||||
Vec3i parent_ijk = 5;
|
||||
}
|
||||
|
||||
message CoarseningInfoArray
|
||||
{
|
||||
repeated CoarseningInfo data = 1;
|
||||
}
|
||||
|
||||
message CoarseningInfo
|
||||
{
|
||||
Vec3i min = 1;
|
||||
Vec3i max = 2;
|
||||
}
|
||||
|
||||
message TimeStepDates
|
||||
{
|
||||
repeated TimeStepDate dates = 1;
|
||||
}
|
||||
|
||||
message TimeStepDate
|
||||
{
|
||||
int32 year = 1;
|
||||
int32 month = 2;
|
||||
int32 day = 3;
|
||||
int32 hour = 4;
|
||||
int32 minute = 5;
|
||||
int32 second = 6;
|
||||
}
|
||||
|
||||
message DaysSinceStart
|
||||
{
|
||||
repeated double day_decimals = 1;
|
||||
}
|
||||
|
||||
message SelectedCell
|
||||
{
|
||||
int32 grid_index = 1;
|
||||
Vec3i ijk = 2;
|
||||
}
|
||||
|
||||
|
||||
message SelectedCells
|
||||
{
|
||||
repeated SelectedCell cells = 1;
|
||||
}
|
||||
447
GrpcInterface/GrpcProtos/Commands.proto
Normal file
447
GrpcInterface/GrpcProtos/Commands.proto
Normal file
@@ -0,0 +1,447 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "Case.proto";
|
||||
import "Definitions.proto";
|
||||
import "PdmObject.proto";
|
||||
|
||||
package rips;
|
||||
|
||||
/*
|
||||
* The Commands service handles generic ResInsight RicfCommandObject-commands
|
||||
* The CommandParams is used to deduce command name from the chosen oneof-message
|
||||
* .. and the parameters are in the oneof-message itself.
|
||||
* Note that we several times duplicate nearly the same message. This is because
|
||||
* it is not recommended to reuse existing messages for different purposes.
|
||||
*/
|
||||
service Commands
|
||||
{
|
||||
rpc Execute(CommandParams) returns(CommandReply) {}
|
||||
}
|
||||
|
||||
message FilePathRequest
|
||||
{
|
||||
string path = 1;
|
||||
}
|
||||
|
||||
message ReplaceCaseRequest
|
||||
{
|
||||
string newGridFile = 1;
|
||||
int32 caseId = 2;
|
||||
}
|
||||
|
||||
message ReplaceCaseRequests
|
||||
{
|
||||
repeated ReplaceCaseRequest casePairs = 1;
|
||||
}
|
||||
|
||||
message ReplaceSourceCasesRequest
|
||||
{
|
||||
string gridListFile = 1;
|
||||
int32 caseGroupId = 2;
|
||||
}
|
||||
|
||||
message ExportMultiCaseRequest
|
||||
{
|
||||
string gridListFile = 1;
|
||||
}
|
||||
|
||||
enum PlotOutputFormat
|
||||
{
|
||||
PNG = 0;
|
||||
PDF = 1;
|
||||
}
|
||||
|
||||
enum SnapshotType
|
||||
{
|
||||
VIEWS = 0;
|
||||
PLOTS = 1;
|
||||
ALL = 2;
|
||||
}
|
||||
|
||||
message ExportSnapshotsRequest
|
||||
{
|
||||
SnapshotType type = 1;
|
||||
string prefix = 2;
|
||||
int32 caseId = 3;
|
||||
int32 viewId = 4;
|
||||
string exportFolder = 5;
|
||||
PlotOutputFormat plotOutputFormat = 6;
|
||||
}
|
||||
|
||||
message ExportPropertyRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
int32 timeStep = 2;
|
||||
string property = 3;
|
||||
string eclipseKeyword = 4;
|
||||
double undefinedValue = 5;
|
||||
string exportFile = 6;
|
||||
}
|
||||
|
||||
message ExportPropertyInViewsRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
repeated int32 viewIds = 2;
|
||||
double undefinedValue = 3;
|
||||
}
|
||||
|
||||
enum CompdatExportSplit
|
||||
{
|
||||
UNIFIED_FILE = 0;
|
||||
SPLIT_ON_WELL = 1;
|
||||
SPLIT_ON_WELL_AND_COMPLETION_TYPE = 2;
|
||||
}
|
||||
|
||||
enum CompdatExportType
|
||||
{
|
||||
TRANSMISSIBILITIES = 0;
|
||||
WPIMULT_AND_DEFAULT_CONNECTION_FACTORS = 1;
|
||||
NO_COMPLETIONS = 2;
|
||||
}
|
||||
|
||||
enum CompdatCombinationMode
|
||||
{
|
||||
INDIVIDUALLY = 0;
|
||||
COMBINED = 1;
|
||||
}
|
||||
|
||||
message ExportWellPathCompRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
int32 timeStep = 2;
|
||||
repeated string wellPathNames = 3;
|
||||
CompdatExportSplit fileSplit = 4;
|
||||
CompdatExportType compdatExport = 5;
|
||||
bool includePerforations = 6;
|
||||
bool includeFishbones = 7;
|
||||
bool excludeMainBoreForFishbones = 8;
|
||||
CompdatCombinationMode combinationMode = 9;
|
||||
}
|
||||
|
||||
message ExportSimWellPathFracRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
int32 viewId = 2;
|
||||
int32 timeStep = 3;
|
||||
repeated string simulationWellNames = 4;
|
||||
CompdatExportSplit fileSplit = 5;
|
||||
CompdatExportType compdatExport = 6;
|
||||
}
|
||||
|
||||
message ExportMswRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
string wellPath = 2;
|
||||
}
|
||||
|
||||
message ExportWellPathRequest
|
||||
{
|
||||
repeated string wellPathNames = 1;
|
||||
double mdStepSize = 2;
|
||||
}
|
||||
|
||||
message ExportVisibleCellsRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
int32 viewId = 2;
|
||||
string exportKeyword = 3;
|
||||
int32 visibleActiveCellsValue = 4;
|
||||
int32 hiddenActiveCellsValue = 5;
|
||||
int32 inactiveCellsValue = 6;
|
||||
}
|
||||
|
||||
enum ExportFolderType {
|
||||
COMPLETIONS = 0;
|
||||
SNAPSHOTS = 1;
|
||||
PROPERTIES = 2;
|
||||
STATISTICS = 3;
|
||||
WELLPATHS = 4;
|
||||
CELLS = 5;
|
||||
LGRS = 6;
|
||||
}
|
||||
|
||||
message SetExportFolderRequest
|
||||
{
|
||||
ExportFolderType type = 1;
|
||||
string path = 2;
|
||||
bool createFolder = 3;
|
||||
}
|
||||
|
||||
message RunOctaveScriptRequest
|
||||
{
|
||||
string path = 1;
|
||||
repeated int32 caseIds = 2;
|
||||
}
|
||||
|
||||
message SetWindowSizeParams
|
||||
{
|
||||
int32 height = 1;
|
||||
int32 width = 2;
|
||||
}
|
||||
|
||||
message ComputeCaseGroupStatRequest
|
||||
{
|
||||
repeated int32 caseIds = 1;
|
||||
int32 caseGroupId = 2;
|
||||
}
|
||||
|
||||
message SetTimeStepParams
|
||||
{
|
||||
int32 caseId = 1;
|
||||
int32 viewId = 2;
|
||||
int32 timeStep = 3;
|
||||
}
|
||||
|
||||
message ScaleFractureTemplateRequest
|
||||
{
|
||||
int32 id = 1;
|
||||
double halfLength = 2;
|
||||
double height = 3;
|
||||
}
|
||||
|
||||
message SetFracContainmentRequest
|
||||
{
|
||||
int32 id = 1;
|
||||
int32 topLayer = 2;
|
||||
int32 baseLayer = 3;
|
||||
}
|
||||
|
||||
enum MultipleFracAction
|
||||
{
|
||||
NONE = 0;
|
||||
APPEND_FRACTURES = 1;
|
||||
REPLACE_FRACTURES = 2;
|
||||
}
|
||||
|
||||
message CreateMultipleFracRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
int32 templateId = 2;
|
||||
repeated string wellPathNames = 3;
|
||||
double minDistFromWellTd = 4;
|
||||
int32 maxFracturesPerWell = 5;
|
||||
int32 topLayer = 6;
|
||||
int32 baseLayer = 7;
|
||||
int32 spacing = 8;
|
||||
MultipleFracAction action = 9;
|
||||
}
|
||||
|
||||
enum LgrSplitType
|
||||
{
|
||||
LGR_PER_CELL = 0;
|
||||
LGR_PER_COMPLETION = 1;
|
||||
LGR_PER_WELL = 2;
|
||||
}
|
||||
|
||||
message CreateLgrForCompRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
int32 timeStep = 2;
|
||||
repeated string wellPathNames = 3;
|
||||
int32 refinementI = 4;
|
||||
int32 refinementJ = 5;
|
||||
int32 refinementK = 6;
|
||||
LgrSplitType splitType = 7;
|
||||
}
|
||||
|
||||
message CreateSatPressPlotRequest
|
||||
{
|
||||
repeated int32 caseIds = 1;
|
||||
}
|
||||
|
||||
message CreateGridCaseGroupRequest
|
||||
{
|
||||
repeated string casePaths = 1;
|
||||
}
|
||||
|
||||
message CreateStatisticsCaseRequest
|
||||
{
|
||||
int32 caseGroupId = 1;
|
||||
}
|
||||
|
||||
message ExportFlowInfoRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
repeated int32 timeSteps = 2;
|
||||
repeated string injectors = 3;
|
||||
repeated string producers = 4;
|
||||
string fileName = 5;
|
||||
double minimumCommunication = 6;
|
||||
double aquiferCellThreshold = 7;
|
||||
}
|
||||
|
||||
message CreateViewRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
}
|
||||
|
||||
message CloneViewRequest
|
||||
{
|
||||
int32 viewId = 1;
|
||||
}
|
||||
|
||||
message CreateWbsPlotRequest
|
||||
{
|
||||
int32 caseId = 1;
|
||||
string wellPath = 2;
|
||||
int32 timeStep = 3;
|
||||
PdmObject wbsParameters = 4;
|
||||
}
|
||||
|
||||
message ImportWellPathsRequest
|
||||
{
|
||||
string wellPathFolder = 1;
|
||||
repeated string wellPathFiles = 2;
|
||||
}
|
||||
|
||||
message ImportWellLogFilesRequest
|
||||
{
|
||||
string wellLogFolder = 1;
|
||||
repeated string wellLogFiles = 2;
|
||||
}
|
||||
|
||||
message ImportFormationNamesRequest
|
||||
{
|
||||
repeated string formationFiles = 1;
|
||||
int32 applyToCaseId = 2;
|
||||
}
|
||||
|
||||
enum ExportFormat
|
||||
{
|
||||
LAS = 0;
|
||||
ASCII = 1;
|
||||
}
|
||||
|
||||
message ExportWellLogPlotDataRequest
|
||||
{
|
||||
ExportFormat exportFormat = 1;
|
||||
int32 viewId = 2;
|
||||
string exportFolder = 3;
|
||||
string filePrefix = 4;
|
||||
bool exportTvdRkb = 5;
|
||||
bool capitalizeFileNames = 6;
|
||||
double resampleInterval = 7;
|
||||
bool convertCurveUnits = 8;
|
||||
}
|
||||
|
||||
message ExportContourMapToTextRequest
|
||||
{
|
||||
string exportFileName = 1;
|
||||
bool exportLocalCoordinates = 2;
|
||||
string undefinedValueLabel = 3;
|
||||
bool excludeUndefinedValues = 4;
|
||||
int32 viewId = 5;
|
||||
}
|
||||
|
||||
message SaveProjectRequest
|
||||
{
|
||||
string filePath = 1;
|
||||
}
|
||||
|
||||
/* CommandParams handles both command name and parameters in one.
|
||||
* The message type and content is used as parameters and
|
||||
* the name of the variable is used to find the command name. */
|
||||
message CommandParams
|
||||
{
|
||||
/* Since only one of these oneof-parameters can be set, we know which
|
||||
* command to run from the name of parameter. I.e. if openProject is set
|
||||
* we will run the RicfOpenProject command with the parameters set in
|
||||
* the FilePathRequest message. */
|
||||
oneof params
|
||||
{
|
||||
FilePathRequest openProject = 1;
|
||||
Empty closeProject = 2;
|
||||
FilePathRequest setStartDir = 3;
|
||||
FilePathRequest loadCase = 4;
|
||||
ReplaceCaseRequest replaceCase = 5;
|
||||
ReplaceSourceCasesRequest replaceSourceCases = 6;
|
||||
ExportMultiCaseRequest exportMultiCaseSnapshots = 7;
|
||||
ExportSnapshotsRequest exportSnapshots = 8;
|
||||
ExportPropertyRequest exportProperty = 9;
|
||||
ExportPropertyInViewsRequest exportPropertyInViews = 10;
|
||||
ExportWellPathCompRequest exportWellPathCompletions = 11;
|
||||
ExportSimWellPathFracRequest exportSimWellFractureCompletions = 12;
|
||||
ExportMswRequest exportMsw = 13;
|
||||
ExportWellPathRequest exportWellPaths = 14;
|
||||
ExportVisibleCellsRequest exportVisibleCells = 15;
|
||||
SetExportFolderRequest setExportFolder = 16;
|
||||
RunOctaveScriptRequest runOctaveScript = 17;
|
||||
SetWindowSizeParams setMainWindowSize = 18;
|
||||
ComputeCaseGroupStatRequest computeCaseGroupStatistics = 19;
|
||||
SetTimeStepParams setTimeStep = 20;
|
||||
ScaleFractureTemplateRequest scaleFractureTemplate = 21;
|
||||
SetFracContainmentRequest setFractureContainment = 22;
|
||||
CreateMultipleFracRequest createMultipleFractures = 23;
|
||||
CreateLgrForCompRequest createLgrForCompletions = 24;
|
||||
CreateSatPressPlotRequest createSaturationPressurePlots = 25;
|
||||
ReplaceCaseRequests replaceMultipleCases = 26;
|
||||
CreateGridCaseGroupRequest createGridCaseGroup = 27;
|
||||
CreateStatisticsCaseRequest createStatisticsCase = 28;
|
||||
ExportFlowInfoRequest exportFlowCharacteristics = 29;
|
||||
CreateViewRequest createView = 30;
|
||||
CloneViewRequest cloneView = 31;
|
||||
CreateWbsPlotRequest createWellBoreStabilityPlot = 32;
|
||||
ImportWellPathsRequest importWellPaths = 33;
|
||||
ImportWellLogFilesRequest importWellLogFiles = 34;
|
||||
ImportFormationNamesRequest importFormationNames = 35;
|
||||
ExportWellLogPlotDataRequest exportWellLogPlotData = 36;
|
||||
SetWindowSizeParams setPlotWindowSize = 37;
|
||||
ExportContourMapToTextRequest exportContourMapToText = 38;
|
||||
SaveProjectRequest saveProject = 39;
|
||||
}
|
||||
}
|
||||
|
||||
message GridCaseGroupResult
|
||||
{
|
||||
int32 groupId = 1;
|
||||
string groupName = 2;
|
||||
}
|
||||
|
||||
message CreateStatisticsCaseResult
|
||||
{
|
||||
int32 caseId = 1;
|
||||
}
|
||||
|
||||
message CreateViewResult
|
||||
{
|
||||
int32 viewId = 1;
|
||||
}
|
||||
|
||||
message CreateWbsPlotResult
|
||||
{
|
||||
int32 viewId = 1;
|
||||
}
|
||||
|
||||
message ImportWellPathsResult
|
||||
{
|
||||
repeated string wellPathNames = 1;
|
||||
}
|
||||
|
||||
message ImportWellLogFilesResult
|
||||
{
|
||||
repeated string wellPathNames = 1;
|
||||
}
|
||||
|
||||
message ExportWellLogPlotDataResult
|
||||
{
|
||||
repeated string exportedFiles = 1;
|
||||
}
|
||||
|
||||
/* Command reply handles the return values for the generic command
|
||||
* The name of the variable is used to map to the cafPdmObject classKeyword */
|
||||
message CommandReply
|
||||
{
|
||||
oneof result
|
||||
{
|
||||
Empty emptyResult = 1;
|
||||
CaseRequest loadCaseResult = 2;
|
||||
GridCaseGroupResult createGridCaseGroupResult = 3;
|
||||
CreateStatisticsCaseResult createStatisticsCaseResult = 4;
|
||||
CreateViewResult createViewResult = 5;
|
||||
CreateWbsPlotResult createWbsPlotResult = 6;
|
||||
ImportWellPathsResult importWellPathsResult = 7;
|
||||
ImportWellLogFilesResult importWellLogFilesResult = 8;
|
||||
ExportWellLogPlotDataResult exportWellLogPlotDataResult = 9;
|
||||
}
|
||||
}
|
||||
|
||||
46
GrpcInterface/GrpcProtos/Definitions.proto
Normal file
46
GrpcInterface/GrpcProtos/Definitions.proto
Normal file
@@ -0,0 +1,46 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package rips;
|
||||
|
||||
message Empty
|
||||
{
|
||||
}
|
||||
|
||||
message ClientToServerStreamReply
|
||||
{
|
||||
int64 accepted_value_count = 1;
|
||||
}
|
||||
|
||||
message Vec3i {
|
||||
int32 i = 1;
|
||||
int32 j = 2;
|
||||
int32 k = 3;
|
||||
}
|
||||
|
||||
message Vec3d
|
||||
{
|
||||
double x = 1;
|
||||
double y = 2;
|
||||
double z = 3;
|
||||
}
|
||||
|
||||
message CellCenters
|
||||
{
|
||||
repeated Vec3d centers = 1;
|
||||
}
|
||||
|
||||
message CellCorners {
|
||||
Vec3d c0 = 1;
|
||||
Vec3d c1 = 2;
|
||||
Vec3d c2 = 3;
|
||||
Vec3d c3 = 4;
|
||||
Vec3d c4 = 5;
|
||||
Vec3d c5 = 6;
|
||||
Vec3d c6 = 7;
|
||||
Vec3d c7 = 8;
|
||||
}
|
||||
|
||||
message CellCornersArray
|
||||
{
|
||||
repeated CellCorners cells = 1;
|
||||
}
|
||||
25
GrpcInterface/GrpcProtos/Grid.proto
Normal file
25
GrpcInterface/GrpcProtos/Grid.proto
Normal file
@@ -0,0 +1,25 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package rips;
|
||||
|
||||
import "Definitions.proto";
|
||||
import "Case.proto";
|
||||
|
||||
service Grid
|
||||
{
|
||||
rpc GetCellCenters(GridRequest) returns(stream CellCenters) {}
|
||||
rpc GetCellCorners(GridRequest) returns(stream CellCornersArray) {}
|
||||
rpc GetDimensions(GridRequest) returns (GridDimensions) {}
|
||||
}
|
||||
|
||||
message GridRequest
|
||||
{
|
||||
CaseRequest case_request = 1;
|
||||
int32 grid_index = 2;
|
||||
}
|
||||
|
||||
message GridDimensions
|
||||
{
|
||||
Vec3i dimensions = 1;
|
||||
}
|
||||
|
||||
76
GrpcInterface/GrpcProtos/NNCProperties.proto
Normal file
76
GrpcInterface/GrpcProtos/NNCProperties.proto
Normal file
@@ -0,0 +1,76 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "Case.proto";
|
||||
import "Definitions.proto";
|
||||
|
||||
package rips;
|
||||
|
||||
service NNCProperties
|
||||
{
|
||||
rpc GetAvailableNNCProperties(CaseRequest) returns (AvailableNNCProperties) {}
|
||||
rpc GetNNCConnections(CaseRequest) returns (stream NNCConnections) {}
|
||||
rpc GetNNCValues(NNCValuesRequest) returns (stream NNCValues) {}
|
||||
rpc SetNNCValues(stream NNCValuesChunk) returns (ClientToServerStreamReply) {}
|
||||
}
|
||||
|
||||
enum NNCPropertyType
|
||||
{
|
||||
NNC_DYNAMIC = 0;
|
||||
NNC_STATIC = 1;
|
||||
NNC_GENERATED = 2;
|
||||
}
|
||||
|
||||
message AvailableNNCProperty
|
||||
{
|
||||
string name = 1;
|
||||
NNCPropertyType property_type = 2;
|
||||
}
|
||||
|
||||
message AvailableNNCProperties
|
||||
{
|
||||
repeated AvailableNNCProperty properties = 1;
|
||||
}
|
||||
|
||||
message NNCConnection
|
||||
{
|
||||
int32 cell_grid_index1 = 1;
|
||||
int32 cell_grid_index2 = 2;
|
||||
Vec3i cell1 = 3;
|
||||
Vec3i cell2 = 4;
|
||||
}
|
||||
|
||||
message NNCConnections
|
||||
{
|
||||
repeated NNCConnection connections = 1;
|
||||
}
|
||||
|
||||
message NNCValuesRequest
|
||||
{
|
||||
int32 case_id = 1;
|
||||
string property_name = 2;
|
||||
NNCPropertyType property_type = 3;
|
||||
int32 time_step = 4;
|
||||
}
|
||||
|
||||
message NNCValues
|
||||
{
|
||||
repeated double values = 1;
|
||||
}
|
||||
|
||||
message NNCValuesInputRequest
|
||||
{
|
||||
int32 case_id = 1;
|
||||
string property_name = 2;
|
||||
PorosityModelType porosity_model = 3;
|
||||
int32 time_step = 4;
|
||||
}
|
||||
|
||||
message NNCValuesChunk
|
||||
{
|
||||
oneof ChunkType
|
||||
{
|
||||
// Params needs to be sent in the first message
|
||||
NNCValuesInputRequest params = 1;
|
||||
NNCValues values = 2;
|
||||
}
|
||||
}
|
||||
111
GrpcInterface/GrpcProtos/PdmObject.proto
Normal file
111
GrpcInterface/GrpcProtos/PdmObject.proto
Normal file
@@ -0,0 +1,111 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "Definitions.proto";
|
||||
|
||||
package rips;
|
||||
|
||||
service PdmObjectService
|
||||
{
|
||||
rpc GetDescendantPdmObjects(PdmDescendantObjectRequest) returns (PdmObjectArray) {}
|
||||
rpc GetChildPdmObjects(PdmChildObjectRequest) returns (PdmObjectArray) {}
|
||||
rpc GetAncestorPdmObject(PdmParentObjectRequest) returns (PdmObject) {}
|
||||
rpc CreateChildPdmObject(CreatePdmChildObjectRequest) returns (PdmObject) {}
|
||||
rpc UpdateExistingPdmObject(PdmObject) returns (Empty) {}
|
||||
rpc CallPdmObjectGetter(PdmObjectGetterRequest) returns (stream PdmObjectGetterReply) {}
|
||||
rpc CallPdmObjectSetter(stream PdmObjectSetterChunk) returns (ClientToServerStreamReply) {}
|
||||
rpc CallPdmObjectMethod(PdmObjectMethodRequest) returns (PdmObject) {}
|
||||
}
|
||||
|
||||
message PdmDescendantObjectRequest
|
||||
{
|
||||
PdmObject object = 1;
|
||||
string child_keyword = 2;
|
||||
}
|
||||
|
||||
message PdmChildObjectRequest
|
||||
{
|
||||
PdmObject object = 1;
|
||||
string child_field = 2;
|
||||
}
|
||||
|
||||
message CreatePdmChildObjectRequest
|
||||
{
|
||||
PdmObject object = 1;
|
||||
string child_field = 2;
|
||||
}
|
||||
|
||||
message PdmParentObjectRequest
|
||||
{
|
||||
PdmObject object = 1;
|
||||
string parent_keyword = 2;
|
||||
}
|
||||
|
||||
message PdmObject
|
||||
{
|
||||
string class_keyword = 1;
|
||||
uint64 address = 2;
|
||||
map<string, string> parameters = 3;
|
||||
bool visible = 4;
|
||||
bool persistent = 5; // Does this object live on in ResInsight?
|
||||
}
|
||||
|
||||
message PdmObjectArray
|
||||
{
|
||||
repeated PdmObject objects = 1;
|
||||
}
|
||||
|
||||
message PdmObjectGetterRequest
|
||||
{
|
||||
PdmObject object = 1;
|
||||
string method = 2;
|
||||
}
|
||||
|
||||
message PdmObjectSetterRequest
|
||||
{
|
||||
PdmObjectGetterRequest request = 1;
|
||||
int32 data_count = 2;
|
||||
}
|
||||
|
||||
message PdmObjectSetterChunk
|
||||
{
|
||||
oneof data
|
||||
{
|
||||
PdmObjectSetterRequest set_request = 1;
|
||||
DoubleArray doubles = 2;
|
||||
IntArray ints = 3;
|
||||
StringArray strings = 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
message DoubleArray
|
||||
{
|
||||
repeated double data = 1;
|
||||
}
|
||||
|
||||
message IntArray
|
||||
{
|
||||
repeated int32 data = 1;
|
||||
}
|
||||
|
||||
message StringArray
|
||||
{
|
||||
repeated string data = 1;
|
||||
}
|
||||
|
||||
message PdmObjectGetterReply
|
||||
{
|
||||
oneof data
|
||||
{
|
||||
DoubleArray doubles = 1;
|
||||
IntArray ints = 2;
|
||||
StringArray strings = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message PdmObjectMethodRequest
|
||||
{
|
||||
PdmObject object = 1;
|
||||
string method = 2;
|
||||
PdmObject params = 3;
|
||||
}
|
||||
16
GrpcInterface/GrpcProtos/Project.proto
Normal file
16
GrpcInterface/GrpcProtos/Project.proto
Normal file
@@ -0,0 +1,16 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "Definitions.proto";
|
||||
import "Case.proto";
|
||||
import "PdmObject.proto";
|
||||
|
||||
package rips;
|
||||
|
||||
service Project {
|
||||
rpc GetCurrentCase(Empty) returns (CaseRequest) {}
|
||||
rpc GetSelectedCases(Empty) returns (CaseInfoArray) {}
|
||||
rpc GetAllCaseGroups(Empty) returns (CaseGroups) {}
|
||||
rpc GetAllCases(Empty) returns (CaseInfoArray) {}
|
||||
rpc GetCasesInGroup(CaseGroup) returns (CaseInfoArray) {}
|
||||
rpc GetPdmObject(Empty) returns (PdmObject) {}
|
||||
}
|
||||
72
GrpcInterface/GrpcProtos/Properties.proto
Normal file
72
GrpcInterface/GrpcProtos/Properties.proto
Normal file
@@ -0,0 +1,72 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "Definitions.proto";
|
||||
import "Case.proto";
|
||||
|
||||
package rips;
|
||||
|
||||
service Properties
|
||||
{
|
||||
rpc GetAvailableProperties(AvailablePropertiesRequest) returns (AvailableProperties) {}
|
||||
rpc GetActiveCellProperty(PropertyRequest) returns (stream PropertyChunk) {}
|
||||
rpc GetSelectedCellProperty(PropertyRequest) returns (stream PropertyChunk) {}
|
||||
rpc GetGridProperty(PropertyRequest) returns (stream PropertyChunk) {}
|
||||
rpc SetActiveCellProperty(stream PropertyInputChunk) returns (ClientToServerStreamReply) {}
|
||||
rpc SetGridProperty(stream PropertyInputChunk) returns (ClientToServerStreamReply) {}
|
||||
}
|
||||
|
||||
enum PropertyType
|
||||
{
|
||||
DYNAMIC_NATIVE = 0;
|
||||
STATIC_NATIVE = 1;
|
||||
SOURSIMRL = 2;
|
||||
GENERATED = 3;
|
||||
INPUT_PROPERTY = 4;
|
||||
FORMATION_NAMES = 5;
|
||||
FLOW_DIAGNOSTICS = 6;
|
||||
INJECTION_FLOODING = 7;
|
||||
REMOVED = 8;
|
||||
UNDEFINED = 999;
|
||||
}
|
||||
|
||||
message AvailablePropertiesRequest
|
||||
{
|
||||
CaseRequest case_request = 1;
|
||||
PropertyType property_type = 2;
|
||||
PorosityModelType porosity_model = 3;
|
||||
}
|
||||
|
||||
message AvailableProperties
|
||||
{
|
||||
repeated string property_names = 1;
|
||||
}
|
||||
|
||||
message PropertyRequest
|
||||
{
|
||||
CaseRequest case_request = 1;
|
||||
PropertyType property_type = 2;
|
||||
string property_name = 3;
|
||||
int32 time_step = 4;
|
||||
int32 grid_index = 5;
|
||||
PorosityModelType porosity_model = 6;
|
||||
}
|
||||
|
||||
message TimeStep
|
||||
{
|
||||
int32 index = 1;
|
||||
}
|
||||
|
||||
message PropertyInputChunk
|
||||
{
|
||||
oneof ChunkType
|
||||
{
|
||||
// Params needs to be sent in the first message
|
||||
PropertyRequest params = 1;
|
||||
PropertyChunk values = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message PropertyChunk
|
||||
{
|
||||
repeated double values = 1;
|
||||
}
|
||||
37
GrpcInterface/GrpcProtos/SimulationWell.proto
Normal file
37
GrpcInterface/GrpcProtos/SimulationWell.proto
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
18
GrpcInterface/Python/.gitignore
vendored
Normal file
18
GrpcInterface/Python/.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
__pycache__
|
||||
.pytest_cache
|
||||
generated
|
||||
dist
|
||||
build
|
||||
rips.egg-info
|
||||
setup.py
|
||||
grpc
|
||||
grpcio*
|
||||
six*
|
||||
easy_install*
|
||||
bin*
|
||||
grpc_tools
|
||||
pkg_resources
|
||||
google
|
||||
protobuf*
|
||||
setuptools*
|
||||
extern*
|
||||
14
GrpcInterface/Python/LICENSE
Normal file
14
GrpcInterface/Python/LICENSE
Normal file
@@ -0,0 +1,14 @@
|
||||
Copyright (C) 2019- Equinor ASA
|
||||
|
||||
ResInsight is free software: you can redistribute it andor 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.orglicensesgpl.html>
|
||||
for more details.
|
||||
|
||||
4
GrpcInterface/Python/MANIFEST.in
Normal file
4
GrpcInterface/Python/MANIFEST.in
Normal file
@@ -0,0 +1,4 @@
|
||||
include *.txt
|
||||
include *.md
|
||||
include LICENSE
|
||||
recursive-include rips *.py
|
||||
5
GrpcInterface/Python/README.md
Normal file
5
GrpcInterface/Python/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# ResInsight Processing Server - rips
|
||||
|
||||
A Python interface for the ResInsight visualization and post-processing suite for Reservoir Simulations
|
||||
|
||||
[Learn More](https://www.resinsight.org)
|
||||
6
GrpcInterface/Python/autoformat_pep8.txt
Normal file
6
GrpcInterface/Python/autoformat_pep8.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
Set working folder to /rips
|
||||
---------------------------
|
||||
python -m autopep8 --in-place --recursive .
|
||||
|
||||
Adjustments to behaviour is configured in setup.cfg at repository top level, in section [pep8]
|
||||
26
GrpcInterface/Python/create_pip_package.txt
Normal file
26
GrpcInterface/Python/create_pip_package.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
######################################################################
|
||||
# All this is based on the MANIFEST.in and setup.py in Python-folder
|
||||
######################################################################
|
||||
|
||||
# 1. Make sure dist folder is clear
|
||||
del dist/*
|
||||
|
||||
# 2. Update rips-version tag in setup.py (".N after ResInsight version"). This is generated from setup.py.cmake
|
||||
# So that you for instance have version 2019.08.1 of rips.
|
||||
|
||||
# 3. Build source distribution
|
||||
python setup.py sdist
|
||||
|
||||
# 4. Test upload to test.pypi.org. This requires a ResInsight testpypi-user and you will be prompted for username and password
|
||||
python -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*
|
||||
|
||||
# 5. Test install rips module.
|
||||
pip install --index-url https://test.pypi.org/simple/ rips
|
||||
|
||||
# 6. Test the newly installed module
|
||||
|
||||
# 8. If anything is wrong, start again from 1. with an incremented rips-version (ResInsightVersion.2+)
|
||||
# These incremented versions are just for testpypi and you can reset back to the wanted version before real upload
|
||||
|
||||
# 9. Upload to real Pypi. This requires a ResInsight pypi-user.
|
||||
python -m twine upload dist/*
|
||||
7
GrpcInterface/Python/doc/README_DOCUMENTATION.txt
Normal file
7
GrpcInterface/Python/doc/README_DOCUMENTATION.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
You need sphinx to update the documentation.
|
||||
|
||||
pip install sphinx sphinx-markdown-builder
|
||||
|
||||
To update run "make markdown" to update to reflect changes to the python code.
|
||||
The generated files are located in build/markdown
|
||||
|
||||
35
GrpcInterface/Python/doc/make.bat
Normal file
35
GrpcInterface/Python/doc/make.bat
Normal file
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
||||
39
GrpcInterface/Python/doc/make_and_copy.bat
Normal file
39
GrpcInterface/Python/doc/make_and_copy.bat
Normal file
@@ -0,0 +1,39 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
||||
|
||||
REM Copy files to deployment folder using second parameter
|
||||
REM Example "d:\gitroot\ResInsight-UserDocumentation\content\scripting"
|
||||
xcopy /Y build\markdown %2
|
||||
134
GrpcInterface/Python/doc/source/PythonExamples.rst
Normal file
134
GrpcInterface/Python/doc/source/PythonExamples.rst
Normal file
@@ -0,0 +1,134 @@
|
||||
+++
|
||||
title = "Python Examples"
|
||||
published = true
|
||||
weight = 40
|
||||
+++
|
||||
|
||||

|
||||
|
||||
This pages is created based on the content in the **PythonExamples** folder located inside the **rips** module, made available online for convenience.
|
||||
|
||||
|
||||
AllCases
|
||||
--------
|
||||
.. literalinclude:: ../../rips/PythonExamples/all_cases.py
|
||||
|
||||
AllSimulationWells
|
||||
------------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/all_simulation_wells.py
|
||||
|
||||
AllWells
|
||||
--------
|
||||
.. literalinclude:: ../../rips/PythonExamples/all_wells.py
|
||||
|
||||
AlterWbsPlot
|
||||
------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/alter_wbs_plot.py
|
||||
|
||||
CaseGridGroup
|
||||
-------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/case_grid_group.py
|
||||
|
||||
CaseInfoStreamingExample
|
||||
------------------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/case_info_streaming_example.py
|
||||
|
||||
CellResultData
|
||||
--------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/cell_result_data.py
|
||||
|
||||
CommandExample
|
||||
--------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/command_example.py
|
||||
|
||||
Create WBS Plot
|
||||
---------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/create_wbs_plot.py
|
||||
|
||||
ErrorHandling
|
||||
-------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/error_handling.py
|
||||
|
||||
ExportContourMaps
|
||||
-----------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/export_contour_maps.py
|
||||
|
||||
ExportPlots
|
||||
-----------
|
||||
.. literalinclude:: ../../rips/PythonExamples/export_plots.py
|
||||
|
||||
ExportSnapshots
|
||||
---------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/export_snapshots.py
|
||||
|
||||
GridInformation
|
||||
---------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/grid_information.py
|
||||
|
||||
Import Well Paths
|
||||
-----------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/import_well_paths_and_logs.py
|
||||
|
||||
InputPropTestAsync
|
||||
------------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/input_prop_test_async.py
|
||||
|
||||
InputPropTestSync
|
||||
-----------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/input_prop_test_sync.py
|
||||
|
||||
InstanceExample
|
||||
---------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/instance_example.py
|
||||
|
||||
LaunchWithCommandLineOptions
|
||||
----------------------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/launch_with_commandline_options.py
|
||||
|
||||
Launch Using Command Line Options
|
||||
---------------------------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/launch_with_commandline_options.py
|
||||
|
||||
NewSummaryPlot
|
||||
--------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/new_summary_plot.py
|
||||
|
||||
SelectedCases
|
||||
-------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/selected_cases.py
|
||||
|
||||
SelectedCells
|
||||
-------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/selected_cells.py
|
||||
|
||||
SetCellResult
|
||||
-------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/set_cell_result.py
|
||||
|
||||
SetFlowDiagnosticsResult
|
||||
------------------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/set_flow_diagnostics_result.py
|
||||
|
||||
SetGridProperties
|
||||
-----------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/set_grid_properties.py
|
||||
|
||||
SoilAverageAsync
|
||||
----------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/soil_average_async.py
|
||||
|
||||
SoilAverageSync
|
||||
---------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/soil_average_sync.py
|
||||
|
||||
SoilPorvAsync
|
||||
-------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/soil_porv_async.py
|
||||
|
||||
SoilPorvSync
|
||||
------------
|
||||
.. literalinclude:: ../../rips/PythonExamples/soil_porv_sync.py
|
||||
|
||||
ViewExample
|
||||
-----------
|
||||
.. literalinclude:: ../../rips/PythonExamples/view_example.py
|
||||
9
GrpcInterface/Python/doc/source/PythonRips.rst
Normal file
9
GrpcInterface/Python/doc/source/PythonRips.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
+++
|
||||
title = "Python API - rips"
|
||||
published = true
|
||||
weight = 42
|
||||
+++
|
||||
|
||||

|
||||
|
||||
.. include:: rips.rst
|
||||
67
GrpcInterface/Python/doc/source/conf.py
Normal file
67
GrpcInterface/Python/doc/source/conf.py
Normal file
@@ -0,0 +1,67 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath('../../'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'rips'
|
||||
copyright = '2019, Ceetron Solutions AS'
|
||||
author = 'Ceetron Solutions AS'
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = '2019.04.01'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.napoleon',
|
||||
'sphinx_markdown_builder'
|
||||
]
|
||||
|
||||
master_doc = 'PythonRips'
|
||||
|
||||
napoleon_google_docstring = True
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['build/*', 'rips.rst']
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'alabaster'
|
||||
|
||||
smartquotes = False
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
|
||||
# -- Extension configuration -------------------------------------------------
|
||||
113
GrpcInterface/Python/doc/source/rips.rst
Normal file
113
GrpcInterface/Python/doc/source/rips.rst
Normal file
@@ -0,0 +1,113 @@
|
||||
Instance Module
|
||||
===============
|
||||
|
||||
.. autoclass:: rips.instance.Instance
|
||||
:members:
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. literalinclude:: ../../rips/PythonExamples/instance_example.py
|
||||
:language: python
|
||||
:lines: 5-
|
||||
:emphasize-lines: 3
|
||||
|
||||
Case Module
|
||||
===========
|
||||
.. autoclass:: rips.case.Case
|
||||
:members:
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. literalinclude:: ../../rips/PythonExamples/all_cases.py
|
||||
:language: python
|
||||
:lines: 5-
|
||||
:emphasize-lines: 5
|
||||
|
||||
Contour Map Module
|
||||
==================
|
||||
|
||||
.. autoclass:: rips.contour_map.EclipseContourMap
|
||||
:members:
|
||||
|
||||
.. autoclass:: rips.contour_map.GeoMechContourMap
|
||||
:members:
|
||||
|
||||
Grid Module
|
||||
===========
|
||||
|
||||
.. autoclass:: rips.grid.Grid
|
||||
:members:
|
||||
|
||||
Example
|
||||
-------
|
||||
.. code-block:: python
|
||||
|
||||
case = rips_instance.project.loadCase(path=casePath)
|
||||
print (case.gridCount())
|
||||
if case.gridCount() > 0:
|
||||
grid = case.grid(index=0)
|
||||
dimensions = grid.dimensions()
|
||||
print(dimensions.i)
|
||||
print(dimensions.j)
|
||||
print(dimensions.k)
|
||||
|
||||
GridCaseGroup Module
|
||||
====================
|
||||
|
||||
.. autoclass:: rips.gridcasegroup.GridCaseGroup
|
||||
:members:
|
||||
|
||||
|
||||
Plot Module
|
||||
==============
|
||||
|
||||
.. autoclass:: rips.project.Plot
|
||||
:members:
|
||||
|
||||
Project Module
|
||||
==============
|
||||
|
||||
.. autoclass:: rips.project.Project
|
||||
:members:
|
||||
|
||||
|
||||
Simulation Well Module
|
||||
======================
|
||||
|
||||
.. autoclass:: rips.simulation_well.SimulationWell
|
||||
:members:
|
||||
|
||||
View Module
|
||||
===========
|
||||
|
||||
.. autoclass:: rips.view.View
|
||||
:members:
|
||||
|
||||
Well Log Plot Module
|
||||
====================
|
||||
|
||||
.. autoclass:: rips.well_log_plot.WellLogPlot
|
||||
:members:
|
||||
|
||||
Synchronous Example
|
||||
-------------------
|
||||
Read two properties, multiply them together and push the results back to ResInsight in a naïve way, by reading PORO into a list, then reading PERMX into a list, then multiplying them both in a resulting list and finally transferring back the list.
|
||||
|
||||
This is slow and inefficient, but works.
|
||||
|
||||
.. literalinclude:: ../../rips/PythonExamples/input_prop_test_async.py
|
||||
:language: python
|
||||
:lines: 5-
|
||||
|
||||
Asynchronous Example
|
||||
--------------------
|
||||
Read two properties at the same time chunk by chunk, multiply each chunk together and start transferring the result back to ResInsight as soon as the chunk is finished.
|
||||
|
||||
This is far more efficient.
|
||||
|
||||
.. literalinclude:: ../../rips/PythonExamples/input_prop_test_sync.py
|
||||
:language: python
|
||||
:lines: 5-
|
||||
|
||||
3
GrpcInterface/Python/requirements.txt
Normal file
3
GrpcInterface/Python/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
grpcio
|
||||
grpcio-tools
|
||||
protobuf
|
||||
36
GrpcInterface/Python/rips/PythonExamples/all_cases.py
Normal file
36
GrpcInterface/Python/rips/PythonExamples/all_cases.py
Normal file
@@ -0,0 +1,36 @@
|
||||
###################################################################################
|
||||
# This example will connect to ResInsight, retrieve a list of cases 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 cases
|
||||
cases = resinsight.project.cases()
|
||||
|
||||
print ("Got " + str(len(cases)) + " cases: ")
|
||||
for case in cases:
|
||||
print("Case id: " + str(case.id))
|
||||
print("Case name: " + case.name)
|
||||
print("Case type: " + case.__class__.__name__)
|
||||
print("Case file name: " + case.file_path)
|
||||
print("Case reservoir bounding box:", case.reservoir_boundingbox())
|
||||
|
||||
timesteps = case.time_steps()
|
||||
for t in timesteps:
|
||||
print("Year: " + str(t.year))
|
||||
print("Month: " + str(t.month))
|
||||
|
||||
if isinstance(case, rips.EclipseCase):
|
||||
print ("Getting coarsening info for case: ", case.name, case.id)
|
||||
coarsening_info = case.coarsening_info()
|
||||
if coarsening_info:
|
||||
print("Coarsening information:")
|
||||
|
||||
for c in coarsening_info:
|
||||
print("[{}, {}, {}] - [{}, {}, {}]".format(c.min.x, c.min.y, c.min.z,
|
||||
c.max.x, c.max.y, c.max.z))
|
||||
@@ -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.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
GrpcInterface/Python/rips/PythonExamples/all_wells.py
Normal file
17
GrpcInterface/Python/rips/PythonExamples/all_wells.py
Normal file
@@ -0,0 +1,17 @@
|
||||
###################################################################################
|
||||
# This example will connect to ResInsight, retrieve a list of 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
|
||||
wells = resinsight.project.well_paths()
|
||||
|
||||
print ("Got " + str(len(wells)) + " wells: ")
|
||||
for well in wells:
|
||||
print("Well name: " + well.name)
|
||||
29
GrpcInterface/Python/rips/PythonExamples/alter_wbs_plot.py
Normal file
29
GrpcInterface/Python/rips/PythonExamples/alter_wbs_plot.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
import tempfile
|
||||
|
||||
# Connect to ResInsight instance
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
# Get the project
|
||||
project = resinsight.project
|
||||
|
||||
# Find all the well bore stability plots in the project
|
||||
wbsplots = project.descendants(rips.WellBoreStabilityPlot)
|
||||
|
||||
# Chose a sensible output folder
|
||||
dirname = tempfile.gettempdir()
|
||||
|
||||
# Loop through all Well Bore Stability plots
|
||||
for wbsplot in wbsplots:
|
||||
# Set depth type a parameter and export snapshot
|
||||
wbsplot.depth_type = "TRUE_VERTICAL_DEPTH_RKB"
|
||||
|
||||
# Example of setting parameters for existing plots
|
||||
params = wbsplot.parameters()
|
||||
params.user_poisson_ratio = 0.12345
|
||||
params.update()
|
||||
wbsplot.update()
|
||||
wbsplot.export_snapshot(export_folder=dirname)
|
||||
|
||||
|
||||
27
GrpcInterface/Python/rips/PythonExamples/case_grid_group.py
Normal file
27
GrpcInterface/Python/rips/PythonExamples/case_grid_group.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import os
|
||||
import rips
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
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/Real10/BRUGGE_0010.EGRID")
|
||||
for case_path in case_paths:
|
||||
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.print_object_info()
|
||||
|
||||
#stat_cases = caseGroup.statistics_cases()
|
||||
#case_ids = []
|
||||
#for stat_case in stat_cases:
|
||||
# stat_case.set_dynamic_properties_to_calculate(["SWAT"])
|
||||
# case_ids.append(stat_case.id)
|
||||
|
||||
case_group.compute_statistics()
|
||||
|
||||
view = case_group.views()[0]
|
||||
cell_result = view.cell_result()
|
||||
cell_result.set_result_variable("PRESSURE_DEV")
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
###############################################################################
|
||||
# This example will get the cell info for the active cells for the first case
|
||||
###############################################################################
|
||||
|
||||
# Import the ResInsight Processing Server Module
|
||||
import rips
|
||||
|
||||
# Connect to ResInsight
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
# Get the first case. This will fail if you haven't loaded any cases
|
||||
case = resinsight.project.cases()[0]
|
||||
|
||||
# Get the cell count object
|
||||
cell_counts = case.cell_count()
|
||||
print("Number of active cells: " + str(cell_counts.active_cell_count))
|
||||
print("Total number of reservoir cells: " + str(cell_counts.reservoir_cell_count))
|
||||
|
||||
# Get information for all active cells
|
||||
active_cell_infos = case.cell_info_for_active_cells()
|
||||
|
||||
# A simple check on the size of the cell info
|
||||
assert(cell_counts.active_cell_count == len(active_cell_infos))
|
||||
|
||||
# Print information for the first active cell
|
||||
print("First active cell: ")
|
||||
print(active_cell_infos[0])
|
||||
17
GrpcInterface/Python/rips/PythonExamples/cell_result_data.py
Normal file
17
GrpcInterface/Python/rips/PythonExamples/cell_result_data.py
Normal file
@@ -0,0 +1,17 @@
|
||||
######################################################################
|
||||
# This script retrieves cell result data and alters it
|
||||
######################################################################
|
||||
import rips
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
view = resinsight.project.views()[0]
|
||||
results = view.cell_result_data()
|
||||
print ("Number of result values: ", len(results))
|
||||
|
||||
newresults = []
|
||||
for i in range(0, len(results)):
|
||||
newresults.append(results[i] * -1.0)
|
||||
view.set_cell_result_data(newresults)
|
||||
|
||||
|
||||
57
GrpcInterface/Python/rips/PythonExamples/command_example.py
Normal file
57
GrpcInterface/Python/rips/PythonExamples/command_example.py
Normal file
@@ -0,0 +1,57 @@
|
||||
###############################################################################
|
||||
# This example will show setting time step, window size and export snapshots and properties
|
||||
###############################################################################
|
||||
import os
|
||||
import tempfile
|
||||
import rips
|
||||
|
||||
# Load instance
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
# Set window sizes
|
||||
resinsight.set_main_window_size(width=800, height=500)
|
||||
resinsight.set_plot_window_size(width=1000, height=1000)
|
||||
|
||||
|
||||
# Retrieve first case
|
||||
case = resinsight.project.cases()[0]
|
||||
|
||||
# Get a view
|
||||
view1 = case.views()[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
|
||||
# If you want to keep the files, provide a good path name instead of tmpdirname
|
||||
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
|
||||
print("Temporary folder: ", tmpdirname)
|
||||
|
||||
# Set export folder for snapshots and properties
|
||||
resinsight.set_export_folder(export_type='SNAPSHOTS', path=tmpdirname)
|
||||
resinsight.set_export_folder(export_type='PROPERTIES', path=tmpdirname)
|
||||
|
||||
# Export all snapshots
|
||||
resinsight.project.export_snapshots()
|
||||
|
||||
assert(len(os.listdir(tmpdirname)) > 0)
|
||||
|
||||
# Export properties in the view
|
||||
view1.export_property()
|
||||
|
||||
# Check that the exported file exists
|
||||
expected_file_name = case.name + "-" + str("3D_View") + "-" + "T2" + "-SOIL"
|
||||
full_path = tmpdirname + "/" + expected_file_name
|
||||
|
||||
# Print contents of temporary folder
|
||||
print(os.listdir(tmpdirname))
|
||||
|
||||
assert(os.path.exists(full_path))
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
import tempfile
|
||||
from os.path import expanduser
|
||||
from pathlib import Path
|
||||
|
||||
# Connect to ResInsight instance
|
||||
resinsight = rips.Instance.find()
|
||||
# Example code
|
||||
project = resinsight.project
|
||||
|
||||
# Look for input files in the home directory of the user
|
||||
home_dir = expanduser("~")
|
||||
elastic_properties_file_path = (Path(home_dir) / "elastic_properties.csv").as_posix()
|
||||
print("Elastic properties file path:", elastic_properties_file_path)
|
||||
|
||||
facies_properties_file_path = (Path(home_dir) / "facies_id.roff").as_posix()
|
||||
print("Facies properties file path:", facies_properties_file_path)
|
||||
|
||||
# Create stim plan model template
|
||||
fmt_collection = project.descendants(rips.StimPlanModelTemplateCollection)[0]
|
||||
stim_plan_model_template = fmt_collection.new_stim_plan_model_template(elastic_properties_file_path=elastic_properties_file_path,
|
||||
facies_properties_file_path=facies_properties_file_path)
|
||||
stim_plan_model_template.overburden_formation = "Garn"
|
||||
stim_plan_model_template.overburden_facies = "Shale"
|
||||
stim_plan_model_template.underburden_formation = "Garn"
|
||||
stim_plan_model_template.underburden_facies = "Shale"
|
||||
stim_plan_model_template.overburden_height = 68
|
||||
stim_plan_model_template.update()
|
||||
print("Overburden: ", stim_plan_model_template.overburden_formation)
|
||||
|
||||
|
||||
# Set eclipse result for facies definition
|
||||
eclipse_result = stim_plan_model_template.facies_properties().facies_definition()
|
||||
eclipse_result.result_type = "INPUT_PROPERTY"
|
||||
eclipse_result.result_variable = "OPERNUM_1"
|
||||
eclipse_result.update()
|
||||
|
||||
# Set eclipse result for non-net layers
|
||||
non_net_layers = stim_plan_model_template.non_net_layers()
|
||||
non_net_layers_result = non_net_layers.facies_definition()
|
||||
non_net_layers_result.result_type = "STATIC_NATIVE"
|
||||
non_net_layers_result.result_variable = "NTG"
|
||||
non_net_layers_result.update()
|
||||
non_net_layers.formation = "Not"
|
||||
non_net_layers.facies = "Shale"
|
||||
non_net_layers.update()
|
||||
|
||||
|
||||
# Add some scaling factors
|
||||
elastic_properties = stim_plan_model_template.elastic_properties()
|
||||
elastic_properties.add_property_scaling(formation="Garn", facies="Calcite", property="YOUNGS_MODULUS", scale=1.44)
|
||||
|
||||
|
||||
well_name = "B-2 H"
|
||||
|
||||
# Find a well
|
||||
well_path = project.well_path_by_name(well_name)
|
||||
print("well path:", well_path)
|
||||
stim_plan_model_collection = project.descendants(rips.StimPlanModelCollection)[0]
|
||||
|
||||
# Find a case
|
||||
cases = resinsight.project.cases()
|
||||
case = cases[0]
|
||||
|
||||
# Use the last time step
|
||||
time_steps = case.time_steps()
|
||||
time_step = time_steps[len(time_steps) - 1]
|
||||
|
||||
|
||||
export_folder = tempfile.gettempdir()
|
||||
|
||||
stim_plan_models = []
|
||||
|
||||
# Create and export a StimPlan model for each depth
|
||||
measured_depths = [ 3200.0, 3400.0, 3600.0 ]
|
||||
for measured_depth in measured_depths:
|
||||
|
||||
# Create stim plan model at a give measured depth
|
||||
stim_plan_model = stim_plan_model_collection.new_stim_plan_model(eclipse_case=case,
|
||||
time_step=time_step,
|
||||
well_path=well_path,
|
||||
measured_depth=measured_depth,
|
||||
stim_plan_model_template=stim_plan_model_template)
|
||||
stim_plan_models.append(stim_plan_model)
|
||||
|
||||
# Make the well name safer to use as a directory path
|
||||
well_name_part = well_name.replace(" ", "_")
|
||||
directory_path = Path(export_folder) / '{}_{}'.format(well_name_part, int(measured_depth))
|
||||
|
||||
# Create the folder
|
||||
directory_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print("Exporting fracture model to: ", directory_path)
|
||||
stim_plan_model.export_to_file(directory_path=directory_path.as_posix())
|
||||
|
||||
# Create a fracture mode plot
|
||||
stim_plan_model_plot_collection = project.descendants(rips.StimPlanModelPlotCollection)[0]
|
||||
stim_plan_model_plot = stim_plan_model_plot_collection.new_stim_plan_model_plot(stim_plan_model=stim_plan_model)
|
||||
|
||||
print("Exporting fracture model plot to: ", directory_path)
|
||||
stim_plan_model_plot.export_snapshot(export_folder=directory_path.as_posix())
|
||||
|
||||
|
||||
|
||||
print("Setting measured depth and perforation length.")
|
||||
stim_plan_models[0].measured_depth = 3300.0
|
||||
stim_plan_models[0].perforation_length = 123.445
|
||||
stim_plan_models[0].update()
|
||||
43
GrpcInterface/Python/rips/PythonExamples/create_wbs_plot.py
Normal file
43
GrpcInterface/Python/rips/PythonExamples/create_wbs_plot.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import os
|
||||
import grpc
|
||||
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
# Connect to ResInsight instance
|
||||
resInsight = rips.Instance.find()
|
||||
|
||||
# Get all GeoMech cases
|
||||
cases = resInsight.project.descendants(rips.GeoMechCase)
|
||||
|
||||
# Get all well paths
|
||||
well_paths = resInsight.project.well_paths()
|
||||
|
||||
# Ensure there's at least one well path
|
||||
if len(well_paths) < 1:
|
||||
print("No well paths in project")
|
||||
exit(1)
|
||||
|
||||
# Create a set of WbsParameters
|
||||
params = rips.WbsParameters()
|
||||
params.user_poisson_ratio = 0.23456
|
||||
params.user_ucs = 123
|
||||
|
||||
# Loop through all cases
|
||||
for case in cases:
|
||||
assert(isinstance(case, rips.GeoMechCase))
|
||||
min_res_depth, max_res_depth = case.reservoir_depth_range()
|
||||
|
||||
# Find a good output path
|
||||
case_path = case.file_path
|
||||
folder_name = os.path.dirname(case_path)
|
||||
|
||||
# Import formation names
|
||||
case.import_formation_names(formation_files=['D:/Projects/ResInsight-regression-test/ModelData/norne/Norne_ATW2013.lyr'])
|
||||
|
||||
# create a folder to hold the snapshots
|
||||
dirname = os.path.join(folder_name, 'snapshots')
|
||||
print("Exporting to: " + dirname)
|
||||
|
||||
for well_path in well_paths[0:4]: # Loop through the first five well paths
|
||||
# Create plot with parameters
|
||||
wbsplot = case.create_well_bore_stability_plot(well_path=well_path.name, time_step=0, parameters=params)
|
||||
76
GrpcInterface/Python/rips/PythonExamples/error_handling.py
Normal file
76
GrpcInterface/Python/rips/PythonExamples/error_handling.py
Normal file
@@ -0,0 +1,76 @@
|
||||
###################################################################
|
||||
# This example demonstrates the use of ResInsight exceptions
|
||||
# for proper error handling
|
||||
###################################################################
|
||||
|
||||
import rips
|
||||
import grpc
|
||||
import tempfile
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
case = None
|
||||
|
||||
# Try loading a non-existing case. We should get a grpc.RpcError exception from the server
|
||||
try:
|
||||
case = resinsight.project.load_case("Nonsense")
|
||||
except grpc.RpcError as e:
|
||||
print("Expected Server Exception Received while loading case: ", e.code(), e.details())
|
||||
|
||||
# Try loading well paths from a non-existing folder. We should get a grpc.RpcError exception from the server
|
||||
try:
|
||||
well_path_files = resinsight.project.import_well_paths(well_path_folder="NONSENSE/NONSENSE")
|
||||
except grpc.RpcError as e:
|
||||
print("Expected Server Exception Received while loading wellpaths: ", e.code(), e.details())
|
||||
|
||||
# Try loading well paths from an existing but empty folder. We should get a warning.
|
||||
try:
|
||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||
well_path_files = resinsight.project.import_well_paths(well_path_folder=tmpdirname)
|
||||
assert(len(well_path_files) == 0)
|
||||
assert(resinsight.project.has_warnings())
|
||||
print("Should get warnings below")
|
||||
for warning in resinsight.project.warnings():
|
||||
print (warning)
|
||||
except grpc.RpcError as e:
|
||||
print("Unexpected Server Exception caught!!!", e)
|
||||
|
||||
case = resinsight.project.case(case_id=0)
|
||||
if case is not None:
|
||||
results = case.active_cell_property('STATIC_NATIVE', 'PORO', 0)
|
||||
active_cell_count = len(results)
|
||||
|
||||
# Send the results back to ResInsight inside try / except construct
|
||||
try:
|
||||
case.set_active_cell_property(results, 'GENERATED', 'POROAPPENDED', 0)
|
||||
print("Everything went well as expected")
|
||||
except: # Match any exception, but it should not happen
|
||||
print("Ooops!")
|
||||
|
||||
# Add another value, so this is outside the bounds of the active cell result storage
|
||||
results.append(1.0)
|
||||
|
||||
# This time we should get a grpc.RpcError exception, which is a server side error.
|
||||
try:
|
||||
case.set_active_cell_property(results, 'GENERATED', 'POROAPPENDED', 0)
|
||||
print("Everything went well??")
|
||||
except grpc.RpcError as e:
|
||||
print("Expected Server Exception Received: ", e)
|
||||
except IndexError:
|
||||
print ("Got index out of bounds error. This shouldn't happen here")
|
||||
|
||||
# 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
|
||||
# the correct number of values, even if the python client has more chunks to send
|
||||
case.chunk_size = active_cell_count
|
||||
|
||||
try:
|
||||
case.set_active_cell_property(results, 'GENERATED', 'POROAPPENDED', 0)
|
||||
print("Everything went well??")
|
||||
except grpc.RpcError as e:
|
||||
print("Got unexpected server exception", e, "This should not happen now")
|
||||
except IndexError:
|
||||
print ("Got expected index out of bounds error on client side")
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
import tempfile
|
||||
import pathlib
|
||||
|
||||
# Connect to ResInsight instance
|
||||
resInsight = rips.Instance.find()
|
||||
|
||||
# Data will be written to temp
|
||||
tmpdir = pathlib.Path(tempfile.gettempdir())
|
||||
|
||||
# Find all eclipse contour maps of the project
|
||||
contour_maps = resInsight.project.descendants(rips.EclipseContourMap)
|
||||
print("Number of eclipse contour maps:", len(contour_maps))
|
||||
|
||||
# Export the contour maps to a text file
|
||||
for (index, contour_map) in enumerate(contour_maps):
|
||||
filename = "eclipse_contour_map" + str(index) + ".txt"
|
||||
filepath = tmpdir / filename
|
||||
print("Exporting to:", filepath)
|
||||
contour_map.export_to_text(str(filepath))
|
||||
|
||||
# The contour maps is also available for a Case
|
||||
cases = resInsight.project.cases()
|
||||
for case in cases:
|
||||
contour_maps = case.descendants(rips.GeoMechContourMap)
|
||||
# Export the contour maps to a text file
|
||||
for (index, contour_map) in enumerate(contour_maps):
|
||||
filename = "geomech_contour_map" + str(index) + ".txt"
|
||||
filepath = tmpdir / filename
|
||||
print("Exporting to:", filepath)
|
||||
contour_map.export_to_text(str(filepath))
|
||||
20
GrpcInterface/Python/rips/PythonExamples/export_plots.py
Normal file
20
GrpcInterface/Python/rips/PythonExamples/export_plots.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# Import the tempfile module
|
||||
import tempfile
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
# Connect to ResInsight instance
|
||||
resInsight = rips.Instance.find()
|
||||
|
||||
# Get a list of all plots
|
||||
plots = resInsight.project.plots()
|
||||
|
||||
export_folder = tempfile.mkdtemp()
|
||||
|
||||
print("Exporting to: " + export_folder)
|
||||
|
||||
for plot in plots:
|
||||
plot.export_snapshot(export_folder=export_folder)
|
||||
plot.export_snapshot(export_folder=export_folder, output_format='PDF')
|
||||
if isinstance(plot, rips.WellLogPlot):
|
||||
plot.export_data_as_las(export_folder=export_folder)
|
||||
plot.export_data_as_ascii(export_folder=export_folder)
|
||||
44
GrpcInterface/Python/rips/PythonExamples/export_snapshots.py
Normal file
44
GrpcInterface/Python/rips/PythonExamples/export_snapshots.py
Normal file
@@ -0,0 +1,44 @@
|
||||
############################################################################
|
||||
# This script will export snapshots for two properties in every loaded case
|
||||
# And put them in a snapshots folder in the same folder as the case grid
|
||||
############################################################################
|
||||
import os
|
||||
import rips
|
||||
|
||||
# Load instance
|
||||
resinsight = rips.Instance.find()
|
||||
cases = resinsight.project.cases()
|
||||
|
||||
# Set main window size
|
||||
resinsight.set_main_window_size(width=800, height=500)
|
||||
|
||||
n = 5 # every n-th time_step for snapshot
|
||||
property_list = ['SOIL', 'PRESSURE'] # list of parameter for snapshot
|
||||
|
||||
print ("Looping through cases")
|
||||
for case in cases:
|
||||
print("Case name: ", case.name)
|
||||
print("Case id: ", case.id)
|
||||
# Get grid path and its folder name
|
||||
case_path = case.file_path
|
||||
folder_name = os.path.dirname(case_path)
|
||||
|
||||
# create a folder to hold the snapshots
|
||||
dirname = os.path.join(folder_name, 'snapshots')
|
||||
|
||||
if os.path.exists(dirname) is False:
|
||||
os.mkdir(dirname)
|
||||
|
||||
print ("Exporting to folder: " + dirname)
|
||||
resinsight.set_export_folder(export_type='SNAPSHOTS', path=dirname)
|
||||
|
||||
time_steps = case.time_steps()
|
||||
print('Number of time_steps: ' + str(len(time_steps)))
|
||||
|
||||
for view in case.views():
|
||||
if view.is_eclipse_view():
|
||||
for property in property_list:
|
||||
view.apply_cell_result(result_type='DYNAMIC_NATIVE', result_variable=property)
|
||||
for time_step in range(0, len(time_steps), 10):
|
||||
view.set_time_step(time_step = time_step)
|
||||
view.export_snapshot()
|
||||
19
GrpcInterface/Python/rips/PythonExamples/grid_information.py
Normal file
19
GrpcInterface/Python/rips/PythonExamples/grid_information.py
Normal file
@@ -0,0 +1,19 @@
|
||||
######################################################################################
|
||||
# This example prints information about the grids of all cases in the current project
|
||||
######################################################################################
|
||||
|
||||
import rips
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
cases = resinsight.project.cases()
|
||||
print("Number of cases found: ", len(cases))
|
||||
for case in cases:
|
||||
print(case.name)
|
||||
grids = case.grids()
|
||||
print("Number of grids: ", len(grids))
|
||||
for grid in grids:
|
||||
print("Grid dimensions: ", grid.dimensions())
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
# Connect to ResInsight instance
|
||||
resInsight = rips.Instance.find()
|
||||
|
||||
well_paths = resInsight.project.import_well_paths(well_path_folder='D:/Projects/ResInsight-regression-test/ModelData/norne/wellpaths')
|
||||
if resInsight.project.has_warnings():
|
||||
for warning in resInsight.project.warnings():
|
||||
print(warning)
|
||||
|
||||
|
||||
for well_path in well_paths:
|
||||
print("Imported from folder: " + well_path.name)
|
||||
|
||||
well_paths = resInsight.project.import_well_paths(well_path_files=['D:/Projects/ResInsight-regression-test/ModelData/Norne_WellPaths/E-3H.json',
|
||||
'D:/Projects/ResInsight-regression-test/ModelData/Norne_WellPaths/C-1H.json'])
|
||||
if resInsight.project.has_warnings():
|
||||
for warning in resInsight.project.warnings():
|
||||
print(warning)
|
||||
|
||||
|
||||
for well_path in well_paths:
|
||||
print("Imported from individual files: " + well_path.name)
|
||||
|
||||
|
||||
well_path_names = resInsight.project.import_well_log_files(well_log_folder='D:/Projects/ResInsight-regression-test/ModelData/Norne_PLT_LAS')
|
||||
if resInsight.project.has_warnings():
|
||||
for warning in resInsight.project.warnings():
|
||||
print(warning)
|
||||
|
||||
for well_path_name in well_path_names:
|
||||
print("Imported well log file for: " + well_path_name)
|
||||
@@ -0,0 +1,38 @@
|
||||
########################################################################################
|
||||
# This example generates a derived property in an asynchronous manner
|
||||
# Meaning it does not wait for all the data for each stage to be read before proceeding
|
||||
########################################################################################
|
||||
import rips
|
||||
import time
|
||||
|
||||
# Internal function for creating a result from a small chunk of poro and permx results
|
||||
# The return value of the function is a generator for the results rather than the result itself.
|
||||
def create_result(poro_chunks, permx_chunks):
|
||||
# Loop through all the chunks of poro and permx in order
|
||||
for (poroChunk, permxChunk) in zip(poro_chunks, permx_chunks):
|
||||
resultChunk = []
|
||||
# Loop through all the values inside the chunks, in order
|
||||
for (poro, permx) in zip(poroChunk.values, permxChunk.values):
|
||||
resultChunk.append(poro * permx)
|
||||
# Return a generator object that behaves like a Python iterator
|
||||
yield resultChunk
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
start = time.time()
|
||||
case = resinsight.project.cases()[0]
|
||||
|
||||
# Get a generator for the poro results. The generator will provide a chunk each time it is iterated
|
||||
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
|
||||
permx_chunks = case.active_cell_property_async('STATIC_NATIVE', 'PERMX', 0)
|
||||
|
||||
# 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
|
||||
# And return the result of each iteration
|
||||
case.set_active_cell_property_async(create_result(poro_chunks, permx_chunks),
|
||||
'GENERATED', 'POROPERMXAS', 0)
|
||||
|
||||
end = time.time()
|
||||
print("Time elapsed: ", end - start)
|
||||
print("Transferred all results back")
|
||||
view = case.views()[0].apply_cell_result('GENERATED', 'POROPERMXAS')
|
||||
@@ -0,0 +1,35 @@
|
||||
########################################################################################
|
||||
# This example generates a derived property in an synchronous manner
|
||||
# Meaning it completes reading each result before calculating the derived result
|
||||
# See InputPropTestAsync for how to do this asynchronously instead.
|
||||
########################################################################################
|
||||
import rips
|
||||
import time
|
||||
import grpc
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
start = time.time()
|
||||
case = resinsight.project.cases()[0]
|
||||
|
||||
# Read poro result into list
|
||||
poro_results = case.active_cell_property('STATIC_NATIVE', 'PORO', 0)
|
||||
# Read permx result into list
|
||||
permx_results = case.active_cell_property('STATIC_NATIVE', 'PERMX', 0)
|
||||
|
||||
# Generate output result
|
||||
results = []
|
||||
for (poro, permx) in zip(poro_results, permx_results):
|
||||
results.append(poro * permx)
|
||||
|
||||
try:
|
||||
# Send back output result
|
||||
case.set_active_cell_property(results, 'GENERATED', 'POROPERMXSY', 0)
|
||||
except grpc.RpcError as e:
|
||||
print("Exception Received: ", e)
|
||||
|
||||
|
||||
end = time.time()
|
||||
print("Time elapsed: ", end - start)
|
||||
print("Transferred all results back")
|
||||
|
||||
view = case.views()[0].apply_cell_result('GENERATED', 'POROPERMXSY')
|
||||
11
GrpcInterface/Python/rips/PythonExamples/instance_example.py
Normal file
11
GrpcInterface/Python/rips/PythonExamples/instance_example.py
Normal file
@@ -0,0 +1,11 @@
|
||||
#######################################
|
||||
# This example connects to ResInsight
|
||||
#######################################
|
||||
import rips
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
if resinsight is None:
|
||||
print('ERROR: could not find ResInsight')
|
||||
else:
|
||||
print('Successfully connected to ResInsight')
|
||||
@@ -0,0 +1,11 @@
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
# Launch ResInsight with last project file and a Window size of 600x1000 pixels
|
||||
resinsight = rips.Instance.launch(command_line_parameters=['--last', '--size', 600, 1000])
|
||||
# Get a list of all cases
|
||||
cases = resinsight.project.cases()
|
||||
|
||||
print ("Got " + str(len(cases)) + " cases: ")
|
||||
for case in cases:
|
||||
print("Case name: " + case.name)
|
||||
print("Case grid path: " + case.file_path)
|
||||
@@ -0,0 +1,16 @@
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
# Connect to ResInsight instance
|
||||
resinsight = rips.Instance.find()
|
||||
# Example code
|
||||
print("ResInsight version: " + resinsight.version_string())
|
||||
|
||||
modeled_well_paths = resinsight.project.descendants(rips.ModeledWellPath)
|
||||
|
||||
for wellpath in modeled_well_paths:
|
||||
geometry = wellpath.well_path_geometry()
|
||||
geometry.print_object_info()
|
||||
reference_point = geometry.reference_point
|
||||
reference_point[0] += 100
|
||||
geometry.update()
|
||||
geometry.print_object_info()
|
||||
11
GrpcInterface/Python/rips/PythonExamples/new_summary_plot.py
Normal file
11
GrpcInterface/Python/rips/PythonExamples/new_summary_plot.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
# Connect to ResInsight instance
|
||||
resinsight = rips.Instance.find()
|
||||
# Example code
|
||||
project = resinsight.project
|
||||
|
||||
summary_cases = project.descendants(rips.SummaryCase)
|
||||
summary_plot_collection = project.descendants(rips.SummaryPlotCollection)[0]
|
||||
if len(summary_cases) > 0:
|
||||
summary_plot = summary_plot_collection.new_summary_plot(summary_cases=summary_cases, address="FOP*")
|
||||
9
GrpcInterface/Python/rips/PythonExamples/replace_case.py
Normal file
9
GrpcInterface/Python/rips/PythonExamples/replace_case.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
# Connect to ResInsight instance
|
||||
resinsight = rips.Instance.find()
|
||||
# Example code
|
||||
print("ResInsight version: " + resinsight.version_string())
|
||||
|
||||
case = resinsight.project.case(case_id=0)
|
||||
case.replace(new_grid_file='C:/Users/lindkvis/Projects/ResInsight/TestModels/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID')
|
||||
20
GrpcInterface/Python/rips/PythonExamples/selected_cases.py
Normal file
20
GrpcInterface/Python/rips/PythonExamples/selected_cases.py
Normal file
@@ -0,0 +1,20 @@
|
||||
############################################################################
|
||||
# This example returns the currently selected cases in ResInsight
|
||||
# Because running this script in the GUI takes away the selection
|
||||
# This script does not run successfully from within the ResInsight GUI
|
||||
# And will need to be run from the command line separately from ResInsight
|
||||
############################################################################
|
||||
|
||||
import rips
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
if resinsight is not None:
|
||||
cases = resinsight.project.selected_cases()
|
||||
|
||||
print ("Got " + str(len(cases)) + " cases: ")
|
||||
for case in cases:
|
||||
print(case.name)
|
||||
for property in case.available_properties('DYNAMIC_NATIVE'):
|
||||
print(property)
|
||||
|
||||
|
||||
50
GrpcInterface/Python/rips/PythonExamples/selected_cells.py
Normal file
50
GrpcInterface/Python/rips/PythonExamples/selected_cells.py
Normal file
@@ -0,0 +1,50 @@
|
||||
############################################################################
|
||||
# This example prints center and corners for the currently selected cells
|
||||
# in ResInsight
|
||||
############################################################################
|
||||
|
||||
import rips
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
if resinsight is not None:
|
||||
cases = resinsight.project.cases()
|
||||
|
||||
print ("Got " + str(len(cases)) + " cases: ")
|
||||
for case in cases:
|
||||
print(case.name)
|
||||
cells = case.selected_cells()
|
||||
print("Found " + str(len(cells)) + " selected cells")
|
||||
|
||||
time_step_info = case.time_steps()
|
||||
|
||||
for (idx, cell) in enumerate(cells):
|
||||
print("Selected cell: [{}, {}, {}] grid: {}".format(cell.ijk.i+1, cell.ijk.j+1, cell.ijk.k+1, cell.grid_index))
|
||||
|
||||
# Get the grid and dimensions
|
||||
grid = case.grids()[cell.grid_index]
|
||||
dimensions = grid.dimensions()
|
||||
|
||||
# Map ijk to cell index
|
||||
cell_index = dimensions.i * dimensions.j * cell.ijk.k + dimensions.i * cell.ijk.j + cell.ijk.i
|
||||
|
||||
# Print the cell center
|
||||
cell_centers = grid.cell_centers()
|
||||
cell_center = cell_centers[cell_index]
|
||||
print("Cell center: [{}, {}, {}]".format(cell_center.x, cell_center.y, cell_center.z))
|
||||
|
||||
# Print the cell corners
|
||||
cell_corners = grid.cell_corners()[cell_index]
|
||||
print("Cell corners:")
|
||||
print("c0:\n" + str(cell_corners.c0))
|
||||
print("c1:\n" + str(cell_corners.c1))
|
||||
print("c2:\n" + str(cell_corners.c2))
|
||||
print("c3:\n" + str(cell_corners.c3))
|
||||
print("c4:\n" + str(cell_corners.c4))
|
||||
print("c5:\n" + str(cell_corners.c5))
|
||||
print("c6:\n" + str(cell_corners.c6))
|
||||
print("c7:\n" + str(cell_corners.c7))
|
||||
|
||||
for (tidx, timestep) in enumerate(time_step_info):
|
||||
# Read the full SOIL result for time step
|
||||
soil_results = case.selected_cell_property('DYNAMIC_NATIVE', 'SOIL', tidx)
|
||||
print("SOIL: {} ({}.{}.{})".format(soil_results[idx], timestep.year, timestep.month, timestep.day))
|
||||
@@ -0,0 +1,9 @@
|
||||
######################################################################
|
||||
# This script applies a cell result to the first view in the project
|
||||
######################################################################
|
||||
import rips
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
view = resinsight.project.views()[0]
|
||||
view.apply_cell_result(result_type='STATIC_NATIVE', result_variable='DX')
|
||||
@@ -0,0 +1,18 @@
|
||||
######################################################################
|
||||
# This script applies a flow diagnostics cell result to the first view in the project
|
||||
######################################################################
|
||||
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
# Connect to ResInsight instance
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
view = resinsight.project.view(view_id=1)
|
||||
#view.apply_flow_diagnostics_cell_result(result_variable='Fraction',
|
||||
# selection_mode='FLOW_TR_INJ_AND_PROD')
|
||||
|
||||
# Example of setting individual wells. Commented out because well names are case specific.
|
||||
view.apply_flow_diagnostics_cell_result(result_variable='Fraction',
|
||||
selection_mode='FLOW_TR_BY_SELECTION',
|
||||
injectors = ['C-1H', 'C-2H', 'F-2H'],
|
||||
producers = ['B-1AH', 'B-3H', 'D-1H'])
|
||||
@@ -0,0 +1,17 @@
|
||||
######################################################################
|
||||
# This script sets values for SOIL for all grid cells in the first case in the project
|
||||
######################################################################
|
||||
import rips
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
case = resinsight.project.case(case_id=0)
|
||||
total_cell_count = case.cell_count().reservoir_cell_count
|
||||
|
||||
values = []
|
||||
for i in range(0, total_cell_count):
|
||||
values.append(i % 2 * 0.75);
|
||||
|
||||
print("Applying values to full grid")
|
||||
case.set_grid_property(values, 'DYNAMIC_NATIVE', 'SOIL', 0)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
###########################################################################################
|
||||
# This example will asynchronously calculate the average value for SOIL for all time steps
|
||||
###########################################################################################
|
||||
|
||||
import rips
|
||||
import itertools
|
||||
import time
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
start = time.time()
|
||||
|
||||
# Get the case with case id 0
|
||||
case = resinsight.project.case(case_id=0)
|
||||
|
||||
# Get a list of all time steps
|
||||
timeSteps = case.time_steps()
|
||||
|
||||
averages = []
|
||||
for i in range(0, len(timeSteps)):
|
||||
# Get the results from time step i asynchronously
|
||||
# It actually returns a generator object almost immediately
|
||||
result_chunks = case.active_cell_property_async('DYNAMIC_NATIVE', 'SOIL', i)
|
||||
mysum = 0.0
|
||||
count = 0
|
||||
# Loop through and append the average. each time we loop resultChunks
|
||||
# We will trigger a read of the input data, meaning the script will start
|
||||
# Calculating averages before the whole resultValue for this time step has been received
|
||||
for chunk in result_chunks:
|
||||
mysum += sum(chunk.values)
|
||||
count += len(chunk.values)
|
||||
|
||||
averages.append(mysum/count)
|
||||
|
||||
end = time.time()
|
||||
print("Time elapsed: ", end - start)
|
||||
print(averages)
|
||||
@@ -0,0 +1,27 @@
|
||||
###########################################################################################
|
||||
# This example will synchronously calculate the average value for SOIL for all time steps
|
||||
###########################################################################################
|
||||
import rips
|
||||
import itertools
|
||||
import time
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
start = time.time()
|
||||
|
||||
# Get the case with case id 0
|
||||
case = resinsight.project.case(case_id=0)
|
||||
|
||||
# Get a list of all time steps
|
||||
time_steps = case.time_steps()
|
||||
|
||||
averages = []
|
||||
for i in range(0, len(time_steps)):
|
||||
# Get a list of all the results for time step i
|
||||
results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', i)
|
||||
mysum = sum(results)
|
||||
averages.append(mysum/len(results))
|
||||
|
||||
end = time.time()
|
||||
print("Time elapsed: ", end - start)
|
||||
print(averages)
|
||||
47
GrpcInterface/Python/rips/PythonExamples/soil_porv_async.py
Normal file
47
GrpcInterface/Python/rips/PythonExamples/soil_porv_async.py
Normal file
@@ -0,0 +1,47 @@
|
||||
##############################################################################
|
||||
# This example will create a derived result for each time step asynchronously
|
||||
##############################################################################
|
||||
|
||||
import rips
|
||||
import time
|
||||
|
||||
# Internal function for creating a result from a small chunk of soil and porv results
|
||||
# The return value of the function is a generator for the results rather than the result itself.
|
||||
def create_result(soil_chunks, porv_chunks):
|
||||
for (soil_chunk, porv_chunk) in zip(soil_chunks, porv_chunks):
|
||||
resultChunk = []
|
||||
number = 0
|
||||
for (soil_value, porv_value) in zip(soil_chunk.values, porv_chunk.values):
|
||||
resultChunk.append(soil_value * porv_value)
|
||||
# Return a Python generator
|
||||
yield resultChunk
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
start = time.time()
|
||||
case = resinsight.project.cases()[0]
|
||||
timeStepInfo = case.time_steps()
|
||||
|
||||
# Get a generator for the porv results. The generator will provide a chunk each time it is iterated
|
||||
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
|
||||
# Note we use the async method even if we synchronise here, because we need the values chunked
|
||||
# ... to match the soil chunks
|
||||
porv_array = []
|
||||
for porv_chunk in porv_chunks:
|
||||
porv_array.append(porv_chunk)
|
||||
|
||||
for i in range (0, len(timeStepInfo)):
|
||||
# Get a generator object for the SOIL property for time step i
|
||||
soil_chunks = case.active_cell_property_async('DYNAMIC_NATIVE', 'SOIL', i)
|
||||
# Create the generator object for the SOIL * PORV derived result
|
||||
result_generator = create_result(soil_chunks, iter(porv_array))
|
||||
# Send back the result asynchronously with a generator object
|
||||
case.set_active_cell_property_async(result_generator, 'GENERATED', 'SOILPORVAsync', i)
|
||||
|
||||
end = time.time()
|
||||
print("Time elapsed: ", end - start)
|
||||
|
||||
print("Transferred all results back")
|
||||
|
||||
view = case.views()[0].apply_cell_result('GENERATED', 'SOILPORVAsync')
|
||||
33
GrpcInterface/Python/rips/PythonExamples/soil_porv_sync.py
Normal file
33
GrpcInterface/Python/rips/PythonExamples/soil_porv_sync.py
Normal file
@@ -0,0 +1,33 @@
|
||||
##############################################################################
|
||||
# This example will create a derived result for each time step synchronously
|
||||
##############################################################################
|
||||
|
||||
import rips
|
||||
import time
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
start = time.time()
|
||||
case = resinsight.project.cases()[0]
|
||||
|
||||
# Read the full porv result
|
||||
porv_results = case.active_cell_property('STATIC_NATIVE', 'PORV', 0)
|
||||
time_step_info = case.time_steps()
|
||||
|
||||
for i in range (0, len(time_step_info)):
|
||||
# Read the full SOIl result for time step i
|
||||
soil_results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', i)
|
||||
|
||||
# Generate the result by looping through both lists in order
|
||||
results = []
|
||||
for (soil, porv) in zip(soil_results, porv_results):
|
||||
results.append(soil * porv)
|
||||
|
||||
# Send back result
|
||||
case.set_active_cell_property(results, 'GENERATED', 'SOILPORVSync', i)
|
||||
|
||||
end = time.time()
|
||||
print("Time elapsed: ", end - start)
|
||||
|
||||
print("Transferred all results back")
|
||||
|
||||
view = case.views()[0].apply_cell_result('GENERATED', 'SOILPORVSync')
|
||||
14
GrpcInterface/Python/rips/PythonExamples/summary_cases.py
Normal file
14
GrpcInterface/Python/rips/PythonExamples/summary_cases.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
# Connect to ResInsight instance
|
||||
resinsight = rips.Instance.find()
|
||||
# Example code
|
||||
|
||||
# Specific summary case with case_id = 1
|
||||
summary_case = resinsight.project.summary_case(case_id=1)
|
||||
summary_case.print_object_info()
|
||||
|
||||
# All summary cases
|
||||
summary_cases = resinsight.project.summary_cases()
|
||||
for summary_case in summary_cases:
|
||||
print("Summary case found: ", summary_case.short_name)
|
||||
31
GrpcInterface/Python/rips/PythonExamples/summary_vectors.py
Normal file
31
GrpcInterface/Python/rips/PythonExamples/summary_vectors.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import rips
|
||||
import time
|
||||
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
project = resinsight.project
|
||||
|
||||
# Use the following commented lines to import a file from disk
|
||||
# filename = "path/to/file/1_R001_REEK-0.SMSPEC"
|
||||
# summary_case = project.import_summary_case(filename)
|
||||
|
||||
# Assumes at least one summery case loaded with case_id 1
|
||||
summary_case = project.summary_case(1)
|
||||
if summary_case is None:
|
||||
print("No summary case found")
|
||||
exit()
|
||||
|
||||
vector_name = "FOPT"
|
||||
summary_data = summary_case.summary_vector_values(vector_name)
|
||||
|
||||
print("Data for summary vector " + vector_name)
|
||||
print(summary_data.values)
|
||||
|
||||
time_steps = summary_case.available_time_steps()
|
||||
print(time_steps.values)
|
||||
|
||||
summary_data_sampled = summary_case.resample_values("FOPT", "QUARTER")
|
||||
print("\nResampled data")
|
||||
|
||||
for t, value in zip(summary_data_sampled.time_steps, summary_data_sampled.values):
|
||||
print(time.strftime("%a, %d %b %Y ", time.gmtime(t)) + " | " + str(value))
|
||||
40
GrpcInterface/Python/rips/PythonExamples/surface_import.py
Normal file
40
GrpcInterface/Python/rips/PythonExamples/surface_import.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# Load ResInsight Processing Server Client Library
|
||||
import rips
|
||||
# Connect to ResInsight instance
|
||||
resinsight = rips.Instance.find()
|
||||
print("ResInsight version: " + resinsight.version_string())
|
||||
|
||||
# Example code
|
||||
|
||||
# get the project
|
||||
project = resinsight.project
|
||||
|
||||
# get the topmost surface folder from the project
|
||||
surfacefolder = project.surface_folder()
|
||||
|
||||
# list of surface files to load
|
||||
filenames = ["surface1.ts", "surface2.ts", "surface3.ts"]
|
||||
|
||||
# Load the files into the top level
|
||||
for surffile in filenames:
|
||||
surface = surfacefolder.import_surface(surffile)
|
||||
if surface is None:
|
||||
print("Could not import the surface " + surffile)
|
||||
|
||||
# add a subfolder
|
||||
subfolder = surfacefolder.add_folder("ExampleFolder")
|
||||
|
||||
# load the same surface multiple times using increasing depth offsets
|
||||
# store them in the new subfolder we just created
|
||||
for offset in range(0, 200, 20):
|
||||
surface = subfolder.import_surface("mysurface.ts")
|
||||
if surface:
|
||||
surface.depth_offset = offset
|
||||
surface.update()
|
||||
else:
|
||||
print("Could not import surface.")
|
||||
|
||||
# get an existing subfolder
|
||||
existingfolder = project.surface_folder("ExistingFolder")
|
||||
if existingfolder is None:
|
||||
print("Could not find the specified folder.")
|
||||
29
GrpcInterface/Python/rips/PythonExamples/view_example.py
Normal file
29
GrpcInterface/Python/rips/PythonExamples/view_example.py
Normal file
@@ -0,0 +1,29 @@
|
||||
#############################################################
|
||||
# This example will alter the views of all cases
|
||||
# By setting the background color and toggle the grid box
|
||||
# Also clones the first view
|
||||
#############################################################
|
||||
import rips
|
||||
# Connect to ResInsight instance
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
# Check if connection worked
|
||||
if resinsight is not None:
|
||||
# Get a list of all cases
|
||||
cases = resinsight.project.cases()
|
||||
for case in cases:
|
||||
# Get a list of all views
|
||||
views = case.views()
|
||||
for view in views:
|
||||
# Set some parameters for the view
|
||||
view.show_grid_box = not view.show_grid_box
|
||||
view.background_color = "#3388AA"
|
||||
# Update the view in ResInsight
|
||||
view.update()
|
||||
# Clone the first view
|
||||
new_view = views[0].clone()
|
||||
new_view.background_color = "#FFAA33"
|
||||
new_view.update()
|
||||
view.show_grid_box = False
|
||||
view.set_visible(False)
|
||||
view.update()
|
||||
18
GrpcInterface/Python/rips/__init__.py
Normal file
18
GrpcInterface/Python/rips/__init__.py
Normal file
@@ -0,0 +1,18 @@
|
||||
name = "rips"
|
||||
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
|
||||
|
||||
from resinsight_classes import *
|
||||
|
||||
from .case import Case, EclipseCase, GeoMechCase
|
||||
from .grid import Grid
|
||||
from .instance import Instance
|
||||
from .pdmobject import PdmObjectBase
|
||||
from .view import View
|
||||
from .project import Project
|
||||
from .plot import Plot, PlotWindow
|
||||
from .contour_map import EclipseContourMap, GeoMechContourMap
|
||||
from .well_log_plot import WellLogPlot
|
||||
from .simulation_well import SimulationWell
|
||||
1287
GrpcInterface/Python/rips/case.py
Normal file
1287
GrpcInterface/Python/rips/case.py
Normal file
File diff suppressed because it is too large
Load Diff
46
GrpcInterface/Python/rips/contour_map.py
Normal file
46
GrpcInterface/Python/rips/contour_map.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
ResInsight 3d contour map module
|
||||
"""
|
||||
import Commands_pb2
|
||||
|
||||
from .pdmobject import add_method
|
||||
from .view import View
|
||||
from resinsight_classes import EclipseContourMap, GeoMechContourMap
|
||||
|
||||
|
||||
@add_method(EclipseContourMap)
|
||||
def export_to_text(self, export_file_name='', export_local_coordinates=False, undefined_value_label="NaN", exclude_undefined_values=False):
|
||||
""" Export snapshot for the current view
|
||||
|
||||
Arguments:
|
||||
export_file_name(str): The file location to store results in.
|
||||
export_local_coordinates(bool): Should we export local coordinates, or UTM.
|
||||
undefined_value_label(str): Replace undefined values with this label.
|
||||
exclude_undefined_values(bool): Skip undefined values.
|
||||
"""
|
||||
return self._execute_command(
|
||||
exportContourMapToText=Commands_pb2.ExportContourMapToTextRequest(
|
||||
exportFileName=export_file_name,
|
||||
exportLocalCoordinates=export_local_coordinates,
|
||||
undefinedValueLabel=undefined_value_label,
|
||||
excludeUndefinedValues=exclude_undefined_values,
|
||||
viewId=self.id))
|
||||
|
||||
|
||||
@add_method(GeoMechContourMap)
|
||||
def export_to_text(self, export_file_name='', export_local_coordinates=False, undefined_value_label="NaN", exclude_undefined_values=False):
|
||||
""" Export snapshot for the current view
|
||||
|
||||
Arguments:
|
||||
export_file_name(str): The file location to store results in.
|
||||
export_local_coordinates(bool): Should we export local coordinates, or UTM.
|
||||
undefined_value_label(str): Replace undefined values with this label.
|
||||
exclude_undefined_values(bool): Skip undefined values.
|
||||
"""
|
||||
return self._execute_command(
|
||||
exportContourMapToText=Commands_pb2.ExportContourMapToTextRequest(
|
||||
exportFileName=export_file_name,
|
||||
exportLocalCoordinates=export_local_coordinates,
|
||||
undefinedValueLabel=undefined_value_label,
|
||||
excludeUndefinedValues=exclude_undefined_values,
|
||||
viewId=self.id))
|
||||
88
GrpcInterface/Python/rips/grid.py
Normal file
88
GrpcInterface/Python/rips/grid.py
Normal file
@@ -0,0 +1,88 @@
|
||||
# pylint: disable=too-few-public-methods
|
||||
|
||||
"""
|
||||
Module containing the Grid class, containing information
|
||||
about Case grids.
|
||||
"""
|
||||
|
||||
import Case_pb2
|
||||
import Grid_pb2
|
||||
import Grid_pb2_grpc
|
||||
|
||||
|
||||
class Grid:
|
||||
"""Grid Information. Created by methods in Case
|
||||
:meth:`rips.case.grid()`
|
||||
:meth:`rips.case.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.id)
|
||||
return self.__stub.GetDimensions(
|
||||
Grid_pb2.GridRequest(case_request=case_request,
|
||||
grid_index=self.index)).dimensions
|
||||
|
||||
def cell_centers_async(self):
|
||||
"""The cells center for all cells in given grid async.
|
||||
|
||||
Returns:
|
||||
Iterator to a list of Vec3d: class with double attributes x, y, x giving cell centers
|
||||
"""
|
||||
case_request = Case_pb2.CaseRequest(id=self.case.id)
|
||||
chunks = self.__stub.GetCellCenters(
|
||||
Grid_pb2.GridRequest(case_request=case_request,
|
||||
grid_index=self.index))
|
||||
for chunk in chunks:
|
||||
yield chunk
|
||||
|
||||
def cell_centers(self):
|
||||
"""The cell center for all cells in given grid
|
||||
|
||||
Returns:
|
||||
List of Vec3d: class with double attributes x, y, x giving cell centers
|
||||
"""
|
||||
centers = []
|
||||
chunks = self.cell_centers_async()
|
||||
for chunk in chunks:
|
||||
for center in chunk.centers:
|
||||
centers.append(center)
|
||||
return centers
|
||||
|
||||
def cell_corners_async(self):
|
||||
"""The cell corners for all cells in given grid, async.
|
||||
|
||||
Returns:
|
||||
iterator to a list of CellCorners: a class with Vec3d for each corner (c0, c1.., c7)
|
||||
"""
|
||||
case_request = Case_pb2.CaseRequest(id=self.case.id)
|
||||
chunks = self.__stub.GetCellCorners(
|
||||
Grid_pb2.GridRequest(case_request=case_request,
|
||||
grid_index=self.index))
|
||||
|
||||
for chunk in chunks:
|
||||
yield chunk
|
||||
|
||||
def cell_corners(self):
|
||||
"""The cell corners for all cells in given grid
|
||||
|
||||
Returns:
|
||||
list of CellCorners: a class with Vec3d for each corner (c0, c1.., c7)
|
||||
"""
|
||||
corners = []
|
||||
chunks = self.cell_corners_async()
|
||||
for chunk in chunks:
|
||||
for center in chunk.cells:
|
||||
corners.append(center)
|
||||
return corners
|
||||
83
GrpcInterface/Python/rips/gridcasegroup.py
Normal file
83
GrpcInterface/Python/rips/gridcasegroup.py
Normal file
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
Grid Case Group statistics module
|
||||
"""
|
||||
|
||||
from .pdmobject import add_method
|
||||
from .view import View
|
||||
from .case import Case
|
||||
|
||||
import Commands_pb2
|
||||
from resinsight_classes import GridCaseGroup
|
||||
|
||||
|
||||
@add_method(GridCaseGroup)
|
||||
def create_statistics_case(self):
|
||||
"""Create a Statistics case in the Grid Case Group
|
||||
|
||||
Returns:
|
||||
:class:`rips.generated.resinsight_classes.EclipseCase`
|
||||
"""
|
||||
command_reply = self._execute_command(
|
||||
createStatisticsCase=Commands_pb2.CreateStatisticsCaseRequest(
|
||||
caseGroupId=self.group_id))
|
||||
return Case(self.channel,
|
||||
command_reply.createStatisticsCaseResult.caseId)
|
||||
|
||||
|
||||
@add_method(GridCaseGroup)
|
||||
def statistics_cases(self):
|
||||
"""Get a list of all statistics cases in the Grid Case Group
|
||||
|
||||
Returns:
|
||||
List of :class:`rips.generated.resinsight_classes.EclipseCase`
|
||||
|
||||
"""
|
||||
stat_case_collection = self.children("StatisticsCaseCollection")[0]
|
||||
return stat_case_collection.children("Reservoirs")
|
||||
|
||||
|
||||
@add_method(GridCaseGroup)
|
||||
def views(self):
|
||||
"""Get a list of views belonging to a grid case group
|
||||
|
||||
Returns:
|
||||
List of :class:`rips.generated.resinsight_classes.EclipseView`
|
||||
|
||||
"""
|
||||
resinsight_classes = self.descendants(EclipseView)
|
||||
view_list = []
|
||||
for pdm_object in resinsight_classes:
|
||||
view_list.append(pdm_object)
|
||||
return view_list
|
||||
|
||||
|
||||
@add_method(GridCaseGroup)
|
||||
def view(self, view_id):
|
||||
"""Get a particular view belonging to a case group by providing view id
|
||||
Arguments:
|
||||
id(int): view id
|
||||
|
||||
Returns:
|
||||
List of :class:`rips.generated.resinsight_classes.EclipseView`
|
||||
|
||||
"""
|
||||
views = self.views()
|
||||
for view_object in views:
|
||||
if view_object.id == view_id:
|
||||
return view_object
|
||||
return None
|
||||
|
||||
|
||||
@add_method(GridCaseGroup)
|
||||
def compute_statistics(self, case_ids=None):
|
||||
""" Compute statistics for the given case ids
|
||||
|
||||
Arguments:
|
||||
case_ids(list of integers): 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=Commands_pb2.ComputeCaseGroupStatRequest(
|
||||
caseIds=case_ids, caseGroupId=self.group_id))
|
||||
44
GrpcInterface/Python/rips/grpc_retry_interceptor.py
Normal file
44
GrpcInterface/Python/rips/grpc_retry_interceptor.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import grpc
|
||||
|
||||
|
||||
class RetryOnRpcErrorClientInterceptor(
|
||||
grpc.UnaryUnaryClientInterceptor, grpc.StreamUnaryClientInterceptor
|
||||
):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
retry_policy,
|
||||
status_for_retry,
|
||||
):
|
||||
self.retry_policy = retry_policy
|
||||
self.status_for_retry = status_for_retry
|
||||
|
||||
def _intercept_call(self, continuation, client_call_details, request_or_iterator):
|
||||
|
||||
for retry_num in range(self.retry_policy.num_retries()):
|
||||
response = continuation(client_call_details, request_or_iterator)
|
||||
|
||||
if isinstance(response, grpc.RpcError):
|
||||
|
||||
# Return if it was last attempt
|
||||
if retry_num == (self.retry_policy.num_retries() - 1):
|
||||
return response
|
||||
|
||||
# If status code is not in retryable status codes
|
||||
if (
|
||||
self.status_for_retry
|
||||
and response.code() not in self.status_for_retry
|
||||
):
|
||||
return response
|
||||
|
||||
self.retry_policy.sleep(retry_num)
|
||||
else:
|
||||
return response
|
||||
|
||||
def intercept_unary_unary(self, continuation, client_call_details, request):
|
||||
return self._intercept_call(continuation, client_call_details, request)
|
||||
|
||||
def intercept_stream_unary(
|
||||
self, continuation, client_call_details, request_iterator
|
||||
):
|
||||
return self._intercept_call(continuation, client_call_details, request_iterator)
|
||||
336
GrpcInterface/Python/rips/instance.py
Normal file
336
GrpcInterface/Python/rips/instance.py
Normal file
@@ -0,0 +1,336 @@
|
||||
# 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 App_pb2
|
||||
import App_pb2_grpc
|
||||
import Commands_pb2
|
||||
import Commands_pb2_grpc
|
||||
from Definitions_pb2 import Empty
|
||||
|
||||
import RiaVersionInfo
|
||||
|
||||
from .project import Project
|
||||
from .retry_policy import ExponentialBackoffRetryPolicy
|
||||
from .grpc_retry_interceptor import RetryOnRpcErrorClientInterceptor
|
||||
|
||||
|
||||
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 __is_valid_port(port):
|
||||
location = "localhost:" + str(port)
|
||||
channel = grpc.insecure_channel(location,
|
||||
options=[
|
||||
('grpc.enable_http_proxy',
|
||||
False)
|
||||
])
|
||||
app = App_pb2_grpc.AppStub(channel)
|
||||
try:
|
||||
app.GetVersion(Empty(), timeout=1)
|
||||
except grpc.RpcError:
|
||||
return False
|
||||
return True
|
||||
|
||||
@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
|
||||
|
||||
print("Trying port " + str(port))
|
||||
while Instance.__is_port_in_use(port):
|
||||
port += 1
|
||||
print("Trying port " + str(port))
|
||||
|
||||
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 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:
|
||||
print("Got port " + port_env + " from environment")
|
||||
start_port = int(port_env)
|
||||
end_port = start_port + 20
|
||||
|
||||
for try_port in range(start_port, end_port):
|
||||
print("Trying port " + str(try_port))
|
||||
if Instance.__is_port_in_use(try_port) and Instance.__is_valid_port(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(Commands_pb2.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 = Commands_pb2_grpc.CommandsStub(self.channel)
|
||||
|
||||
# Main version check package
|
||||
self.app = App_pb2_grpc.AppStub(self.channel)
|
||||
|
||||
self._check_connection_and_version(self.channel, launched)
|
||||
|
||||
# Intercept UNAVAILABLE errors and retry on failures
|
||||
interceptors = (
|
||||
RetryOnRpcErrorClientInterceptor(
|
||||
retry_policy=ExponentialBackoffRetryPolicy(min_backoff=100, max_backoff=5000, max_num_retries=20),
|
||||
status_for_retry=(grpc.StatusCode.UNAVAILABLE,),
|
||||
),
|
||||
)
|
||||
|
||||
intercepted_channel = grpc.intercept_channel(self.channel, *interceptors)
|
||||
|
||||
# Recreate ommand stubs with the retry policy
|
||||
self.commands = Commands_pb2_grpc.CommandsStub(intercepted_channel)
|
||||
|
||||
# Service packages
|
||||
self.project = Project.create(intercepted_channel)
|
||||
|
||||
path = os.getcwd()
|
||||
self.set_start_dir(path=path)
|
||||
|
||||
def _check_connection_and_version(self, channel, launched):
|
||||
connection_ok = False
|
||||
version_ok = False
|
||||
|
||||
retry_policy = ExponentialBackoffRetryPolicy()
|
||||
if self.launched:
|
||||
for num_tries in range(0, retry_policy.num_retries()):
|
||||
connection_ok, version_ok = self.__check_version()
|
||||
if connection_ok:
|
||||
break
|
||||
retry_policy.sleep(num_tries)
|
||||
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,
|
||||
'.', retry_policy.time_out_message())
|
||||
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())
|
||||
|
||||
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=Commands_pb2.FilePathRequest(path=path))
|
||||
|
||||
def set_export_folder(self, export_type, path, create_folder=False):
|
||||
"""
|
||||
Set the export folder used for all export functions
|
||||
|
||||
**Parameters**::
|
||||
|
||||
Parameter | Description | Type
|
||||
---------------- | -------------------------------------------- | -----
|
||||
export_type | String specifying what to export | String
|
||||
path | Path to folder | String
|
||||
create_folder | Create folder if it doesn't exist? | Boolean
|
||||
|
||||
**Enum export_type**::
|
||||
|
||||
Option | Description
|
||||
--------------- | ------------
|
||||
"COMPLETIONS" |
|
||||
"SNAPSHOTS" |
|
||||
"PROPERTIES" |
|
||||
"STATISTICS" |
|
||||
|
||||
"""
|
||||
return self.__execute_command(setExportFolder=Commands_pb2.SetExportFolderRequest(
|
||||
type=export_type, path=path, createFolder=create_folder))
|
||||
|
||||
def set_main_window_size(self, width, height):
|
||||
"""
|
||||
Set the main window size in pixels
|
||||
|
||||
**Parameters**::
|
||||
|
||||
Parameter | Description | Type
|
||||
--------- | ---------------- | -----
|
||||
width | Width in pixels | Integer
|
||||
height | Height in pixels | Integer
|
||||
|
||||
"""
|
||||
return self.__execute_command(setMainWindowSize=Commands_pb2.SetWindowSizeParams(
|
||||
width=width, height=height))
|
||||
|
||||
def set_plot_window_size(self, width, height):
|
||||
"""
|
||||
Set the plot window size in pixels
|
||||
|
||||
**Parameters**::
|
||||
|
||||
Parameter | Description | Type
|
||||
--------- | ---------------- | -----
|
||||
width | Width in pixels | Integer
|
||||
height | Height in pixels | Integer
|
||||
"""
|
||||
return self.__execute_command(setPlotWindowSize=Commands_pb2.SetWindowSizeParams(
|
||||
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')
|
||||
367
GrpcInterface/Python/rips/pdmobject.py
Normal file
367
GrpcInterface/Python/rips/pdmobject.py
Normal file
@@ -0,0 +1,367 @@
|
||||
# pylint: disable=no-self-use
|
||||
"""
|
||||
ResInsight caf::PdmObject connection module
|
||||
"""
|
||||
|
||||
from functools import partial, wraps
|
||||
import grpc
|
||||
import re
|
||||
import builtins
|
||||
import importlib
|
||||
import inspect
|
||||
import sys
|
||||
|
||||
import PdmObject_pb2
|
||||
import PdmObject_pb2_grpc
|
||||
import Commands_pb2
|
||||
import Commands_pb2_grpc
|
||||
import resinsight_classes as ClassList
|
||||
|
||||
|
||||
def camel_to_snake(name):
|
||||
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
|
||||
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
|
||||
|
||||
|
||||
def snake_to_camel(name):
|
||||
return ''.join(word.title() for word in name.split('_'))
|
||||
|
||||
|
||||
def add_method(cls):
|
||||
def decorator(func):
|
||||
setattr(cls, func.__name__, func)
|
||||
return func # returning func means func can still be used normally
|
||||
return decorator
|
||||
|
||||
|
||||
def add_static_method(cls):
|
||||
def decorator(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
setattr(cls, func.__name__, wrapper)
|
||||
# Note we are not binding func, but wrapper which accepts self but does exactly the same as func
|
||||
return func # returning func means func can still be used normally
|
||||
return decorator
|
||||
|
||||
|
||||
class PdmObjectBase:
|
||||
"""
|
||||
The ResInsight base class for the Project Data Model
|
||||
"""
|
||||
|
||||
def _execute_command(self, **command_params):
|
||||
self.__warnings = []
|
||||
response, call = self._commands.Execute.with_call(
|
||||
Commands_pb2.CommandParams(**command_params))
|
||||
for key, value in call.trailing_metadata():
|
||||
value = value.replace(';;', '\n')
|
||||
if key == 'warning':
|
||||
self.__warnings.append(value)
|
||||
|
||||
return response
|
||||
|
||||
def __init__(self, pb2_object, channel):
|
||||
self.__warnings = []
|
||||
self.__chunk_size = 8160
|
||||
|
||||
self._channel = channel
|
||||
|
||||
# Create stubs
|
||||
if self._channel:
|
||||
self._pdm_object_stub = PdmObject_pb2_grpc.PdmObjectServiceStub(self._channel)
|
||||
self._commands = Commands_pb2_grpc.CommandsStub(self._channel)
|
||||
|
||||
if pb2_object is not None:
|
||||
# Copy parameters from ResInsight
|
||||
assert(isinstance(pb2_object, PdmObject_pb2.PdmObject))
|
||||
self._pb2_object = pb2_object
|
||||
for camel_keyword in self._pb2_object.parameters:
|
||||
snake_keyword = camel_to_snake(camel_keyword)
|
||||
setattr(self, snake_keyword, self.__get_grpc_value(camel_keyword))
|
||||
else:
|
||||
# Copy parameters from PdmObject defaults
|
||||
self._pb2_object = PdmObject_pb2.PdmObject(class_keyword=self.__class__.__name__)
|
||||
self.__copy_to_pb2()
|
||||
|
||||
def copy_from(self, object):
|
||||
"""Copy attribute values from object to self
|
||||
"""
|
||||
for attribute in dir(object):
|
||||
if not attribute.startswith('__'):
|
||||
value = getattr(object, attribute)
|
||||
# This is crucial to avoid overwriting methods
|
||||
if not callable(value):
|
||||
setattr(self, attribute, value)
|
||||
if self.__custom_init__ is not None:
|
||||
self.__custom_init__(self._pb2_object, self._channel)
|
||||
self.update()
|
||||
|
||||
def warnings(self):
|
||||
return self.__warnings
|
||||
|
||||
def has_warnings(self):
|
||||
return len(self.__warnings) > 0
|
||||
|
||||
def __copy_to_pb2(self):
|
||||
if self._pb2_object is not None:
|
||||
for snake_kw in dir(self):
|
||||
if not snake_kw.startswith('_'):
|
||||
value = getattr(self, snake_kw)
|
||||
# This is crucial to avoid overwriting methods
|
||||
if not callable(value):
|
||||
camel_kw = snake_to_camel(snake_kw)
|
||||
self.__set_grpc_value(camel_kw, value)
|
||||
|
||||
def pb2_object(self):
|
||||
""" Private method"""
|
||||
return self._pb2_object
|
||||
|
||||
def channel(self):
|
||||
""" Private method"""
|
||||
return self._channel
|
||||
|
||||
def address(self):
|
||||
"""Get the unique address of the PdmObject
|
||||
|
||||
Returns:
|
||||
A 64-bit unsigned integer address
|
||||
"""
|
||||
|
||||
return self._pb2_object.address
|
||||
|
||||
def set_visible(self, visible):
|
||||
"""Set the visibility of the object in the ResInsight project tree"""
|
||||
self._pb2_object.visible = visible
|
||||
|
||||
def visible(self):
|
||||
"""Get the visibility of the object in the ResInsight project tree"""
|
||||
return self._pb2_object.visible
|
||||
|
||||
def print_object_info(self):
|
||||
"""Print the structure and data content of the PdmObject"""
|
||||
print("=========== " + self.__class__.__name__ + " =================")
|
||||
print("Object Attributes: ")
|
||||
for snake_kw in dir(self):
|
||||
if not snake_kw.startswith("_") and not callable(getattr(self, snake_kw)):
|
||||
camel_kw = snake_to_camel(snake_kw)
|
||||
print(" " + snake_kw + " [" + type(getattr(self, snake_kw)).__name__ +
|
||||
"]: " + str(getattr(self, snake_kw)))
|
||||
print("Object Methods:")
|
||||
for snake_kw in dir(self):
|
||||
if not snake_kw.startswith("_") and callable(getattr(self, snake_kw)):
|
||||
print(" " + snake_kw)
|
||||
|
||||
def __convert_from_grpc_value(self, value):
|
||||
if value.lower() == 'false':
|
||||
return False
|
||||
if value.lower() == 'true':
|
||||
return True
|
||||
try:
|
||||
int_val = int(value)
|
||||
return int_val
|
||||
except ValueError:
|
||||
try:
|
||||
float_val = float(value)
|
||||
return float_val
|
||||
except ValueError:
|
||||
# We may have a string. Strip internal start and end quotes
|
||||
value = value.strip('\"')
|
||||
if self.__islist(value):
|
||||
return self.__makelist(value)
|
||||
return value
|
||||
|
||||
def __convert_to_grpc_value(self, value):
|
||||
if isinstance(value, bool):
|
||||
if value:
|
||||
return "true"
|
||||
return "false"
|
||||
if isinstance(value, PdmObjectBase):
|
||||
return value.__class__.__name__ + ":" + str(value.address())
|
||||
if isinstance(value, list):
|
||||
list_of_values = []
|
||||
for val in value:
|
||||
list_of_values.append(self.__convert_to_grpc_value(val))
|
||||
return "[" + ", ".join(list_of_values) + "]"
|
||||
return str(value)
|
||||
|
||||
def __get_grpc_value(self, camel_keyword):
|
||||
return self.__convert_from_grpc_value(self._pb2_object.parameters[camel_keyword])
|
||||
|
||||
def __set_grpc_value(self, camel_keyword, value):
|
||||
self._pb2_object.parameters[camel_keyword] = self.__convert_to_grpc_value(value)
|
||||
|
||||
def set_value(self, snake_keyword, value):
|
||||
"""Set the value associated with the provided keyword and updates ResInsight
|
||||
Arguments:
|
||||
keyword(str): A string containing the parameter keyword
|
||||
value(varying): A value matching the type of the parameter.
|
||||
See keyword documentation and/or print_object_info() to find
|
||||
the correct data type.
|
||||
"""
|
||||
setattr(self, snake_keyword, value)
|
||||
self.update()
|
||||
|
||||
def __islist(self, value):
|
||||
return value.startswith("[") and value.endswith("]")
|
||||
|
||||
def __makelist(self, list_string):
|
||||
list_string = list_string.lstrip("[")
|
||||
list_string = list_string.rstrip("]")
|
||||
strings = list_string.split(", ")
|
||||
values = []
|
||||
for string in strings:
|
||||
values.append(self.__convert_from_grpc_value(string))
|
||||
return values
|
||||
|
||||
def __from_pb2_to_resinsight_classes(self, pb2_object_list, super_class_definition):
|
||||
pdm_object_list = []
|
||||
for pb2_object in pb2_object_list:
|
||||
child_class_definition = ClassList.class_from_keyword(pb2_object.class_keyword)
|
||||
if child_class_definition is None:
|
||||
child_class_definition = super_class_definition
|
||||
|
||||
pdm_object = child_class_definition(pb2_object=pb2_object, channel=self.channel())
|
||||
pdm_object_list.append(pdm_object)
|
||||
return pdm_object_list
|
||||
|
||||
def descendants(self, class_definition):
|
||||
"""Get a list of all project tree descendants matching the class keyword
|
||||
Arguments:
|
||||
class_definition[class]: A class definition matching the type of class wanted
|
||||
|
||||
Returns:
|
||||
A list of PdmObjects matching the class_definition
|
||||
"""
|
||||
assert(inspect.isclass(class_definition))
|
||||
|
||||
class_keyword = class_definition.__name__
|
||||
try:
|
||||
request = PdmObject_pb2.PdmDescendantObjectRequest(
|
||||
object=self._pb2_object, child_keyword=class_keyword)
|
||||
object_list = self._pdm_object_stub.GetDescendantPdmObjects(
|
||||
request).objects
|
||||
return self.__from_pb2_to_resinsight_classes(object_list, class_definition)
|
||||
except grpc.RpcError as e:
|
||||
if e.code() == grpc.StatusCode.NOT_FOUND:
|
||||
return [] # Valid empty result
|
||||
raise e
|
||||
|
||||
def children(self, child_field, class_definition):
|
||||
"""Get a list of all direct project tree children inside the provided child_field
|
||||
Arguments:
|
||||
child_field[str]: A field name
|
||||
Returns:
|
||||
A list of PdmObjects inside the child_field
|
||||
"""
|
||||
request = PdmObject_pb2.PdmChildObjectRequest(object=self._pb2_object,
|
||||
child_field=child_field)
|
||||
try:
|
||||
object_list = self._pdm_object_stub.GetChildPdmObjects(request).objects
|
||||
return self.__from_pb2_to_resinsight_classes(object_list, class_definition)
|
||||
except grpc.RpcError as e:
|
||||
if e.code() == grpc.StatusCode.NOT_FOUND:
|
||||
return []
|
||||
raise e
|
||||
|
||||
def ancestor(self, class_definition):
|
||||
"""Find the first ancestor that matches the provided class_keyword
|
||||
Arguments:
|
||||
class_definition[class]: A class definition matching the type of class wanted
|
||||
"""
|
||||
assert(inspect.isclass(class_definition))
|
||||
|
||||
class_keyword = class_definition.__name__
|
||||
|
||||
request = PdmObject_pb2.PdmParentObjectRequest(
|
||||
object=self._pb2_object, parent_keyword=class_keyword)
|
||||
try:
|
||||
pb2_object = self._pdm_object_stub.GetAncestorPdmObject(request)
|
||||
child_class_definition = ClassList.class_from_keyword(pb2_object.class_keyword)
|
||||
|
||||
if child_class_definition is None:
|
||||
child_class_definition = class_definition
|
||||
|
||||
pdm_object = child_class_definition(pb2_object=pb2_object, channel=self.channel())
|
||||
return pdm_object
|
||||
except grpc.RpcError as e:
|
||||
if e.code() == grpc.StatusCode.NOT_FOUND:
|
||||
return None
|
||||
raise e
|
||||
|
||||
def _call_get_method_async(self, method_name):
|
||||
request = PdmObject_pb2.PdmObjectGetterRequest(object=self._pb2_object, method=method_name)
|
||||
for chunk in self._pdm_object_stub.CallPdmObjectGetter(request):
|
||||
yield chunk
|
||||
|
||||
def _call_get_method(self, method_name):
|
||||
all_values = []
|
||||
generator = self._call_get_method_async(method_name)
|
||||
for chunk in generator:
|
||||
data = getattr(chunk, chunk.WhichOneof('data'))
|
||||
for value in data.data:
|
||||
all_values.append(value)
|
||||
return all_values
|
||||
|
||||
def __generate_set_method_chunks(self, array, method_request):
|
||||
index = -1
|
||||
|
||||
while index < len(array):
|
||||
chunk = PdmObject_pb2.PdmObjectSetterChunk()
|
||||
if index == -1:
|
||||
chunk.set_request.CopyFrom(PdmObject_pb2.PdmObjectSetterRequest(
|
||||
request=method_request, data_count=len(array)))
|
||||
index += 1
|
||||
else:
|
||||
actual_chunk_size = min(len(array) - index + 1, self.__chunk_size)
|
||||
if isinstance(array[0], float):
|
||||
chunk.CopyFrom(
|
||||
PdmObject_pb2.PdmObjectSetterChunk(doubles=PdmObject_pb2.DoubleArray(data=array[index:index +
|
||||
actual_chunk_size])))
|
||||
elif isinstance(array[0], int):
|
||||
chunk.CopyFrom(
|
||||
PdmObject_pb2.PdmObjectSetterChunk(ints=PdmObject_pb2.IntArray(data=array[index:index +
|
||||
actual_chunk_size])))
|
||||
elif isinstance(array[0], str):
|
||||
chunk.CopyFrom(
|
||||
PdmObject_pb2.PdmObjectSetterChunk(strings=PdmObject_pb2.StringArray(data=array[index:index +
|
||||
actual_chunk_size])))
|
||||
else:
|
||||
raise Exception("Wrong data type for set method")
|
||||
index += actual_chunk_size
|
||||
yield chunk
|
||||
# Final empty message to signal completion
|
||||
chunk = PdmObject_pb2.PdmObjectSetterChunk()
|
||||
yield chunk
|
||||
|
||||
def _call_set_method(self, method_name, values):
|
||||
method_request = PdmObject_pb2.PdmObjectGetterRequest(
|
||||
object=self._pb2_object, method=method_name)
|
||||
request_iterator = self.__generate_set_method_chunks(values, method_request)
|
||||
reply = self._pdm_object_stub.CallPdmObjectSetter(request_iterator)
|
||||
if reply.accepted_value_count < len(values):
|
||||
raise IndexError
|
||||
|
||||
def _call_pdm_method(self, method_name, **kwargs):
|
||||
pb2_params = PdmObject_pb2.PdmObject(class_keyword=method_name)
|
||||
for key, value in kwargs.items():
|
||||
pb2_params.parameters[snake_to_camel(key)] = self.__convert_to_grpc_value(value)
|
||||
request = PdmObject_pb2.PdmObjectMethodRequest(
|
||||
object=self._pb2_object, method=method_name, params=pb2_params)
|
||||
|
||||
pb2_object = self._pdm_object_stub.CallPdmObjectMethod(request)
|
||||
|
||||
child_class_definition = ClassList.class_from_keyword(pb2_object.class_keyword)
|
||||
if child_class_definition is None:
|
||||
return None
|
||||
|
||||
pdm_object = child_class_definition(pb2_object=pb2_object, channel=self.channel())
|
||||
return pdm_object
|
||||
|
||||
def update(self):
|
||||
"""Sync all fields from the Python Object to ResInsight"""
|
||||
self.__copy_to_pb2()
|
||||
if self._pdm_object_stub is not None:
|
||||
self._pdm_object_stub.UpdateExistingPdmObject(self._pb2_object)
|
||||
else:
|
||||
raise Exception("Object is not connected to GRPC service so cannot update ResInsight")
|
||||
25
GrpcInterface/Python/rips/plot.py
Normal file
25
GrpcInterface/Python/rips/plot.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""
|
||||
ResInsight 2d plot module
|
||||
"""
|
||||
import Commands_pb2
|
||||
|
||||
from .pdmobject import PdmObjectBase, add_method
|
||||
from resinsight_classes import PlotWindow, Plot
|
||||
|
||||
|
||||
@add_method(PlotWindow)
|
||||
def export_snapshot(self, export_folder='', file_prefix='', output_format='PNG'):
|
||||
""" Export snapshot for the current plot
|
||||
|
||||
Arguments:
|
||||
export_folder(str): The path to export to. By default will use the global export folder
|
||||
prefix (str): Exported file name prefix
|
||||
output_format(str): Enum string. Can be 'PNG' or 'PDF'.
|
||||
|
||||
"""
|
||||
return self._execute_command(
|
||||
exportSnapshots=Commands_pb2.ExportSnapshotsRequest(type='PLOTS',
|
||||
prefix=file_prefix,
|
||||
viewId=self.id,
|
||||
exportFolder=export_folder,
|
||||
plotOutputFormat=output_format))
|
||||
393
GrpcInterface/Python/rips/project.py
Normal file
393
GrpcInterface/Python/rips/project.py
Normal file
@@ -0,0 +1,393 @@
|
||||
# pylint: disable=too-many-arguments
|
||||
# pylint: disable=no-member
|
||||
"""
|
||||
The ResInsight project module
|
||||
"""
|
||||
import builtins
|
||||
import grpc
|
||||
|
||||
from .case import Case
|
||||
from .gridcasegroup import GridCaseGroup
|
||||
from .pdmobject import PdmObjectBase, add_method, add_static_method
|
||||
from .plot import Plot
|
||||
from .view import View
|
||||
|
||||
import Commands_pb2
|
||||
from Definitions_pb2 import Empty
|
||||
import Project_pb2_grpc
|
||||
import Project_pb2
|
||||
import PdmObject_pb2
|
||||
from resinsight_classes import Project, PlotWindow, WellPath, SummaryCase
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def __custom_init__(self, pb2_object, channel):
|
||||
self._project_stub = Project_pb2_grpc.ProjectStub(self._channel)
|
||||
|
||||
|
||||
@add_static_method(Project)
|
||||
def create(channel):
|
||||
project_stub = Project_pb2_grpc.ProjectStub(channel)
|
||||
pb2_object = project_stub.GetPdmObject(Empty())
|
||||
return Project(pb2_object, channel)
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def open(self, path):
|
||||
"""Open a new project from the given path
|
||||
|
||||
Arguments:
|
||||
path(str): path to project file
|
||||
|
||||
"""
|
||||
self._execute_command(openProject=Commands_pb2.FilePathRequest(path=path))
|
||||
return self
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def save(self, path=""):
|
||||
"""Save the project to the existing project file, or to a new file
|
||||
|
||||
Arguments:
|
||||
path(str): File path to the file to save the project to. If empty, saves to the active project file
|
||||
"""
|
||||
self._execute_command(saveProject=Commands_pb2.SaveProjectRequest(filePath=path))
|
||||
return self
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def close(self):
|
||||
"""Close the current project (and open new blank project)"""
|
||||
self._execute_command(closeProject=Empty())
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def load_case(self, path):
|
||||
"""Load a new grid case from the given file path
|
||||
|
||||
Arguments:
|
||||
path(str): file path to case
|
||||
Returns:
|
||||
:class:`rips.generated.resinsight_classes.Case`
|
||||
"""
|
||||
command_reply = self._execute_command(loadCase=Commands_pb2.FilePathRequest(
|
||||
path=path))
|
||||
return self.case(command_reply.loadCaseResult.id)
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def selected_cases(self):
|
||||
"""Get a list of all grid cases selected in the project tree
|
||||
|
||||
Returns:
|
||||
A list of :class:`rips.generated.resinsight_classes.Case`
|
||||
"""
|
||||
case_infos = self._project_stub.GetSelectedCases(Empty())
|
||||
cases = []
|
||||
for case_info in case_infos.data:
|
||||
cases.append(self.case(case_info.id))
|
||||
return cases
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def cases(self):
|
||||
"""Get a list of all grid cases in the project
|
||||
|
||||
Returns:
|
||||
A list of :class:`rips.generated.resinsight_classes.Case`
|
||||
"""
|
||||
return self.descendants(Case)
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def case(self, case_id):
|
||||
"""Get a specific grid case from the provided case Id
|
||||
|
||||
Arguments:
|
||||
id(int): case id
|
||||
Returns:
|
||||
:class:`rips.generated.resinsight_classes.Case`
|
||||
"""
|
||||
allCases = self.cases()
|
||||
for case in allCases:
|
||||
if case.id == case_id:
|
||||
return case
|
||||
return None
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def replace_source_cases(self, grid_list_file, case_group_id=0):
|
||||
"""Replace all source grid 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=Commands_pb2.ReplaceSourceCasesRequest(
|
||||
gridListFile=grid_list_file, caseGroupId=case_group_id))
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
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:
|
||||
:class:`rips.generated.resinsight_classes.GridCaseGroup`
|
||||
"""
|
||||
command_reply = self._execute_command(
|
||||
createGridCaseGroup=Commands_pb2.CreateGridCaseGroupRequest(
|
||||
casePaths=case_paths))
|
||||
return self.grid_case_group(
|
||||
command_reply.createGridCaseGroupResult.groupId)
|
||||
|
||||
@add_method(Project)
|
||||
def summary_cases(self):
|
||||
"""Get a list of all summary cases in the Project
|
||||
|
||||
Returns: A list of :class:`rips.generated.resinsight_classes.SummaryCase`
|
||||
"""
|
||||
return self.descendants(SummaryCase)
|
||||
|
||||
@add_method(Project)
|
||||
def views(self):
|
||||
"""Get a list of views belonging to a project"""
|
||||
return self.descendants(View)
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def view(self, view_id):
|
||||
"""Get a particular view belonging to a case by providing view id
|
||||
|
||||
Arguments:
|
||||
view_id(int): view id
|
||||
Returns:
|
||||
:class:`rips.generated.resinsight_classes.View`
|
||||
"""
|
||||
views = self.views()
|
||||
for view_object in views:
|
||||
if view_object.id == view_id:
|
||||
return view_object
|
||||
return None
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def plots(self):
|
||||
"""Get a list of all plots belonging to a project
|
||||
|
||||
Returns:
|
||||
List of :class:`rips.generated.resinsight_classes.Plot`
|
||||
"""
|
||||
resinsight_classes = self.descendants(PlotWindow)
|
||||
plot_list = []
|
||||
for pdm_object in resinsight_classes:
|
||||
if pdm_object.id != -1:
|
||||
plot_list.append(pdm_object)
|
||||
return plot_list
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def plot(self, view_id):
|
||||
"""Get a particular plot by providing view id
|
||||
|
||||
Arguments:
|
||||
view_id(int): view id
|
||||
|
||||
Returns:
|
||||
:class:`rips.generated.resinsight_classes.Plot`
|
||||
"""
|
||||
plots = self.plots()
|
||||
for plot_object in plots:
|
||||
if plot_object.id == view_id:
|
||||
return plot_object
|
||||
return None
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def grid_case_groups(self):
|
||||
"""Get a list of all grid case groups in the project
|
||||
|
||||
Returns:
|
||||
List of :class:`rips.generated.resinsight_classes.GridCaseGroup`
|
||||
|
||||
"""
|
||||
case_groups = self.descendants(GridCaseGroup)
|
||||
return case_groups
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def grid_case_group(self, group_id):
|
||||
"""Get a particular grid case group belonging to a project
|
||||
|
||||
Arguments:
|
||||
groupId(int): group id
|
||||
|
||||
Returns:
|
||||
:class:`rips.generated.resinsight_classes.GridCaseGroup`
|
||||
"""
|
||||
case_groups = self.grid_case_groups()
|
||||
for case_group in case_groups:
|
||||
if case_group.group_id == group_id:
|
||||
return case_group
|
||||
return None
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
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=Commands_pb2.ExportMultiCaseRequest(
|
||||
gridListFile=grid_list_file))
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def export_snapshots(self, snapshot_type='ALL', prefix='', plot_format='PNG'):
|
||||
""" Export all snapshots of a given type
|
||||
|
||||
Arguments:
|
||||
snapshot_type (str): Enum string ('ALL', 'VIEWS' or 'PLOTS')
|
||||
prefix (str): Exported file name prefix
|
||||
plot_format(str): Enum string, 'PNG' or 'PDF'
|
||||
"""
|
||||
return self._execute_command(
|
||||
exportSnapshots=Commands_pb2.ExportSnapshotsRequest(
|
||||
type=snapshot_type, prefix=prefix, caseId=-1, viewId=-1, plotOutputFormat=plot_format))
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
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=Commands_pb2.ExportWellPathRequest(
|
||||
wellPathNames=well_paths, mdStepSize=md_step_size))
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def scale_fracture_template(self, template_id, half_length, height,
|
||||
d_factor, conductivity):
|
||||
""" Scale fracture template parameters
|
||||
|
||||
Arguments:
|
||||
template_id(int): ID of fracture template
|
||||
half_length (double): Half Length scale factor
|
||||
height (double): Height scale factor
|
||||
d_factor (double): D-factor scale factor
|
||||
conductivity (double): Conductivity scale factor
|
||||
"""
|
||||
return self._execute_command(
|
||||
scaleFractureTemplate=Commands_pb2.ScaleFractureTemplateRequest(
|
||||
id=template_id,
|
||||
halfLength=half_length,
|
||||
height=height,
|
||||
dFactor=d_factor,
|
||||
conductivity=conductivity))
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def set_fracture_containment(self, template_id, top_layer, base_layer):
|
||||
""" Set fracture template containment parameters
|
||||
|
||||
Arguments:
|
||||
template_id(int): ID of fracture template
|
||||
top_layer (int): Top layer containment
|
||||
base_layer (int): Base layer containment
|
||||
"""
|
||||
return self._execute_command(
|
||||
setFractureContainment=Commands_pb2.SetFracContainmentRequest(
|
||||
id=template_id, topLayer=top_layer, baseLayer=base_layer))
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def import_well_paths(self, well_path_files=None, well_path_folder=''):
|
||||
""" Import well paths into project
|
||||
|
||||
Arguments:
|
||||
well_path_files(list): List of file paths to import
|
||||
well_path_folder(str): A folder path containing files to import
|
||||
|
||||
Returns:
|
||||
List of :class:`rips.generated.resinsight_classes.WellPath`
|
||||
"""
|
||||
if well_path_files is None:
|
||||
well_path_files = []
|
||||
|
||||
res = self._execute_command(importWellPaths=Commands_pb2.ImportWellPathsRequest(wellPathFolder=well_path_folder,
|
||||
wellPathFiles=well_path_files))
|
||||
well_paths = []
|
||||
for well_path_name in res.importWellPathsResult.wellPathNames:
|
||||
well_paths.append(self.well_path_by_name(well_path_name))
|
||||
return well_paths
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def well_paths(self):
|
||||
"""Get a list of all well paths in the project
|
||||
|
||||
Returns:
|
||||
List of :class:`rips.generated.resinsight_classes.WellPath`
|
||||
"""
|
||||
return self.descendants(WellPath)
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def well_path_by_name(self, well_path_name):
|
||||
"""Get a specific well path by name from the project
|
||||
|
||||
Returns:
|
||||
:class:`rips.generated.resinsight_classes.WellPath`
|
||||
"""
|
||||
all_well_paths = self.well_paths()
|
||||
for well_path in all_well_paths:
|
||||
if well_path.name == well_path_name:
|
||||
return well_path
|
||||
return None
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def import_well_log_files(self, well_log_files=None, well_log_folder=''):
|
||||
""" Import well log files into project
|
||||
|
||||
Arguments:
|
||||
well_log_files(list): List of file paths to import
|
||||
well_log_folder(str): A folder path containing files to import
|
||||
|
||||
Returns:
|
||||
A list of well path names (strings) that had logs imported
|
||||
"""
|
||||
|
||||
if well_log_files is None:
|
||||
well_log_files = []
|
||||
res = self._execute_command(importWellLogFiles=Commands_pb2.ImportWellLogFilesRequest(wellLogFolder=well_log_folder,
|
||||
wellLogFiles=well_log_files))
|
||||
return res.importWellLogFilesResult.wellPathNames
|
||||
|
||||
|
||||
@add_method(Project)
|
||||
def import_formation_names(self, formation_files=None):
|
||||
""" Import formation names into project
|
||||
|
||||
Arguments:
|
||||
formation_files(list): list of files to import
|
||||
|
||||
"""
|
||||
if formation_files is None:
|
||||
formation_files = []
|
||||
elif isinstance(formation_files, str):
|
||||
formation_files = [formation_files]
|
||||
|
||||
self._execute_command(importFormationNames=Commands_pb2.ImportFormationNamesRequest(formationFiles=formation_files,
|
||||
applyToCaseId=-1))
|
||||
83
GrpcInterface/Python/rips/retry_policy.py
Normal file
83
GrpcInterface/Python/rips/retry_policy.py
Normal file
@@ -0,0 +1,83 @@
|
||||
import abc
|
||||
|
||||
import time
|
||||
import random
|
||||
|
||||
|
||||
class RetryPolicy(abc.ABC):
|
||||
@abc.abstractmethod
|
||||
def sleep(self, retry_num):
|
||||
"""
|
||||
How long to sleep in milliseconds.
|
||||
:param retry_num: the number of retry (starting from zero)
|
||||
"""
|
||||
assert retry_num >= 0
|
||||
|
||||
@abc.abstractmethod
|
||||
def time_out_message(self):
|
||||
"""
|
||||
Generate a error message for user on time out.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def num_retries(self):
|
||||
"""
|
||||
Max number retries.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class FixedRetryPolicy(RetryPolicy):
|
||||
def __init__(self, sleep_time=1000, max_num_retries=10):
|
||||
"""
|
||||
Create a fixed time retry policy.
|
||||
:param sleep_time: time to sleep in milliseconds.
|
||||
:param max_num_retries: max number of retries.
|
||||
"""
|
||||
self.sleep_time = sleep_time
|
||||
self.max_num_retries = max_num_retries
|
||||
|
||||
def sleep(self, retry_num):
|
||||
time.sleep(self.sleep_time / 1000)
|
||||
|
||||
def time_out_message(self):
|
||||
return "Tried {} times with {} milliseconds apart.".format(
|
||||
self.max_num_retries, self.sleep_time
|
||||
)
|
||||
|
||||
def num_retries(self):
|
||||
return self.max_num_retries
|
||||
|
||||
|
||||
class ExponentialBackoffRetryPolicy(RetryPolicy):
|
||||
def __init__(self, min_backoff=200, max_backoff=10000, max_num_retries=20):
|
||||
"""
|
||||
Create a truncated exponential backoff policy.
|
||||
See: https://en.wikipedia.org/wiki/Exponential_backoff
|
||||
:param min_backoff: minimum time to sleep in milliseconds.
|
||||
:param max_backoff: maximum time to sleep in milliseconds.
|
||||
:param max_num_retries: max number of retries.
|
||||
"""
|
||||
self.min_backoff = min_backoff
|
||||
self.max_backoff = max_backoff
|
||||
self.max_num_retries = max_num_retries
|
||||
self.multiplier = 2
|
||||
|
||||
def sleep(self, retry_num):
|
||||
# Add a random component to avoid synchronized retries
|
||||
wiggle = random.randint(0, 100)
|
||||
sleep_ms = min(
|
||||
self.min_backoff + self.multiplier ** retry_num + wiggle, self.max_backoff
|
||||
)
|
||||
time.sleep(sleep_ms / 1000)
|
||||
|
||||
def time_out_message(self):
|
||||
return (
|
||||
"Tried {} times with increasing delay (from {} to {} milliseconds).".format(
|
||||
self.max_num_retries, self.min_backoff, self.max_backoff
|
||||
)
|
||||
)
|
||||
|
||||
def num_retries(self):
|
||||
return self.max_num_retries
|
||||
74
GrpcInterface/Python/rips/simulation_well.py
Normal file
74
GrpcInterface/Python/rips/simulation_well.py
Normal file
@@ -0,0 +1,74 @@
|
||||
"""
|
||||
ResInsight SimulationWell
|
||||
"""
|
||||
import grpc
|
||||
|
||||
import SimulationWell_pb2
|
||||
import SimulationWell_pb2_grpc
|
||||
|
||||
import Properties_pb2
|
||||
import Properties_pb2_grpc
|
||||
|
||||
from resinsight_classes import SimulationWell
|
||||
|
||||
from .pdmobject import PdmObjectBase, add_method
|
||||
|
||||
import rips.case
|
||||
|
||||
|
||||
@add_method(SimulationWell)
|
||||
def __custom_init__(self, pb2_object, channel):
|
||||
self._simulation_well_stub = SimulationWell_pb2_grpc.SimulationWellStub(channel)
|
||||
|
||||
|
||||
@add_method(SimulationWell)
|
||||
def status(self, timestep):
|
||||
"""Get simulation well status
|
||||
|
||||
**SimulationWellStatus class description**::
|
||||
|
||||
Parameter | Description | Type
|
||||
----------- | ------------------------------------------------------------- | -----
|
||||
well_type | Well type as string | string
|
||||
is_open | True if simulation well is open at the specified time step | bool
|
||||
|
||||
Arguments:
|
||||
timestep(int): Time step index
|
||||
|
||||
"""
|
||||
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)
|
||||
|
||||
|
||||
@add_method(SimulationWell)
|
||||
def cells(self, timestep):
|
||||
"""Get reservoir cells the simulation well is defined for
|
||||
|
||||
**SimulationWellCellInfo class description**::
|
||||
|
||||
Parameter | Description | Type
|
||||
----------- | --------------------------------------------------------- | -----
|
||||
ijk | Cell IJK location | Vec3i
|
||||
grid_index | Grid index | int
|
||||
is_open | True if connection to is open at the specified time step | bool
|
||||
branch_id | | int
|
||||
segment_id | | int
|
||||
|
||||
Arguments:
|
||||
timestep(int): Time step index
|
||||
|
||||
Returns:
|
||||
List of SimulationWellCellInfo
|
||||
|
||||
"""
|
||||
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
|
||||
|
||||
|
||||
@add_method(SimulationWell)
|
||||
def case(self):
|
||||
return self.ancestor(rips.case.Case)
|
||||
49
GrpcInterface/Python/rips/tests/conftest.py
Normal file
49
GrpcInterface/Python/rips/tests/conftest.py
Normal file
@@ -0,0 +1,49 @@
|
||||
import pytest
|
||||
import sys
|
||||
import os
|
||||
import getopt
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../../'))
|
||||
import rips
|
||||
|
||||
_rips_instance = None
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def rips_instance():
|
||||
return _rips_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def initialize_test():
|
||||
_rips_instance.project.close() # make sure ResInsight is clean before execution of test
|
||||
yield initialize_test
|
||||
_rips_instance.project.close() # make sure ResInsight is clean after test
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--console", action="store_true", default=False,
|
||||
help="Run as console application")
|
||||
parser.addoption("--existing", action="store_true", default=False,
|
||||
help="Look for existing ResInsight")
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
global _rips_instance
|
||||
console = False
|
||||
if config.getoption('--existing'):
|
||||
print("Looking for existing ResInsight")
|
||||
_rips_instance = rips.Instance.find()
|
||||
else:
|
||||
if config.getoption('--console'):
|
||||
console = True
|
||||
_rips_instance = rips.Instance.launch(console=console)
|
||||
if not _rips_instance:
|
||||
print("Need a valid ResInsight executable to launch tests")
|
||||
exit(0)
|
||||
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
if not config.getoption('--existing'):
|
||||
if _rips_instance:
|
||||
_rips_instance.exit()
|
||||
3
GrpcInterface/Python/rips/tests/dataroot.py
Normal file
3
GrpcInterface/Python/rips/tests/dataroot.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# The path here is intended to be used when pytest is launced from the source tree of the ResInsight repository
|
||||
# This enables use of test datasets from the TestModels folder
|
||||
PATH = "../../../../TestModels"
|
||||
205
GrpcInterface/Python/rips/tests/test_cases.py
Normal file
205
GrpcInterface/Python/rips/tests/test_cases.py
Normal file
@@ -0,0 +1,205 @@
|
||||
import sys
|
||||
import os
|
||||
import math
|
||||
import pytest
|
||||
import grpc
|
||||
import tempfile
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../../'))
|
||||
import rips
|
||||
|
||||
import dataroot
|
||||
|
||||
|
||||
def test_Launch(rips_instance, initialize_test):
|
||||
assert(rips_instance is not None)
|
||||
|
||||
|
||||
def test_EmptyProject(rips_instance, initialize_test):
|
||||
cases = rips_instance.project.cases()
|
||||
assert(len(cases) is 0)
|
||||
|
||||
|
||||
def test_OneCase(rips_instance, initialize_test):
|
||||
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.id == 0)
|
||||
cases = rips_instance.project.cases()
|
||||
assert(len(cases) is 1)
|
||||
|
||||
|
||||
def test_BoundingBox(rips_instance, initialize_test):
|
||||
case = rips_instance.project.load_case(
|
||||
dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID")
|
||||
assert(case.name == "TEST10K_FLT_LGR_NNC")
|
||||
boundingbox = case.reservoir_boundingbox()
|
||||
assert(math.isclose(3382.90, boundingbox.min_x, abs_tol=1.0e-1))
|
||||
assert(math.isclose(5850.48, boundingbox.max_x, abs_tol=1.0e-1))
|
||||
assert(math.isclose(4157.45, boundingbox.min_y, abs_tol=1.0e-1))
|
||||
assert(math.isclose(7354.93, boundingbox.max_y, abs_tol=1.0e-1))
|
||||
assert(math.isclose(-4252.61, boundingbox.min_z, abs_tol=1.0e-1))
|
||||
assert(math.isclose(-4103.60, boundingbox.max_z, abs_tol=1.0e-1))
|
||||
|
||||
min_depth, max_depth = case.reservoir_depth_range()
|
||||
assert(math.isclose(4103.60, min_depth, abs_tol=1.0e-1))
|
||||
assert(math.isclose(4252.61, max_depth, abs_tol=1.0e-1))
|
||||
|
||||
|
||||
def test_MultipleCases(rips_instance, initialize_test):
|
||||
case_paths = []
|
||||
case_paths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID")
|
||||
case_paths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID")
|
||||
case_paths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID")
|
||||
|
||||
case_names = []
|
||||
for case_path in case_paths:
|
||||
case_name = os.path.splitext(os.path.basename(case_path))[0]
|
||||
case_names.append(case_name)
|
||||
rips_instance.project.load_case(path=case_path)
|
||||
|
||||
cases = rips_instance.project.cases()
|
||||
assert(len(cases) == len(case_names))
|
||||
for i, case_name in enumerate(case_names):
|
||||
assert(case_name == cases[i].name)
|
||||
|
||||
|
||||
def get_cell_index_with_ijk(cell_info, i, j, k):
|
||||
for (idx, cell) in enumerate(cell_info):
|
||||
if cell.local_ijk.i == i and cell.local_ijk.j == j and cell.local_ijk.k == k:
|
||||
return idx
|
||||
return -1
|
||||
|
||||
|
||||
def check_corner(actual, expected):
|
||||
assert(math.isclose(actual.x, expected[0], abs_tol=0.1))
|
||||
assert(math.isclose(actual.y, expected[1], abs_tol=0.1))
|
||||
assert(math.isclose(actual.z, expected[2], abs_tol=0.1))
|
||||
|
||||
|
||||
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()
|
||||
assert(cell_count_info.active_cell_count == 11125)
|
||||
assert(cell_count_info.reservoir_cell_count == 316224)
|
||||
time_steps = case.time_steps()
|
||||
assert(len(time_steps) == 9)
|
||||
days_since_start = case.days_since_start()
|
||||
assert(len(days_since_start) == 9)
|
||||
cell_info = case.cell_info_for_active_cells()
|
||||
assert(len(cell_info) == cell_count_info.active_cell_count)
|
||||
|
||||
# Check an active cell (found in resinsight ui)
|
||||
cell_index = get_cell_index_with_ijk(cell_info, 23, 44, 19)
|
||||
assert(cell_index != -1)
|
||||
|
||||
cell_centers = case.active_cell_centers()
|
||||
assert(len(cell_centers) == cell_count_info.active_cell_count)
|
||||
|
||||
# Check the cell center for the specific cell
|
||||
assert(math.isclose(3627.17, cell_centers[cell_index].x, abs_tol=0.1))
|
||||
assert(math.isclose(5209.75, cell_centers[cell_index].y, abs_tol=0.1))
|
||||
assert(math.isclose(4179.6, cell_centers[cell_index].z, abs_tol=0.1))
|
||||
|
||||
cell_corners = case.active_cell_corners()
|
||||
assert(len(cell_corners) == cell_count_info.active_cell_count)
|
||||
# Expected values from ResInsight UI
|
||||
expected_corners = [[3565.22, 5179.02, 4177.18],
|
||||
[3655.67, 5145.34, 4176.63],
|
||||
[3690.07, 5240.69, 4180.02],
|
||||
[3599.87, 5275.16, 4179.32],
|
||||
[3564.13, 5178.61, 4179.75],
|
||||
[3654.78, 5144.79, 4179.23],
|
||||
[3688.99, 5239.88, 4182.7],
|
||||
[3598.62, 5274.48, 4181.96]]
|
||||
check_corner(cell_corners[cell_index].c0, expected_corners[0])
|
||||
check_corner(cell_corners[cell_index].c1, expected_corners[1])
|
||||
check_corner(cell_corners[cell_index].c2, expected_corners[2])
|
||||
check_corner(cell_corners[cell_index].c3, expected_corners[3])
|
||||
check_corner(cell_corners[cell_index].c4, expected_corners[4])
|
||||
check_corner(cell_corners[cell_index].c5, expected_corners[5])
|
||||
check_corner(cell_corners[cell_index].c6, expected_corners[6])
|
||||
check_corner(cell_corners[cell_index].c7, expected_corners[7])
|
||||
|
||||
# No coarsening info for this case
|
||||
coarsening_info = case.coarsening_info()
|
||||
assert(len(coarsening_info) == 0)
|
||||
|
||||
|
||||
def test_PdmObject(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(case.id == 0)
|
||||
assert(case.address() is not 0)
|
||||
assert(case.__class__.__name__ == "EclipseCase")
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux")
|
||||
def test_brugge_0010(rips_instance, initialize_test):
|
||||
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID"
|
||||
case = rips_instance.project.load_case(path=case_path)
|
||||
assert(len(case.grids()) == 1)
|
||||
cellCountInfo = case.cell_count()
|
||||
assert(cellCountInfo.active_cell_count == 43374)
|
||||
assert(cellCountInfo.reservoir_cell_count == 60048)
|
||||
time_steps = case.time_steps()
|
||||
assert(len(time_steps) == 11)
|
||||
days_since_start = case.days_since_start()
|
||||
assert(len(days_since_start) == 11)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux")
|
||||
def test_replaceCase(rips_instance, initialize_test):
|
||||
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 = project.case(case_id=0)
|
||||
assert(case is not None)
|
||||
assert(case.name == "TEST10K_FLT_LGR_NNC")
|
||||
assert(case.id == 0)
|
||||
cases = rips_instance.project.cases()
|
||||
assert(len(cases) is 1)
|
||||
|
||||
case.replace(new_grid_file=case_path)
|
||||
# Check that the case object has been changed
|
||||
assert(case.name == "BRUGGE_0000")
|
||||
assert(case.id == 0)
|
||||
|
||||
cases = rips_instance.project.cases()
|
||||
assert(len(cases) is 1)
|
||||
# Check that retrieving the case object again will yield the changed object
|
||||
case = project.case(case_id=0)
|
||||
assert(case.name == "BRUGGE_0000")
|
||||
assert(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)
|
||||
|
||||
|
||||
def test_selected_cells(rips_instance, initialize_test):
|
||||
case = rips_instance.project.load_case(
|
||||
dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID")
|
||||
assert(case.name == "TEST10K_FLT_LGR_NNC")
|
||||
selected_cells = case.selected_cells()
|
||||
assert(len(selected_cells) == 0)
|
||||
|
||||
time_step_info = case.time_steps()
|
||||
for (tidx, timestep) in enumerate(time_step_info):
|
||||
# Try to read for SOIL the time step (will be empty since nothing is selected)
|
||||
soil_results = case.selected_cell_property('DYNAMIC_NATIVE', 'SOIL', tidx)
|
||||
assert(len(soil_results) == 0)
|
||||
10
GrpcInterface/Python/rips/tests/test_commands.py
Normal file
10
GrpcInterface/Python/rips/tests/test_commands.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import sys
|
||||
import os
|
||||
import tempfile
|
||||
import pytest
|
||||
import grpc
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../../'))
|
||||
import rips
|
||||
|
||||
import dataroot
|
||||
55
GrpcInterface/Python/rips/tests/test_grids.py
Normal file
55
GrpcInterface/Python/rips/tests/test_grids.py
Normal file
@@ -0,0 +1,55 @@
|
||||
import sys
|
||||
import os
|
||||
import math
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../../'))
|
||||
import rips
|
||||
|
||||
import dataroot
|
||||
|
||||
|
||||
def check_corner(actual, expected):
|
||||
assert(math.isclose(actual.x, expected[0], abs_tol=0.1))
|
||||
assert(math.isclose(actual.y, expected[1], abs_tol=0.1))
|
||||
assert(math.isclose(actual.z, expected[2], abs_tol=0.1))
|
||||
|
||||
|
||||
def test_10k(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
assert(len(case.grids()) == 2)
|
||||
grid = case.grid(index=0)
|
||||
dimensions = grid.dimensions()
|
||||
assert(dimensions.i == 90)
|
||||
assert(dimensions.j == 96)
|
||||
assert(dimensions.k == 36)
|
||||
|
||||
cell_centers = grid.cell_centers()
|
||||
assert(len(cell_centers) == (dimensions.i * dimensions.j * dimensions.k))
|
||||
|
||||
# Test a specific cell (results from ResInsight UI)
|
||||
cell_index = 168143
|
||||
assert(math.isclose(3627.17, cell_centers[cell_index].x, abs_tol=0.1))
|
||||
assert(math.isclose(5209.75, cell_centers[cell_index].y, abs_tol=0.1))
|
||||
assert(math.isclose(4179.6, cell_centers[cell_index].z, abs_tol=0.1))
|
||||
|
||||
cell_corners = grid.cell_corners()
|
||||
assert(len(cell_corners) == (dimensions.i * dimensions.j * dimensions.k))
|
||||
|
||||
# Expected values from ResInsight UI
|
||||
expected_corners = [[3565.22, 5179.02, 4177.18],
|
||||
[3655.67, 5145.34, 4176.63],
|
||||
[3690.07, 5240.69, 4180.02],
|
||||
[3599.87, 5275.16, 4179.32],
|
||||
[3564.13, 5178.61, 4179.75],
|
||||
[3654.78, 5144.79, 4179.23],
|
||||
[3688.99, 5239.88, 4182.7],
|
||||
[3598.62, 5274.48, 4181.96]]
|
||||
check_corner(cell_corners[cell_index].c0, expected_corners[0])
|
||||
check_corner(cell_corners[cell_index].c1, expected_corners[1])
|
||||
check_corner(cell_corners[cell_index].c2, expected_corners[2])
|
||||
check_corner(cell_corners[cell_index].c3, expected_corners[3])
|
||||
check_corner(cell_corners[cell_index].c4, expected_corners[4])
|
||||
check_corner(cell_corners[cell_index].c5, expected_corners[5])
|
||||
check_corner(cell_corners[cell_index].c6, expected_corners[6])
|
||||
check_corner(cell_corners[cell_index].c7, expected_corners[7])
|
||||
74
GrpcInterface/Python/rips/tests/test_nnc_properties.py
Normal file
74
GrpcInterface/Python/rips/tests/test_nnc_properties.py
Normal file
@@ -0,0 +1,74 @@
|
||||
import sys
|
||||
import os
|
||||
import grpc
|
||||
import pytest
|
||||
|
||||
import rips.generated.NNCProperties_pb2 as NNCProperties_pb2
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../../'))
|
||||
import rips
|
||||
|
||||
import dataroot
|
||||
|
||||
|
||||
def test_10kSync(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
|
||||
properties = case.available_nnc_properties()
|
||||
assert(len(properties) == 1)
|
||||
|
||||
assert("TRAN" == properties[0].name)
|
||||
assert(NNCProperties_pb2.NNCPropertyType.Value('NNC_STATIC') == properties[0].property_type)
|
||||
|
||||
nnc_connections = case.nnc_connections()
|
||||
assert(len(nnc_connections) == 3627)
|
||||
|
||||
connection = nnc_connections[0]
|
||||
assert(connection.cell1.i == 33)
|
||||
assert(connection.cell1.j == 40)
|
||||
assert(connection.cell1.k == 14)
|
||||
assert(connection.cell_grid_index1 == 0)
|
||||
|
||||
tran_vals = case.nnc_connections_static_values("TRAN")
|
||||
assert(len(tran_vals) == len(nnc_connections))
|
||||
|
||||
for t in tran_vals:
|
||||
assert(isinstance(t, float))
|
||||
|
||||
# Generate some data
|
||||
new_data = []
|
||||
for (c, _) in enumerate(nnc_connections):
|
||||
new_data.append(float(c))
|
||||
|
||||
property_name = "NEW_PROP"
|
||||
case.set_nnc_connections_values(new_data, property_name, 0)
|
||||
new_prop_vals = case.nnc_connections_generated_values(property_name, 0)
|
||||
assert(len(new_prop_vals) == len(new_data))
|
||||
for i in range(0, len(new_data)):
|
||||
assert(new_data[i] == new_prop_vals[i])
|
||||
|
||||
# Set some other data for second time step
|
||||
for i in range(0, len(new_data)):
|
||||
new_data[i] = new_data[i] * 2.0
|
||||
|
||||
case.set_nnc_connections_values(new_data, property_name, 1)
|
||||
new_prop_vals = case.nnc_connections_generated_values(property_name, 1)
|
||||
assert(len(new_prop_vals) == len(nnc_connections))
|
||||
for i in range(0, len(new_data)):
|
||||
assert(new_data[i] == new_prop_vals[i])
|
||||
|
||||
|
||||
def test_non_existing_dynamic_values(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
|
||||
with pytest.raises(grpc.RpcError):
|
||||
case.nnc_connections_dynamic_values("x", 0)
|
||||
|
||||
|
||||
def test_invalid_time_steps(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
with pytest.raises(grpc.RpcError):
|
||||
case.nnc_connections_generated_values("Formation Allan", 9999)
|
||||
75
GrpcInterface/Python/rips/tests/test_project.py
Normal file
75
GrpcInterface/Python/rips/tests/test_project.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import sys
|
||||
import os
|
||||
import pytest
|
||||
import grpc
|
||||
import tempfile
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../../'))
|
||||
import rips
|
||||
|
||||
import dataroot
|
||||
|
||||
|
||||
def test_loadProject(rips_instance, initialize_test):
|
||||
project = rips_instance.project.open(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp")
|
||||
case = project.cases()[0]
|
||||
assert(case is not None)
|
||||
assert(case.name == "TEST10K_FLT_LGR_NNC")
|
||||
assert(case.id == 0)
|
||||
cases = rips_instance.project.cases()
|
||||
assert(len(cases) is 1)
|
||||
|
||||
|
||||
def test_well_log_plots(rips_instance, initialize_test):
|
||||
project = rips_instance.project.open(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp")
|
||||
plots = project.plots()
|
||||
well_log_plots = []
|
||||
for plot in plots:
|
||||
if isinstance(plot, rips.WellLogPlot):
|
||||
assert(plot.depth_type == "MEASURED_DEPTH")
|
||||
well_log_plots.append(plot)
|
||||
assert(len(well_log_plots) == 2)
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
|
||||
for well_log_plot in well_log_plots:
|
||||
well_log_plot.depth_type = "TRUE_VERTICAL_DEPTH_RKB"
|
||||
well_log_plot.update()
|
||||
if rips_instance.is_gui():
|
||||
well_log_plot.export_snapshot(tmpdirname)
|
||||
well_log_plot.export_data_as_las(tmpdirname)
|
||||
files = os.listdir(tmpdirname)
|
||||
print(files)
|
||||
if rips_instance.is_gui():
|
||||
assert(len(files) == 4)
|
||||
else:
|
||||
assert(len(files) == 2)
|
||||
|
||||
plots2 = project.plots()
|
||||
for plot2 in plots2:
|
||||
if isinstance(plot2, rips.WellLogPlot):
|
||||
assert(plot2.depth_type == "TRUE_VERTICAL_DEPTH_RKB")
|
||||
|
||||
|
||||
@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')
|
||||
112
GrpcInterface/Python/rips/tests/test_properties.py
Normal file
112
GrpcInterface/Python/rips/tests/test_properties.py
Normal file
@@ -0,0 +1,112 @@
|
||||
import sys
|
||||
import os
|
||||
import grpc
|
||||
import pytest
|
||||
import tempfile
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../../'))
|
||||
import rips
|
||||
|
||||
import dataroot
|
||||
|
||||
|
||||
def test_10kAsync(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
|
||||
resultChunks = case.active_cell_property_async('DYNAMIC_NATIVE', 'SOIL', 1)
|
||||
mysum = 0.0
|
||||
count = 0
|
||||
for chunk in resultChunks:
|
||||
mysum += sum(chunk.values)
|
||||
count += len(chunk.values)
|
||||
average = mysum / count
|
||||
assert(mysum == pytest.approx(621.768, abs=0.001))
|
||||
assert(average != pytest.approx(0.0158893, abs=0.0000001))
|
||||
assert(average == pytest.approx(0.0558893, abs=0.0000001))
|
||||
|
||||
|
||||
def test_10kSync(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
|
||||
results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1)
|
||||
mysum = sum(results)
|
||||
average = mysum / len(results)
|
||||
assert(mysum == pytest.approx(621.768, abs=0.001))
|
||||
assert(average != pytest.approx(0.0158893, abs=0.0000001))
|
||||
assert(average == pytest.approx(0.0558893, abs=0.0000001))
|
||||
|
||||
|
||||
def test_10k_set(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
|
||||
results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1)
|
||||
case.set_active_cell_property(results, 'GENERATED', 'SOIL', 1)
|
||||
|
||||
|
||||
def test_10k_set_out_of_bounds(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
|
||||
results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1)
|
||||
results.append(5.0)
|
||||
with pytest.raises(grpc.RpcError):
|
||||
assert case.set_active_cell_property(results, 'GENERATED', 'SOIL', 1)
|
||||
|
||||
|
||||
def test_10k_set_out_of_bounds_client(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
|
||||
results = case.active_cell_property('DYNAMIC_NATIVE', 'SOIL', 1)
|
||||
case.chunk_size = len(results)
|
||||
results.append(5.0)
|
||||
with pytest.raises(IndexError):
|
||||
assert case.set_active_cell_property(results, 'GENERATED', 'SOIL', 1)
|
||||
|
||||
|
||||
def createResult(poroChunks, permxChunks):
|
||||
for (poroChunk, permxChunk) in zip(poroChunks, permxChunks):
|
||||
resultChunk = []
|
||||
for (poro, permx) in zip(poroChunk.values, permxChunk.values):
|
||||
resultChunk.append(poro * permx)
|
||||
yield resultChunk
|
||||
|
||||
|
||||
def checkResults(poroValues, permxValues, poropermxValues):
|
||||
for (poro, permx, poropermx) in zip(poroValues, permxValues, poropermxValues):
|
||||
recalc = poro * permx
|
||||
assert(recalc == pytest.approx(poropermx, rel=1.0e-10))
|
||||
|
||||
|
||||
def test_10k_PoroPermX(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
|
||||
poroChunks = case.active_cell_property_async('STATIC_NATIVE', 'PORO', 0)
|
||||
permxChunks = case.active_cell_property_async('STATIC_NATIVE', 'PERMX', 0)
|
||||
|
||||
case.set_active_cell_property_async(createResult(
|
||||
poroChunks, permxChunks), 'GENERATED', 'POROPERMXAS', 0)
|
||||
|
||||
poro = case.active_cell_property('STATIC_NATIVE', 'PORO', 0)
|
||||
permx = case.active_cell_property('STATIC_NATIVE', 'PERMX', 0)
|
||||
poroPermX = case.active_cell_property('GENERATED', 'POROPERMXAS', 0)
|
||||
|
||||
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.cases()[0]
|
||||
view = case.views()[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))
|
||||
51
GrpcInterface/Python/rips/tests/test_simulation_wells.py
Normal file
51
GrpcInterface/Python/rips/tests/test_simulation_wells.py
Normal file
@@ -0,0 +1,51 @@
|
||||
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])
|
||||
115
GrpcInterface/Python/rips/tests/test_summary_cases.py
Normal file
115
GrpcInterface/Python/rips/tests/test_summary_cases.py
Normal file
@@ -0,0 +1,115 @@
|
||||
import sys
|
||||
import os
|
||||
import math
|
||||
import contextlib
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../../'))
|
||||
import rips
|
||||
|
||||
import dataroot
|
||||
|
||||
|
||||
def test_summary_import_and_find(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/flow_diagnostics_test/SIMPLE_SUMMARY2.SMSPEC"
|
||||
summary_case = rips_instance.project.import_summary_case(casePath)
|
||||
assert(summary_case.id == 1)
|
||||
|
||||
case_id = 234
|
||||
found_summary_case = rips_instance.project.summary_case(case_id)
|
||||
assert(found_summary_case is None)
|
||||
|
||||
correct_case_id = 1
|
||||
found_summary_case = rips_instance.project.summary_case(correct_case_id)
|
||||
assert(found_summary_case is not None)
|
||||
|
||||
rips_instance.project.close()
|
||||
correct_case_id = 1
|
||||
found_summary_case = rips_instance.project.summary_case(correct_case_id)
|
||||
assert(found_summary_case is None)
|
||||
|
||||
|
||||
def test_summary_data(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/flow_diagnostics_test/SIMPLE_SUMMARY2.SMSPEC"
|
||||
summary_case = rips_instance.project.import_summary_case(casePath)
|
||||
assert(summary_case.id == 1)
|
||||
|
||||
addresses = summary_case.available_addresses()
|
||||
assert(len(addresses.values) == 343)
|
||||
|
||||
summary_data = summary_case.summary_vector_values("FOPT")
|
||||
assert(len(summary_data.values) == 60)
|
||||
|
||||
|
||||
def test_summary_resample(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/flow_diagnostics_test/SIMPLE_SUMMARY2.SMSPEC"
|
||||
summary_case = rips_instance.project.import_summary_case(casePath)
|
||||
assert(summary_case.id == 1)
|
||||
|
||||
summary_data_sampled = summary_case.resample_values("FOPT", "NONE")
|
||||
assert(len(summary_data_sampled.values) == 60)
|
||||
assert(len(summary_data_sampled.time_steps) == 60)
|
||||
|
||||
summary_data_sampled = summary_case.resample_values("FOPT", "DAY")
|
||||
assert(len(summary_data_sampled.values) == 721)
|
||||
assert(len(summary_data_sampled.time_steps) == 721)
|
||||
|
||||
summary_data_sampled = summary_case.resample_values("FOPT", "MONTH")
|
||||
assert(len(summary_data_sampled.values) == 24)
|
||||
assert(len(summary_data_sampled.time_steps) == 24)
|
||||
|
||||
summary_data_sampled = summary_case.resample_values("FOPT", "QUARTER")
|
||||
assert(len(summary_data_sampled.values) == 8)
|
||||
assert(len(summary_data_sampled.time_steps) == 8)
|
||||
|
||||
summary_data_sampled = summary_case.resample_values("FOPT", "YEAR")
|
||||
assert(len(summary_data_sampled.values) == 3)
|
||||
assert(len(summary_data_sampled.time_steps) == 3)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def cd(newdir, cleanup=lambda: True):
|
||||
prevdir = os.getcwd()
|
||||
os.chdir(os.path.expanduser(newdir))
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.chdir(prevdir)
|
||||
cleanup()
|
||||
|
||||
@contextlib.contextmanager
|
||||
def tempdir():
|
||||
dirpath = tempfile.mkdtemp()
|
||||
def cleanup():
|
||||
shutil.rmtree(dirpath)
|
||||
with cd(dirpath, cleanup):
|
||||
yield dirpath
|
||||
|
||||
# This test ensures that missing unsmry file is handeled gracefully
|
||||
def test_summary_no_unsmry(rips_instance, initialize_test):
|
||||
casePathRelative = dataroot.PATH + "/flow_diagnostics_test/SIMPLE_SUMMARY2.SMSPEC"
|
||||
|
||||
# create an absolute path, as the helper functions used to create a temporary folder does not work
|
||||
# with the relative (..\..\) part of the file path
|
||||
casePath = os.path.abspath(casePathRelative)
|
||||
|
||||
with tempdir() as dirpath:
|
||||
base_path = os.path.basename(casePath)
|
||||
temp_path = os.path.join(dirpath, base_path)
|
||||
shutil.copy2(casePath, temp_path)
|
||||
|
||||
summary_case = rips_instance.project.import_summary_case(temp_path)
|
||||
|
||||
values = summary_case.summary_vector_values()
|
||||
assert(len(values.values) == 1)
|
||||
|
||||
time_steps = summary_case.available_time_steps()
|
||||
assert(len(time_steps.values) == 1)
|
||||
|
||||
addresses = summary_case.available_addresses()
|
||||
assert(len(addresses.values) == 1)
|
||||
|
||||
summary_case.resample_values()
|
||||
|
||||
20
GrpcInterface/Python/rips/tests/test_wells.py
Normal file
20
GrpcInterface/Python/rips/tests/test_wells.py
Normal file
@@ -0,0 +1,20 @@
|
||||
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_root_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC"
|
||||
case_path = case_root_path + "/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(path=case_path)
|
||||
assert(len(case.grids()) == 2)
|
||||
well_path_files = [case_root_path + "/wellpath_a.dev", case_root_path + "/wellpath_b.dev"]
|
||||
well_path_names = rips_instance.project.import_well_paths(well_path_files)
|
||||
wells = rips_instance.project.well_paths()
|
||||
assert(len(wells) == 2)
|
||||
assert(wells[0].name == "Well Path A")
|
||||
assert(wells[1].name == "Well Path B")
|
||||
201
GrpcInterface/Python/rips/view.py
Normal file
201
GrpcInterface/Python/rips/view.py
Normal file
@@ -0,0 +1,201 @@
|
||||
"""
|
||||
ResInsight 3d view module
|
||||
"""
|
||||
|
||||
import builtins
|
||||
import Commands_pb2 as Cmd
|
||||
|
||||
import rips.case # Circular import of Case, which already imports View. Use full name.
|
||||
from .pdmobject import add_method
|
||||
from resinsight_classes import View, ViewWindow, EclipseView, GeoMechView
|
||||
|
||||
|
||||
@add_method(View)
|
||||
def apply_cell_result(self, result_type, result_variable):
|
||||
"""Apply a regular cell result
|
||||
|
||||
Arguments:
|
||||
result_type (str): String representing the result category. The valid values are::
|
||||
- DYNAMIC_NATIVE
|
||||
- STATIC_NATIVE
|
||||
- SOURSIMRL
|
||||
- GENERATED
|
||||
- INPUT_PROPERTY
|
||||
- FORMATION_NAMES
|
||||
- FLOW_DIAGNOSTICS
|
||||
- INJECTION_FLOODING
|
||||
result_variable (str): String representing the result variable.
|
||||
"""
|
||||
cell_result = self.cell_result()
|
||||
cell_result.result_type = result_type
|
||||
cell_result.result_variable = result_variable
|
||||
cell_result.update()
|
||||
|
||||
|
||||
@add_method(View)
|
||||
def apply_flow_diagnostics_cell_result(
|
||||
self,
|
||||
result_variable='TOF',
|
||||
selection_mode='FLOW_TR_BY_SELECTION',
|
||||
injectors=None,
|
||||
producers=None):
|
||||
"""Apply a flow diagnostics cell result
|
||||
|
||||
**Parameters**::
|
||||
|
||||
Parameter | Description | Type
|
||||
------------------- | ------------------------------------------------------ | -----
|
||||
result_variable | String representing the result value | String
|
||||
selection_mode | String specifying which tracers to select | String
|
||||
injectors | List of injector names, used by 'FLOW_TR_BY_SELECTION' | String List
|
||||
producers | List of injector names, used by 'FLOW_TR_BY_SELECTION' | String List
|
||||
|
||||
**Enum compdat_export**::
|
||||
|
||||
Option | Description
|
||||
------------------------| ------------
|
||||
"TOF" | Time of flight
|
||||
"Fraction" | Fraction
|
||||
"MaxFractionTracer" | Max Fraction Tracer
|
||||
"Communication" | Communication
|
||||
|
||||
"""
|
||||
if injectors is None:
|
||||
injectors = []
|
||||
if producers is None:
|
||||
producers = []
|
||||
cell_result = self.cell_result()
|
||||
cell_result.result_type = "FLOW_DIAGNOSTICS"
|
||||
cell_result.result_variable = result_variable
|
||||
cell_result.flow_tracer_selection_mode = selection_mode
|
||||
if selection_mode == 'FLOW_TR_BY_SELECTION':
|
||||
cell_result.selected_injector_tracers = injectors
|
||||
cell_result.selected_producer_tracers = producers
|
||||
cell_result.update()
|
||||
|
||||
|
||||
@add_method(View)
|
||||
def clone(self):
|
||||
"""Clone the current view"""
|
||||
view_id = self._execute_command(cloneView=Cmd.CloneViewRequest(
|
||||
viewId=self.id)).createViewResult.viewId
|
||||
return self.case().view(view_id)
|
||||
|
||||
|
||||
@add_method(View)
|
||||
def set_time_step(self, time_step):
|
||||
"""Set the time step for current view"""
|
||||
case_id = self.case().id
|
||||
return self._execute_command(setTimeStep=Cmd.SetTimeStepParams(
|
||||
caseId=case_id, viewId=self.id, timeStep=time_step))
|
||||
|
||||
|
||||
@add_method(View)
|
||||
def export_sim_well_fracture_completions(self, time_step,
|
||||
simulation_well_names, file_split,
|
||||
compdat_export):
|
||||
"""Export fracture completions for simulation wells
|
||||
|
||||
**Parameters**::
|
||||
|
||||
Parameter | Description | Type
|
||||
----------------------------| ------------------------------------------------ | -----
|
||||
time_step | Time step to export for | Integer
|
||||
simulation_well_names | List of simulation well names | List
|
||||
file_split | Controls how export data is split into files | String enum
|
||||
compdat_export | Compdat export type | String enum
|
||||
|
||||
**Enum file_split**::
|
||||
|
||||
Option | Description
|
||||
----------------------------------- | ------------
|
||||
"UNIFIED_FILE" <b>Default Option</b>| A single file with all transmissibilities
|
||||
"SPLIT_ON_WELL" | One file for each well transmissibilities
|
||||
"SPLIT_ON_WELL_AND_COMPLETION_TYPE" | One file for each completion type for each well
|
||||
|
||||
**Enum compdat_export**::
|
||||
|
||||
Option | Description
|
||||
-----------------------------------------| ------------
|
||||
"TRANSMISSIBILITIES"<b>Default Option</b>| Direct export of transmissibilities
|
||||
"WPIMULT_AND_DEFAULT_CONNECTION_FACTORS" | Include export of WPIMULT
|
||||
|
||||
"""
|
||||
if isinstance(simulation_well_names, str):
|
||||
simulation_well_names = [simulation_well_names]
|
||||
|
||||
case_id = self.case().id
|
||||
return self._execute_command(
|
||||
exportSimWellFractureCompletions=Cmd.ExportSimWellPathFracRequest(
|
||||
caseId=case_id,
|
||||
viewId=self.id,
|
||||
timeStep=time_step,
|
||||
simulationWellNames=simulation_well_names,
|
||||
fileSplit=file_split,
|
||||
compdatExport=compdat_export))
|
||||
|
||||
|
||||
@add_method(View)
|
||||
def export_visible_cells(self,
|
||||
export_keyword='FLUXNUM',
|
||||
visible_active_cells_value=1,
|
||||
hidden_active_cells_value=0,
|
||||
inactive_cells_value=0):
|
||||
"""Export special properties for all visible cells.
|
||||
|
||||
Arguments:
|
||||
export_keyword (string): The keyword to export.
|
||||
Choices: 'FLUXNUM' or 'MULTNUM'. Default: 'FLUXNUM'
|
||||
visible_active_cells_value (int): Value to export forvisible active cells. Default: 1
|
||||
hidden_active_cells_value (int): Value to export for hidden active cells. Default: 0
|
||||
inactive_cells_value (int): Value to export for inactive cells. Default: 0
|
||||
"""
|
||||
case_id = self.case().id
|
||||
return self._execute_command(
|
||||
exportVisibleCells=Cmd.ExportVisibleCellsRequest(
|
||||
caseId=case_id,
|
||||
viewId=self.id,
|
||||
exportKeyword=export_keyword,
|
||||
visibleActiveCellsValue=visible_active_cells_value,
|
||||
hiddenActiveCellsValue=hidden_active_cells_value,
|
||||
inactiveCellsValue=inactive_cells_value))
|
||||
|
||||
|
||||
@add_method(View)
|
||||
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().id
|
||||
return self._execute_command(
|
||||
exportPropertyInViews=Cmd.ExportPropertyInViewsRequest(
|
||||
caseId=case_id,
|
||||
viewIds=[self.id],
|
||||
undefinedValue=undefined_value))
|
||||
|
||||
|
||||
@add_method(ViewWindow)
|
||||
def case(self):
|
||||
"""Get the case the view belongs to"""
|
||||
mycase = self.ancestor(rips.case.Case)
|
||||
assert(mycase is not None)
|
||||
return mycase
|
||||
|
||||
|
||||
@add_method(ViewWindow)
|
||||
def export_snapshot(self, prefix='', export_folder=''):
|
||||
""" Export snapshot for the current view
|
||||
|
||||
Arguments:
|
||||
prefix (str): Exported file name prefix
|
||||
export_folder(str): The path to export to. By default will use the global export folder
|
||||
"""
|
||||
case_id = self.case().id
|
||||
return self._execute_command(
|
||||
exportSnapshots=Cmd.ExportSnapshotsRequest(type='VIEWS',
|
||||
prefix=prefix,
|
||||
caseId=case_id,
|
||||
viewId=self.id,
|
||||
exportFolder=export_folder))
|
||||
56
GrpcInterface/Python/rips/well_log_plot.py
Normal file
56
GrpcInterface/Python/rips/well_log_plot.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
ResInsight Well Log Plot plot module
|
||||
"""
|
||||
|
||||
import Commands_pb2
|
||||
|
||||
from .plot import Plot
|
||||
from .pdmobject import PdmObjectBase, add_method
|
||||
from resinsight_classes import WellLogPlot
|
||||
|
||||
|
||||
@add_method(WellLogPlot)
|
||||
def export_data_as_las(self, export_folder, file_prefix='', export_tvdrkb=False, capitalize_file_names=False, resample_interval=0.0, convert_to_standard_units=False):
|
||||
""" Export LAS file(s) for the current plot
|
||||
|
||||
Arguments:
|
||||
export_folder(str): The path to export to. By default will use the global export folder
|
||||
file_prefix (str): Exported file name prefix
|
||||
export_tvdrkb(bool): Export in TVD-RKB format
|
||||
capitalize_file_names(bool): Make all file names upper case
|
||||
resample_interval(double): if > 0.0 the files will be resampled
|
||||
|
||||
Returns:
|
||||
A list of files exported
|
||||
"""
|
||||
res = self._execute_command(exportWellLogPlotData=Commands_pb2.ExportWellLogPlotDataRequest(exportFormat='LAS',
|
||||
viewId=self.id,
|
||||
exportFolder=export_folder,
|
||||
filePrefix=file_prefix,
|
||||
exportTvdRkb=export_tvdrkb,
|
||||
capitalizeFileNames=capitalize_file_names,
|
||||
resampleInterval=resample_interval,
|
||||
convertCurveUnits=convert_to_standard_units))
|
||||
return res.exportWellLogPlotDataResult.exportedFiles
|
||||
|
||||
|
||||
@add_method(WellLogPlot)
|
||||
def export_data_as_ascii(self, export_folder, file_prefix='', capitalize_file_names=False):
|
||||
""" Export LAS file(s) for the current plot
|
||||
|
||||
Arguments:
|
||||
export_folder(str): The path to export to. By default will use the global export folder
|
||||
file_prefix (str): Exported file name prefix
|
||||
capitalize_file_names(bool): Make all file names upper case
|
||||
|
||||
Returns:
|
||||
A list of files exported
|
||||
"""
|
||||
res = self._execute_command(exportWellLogPlotData=Commands_pb2.ExportWellLogPlotDataRequest(exportFormat='ASCII',
|
||||
viewId=self.id,
|
||||
exportFolder=export_folder,
|
||||
filePrefix=file_prefix,
|
||||
exportTvdRkb=False,
|
||||
capitalizeFileNames=capitalize_file_names,
|
||||
resampleInterval=0.0))
|
||||
return res.exportWellLogPlotDataResult.exportedFiles
|
||||
23
GrpcInterface/Python/setup.py.cmake
Normal file
23
GrpcInterface/Python/setup.py.cmake
Normal file
@@ -0,0 +1,23 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
with open('README.md') as f:
|
||||
readme = f.read()
|
||||
|
||||
with open('LICENSE') as f:
|
||||
license = f.read()
|
||||
|
||||
RIPS_DIST_VERSION = '1'
|
||||
|
||||
setup(
|
||||
name='rips',
|
||||
version='@RESINSIGHT_MAJOR_VERSION@.@RESINSIGHT_MINOR_VERSION@.@RESINSIGHT_PATCH_VERSION@.' + RIPS_DIST_VERSION,
|
||||
description='Python Interface for ResInsight',
|
||||
long_description=readme,
|
||||
author='Ceetron Solutions',
|
||||
author_email='info@ceetronsolutions.com',
|
||||
url='http://www.resinsight.org',
|
||||
license=license,
|
||||
packages=['rips'],
|
||||
package_data={'rips': ['*.py', 'generated/*.py', 'PythonExamples/*.py', 'tests/*.py']},
|
||||
install_requires=['grpcio>=1.20.0']
|
||||
)
|
||||
75
GrpcInterface/RiaGrpcAppService.cpp
Normal file
75
GrpcInterface/RiaGrpcAppService.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#include "RiaGrpcAppService.h"
|
||||
|
||||
#include "RiaGrpcCallbacks.h"
|
||||
#include "RiaGrpcServer.h"
|
||||
#include "RiaGuiApplication.h"
|
||||
#include "RiaVersionInfo.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcAppService::GetVersion( grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply )
|
||||
{
|
||||
reply->set_major_version( QString( RESINSIGHT_MAJOR_VERSION ).toInt() );
|
||||
reply->set_minor_version( QString( RESINSIGHT_MINOR_VERSION ).toInt() );
|
||||
reply->set_patch_version( QString( RESINSIGHT_PATCH_VERSION ).toInt() );
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcAppService::Exit( grpc::ServerContext* context, const rips::Empty* request, rips::Empty* reply )
|
||||
{
|
||||
RiaGrpcServer::setReceivedExitRequest();
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status
|
||||
RiaGrpcAppService::GetRuntimeInfo( grpc::ServerContext* context, const rips::Empty* request, rips::RuntimeInfo* reply )
|
||||
{
|
||||
rips::ApplicationTypeEnum appType = rips::CONSOLE_APPLICATION;
|
||||
if ( RiaGuiApplication::isRunning() )
|
||||
{
|
||||
appType = rips::GUI_APPLICATION;
|
||||
}
|
||||
reply->set_app_type( appType );
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaGrpcCallbackInterface*> RiaGrpcAppService::createCallbacks()
|
||||
{
|
||||
typedef RiaGrpcAppService Self;
|
||||
return { new RiaGrpcUnaryCallback<Self, rips::Empty, rips::Version>( this, &Self::GetVersion, &Self::RequestGetVersion ),
|
||||
new RiaGrpcUnaryCallback<Self, rips::Empty, rips::Empty>( this, &Self::Exit, &Self::RequestExit ),
|
||||
new RiaGrpcUnaryCallback<Self, rips::Empty, rips::RuntimeInfo>( this,
|
||||
&Self::GetRuntimeInfo,
|
||||
&Self::RequestGetRuntimeInfo ) };
|
||||
}
|
||||
|
||||
static bool RiaGrpcAppInfoService_init =
|
||||
RiaGrpcServiceFactory::instance()->registerCreator<RiaGrpcAppService>( typeid( RiaGrpcAppService ).hash_code() );
|
||||
49
GrpcInterface/RiaGrpcAppService.h
Normal file
49
GrpcInterface/RiaGrpcAppService.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "RiaGrpcServiceInterface.h"
|
||||
|
||||
#include "App.grpc.pb.h"
|
||||
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <vector>
|
||||
|
||||
namespace rips
|
||||
{
|
||||
class Empty;
|
||||
class Version;
|
||||
} // namespace rips
|
||||
|
||||
namespace caf
|
||||
{
|
||||
class PdmValueField;
|
||||
}
|
||||
|
||||
class RiaGrpcCallbackInterface;
|
||||
|
||||
class RiaGrpcAppService : public rips::App::AsyncService, public RiaGrpcServiceInterface
|
||||
{
|
||||
public:
|
||||
grpc::Status GetVersion( grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply ) override;
|
||||
grpc::Status Exit( grpc::ServerContext* context, const rips::Empty* request, rips::Empty* reply ) override;
|
||||
grpc::Status GetRuntimeInfo( grpc::ServerContext* context, const rips::Empty* request, rips::RuntimeInfo* reply ) override;
|
||||
std::vector<RiaGrpcCallbackInterface*> createCallbacks() override;
|
||||
};
|
||||
217
GrpcInterface/RiaGrpcCallbacks.h
Normal file
217
GrpcInterface/RiaGrpcCallbacks.h
Normal file
@@ -0,0 +1,217 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "RiaLogging.h"
|
||||
|
||||
#include <QString>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <grpcpp/server_context.h>
|
||||
#include <grpcpp/support/async_stream.h>
|
||||
#include <grpcpp/support/async_unary_call.h>
|
||||
#include <grpcpp/support/sync_stream.h>
|
||||
|
||||
using grpc::CompletionQueue;
|
||||
using grpc::ServerAsyncReader;
|
||||
using grpc::ServerAsyncResponseWriter;
|
||||
using grpc::ServerAsyncWriter;
|
||||
using grpc::ServerCompletionQueue;
|
||||
using grpc::ServerContext;
|
||||
using grpc::Status;
|
||||
|
||||
class RiaGrpcServiceInterface;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Base class for all gRPC-callbacks
|
||||
//
|
||||
//==================================================================================================
|
||||
class RiaGrpcCallbackInterface
|
||||
{
|
||||
public:
|
||||
enum CallState
|
||||
{
|
||||
CREATE_HANDLER,
|
||||
INIT_REQUEST_STARTED,
|
||||
INIT_REQUEST_COMPLETED,
|
||||
PROCESS_REQUEST,
|
||||
FINISH_REQUEST
|
||||
};
|
||||
|
||||
public:
|
||||
inline RiaGrpcCallbackInterface();
|
||||
|
||||
virtual ~RiaGrpcCallbackInterface() {}
|
||||
virtual QString name() const = 0;
|
||||
virtual RiaGrpcCallbackInterface* createNewFromThis() const = 0;
|
||||
virtual void createRequestHandler( ServerCompletionQueue* completionQueue ) = 0;
|
||||
virtual void onInitRequestStarted() {}
|
||||
virtual void onInitRequestCompleted() {}
|
||||
virtual void onProcessRequest() = 0;
|
||||
virtual void onFinishRequest() {}
|
||||
|
||||
inline CallState callState() const;
|
||||
inline const Status& status() const;
|
||||
inline void setNextCallState( CallState state );
|
||||
|
||||
protected:
|
||||
CallState m_state;
|
||||
Status m_status;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Templated gRPC-callback base class
|
||||
//
|
||||
//==================================================================================================
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
class RiaGrpcServiceCallback : public RiaGrpcCallbackInterface
|
||||
{
|
||||
public:
|
||||
RiaGrpcServiceCallback( ServiceT* service );
|
||||
|
||||
QString name() const override;
|
||||
const RequestT& request() const;
|
||||
ReplyT& reply();
|
||||
|
||||
protected:
|
||||
virtual QString methodType() const = 0;
|
||||
|
||||
protected:
|
||||
ServiceT* m_service;
|
||||
RequestT m_request;
|
||||
ReplyT m_reply;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Templated gRPC-callback for non-streaming services
|
||||
//
|
||||
//==================================================================================================
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
class RiaGrpcUnaryCallback : public RiaGrpcServiceCallback<ServiceT, RequestT, ReplyT>
|
||||
{
|
||||
public:
|
||||
using ResponseWriterT = ServerAsyncResponseWriter<ReplyT>;
|
||||
using MethodImplT = std::function<Status( ServiceT&, ServerContext*, const RequestT*, ReplyT* )>;
|
||||
using MethodRequestT = std::function<
|
||||
void( ServiceT&, ServerContext*, RequestT*, ResponseWriterT*, CompletionQueue*, ServerCompletionQueue*, void* )>;
|
||||
|
||||
RiaGrpcUnaryCallback( ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest );
|
||||
|
||||
RiaGrpcCallbackInterface* createNewFromThis() const override;
|
||||
void createRequestHandler( ServerCompletionQueue* completionQueue ) override;
|
||||
void onProcessRequest() override;
|
||||
|
||||
protected:
|
||||
virtual QString methodType() const override;
|
||||
|
||||
private:
|
||||
ServerContext m_context;
|
||||
ResponseWriterT m_responder;
|
||||
MethodImplT m_methodImpl;
|
||||
MethodRequestT m_methodRequest;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Templated server->client *streaming* gRPC-callback calling service implementation callbacks
|
||||
//
|
||||
// The streaming callback needs a state handler for setting up and maintaining order.
|
||||
//
|
||||
// A fully functional state handler for server->client streaming needs to implement the following methods:
|
||||
// 1. Default Constructor
|
||||
// 2. grpc::Status init(const grpc::Message* request)
|
||||
//
|
||||
//==================================================================================================
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
class RiaGrpcServerToClientStreamCallback : public RiaGrpcServiceCallback<ServiceT, RequestT, ReplyT>
|
||||
{
|
||||
public:
|
||||
using ResponseWriterT = ServerAsyncWriter<ReplyT>;
|
||||
using MethodImplT = std::function<Status( ServiceT&, ServerContext*, const RequestT*, ReplyT*, StateHandlerT* )>;
|
||||
using MethodRequestT = std::function<
|
||||
void( ServiceT&, ServerContext*, RequestT*, ResponseWriterT*, CompletionQueue*, ServerCompletionQueue*, void* )>;
|
||||
|
||||
RiaGrpcServerToClientStreamCallback( ServiceT* service,
|
||||
MethodImplT methodImpl,
|
||||
MethodRequestT methodRequest,
|
||||
StateHandlerT* stateHandler );
|
||||
|
||||
RiaGrpcCallbackInterface* createNewFromThis() const override;
|
||||
void createRequestHandler( ServerCompletionQueue* completionQueue ) override;
|
||||
void onInitRequestCompleted() override;
|
||||
void onProcessRequest() override;
|
||||
|
||||
protected:
|
||||
virtual QString methodType() const override;
|
||||
|
||||
private:
|
||||
ServerContext m_context;
|
||||
ResponseWriterT m_responder;
|
||||
MethodImplT m_methodImpl;
|
||||
MethodRequestT m_methodRequest;
|
||||
std::unique_ptr<StateHandlerT> m_stateHandler;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Templated client->server *streaming* gRPC-callback calling service implementation callbacks
|
||||
//
|
||||
// The streaming callback needs a state handler for setting up and maintaining order.
|
||||
//
|
||||
// A fully functional state handler for client->server streaming needs to implement the following methods:
|
||||
// 1. Default Constructor
|
||||
// 2. grpc::Status init(const grpc::Message* request)
|
||||
// 3. void finish() any updates required after completion
|
||||
//
|
||||
//==================================================================================================
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
class RiaGrpcClientToServerStreamCallback : public RiaGrpcServiceCallback<ServiceT, RequestT, ReplyT>
|
||||
{
|
||||
public:
|
||||
using RequestReaderT = ServerAsyncReader<ReplyT, RequestT>;
|
||||
using MethodImplT = std::function<Status( ServiceT&, ServerContext*, const RequestT*, ReplyT*, StateHandlerT* )>;
|
||||
using MethodRequestT =
|
||||
std::function<void( ServiceT&, ServerContext*, RequestReaderT*, CompletionQueue*, ServerCompletionQueue*, void* )>;
|
||||
|
||||
RiaGrpcClientToServerStreamCallback( ServiceT* service,
|
||||
MethodImplT methodImpl,
|
||||
MethodRequestT methodRequest,
|
||||
StateHandlerT* stateHandler );
|
||||
|
||||
RiaGrpcCallbackInterface* createNewFromThis() const override;
|
||||
void createRequestHandler( ServerCompletionQueue* completionQueue ) override;
|
||||
void onInitRequestStarted() override;
|
||||
void onInitRequestCompleted() override;
|
||||
void onProcessRequest() override;
|
||||
void onFinishRequest() override;
|
||||
|
||||
protected:
|
||||
virtual QString methodType() const override;
|
||||
|
||||
private:
|
||||
ServerContext m_context;
|
||||
RequestReaderT m_reader;
|
||||
MethodImplT m_methodImpl;
|
||||
MethodRequestT m_methodRequest;
|
||||
std::unique_ptr<StateHandlerT> m_stateHandler;
|
||||
};
|
||||
|
||||
#include "RiaGrpcCallbacks.inl"
|
||||
380
GrpcInterface/RiaGrpcCallbacks.inl
Normal file
380
GrpcInterface/RiaGrpcCallbacks.inl
Normal file
@@ -0,0 +1,380 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline RiaGrpcCallbackInterface::RiaGrpcCallbackInterface()
|
||||
: m_state( CREATE_HANDLER )
|
||||
, m_status( Status::OK )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaGrpcCallbackInterface::CallState RiaGrpcCallbackInterface::callState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const Status& RiaGrpcCallbackInterface::status() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
inline void RiaGrpcCallbackInterface::setNextCallState( CallState state )
|
||||
{
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
RiaGrpcServiceCallback<ServiceT, RequestT, ReplyT>::RiaGrpcServiceCallback( ServiceT* service )
|
||||
: m_service( service )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
QString RiaGrpcServiceCallback<ServiceT, RequestT, ReplyT>::name() const
|
||||
{
|
||||
QString fullName = QString( "%1:%2(%3, %4)" )
|
||||
.arg( typeid( ServiceT ).name() )
|
||||
.arg( methodType() )
|
||||
.arg( typeid( RequestT ).name() )
|
||||
.arg( typeid( ReplyT ).name() );
|
||||
return fullName;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
const RequestT& RiaGrpcServiceCallback<ServiceT, RequestT, ReplyT>::request() const
|
||||
{
|
||||
return m_request;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
ReplyT& RiaGrpcServiceCallback<ServiceT, RequestT, ReplyT>::reply()
|
||||
{
|
||||
return m_reply;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
RiaGrpcUnaryCallback<ServiceT, RequestT, ReplyT>::RiaGrpcUnaryCallback( ServiceT* service,
|
||||
MethodImplT methodImpl,
|
||||
MethodRequestT methodRequest )
|
||||
: RiaGrpcServiceCallback<ServiceT, RequestT, ReplyT>( service )
|
||||
, m_responder( &m_context )
|
||||
, m_methodImpl( methodImpl )
|
||||
, m_methodRequest( methodRequest )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
RiaGrpcCallbackInterface* RiaGrpcUnaryCallback<ServiceT, RequestT, ReplyT>::createNewFromThis() const
|
||||
{
|
||||
return new RiaGrpcUnaryCallback<ServiceT, RequestT, ReplyT>( this->m_service, this->m_methodImpl, this->m_methodRequest );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
void RiaGrpcUnaryCallback<ServiceT, RequestT, ReplyT>::createRequestHandler( ServerCompletionQueue* completionQueue )
|
||||
{
|
||||
// The Request-method is where the service gets registered to respond to a given request.
|
||||
m_methodRequest( *this->m_service, &m_context, &this->m_request, &m_responder, completionQueue, completionQueue, this );
|
||||
// Simple unary requests don't need initialisation, so proceed to process as soon as a request turns up.
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::PROCESS_REQUEST );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
void RiaGrpcUnaryCallback<ServiceT, RequestT, ReplyT>::onProcessRequest()
|
||||
{
|
||||
// Call request handler method
|
||||
this->m_status = m_methodImpl( *this->m_service, &m_context, &this->m_request, &this->m_reply );
|
||||
// Simply unary requests are finished as soon as you've done any processing.
|
||||
// So next time we receive a new tag on the command queue we should proceed to finish.
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::FINISH_REQUEST );
|
||||
// Finish will push this callback back on the command queue (now with Finish as the call state).
|
||||
m_responder.Finish( this->m_reply, this->m_status, this );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT>
|
||||
QString RiaGrpcUnaryCallback<ServiceT, RequestT, ReplyT>::methodType() const
|
||||
{
|
||||
return "RegularMethod";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
RiaGrpcServerToClientStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::RiaGrpcServerToClientStreamCallback(
|
||||
ServiceT* service,
|
||||
MethodImplT methodImpl,
|
||||
MethodRequestT methodRequest,
|
||||
StateHandlerT* stateHandler )
|
||||
: RiaGrpcServiceCallback<ServiceT, RequestT, ReplyT>( service )
|
||||
, m_responder( &m_context )
|
||||
, m_methodImpl( methodImpl )
|
||||
, m_methodRequest( methodRequest )
|
||||
, m_stateHandler( stateHandler )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
RiaGrpcCallbackInterface*
|
||||
RiaGrpcServerToClientStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::createNewFromThis() const
|
||||
{
|
||||
return new RiaGrpcServerToClientStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>( this->m_service,
|
||||
m_methodImpl,
|
||||
m_methodRequest,
|
||||
new StateHandlerT );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
void RiaGrpcServerToClientStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::createRequestHandler(
|
||||
ServerCompletionQueue* completionQueue )
|
||||
{
|
||||
// The Request-method is where the service gets registered to respond to a given request.
|
||||
m_methodRequest( *this->m_service, &m_context, &this->m_request, &m_responder, completionQueue, completionQueue, this );
|
||||
// Server->Client Streaming requests require initialisation. However, we receive the complete request immediately.
|
||||
// So can proceed directly to completion of the init request.
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::INIT_REQUEST_COMPLETED );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Perform initialisation tasks at the time of receiving a complete request
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
void RiaGrpcServerToClientStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::onInitRequestCompleted()
|
||||
{
|
||||
// Initialise streaming state handler
|
||||
this->m_status = m_stateHandler->init( &this->m_request );
|
||||
|
||||
if ( !this->m_status.ok() )
|
||||
{
|
||||
// We have an error. Proceed to finish and report the status
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::FINISH_REQUEST );
|
||||
m_responder.Finish( this->m_status, this );
|
||||
return;
|
||||
}
|
||||
|
||||
// Move on to processing and perform the first processing immediately since the client will
|
||||
// not request anything more.
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::PROCESS_REQUEST );
|
||||
this->onProcessRequest();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Process a streaming request and send one package
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
void RiaGrpcServerToClientStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::onProcessRequest()
|
||||
{
|
||||
this->m_reply = ReplyT(); // Make sure it is reset
|
||||
|
||||
// Call request handler method
|
||||
this->m_status = m_methodImpl( *this->m_service, &m_context, &this->m_request, &this->m_reply, m_stateHandler.get() );
|
||||
|
||||
if ( this->m_status.ok() )
|
||||
{
|
||||
// The write call will send data to client AND put this callback back on the command queue
|
||||
// so that this method gets called again to send the next stream package.
|
||||
m_responder.Write( this->m_reply, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::FINISH_REQUEST );
|
||||
// Out of range means we're finished but it isn't an error
|
||||
if ( this->m_status.error_code() == grpc::OUT_OF_RANGE )
|
||||
{
|
||||
this->m_status = Status::OK;
|
||||
}
|
||||
// Finish will put this callback back on the command queue, now with a finish state.
|
||||
m_responder.Finish( this->m_status, this );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
QString RiaGrpcServerToClientStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::methodType() const
|
||||
{
|
||||
return "StreamingMethod";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
RiaGrpcClientToServerStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::RiaGrpcClientToServerStreamCallback(
|
||||
ServiceT* service,
|
||||
MethodImplT methodImpl,
|
||||
MethodRequestT methodRequest,
|
||||
StateHandlerT* stateHandler )
|
||||
: RiaGrpcServiceCallback<ServiceT, RequestT, ReplyT>( service )
|
||||
, m_reader( &m_context )
|
||||
, m_methodImpl( methodImpl )
|
||||
, m_methodRequest( methodRequest )
|
||||
, m_stateHandler( stateHandler )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
RiaGrpcCallbackInterface*
|
||||
RiaGrpcClientToServerStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::createNewFromThis() const
|
||||
{
|
||||
return new RiaGrpcClientToServerStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>( this->m_service,
|
||||
m_methodImpl,
|
||||
m_methodRequest,
|
||||
new StateHandlerT( true ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
void RiaGrpcClientToServerStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::createRequestHandler(
|
||||
ServerCompletionQueue* completionQueue )
|
||||
{
|
||||
// The Request-method is where the service gets registered to respond to a given request.
|
||||
m_methodRequest( *this->m_service, &m_context, &this->m_reader, completionQueue, completionQueue, this );
|
||||
// The client->server streaming requires initialisation and each request package is streamed asynchronously
|
||||
// So we need to start and complete the init request.
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::INIT_REQUEST_STARTED );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
void RiaGrpcClientToServerStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::onInitRequestStarted()
|
||||
{
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::INIT_REQUEST_COMPLETED );
|
||||
// The read call will start reading the request data and push this callback back onto the command queue
|
||||
// when the read call is completed.
|
||||
m_reader.Read( &this->m_request, this );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
void RiaGrpcClientToServerStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::onInitRequestCompleted()
|
||||
{
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::PROCESS_REQUEST );
|
||||
// Fully received the stream package so can now init
|
||||
this->m_status = m_stateHandler->init( &this->m_request );
|
||||
|
||||
if ( !this->m_status.ok() )
|
||||
{
|
||||
// We have an error. Proceed to finish and report the status
|
||||
m_reader.FinishWithError( this->m_status, this );
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::FINISH_REQUEST );
|
||||
return;
|
||||
}
|
||||
|
||||
// Start reading and push this back onto the command queue.
|
||||
m_reader.Read( &this->m_request, this );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
void RiaGrpcClientToServerStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::onProcessRequest()
|
||||
{
|
||||
this->m_reply = ReplyT(); // Make sure it is reset
|
||||
|
||||
// Call request handler method
|
||||
this->m_status = m_methodImpl( *this->m_service, &m_context, &this->m_request, &this->m_reply, m_stateHandler.get() );
|
||||
|
||||
if ( !this->m_status.ok() )
|
||||
{
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::FINISH_REQUEST );
|
||||
m_reader.FinishWithError( this->m_status, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
CAF_ASSERT( m_stateHandler->streamedValueCount() <= m_stateHandler->totalValueCount() );
|
||||
if ( m_stateHandler->streamedValueCount() == m_stateHandler->totalValueCount() )
|
||||
{
|
||||
this->setNextCallState( RiaGrpcCallbackInterface::FINISH_REQUEST );
|
||||
m_reader.Finish( this->m_reply, grpc::Status::OK, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_reader.Read( &this->m_request, this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
void RiaGrpcClientToServerStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::onFinishRequest()
|
||||
{
|
||||
m_stateHandler->finish();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ServiceT, typename RequestT, typename ReplyT, typename StateHandlerT>
|
||||
QString RiaGrpcClientToServerStreamCallback<ServiceT, RequestT, ReplyT, StateHandlerT>::methodType() const
|
||||
{
|
||||
return "ClientStreamingMethod";
|
||||
}
|
||||
778
GrpcInterface/RiaGrpcCaseService.cpp
Normal file
778
GrpcInterface/RiaGrpcCaseService.cpp
Normal file
@@ -0,0 +1,778 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#include "RiaGrpcCaseService.h"
|
||||
|
||||
#include "RiaGrpcCallbacks.h"
|
||||
#include "RiaGrpcHelper.h"
|
||||
#include "RiaSocketTools.h"
|
||||
|
||||
#include "RigActiveCellInfo.h"
|
||||
#include "RigCaseCellResultsData.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseResultAddress.h"
|
||||
#include "RigMainGrid.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
|
||||
#include "Riu3dSelectionManager.h"
|
||||
|
||||
using namespace rips;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaActiveCellInfoStateHandler::RiaActiveCellInfoStateHandler()
|
||||
: m_request( nullptr )
|
||||
, m_eclipseCase( nullptr )
|
||||
, m_activeCellInfo( nullptr )
|
||||
, m_currentCellIdx( 0u )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaActiveCellInfoStateHandler::init( const rips::CellInfoRequest* request )
|
||||
{
|
||||
CAF_ASSERT( request );
|
||||
m_request = request;
|
||||
|
||||
m_porosityModel = RiaDefines::PorosityModelType( m_request->porosity_model() );
|
||||
RimCase* rimCase = RiaGrpcServiceInterface::findCase( m_request->case_request().id() );
|
||||
m_eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
|
||||
|
||||
if ( !m_eclipseCase )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case not found" );
|
||||
}
|
||||
|
||||
if ( !m_eclipseCase->eclipseCaseData() || !m_eclipseCase->eclipseCaseData()->mainGrid() )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case Data not found" );
|
||||
}
|
||||
|
||||
m_activeCellInfo = m_eclipseCase->eclipseCaseData()->activeCellInfo( m_porosityModel );
|
||||
|
||||
if ( !m_activeCellInfo )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Active Cell Info not found" );
|
||||
}
|
||||
|
||||
size_t globalCoarseningBoxCount = 0;
|
||||
|
||||
for ( size_t gridIdx = 0; gridIdx < m_eclipseCase->eclipseCaseData()->gridCount(); gridIdx++ )
|
||||
{
|
||||
m_globalCoarseningBoxIndexStart.push_back( globalCoarseningBoxCount );
|
||||
|
||||
RigGridBase* grid = m_eclipseCase->eclipseCaseData()->grid( gridIdx );
|
||||
|
||||
size_t localCoarseningBoxCount = grid->coarseningBoxCount();
|
||||
globalCoarseningBoxCount += localCoarseningBoxCount;
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaActiveCellInfoStateHandler::assignNextActiveCellInfoData( rips::CellInfo* cellInfo )
|
||||
{
|
||||
const std::vector<RigCell>& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->globalCellArray();
|
||||
|
||||
while ( m_currentCellIdx < reservoirCells.size() )
|
||||
{
|
||||
size_t cellIdxToTry = m_currentCellIdx++;
|
||||
if ( m_activeCellInfo->isActive( cellIdxToTry ) )
|
||||
{
|
||||
assignCellInfoData( cellInfo, reservoirCells, cellIdxToTry );
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaActiveCellInfoStateHandler::assignCellInfoData( rips::CellInfo* cellInfo,
|
||||
const std::vector<RigCell>& reservoirCells,
|
||||
size_t cellIdx )
|
||||
{
|
||||
RigGridBase* grid = reservoirCells[cellIdx].hostGrid();
|
||||
CVF_ASSERT( grid != nullptr );
|
||||
size_t cellIndex = reservoirCells[cellIdx].gridLocalCellIndex();
|
||||
|
||||
size_t i, j, k;
|
||||
grid->ijkFromCellIndex( cellIndex, &i, &j, &k );
|
||||
|
||||
size_t pi, pj, pk;
|
||||
RigGridBase* parentGrid = nullptr;
|
||||
|
||||
if ( grid->isMainGrid() )
|
||||
{
|
||||
pi = i;
|
||||
pj = j;
|
||||
pk = k;
|
||||
parentGrid = grid;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t parentCellIdx = reservoirCells[cellIdx].parentCellIndex();
|
||||
parentGrid = ( static_cast<RigLocalGrid*>( grid ) )->parentGrid();
|
||||
CVF_ASSERT( parentGrid != nullptr );
|
||||
parentGrid->ijkFromCellIndex( parentCellIdx, &pi, &pj, &pk );
|
||||
}
|
||||
|
||||
cellInfo->set_grid_index( (int)grid->gridIndex() );
|
||||
cellInfo->set_parent_grid_index( (int)parentGrid->gridIndex() );
|
||||
|
||||
size_t coarseningIdx = reservoirCells[cellIdx].coarseningBoxIndex();
|
||||
if ( coarseningIdx != cvf::UNDEFINED_SIZE_T )
|
||||
{
|
||||
size_t globalCoarseningIdx = m_globalCoarseningBoxIndexStart[grid->gridIndex()] + coarseningIdx;
|
||||
cellInfo->set_coarsening_box_index( (int)globalCoarseningIdx );
|
||||
}
|
||||
else
|
||||
{
|
||||
cellInfo->set_coarsening_box_index( -1 );
|
||||
}
|
||||
{
|
||||
rips::Vec3i* local_ijk = new rips::Vec3i;
|
||||
local_ijk->set_i( (int)i );
|
||||
local_ijk->set_j( (int)j );
|
||||
local_ijk->set_k( (int)k );
|
||||
cellInfo->set_allocated_local_ijk( local_ijk );
|
||||
}
|
||||
{
|
||||
rips::Vec3i* parent_ijk = new rips::Vec3i;
|
||||
parent_ijk->set_i( (int)pi );
|
||||
parent_ijk->set_j( (int)pj );
|
||||
parent_ijk->set_k( (int)pk );
|
||||
cellInfo->set_allocated_parent_ijk( parent_ijk );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigActiveCellInfo* RiaActiveCellInfoStateHandler::activeCellInfo() const
|
||||
{
|
||||
return m_activeCellInfo;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<RigCell>& RiaActiveCellInfoStateHandler::reservoirCells() const
|
||||
{
|
||||
const std::vector<RigCell>& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->globalCellArray();
|
||||
return reservoirCells;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaActiveCellInfoStateHandler::assignReply( rips::CellInfoArray* reply )
|
||||
{
|
||||
const size_t packageSize = RiaGrpcServiceInterface::numberOfDataUnitsInPackage( sizeof( rips::CellInfo ) );
|
||||
size_t indexInPackage = 0u;
|
||||
reply->mutable_data()->Reserve( (int)packageSize );
|
||||
|
||||
// Stream until you've reached the package size or total cell count. Whatever comes first.
|
||||
// If you've reached the package size you'll come back for another round.
|
||||
for ( ; indexInPackage < packageSize && m_currentCellIdx < m_activeCellInfo->reservoirCellCount(); ++indexInPackage )
|
||||
{
|
||||
rips::CellInfo singleCellInfo;
|
||||
grpc::Status singleCellInfoStatus = assignNextActiveCellInfoData( &singleCellInfo );
|
||||
if ( singleCellInfoStatus.ok() )
|
||||
{
|
||||
rips::CellInfo* allocCellInfo = reply->add_data();
|
||||
*allocCellInfo = singleCellInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( indexInPackage > 0u )
|
||||
{
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaActiveCellInfoStateHandler::assignNextActiveCellCenter( rips::Vec3d* cellCenter )
|
||||
{
|
||||
const std::vector<RigCell>& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->globalCellArray();
|
||||
|
||||
while ( m_currentCellIdx < reservoirCells.size() )
|
||||
{
|
||||
size_t cellIdxToTry = m_currentCellIdx++;
|
||||
if ( m_activeCellInfo->isActive( cellIdxToTry ) )
|
||||
{
|
||||
assignCellCenter( cellCenter, reservoirCells, cellIdxToTry );
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaActiveCellInfoStateHandler::assignCellCenter( rips::Vec3d* cellCenter,
|
||||
const std::vector<RigCell>& reservoirCells,
|
||||
size_t cellIdx )
|
||||
|
||||
{
|
||||
cvf::Vec3d center = reservoirCells[cellIdx].center();
|
||||
|
||||
RiaGrpcHelper::convertVec3dToPositiveDepth( ¢er );
|
||||
|
||||
cellCenter->set_x( center.x() );
|
||||
cellCenter->set_y( center.y() );
|
||||
cellCenter->set_z( center.z() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaActiveCellInfoStateHandler::assignCellCentersReply( rips::CellCenters* reply )
|
||||
{
|
||||
const size_t packageSize = RiaGrpcServiceInterface::numberOfDataUnitsInPackage( sizeof( rips::Vec3d ) );
|
||||
size_t indexInPackage = 0u;
|
||||
reply->mutable_centers()->Reserve( (int)packageSize );
|
||||
for ( ; indexInPackage < packageSize && m_currentCellIdx < m_activeCellInfo->reservoirCellCount(); ++indexInPackage )
|
||||
{
|
||||
rips::Vec3d singleCellCenter;
|
||||
grpc::Status singleCellCenterStatus = assignNextActiveCellCenter( &singleCellCenter );
|
||||
if ( singleCellCenterStatus.ok() )
|
||||
{
|
||||
rips::Vec3d* allocCellCenter = reply->add_centers();
|
||||
*allocCellCenter = singleCellCenter;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( indexInPackage > 0u )
|
||||
{
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Status RiaActiveCellInfoStateHandler::assignNextActiveCellCorners( rips::CellCorners* cellCorners )
|
||||
{
|
||||
const std::vector<RigCell>& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->globalCellArray();
|
||||
|
||||
while ( m_currentCellIdx < reservoirCells.size() )
|
||||
{
|
||||
size_t cellIdxToTry = m_currentCellIdx++;
|
||||
if ( m_activeCellInfo->isActive( cellIdxToTry ) )
|
||||
{
|
||||
assignCellCorners( cellCorners, reservoirCells, cellIdxToTry );
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaActiveCellInfoStateHandler::assignCellCorners( rips::CellCorners* corners,
|
||||
const std::vector<RigCell>& reservoirCells,
|
||||
size_t cellIdx )
|
||||
{
|
||||
cvf::Vec3d cornerVerts[8];
|
||||
RigGridBase* grid = m_eclipseCase->eclipseCaseData()->mainGrid();
|
||||
grid->cellCornerVertices( cellIdx, cornerVerts );
|
||||
for ( cvf::Vec3d& corner : cornerVerts )
|
||||
{
|
||||
RiaGrpcHelper::convertVec3dToPositiveDepth( &corner );
|
||||
}
|
||||
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c0(), cornerVerts[0] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c1(), cornerVerts[1] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c2(), cornerVerts[2] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c3(), cornerVerts[3] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c4(), cornerVerts[4] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c5(), cornerVerts[5] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c6(), cornerVerts[6] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c7(), cornerVerts[7] );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Status RiaActiveCellInfoStateHandler::assignCellCornersReply( rips::CellCornersArray* reply )
|
||||
{
|
||||
const size_t packageSize = RiaGrpcServiceInterface::numberOfDataUnitsInPackage( sizeof( rips::CellCorners ) );
|
||||
size_t indexInPackage = 0u;
|
||||
reply->mutable_cells()->Reserve( (int)packageSize );
|
||||
for ( ; indexInPackage < packageSize && m_currentCellIdx < m_activeCellInfo->reservoirCellCount(); ++indexInPackage )
|
||||
{
|
||||
rips::CellCorners singleCellCorners;
|
||||
grpc::Status singleCellCornersStatus = assignNextActiveCellCorners( &singleCellCorners );
|
||||
if ( singleCellCornersStatus.ok() )
|
||||
{
|
||||
rips::CellCorners* allocCellCorners = reply->add_cells();
|
||||
*allocCellCorners = singleCellCorners;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( indexInPackage > 0u )
|
||||
{
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetGridCount( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::GridCount* reply )
|
||||
{
|
||||
RimCase* rimCase = findCase( request->id() );
|
||||
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
|
||||
if ( eclipseCase )
|
||||
{
|
||||
int gridCount = (int)eclipseCase->mainGrid()->gridCount();
|
||||
reply->set_count( gridCount );
|
||||
return Status::OK;
|
||||
}
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case not found" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetCellCount( grpc::ServerContext* context,
|
||||
const rips::CellInfoRequest* request,
|
||||
rips::CellCount* reply )
|
||||
{
|
||||
RimCase* rimCase = findCase( request->case_request().id() );
|
||||
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
|
||||
if ( eclipseCase )
|
||||
{
|
||||
auto porosityModel = RiaDefines::PorosityModelType( request->porosity_model() );
|
||||
RigActiveCellInfo* activeCellInfo = eclipseCase->eclipseCaseData()->activeCellInfo( porosityModel );
|
||||
reply->set_active_cell_count( (int)activeCellInfo->reservoirActiveCellCount() );
|
||||
reply->set_reservoir_cell_count( (int)activeCellInfo->reservoirCellCount() );
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case not found" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetTimeSteps( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::TimeStepDates* reply )
|
||||
{
|
||||
RimCase* rimCase = findCase( request->id() );
|
||||
|
||||
if ( rimCase )
|
||||
{
|
||||
std::vector<QDateTime> timeStepDates = rimCase->timeStepDates();
|
||||
for ( QDateTime dateTime : timeStepDates )
|
||||
{
|
||||
rips::TimeStepDate* date = reply->add_dates();
|
||||
date->set_year( dateTime.date().year() );
|
||||
date->set_month( dateTime.date().month() );
|
||||
date->set_day( dateTime.date().day() );
|
||||
date->set_hour( dateTime.time().hour() );
|
||||
date->set_minute( dateTime.time().minute() );
|
||||
date->set_second( dateTime.time().second() );
|
||||
}
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
return grpc::Status( grpc::NOT_FOUND, "Case not found" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetDaysSinceStart( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::DaysSinceStart* reply )
|
||||
{
|
||||
RimCase* rimCase = findCase( request->id() );
|
||||
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
|
||||
if ( eclipseCase )
|
||||
{
|
||||
RigEclipseResultAddress addrToMaxTimeStepCountResult;
|
||||
if ( eclipseCase && eclipseCase->eclipseCaseData() )
|
||||
{
|
||||
eclipseCase->eclipseCaseData()
|
||||
->results( RiaDefines::PorosityModelType::MATRIX_MODEL )
|
||||
->maxTimeStepCount( &addrToMaxTimeStepCountResult );
|
||||
if ( !addrToMaxTimeStepCountResult.isValid() )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Invalid result. No time steps found." );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<double> daysSinceSimulationStart = eclipseCase->eclipseCaseData()
|
||||
->results( RiaDefines::PorosityModelType::MATRIX_MODEL )
|
||||
->daysSinceSimulationStart( addrToMaxTimeStepCountResult );
|
||||
|
||||
for ( auto days : daysSinceSimulationStart )
|
||||
{
|
||||
reply->add_day_decimals( days );
|
||||
}
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case not found" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status
|
||||
RiaGrpcCaseService::GetCaseInfo( grpc::ServerContext* context, const rips::CaseRequest* request, rips::CaseInfo* reply )
|
||||
{
|
||||
RimCase* rimCase = findCase( request->id() );
|
||||
if ( rimCase )
|
||||
{
|
||||
qint64 caseId = rimCase->caseId();
|
||||
qint64 caseGroupId = -1;
|
||||
QString caseName, caseType;
|
||||
RiaSocketTools::getCaseInfoFromCase( rimCase, caseId, caseName, caseType, caseGroupId );
|
||||
|
||||
reply->set_id( caseId );
|
||||
reply->set_group_id( caseGroupId );
|
||||
reply->set_name( caseName.toStdString() );
|
||||
reply->set_type( caseType.toStdString() );
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::NOT_FOUND, "Case not found" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetPdmObject( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::PdmObject* reply )
|
||||
{
|
||||
RimCase* rimCase = findCase( request->id() );
|
||||
if ( rimCase )
|
||||
{
|
||||
copyPdmObjectFromCafToRips( rimCase, reply );
|
||||
}
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetCellInfoForActiveCells( grpc::ServerContext* context,
|
||||
const rips::CellInfoRequest* request,
|
||||
rips::CellInfoArray* reply,
|
||||
RiaActiveCellInfoStateHandler* stateHandler )
|
||||
{
|
||||
return stateHandler->assignReply( reply );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetCellCenterForActiveCells( grpc::ServerContext* context,
|
||||
const rips::CellInfoRequest* request,
|
||||
rips::CellCenters* reply,
|
||||
RiaActiveCellInfoStateHandler* stateHandler )
|
||||
{
|
||||
return stateHandler->assignCellCentersReply( reply );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetCellCornersForActiveCells( grpc::ServerContext* context,
|
||||
const rips::CellInfoRequest* request,
|
||||
rips::CellCornersArray* reply,
|
||||
RiaActiveCellInfoStateHandler* stateHandler )
|
||||
{
|
||||
return stateHandler->assignCellCornersReply( reply );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaSelectedCellsStateHandler::RiaSelectedCellsStateHandler()
|
||||
: m_request( nullptr )
|
||||
, m_eclipseCase( nullptr )
|
||||
, m_currentItem( 0u )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Status RiaSelectedCellsStateHandler::init( const rips::CaseRequest* request )
|
||||
{
|
||||
CAF_ASSERT( request );
|
||||
m_request = request;
|
||||
|
||||
RimCase* rimCase = RiaGrpcServiceInterface::findCase( m_request->id() );
|
||||
m_eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
|
||||
|
||||
if ( !m_eclipseCase )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case not found" );
|
||||
}
|
||||
|
||||
if ( !m_eclipseCase->eclipseCaseData() || !m_eclipseCase->eclipseCaseData()->mainGrid() )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case Data not found" );
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Status RiaSelectedCellsStateHandler::assignNextSelectedCell( rips::SelectedCell* cell,
|
||||
const std::vector<RiuEclipseSelectionItem*>& items )
|
||||
{
|
||||
while ( m_currentItem < items.size() )
|
||||
{
|
||||
size_t itemToTry = m_currentItem++;
|
||||
|
||||
const RiuEclipseSelectionItem* item = items[itemToTry];
|
||||
CVF_ASSERT( item->type() == RiuSelectionItem::ECLIPSE_SELECTION_OBJECT );
|
||||
assignSelectedCell( cell, item );
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaSelectedCellsStateHandler::assignSelectedCell( rips::SelectedCell* cell, const RiuEclipseSelectionItem* item )
|
||||
{
|
||||
CVF_ASSERT( item->type() == RiuSelectionItem::ECLIPSE_SELECTION_OBJECT );
|
||||
size_t i = -1;
|
||||
size_t j = -1;
|
||||
size_t k = -1;
|
||||
item->m_resultDefinition->eclipseCase()
|
||||
->eclipseCaseData()
|
||||
->grid( item->m_gridIndex )
|
||||
->ijkFromCellIndex( item->m_gridLocalCellIndex, &i, &j, &k );
|
||||
|
||||
cell->set_grid_index( item->m_gridIndex );
|
||||
rips::Vec3i* ijk = new rips::Vec3i;
|
||||
ijk->set_i( (int)i );
|
||||
ijk->set_j( (int)j );
|
||||
ijk->set_k( (int)k );
|
||||
cell->set_allocated_ijk( ijk );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaSelectedCellsStateHandler::assignReply( rips::SelectedCells* reply )
|
||||
{
|
||||
std::vector<RiuSelectionItem*> items;
|
||||
Riu3dSelectionManager::instance()->selectedItems( items );
|
||||
|
||||
// Only eclipse cases are currently supported. Also filter by case.
|
||||
std::vector<RiuEclipseSelectionItem*> eclipseItems;
|
||||
for ( auto item : items )
|
||||
{
|
||||
RiuEclipseSelectionItem* eclipseItem = dynamic_cast<RiuEclipseSelectionItem*>( item );
|
||||
if ( eclipseItem && eclipseItem->m_resultDefinition->eclipseCase()->caseId == m_request->id() )
|
||||
{
|
||||
eclipseItems.push_back( eclipseItem );
|
||||
}
|
||||
}
|
||||
|
||||
const size_t packageSize = RiaGrpcServiceInterface::numberOfDataUnitsInPackage( sizeof( rips::SelectedCell ) );
|
||||
size_t indexInPackage = 0u;
|
||||
reply->mutable_cells()->Reserve( (int)packageSize );
|
||||
for ( ; indexInPackage < packageSize && m_currentItem < eclipseItems.size(); ++indexInPackage )
|
||||
{
|
||||
rips::SelectedCell singleSelectedCell;
|
||||
grpc::Status singleSelectedCellStatus = assignNextSelectedCell( &singleSelectedCell, eclipseItems );
|
||||
if ( singleSelectedCellStatus.ok() )
|
||||
{
|
||||
rips::SelectedCell* allocSelectedCell = reply->add_cells();
|
||||
*allocSelectedCell = singleSelectedCell;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( indexInPackage > 0u )
|
||||
{
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetSelectedCells( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::SelectedCells* reply,
|
||||
RiaSelectedCellsStateHandler* stateHandler )
|
||||
{
|
||||
return stateHandler->assignReply( reply );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetReservoirBoundingBox( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::BoundingBox* reply )
|
||||
{
|
||||
RimCase* rimCase = findCase( request->id() );
|
||||
if ( rimCase )
|
||||
{
|
||||
cvf::BoundingBox boundingBox = rimCase->reservoirBoundingBox();
|
||||
reply->set_min_x( boundingBox.min().x() );
|
||||
reply->set_min_y( boundingBox.min().y() );
|
||||
reply->set_min_z( boundingBox.min().z() );
|
||||
reply->set_max_x( boundingBox.max().x() );
|
||||
reply->set_max_y( boundingBox.max().y() );
|
||||
reply->set_max_z( boundingBox.max().z() );
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::NOT_FOUND, "Case not found" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCaseService::GetCoarseningInfoArray( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::CoarseningInfoArray* reply )
|
||||
{
|
||||
RimEclipseCase* rimCase = dynamic_cast<RimEclipseCase*>( findCase( request->id() ) );
|
||||
if ( rimCase && rimCase->eclipseCaseData() && rimCase->eclipseCaseData()->mainGrid() )
|
||||
{
|
||||
for ( size_t gridIdx = 0; gridIdx < rimCase->eclipseCaseData()->gridCount(); gridIdx++ )
|
||||
{
|
||||
RigGridBase* grid = rimCase->eclipseCaseData()->grid( gridIdx );
|
||||
|
||||
size_t localCoarseningBoxCount = grid->coarseningBoxCount();
|
||||
for ( size_t boxIdx = 0; boxIdx < localCoarseningBoxCount; boxIdx++ )
|
||||
{
|
||||
size_t i1, i2, j1, j2, k1, k2;
|
||||
grid->coarseningBox( boxIdx, &i1, &i2, &j1, &j2, &k1, &k2 );
|
||||
|
||||
rips::CoarseningInfo* coarseningInfo = reply->add_data();
|
||||
|
||||
rips::Vec3i* min = new rips::Vec3i;
|
||||
min->set_i( (int)i1 );
|
||||
min->set_j( (int)j1 );
|
||||
min->set_k( (int)k1 );
|
||||
coarseningInfo->set_allocated_min( min );
|
||||
|
||||
rips::Vec3i* max = new rips::Vec3i;
|
||||
max->set_i( (int)i2 );
|
||||
max->set_j( (int)j2 );
|
||||
max->set_k( (int)k2 );
|
||||
coarseningInfo->set_allocated_max( max );
|
||||
}
|
||||
}
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::NOT_FOUND, "Case not found" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaGrpcCallbackInterface*> RiaGrpcCaseService::createCallbacks()
|
||||
{
|
||||
typedef RiaGrpcCaseService Self;
|
||||
|
||||
return { new RiaGrpcUnaryCallback<Self, CaseRequest, GridCount>( this, &Self::GetGridCount, &Self::RequestGetGridCount ),
|
||||
new RiaGrpcUnaryCallback<Self, CellInfoRequest, CellCount>( this, &Self::GetCellCount, &Self::RequestGetCellCount ),
|
||||
new RiaGrpcUnaryCallback<Self, CaseRequest, TimeStepDates>( this, &Self::GetTimeSteps, &Self::RequestGetTimeSteps ),
|
||||
new RiaGrpcUnaryCallback<Self, CaseRequest, DaysSinceStart>( this,
|
||||
&Self::GetDaysSinceStart,
|
||||
&Self::RequestGetDaysSinceStart ),
|
||||
new RiaGrpcUnaryCallback<Self, CaseRequest, CaseInfo>( this, &Self::GetCaseInfo, &Self::RequestGetCaseInfo ),
|
||||
new RiaGrpcUnaryCallback<Self, CaseRequest, PdmObject>( this, &Self::GetPdmObject, &Self::RequestGetPdmObject ),
|
||||
new RiaGrpcServerToClientStreamCallback<Self,
|
||||
CellInfoRequest,
|
||||
CellInfoArray,
|
||||
RiaActiveCellInfoStateHandler>( this,
|
||||
&Self::GetCellInfoForActiveCells,
|
||||
&Self::RequestGetCellInfoForActiveCells,
|
||||
new RiaActiveCellInfoStateHandler ),
|
||||
new RiaGrpcServerToClientStreamCallback<Self,
|
||||
CellInfoRequest,
|
||||
CellCenters,
|
||||
RiaActiveCellInfoStateHandler>( this,
|
||||
&Self::GetCellCenterForActiveCells,
|
||||
&Self::RequestGetCellCenterForActiveCells,
|
||||
new RiaActiveCellInfoStateHandler ),
|
||||
new RiaGrpcServerToClientStreamCallback<Self,
|
||||
CellInfoRequest,
|
||||
CellCornersArray,
|
||||
RiaActiveCellInfoStateHandler>( this,
|
||||
&Self::GetCellCornersForActiveCells,
|
||||
&Self::RequestGetCellCornersForActiveCells,
|
||||
new RiaActiveCellInfoStateHandler ),
|
||||
new RiaGrpcServerToClientStreamCallback<Self,
|
||||
CaseRequest,
|
||||
SelectedCells,
|
||||
RiaSelectedCellsStateHandler>( this,
|
||||
&Self::GetSelectedCells,
|
||||
&Self::RequestGetSelectedCells,
|
||||
new RiaSelectedCellsStateHandler ),
|
||||
new RiaGrpcUnaryCallback<Self, CaseRequest, BoundingBox>( this,
|
||||
&Self::GetReservoirBoundingBox,
|
||||
&Self::RequestGetReservoirBoundingBox ),
|
||||
|
||||
new RiaGrpcUnaryCallback<Self, CaseRequest, CoarseningInfoArray>( this,
|
||||
&Self::GetCoarseningInfoArray,
|
||||
&Self::RequestGetCoarseningInfoArray ) };
|
||||
}
|
||||
|
||||
static bool RiaGrpcCaseService_init =
|
||||
RiaGrpcServiceFactory::instance()->registerCreator<RiaGrpcCaseService>( typeid( RiaGrpcCaseService ).hash_code() );
|
||||
149
GrpcInterface/RiaGrpcCaseService.h
Normal file
149
GrpcInterface/RiaGrpcCaseService.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "Case.grpc.pb.h"
|
||||
|
||||
#include "RiaGrpcServiceInterface.h"
|
||||
#include "RiaPorosityModel.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace rips
|
||||
{
|
||||
class CaseRequest;
|
||||
class PdmObject;
|
||||
} // namespace rips
|
||||
|
||||
class RiaGrpcCallbackInterface;
|
||||
class RigCell;
|
||||
class RigActiveCellInfo;
|
||||
class RimEclipseCase;
|
||||
class RiuEclipseSelectionItem;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// State handler for streaming of active cell info
|
||||
//
|
||||
//==================================================================================================
|
||||
class RiaActiveCellInfoStateHandler
|
||||
{
|
||||
typedef grpc::Status Status;
|
||||
|
||||
public:
|
||||
RiaActiveCellInfoStateHandler();
|
||||
|
||||
Status init( const rips::CellInfoRequest* request );
|
||||
|
||||
RigActiveCellInfo* activeCellInfo() const;
|
||||
const std::vector<RigCell>& reservoirCells() const;
|
||||
|
||||
// For cell info:
|
||||
Status assignNextActiveCellInfoData( rips::CellInfo* cellInfo );
|
||||
void assignCellInfoData( rips::CellInfo* cellInfo, const std::vector<RigCell>& reservoirCells, size_t cellIdx );
|
||||
Status assignReply( rips::CellInfoArray* reply );
|
||||
|
||||
// For cell centers:
|
||||
Status assignNextActiveCellCenter( rips::Vec3d* cellCenter );
|
||||
void assignCellCenter( rips::Vec3d* cellCenter, const std::vector<RigCell>& reservoirCells, size_t cellIdx );
|
||||
Status assignCellCentersReply( rips::CellCenters* reply );
|
||||
|
||||
// For cell corners:
|
||||
Status assignNextActiveCellCorners( rips::CellCorners* cellCorners );
|
||||
void assignCellCorners( rips::CellCorners* cellCorners, const std::vector<RigCell>& reservoirCells, size_t cellIdx );
|
||||
Status assignCellCornersReply( rips::CellCornersArray* reply );
|
||||
|
||||
protected:
|
||||
const rips::CellInfoRequest* m_request;
|
||||
RimEclipseCase* m_eclipseCase;
|
||||
RiaDefines::PorosityModelType m_porosityModel;
|
||||
RigActiveCellInfo* m_activeCellInfo;
|
||||
std::vector<size_t> m_globalCoarseningBoxIndexStart;
|
||||
size_t m_currentCellIdx;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// State handler for streaming of selected cells
|
||||
//
|
||||
//==================================================================================================
|
||||
class RiaSelectedCellsStateHandler
|
||||
{
|
||||
typedef grpc::Status Status;
|
||||
|
||||
public:
|
||||
RiaSelectedCellsStateHandler();
|
||||
|
||||
Status init( const rips::CaseRequest* request );
|
||||
Status assignReply( rips::SelectedCells* reply );
|
||||
void assignSelectedCell( rips::SelectedCell* cell, const RiuEclipseSelectionItem* item );
|
||||
Status assignNextSelectedCell( rips::SelectedCell* cell, const std::vector<RiuEclipseSelectionItem*>& items );
|
||||
|
||||
protected:
|
||||
const rips::CaseRequest* m_request;
|
||||
RimEclipseCase* m_eclipseCase;
|
||||
size_t m_currentItem;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// gRPC-service answering requests about grid information for a given case
|
||||
//
|
||||
//==================================================================================================
|
||||
class RiaGrpcCaseService final : public rips::Case::AsyncService, public RiaGrpcServiceInterface
|
||||
{
|
||||
public:
|
||||
grpc::Status
|
||||
GetGridCount( grpc::ServerContext* context, const rips::CaseRequest* request, rips::GridCount* reply ) override;
|
||||
grpc::Status GetCellCount( grpc::ServerContext* context,
|
||||
const rips::CellInfoRequest* request,
|
||||
rips::CellCount* reply ) override;
|
||||
grpc::Status GetTimeSteps( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::TimeStepDates* reply ) override;
|
||||
grpc::Status GetDaysSinceStart( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::DaysSinceStart* reply ) override;
|
||||
grpc::Status GetCaseInfo( grpc::ServerContext* context, const rips::CaseRequest* request, rips::CaseInfo* reply ) override;
|
||||
grpc::Status
|
||||
GetPdmObject( grpc::ServerContext* context, const rips::CaseRequest* request, rips::PdmObject* reply ) override;
|
||||
grpc::Status GetCellInfoForActiveCells( grpc::ServerContext* context,
|
||||
const rips::CellInfoRequest* request,
|
||||
rips::CellInfoArray* reply,
|
||||
RiaActiveCellInfoStateHandler* stateHandler );
|
||||
grpc::Status GetCellCenterForActiveCells( grpc::ServerContext* context,
|
||||
const rips::CellInfoRequest* request,
|
||||
rips::CellCenters* reply,
|
||||
RiaActiveCellInfoStateHandler* stateHandler );
|
||||
grpc::Status GetCellCornersForActiveCells( grpc::ServerContext* context,
|
||||
const rips::CellInfoRequest* request,
|
||||
rips::CellCornersArray* reply,
|
||||
RiaActiveCellInfoStateHandler* stateHandler );
|
||||
grpc::Status GetSelectedCells( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::SelectedCells* reply,
|
||||
RiaSelectedCellsStateHandler* stateHandler );
|
||||
grpc::Status GetReservoirBoundingBox( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::BoundingBox* reply ) override;
|
||||
grpc::Status GetCoarseningInfoArray( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::CoarseningInfoArray* reply ) override;
|
||||
|
||||
std::vector<RiaGrpcCallbackInterface*> createCallbacks() override;
|
||||
};
|
||||
411
GrpcInterface/RiaGrpcCommandService.cpp
Normal file
411
GrpcInterface/RiaGrpcCommandService.cpp
Normal file
@@ -0,0 +1,411 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#include "RiaGrpcCommandService.h"
|
||||
|
||||
#include "RiaGrpcCallbacks.h"
|
||||
|
||||
#include "RicfReplaceCase.h"
|
||||
#include "RicfSetTimeStep.h"
|
||||
|
||||
#include "cafAssert.h"
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cafPdmDataValueField.h"
|
||||
#include "cafPdmDefaultObjectFactory.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmValueField.h"
|
||||
#include <google/protobuf/reflection.h>
|
||||
|
||||
using namespace rips;
|
||||
using namespace google::protobuf;
|
||||
|
||||
// Windows may define GetMessage as a Macro and this is in direct conflict with the gRPC GetMessage calls.
|
||||
#ifdef WIN32
|
||||
#ifdef GetMessage
|
||||
#undef GetMessage
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcCommandService::Execute( grpc::ServerContext* context, const CommandParams* request, CommandReply* reply )
|
||||
{
|
||||
auto requestDescriptor = request->GetDescriptor();
|
||||
|
||||
CommandParams::ParamsCase paramsCase = request->params_case();
|
||||
if ( paramsCase != CommandParams::PARAMS_NOT_SET )
|
||||
{
|
||||
auto grpcOneOfMessage = requestDescriptor->FindFieldByNumber( (int)paramsCase );
|
||||
CAF_ASSERT( grpcOneOfMessage->type() == FieldDescriptor::TYPE_MESSAGE );
|
||||
|
||||
QString grpcOneOfMessageName = QString::fromStdString( grpcOneOfMessage->name() );
|
||||
auto pdmObjectHandle = caf::PdmDefaultObjectFactory::instance()->create( grpcOneOfMessageName );
|
||||
auto commandHandle = dynamic_cast<RicfCommandObject*>( pdmObjectHandle );
|
||||
|
||||
if ( commandHandle )
|
||||
{
|
||||
// Copy parameters
|
||||
RicfMultiCaseReplace* multiCaseReplaceCommand = dynamic_cast<RicfMultiCaseReplace*>( commandHandle );
|
||||
if ( multiCaseReplaceCommand )
|
||||
{
|
||||
CAF_ASSERT( request->has_replacemultiplecases() );
|
||||
auto replaceMultipleCasesRequest = request->replacemultiplecases();
|
||||
std::map<int, QString> caseIdFileMap;
|
||||
for ( auto caseGridFilePair : replaceMultipleCasesRequest.casepairs() )
|
||||
{
|
||||
caseIdFileMap.insert( std::make_pair( caseGridFilePair.caseid(),
|
||||
QString::fromStdString( caseGridFilePair.newgridfile() ) ) );
|
||||
}
|
||||
multiCaseReplaceCommand->setCaseReplacePairs( caseIdFileMap );
|
||||
}
|
||||
else
|
||||
{
|
||||
assignPdmObjectValues( commandHandle, *request, grpcOneOfMessage );
|
||||
}
|
||||
|
||||
// Execute command
|
||||
caf::PdmScriptResponse response = commandHandle->execute();
|
||||
|
||||
// Copy results
|
||||
if ( response.status() == caf::PdmScriptResponse::COMMAND_ERROR )
|
||||
{
|
||||
return grpc::Status( grpc::FAILED_PRECONDITION, response.sanitizedResponseMessage().toStdString() );
|
||||
}
|
||||
else if ( response.status() == caf::PdmScriptResponse::COMMAND_WARNING )
|
||||
{
|
||||
context->AddTrailingMetadata( "warning", response.sanitizedResponseMessage().toStdString() );
|
||||
}
|
||||
|
||||
assignResultToReply( response.result(), reply );
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
}
|
||||
return grpc::Status( grpc::NOT_FOUND, "Command not found" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaGrpcCallbackInterface*> RiaGrpcCommandService::createCallbacks()
|
||||
{
|
||||
typedef RiaGrpcCommandService Self;
|
||||
|
||||
return { new RiaGrpcUnaryCallback<Self, CommandParams, CommandReply>( this, &Self::Execute, &Self::RequestExecute ) };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
caf::PdmField<T>* RiaGrpcCommandService::dataValueField( caf::PdmValueField* valueField )
|
||||
{
|
||||
caf::PdmField<T>* dataValField = dynamic_cast<caf::PdmField<T>*>( valueField );
|
||||
CAF_ASSERT( dataValField );
|
||||
return dataValField;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
const caf::PdmField<T>* RiaGrpcCommandService::constDataValueField( const caf::PdmValueField* valueField )
|
||||
{
|
||||
const caf::PdmField<T>* dataValField = dynamic_cast<const caf::PdmField<T>*>( valueField );
|
||||
CAF_ASSERT( dataValField );
|
||||
return dataValField;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaGrpcCommandService::assignPdmFieldValue( caf::PdmValueField* pdmValueField,
|
||||
const Message& params,
|
||||
const FieldDescriptor* paramDescriptor )
|
||||
{
|
||||
FieldDescriptor::Type fieldDataType = paramDescriptor->type();
|
||||
const Reflection* reflection = params.GetReflection();
|
||||
|
||||
if ( paramDescriptor->is_repeated() && fieldDataType != FieldDescriptor::TYPE_INT32 &&
|
||||
fieldDataType != FieldDescriptor::TYPE_STRING )
|
||||
{
|
||||
CAF_ASSERT( false && "Only integer and string vectors are implemented as command arguments" );
|
||||
}
|
||||
|
||||
switch ( fieldDataType )
|
||||
{
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
{
|
||||
auto value = reflection->GetBool( params, paramDescriptor );
|
||||
auto dataField = dataValueField<bool>( pdmValueField );
|
||||
dataField->setValue( value );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
{
|
||||
if ( paramDescriptor->is_repeated() )
|
||||
{
|
||||
RepeatedFieldRef<int> repeatedField = reflection->GetRepeatedFieldRef<int>( params, paramDescriptor );
|
||||
auto dataField = dataValueField<std::vector<int>>( pdmValueField );
|
||||
dataField->setValue( std::vector<int>( repeatedField.begin(), repeatedField.end() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
int value = reflection->GetInt32( params, paramDescriptor );
|
||||
auto dataField = dataValueField<int>( pdmValueField );
|
||||
dataField->setValue( value );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
{
|
||||
uint value = reflection->GetUInt32( params, paramDescriptor );
|
||||
auto dataField = dataValueField<uint>( pdmValueField );
|
||||
dataField->setValue( value );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
{
|
||||
if ( paramDescriptor->is_repeated() )
|
||||
{
|
||||
RepeatedFieldRef<std::string> repeatedField =
|
||||
reflection->GetRepeatedFieldRef<std::string>( params, paramDescriptor );
|
||||
std::vector<QString> stringVector;
|
||||
for ( const std::string& string : repeatedField )
|
||||
{
|
||||
stringVector.push_back( QString::fromStdString( string ) );
|
||||
}
|
||||
auto dataField = dataValueField<std::vector<QString>>( pdmValueField );
|
||||
dataField->setValue( stringVector );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto value = QString::fromStdString( reflection->GetString( params, paramDescriptor ) );
|
||||
auto dataField = dataValueField<QString>( pdmValueField );
|
||||
dataField->setValue( value );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
{
|
||||
auto value = reflection->GetFloat( params, paramDescriptor );
|
||||
auto dataField = dataValueField<float>( pdmValueField );
|
||||
dataField->setValue( value );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
{
|
||||
auto value = reflection->GetDouble( params, paramDescriptor );
|
||||
auto dataField = dataValueField<double>( pdmValueField );
|
||||
dataField->setValue( value );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
{
|
||||
auto value = reflection->GetEnumValue( params, paramDescriptor );
|
||||
pdmValueField->setFromQVariant( QVariant( value ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaGrpcCommandService::assignPdmObjectValues( caf::PdmObjectHandle* pdmObjectHandle,
|
||||
const google::protobuf::Message& params,
|
||||
const google::protobuf::FieldDescriptor* paramDescriptor )
|
||||
{
|
||||
FieldDescriptor::Type fieldDataType = paramDescriptor->type();
|
||||
const Reflection* reflection = params.GetReflection();
|
||||
|
||||
CAF_ASSERT( fieldDataType == FieldDescriptor::TYPE_MESSAGE );
|
||||
|
||||
const Message& subMessage = reflection->GetMessage( params, paramDescriptor );
|
||||
|
||||
const rips::PdmObject* ripsPdmObject = dynamic_cast<const rips::PdmObject*>( &subMessage );
|
||||
if ( ripsPdmObject )
|
||||
{
|
||||
copyPdmObjectFromRipsToCaf( ripsPdmObject, pdmObjectHandle );
|
||||
return;
|
||||
}
|
||||
|
||||
auto messageDescriptor = paramDescriptor->message_type();
|
||||
int numParameters = messageDescriptor->field_count();
|
||||
for ( int i = 0; i < numParameters; ++i )
|
||||
{
|
||||
auto parameter = messageDescriptor->field( i );
|
||||
if ( parameter )
|
||||
{
|
||||
QString parameterName = QString::fromStdString( parameter->name() );
|
||||
auto pdmChildFieldHandle =
|
||||
dynamic_cast<caf::PdmChildFieldHandle*>( pdmObjectHandle->findField( parameterName ) );
|
||||
auto pdmValueFieldHandle = dynamic_cast<caf::PdmValueField*>( pdmObjectHandle->findField( parameterName ) );
|
||||
if ( pdmChildFieldHandle )
|
||||
{
|
||||
std::vector<caf::PdmObjectHandle*> childObjects;
|
||||
pdmChildFieldHandle->childObjects( &childObjects );
|
||||
caf::PdmObjectHandle* childObject = nullptr;
|
||||
CAF_ASSERT( childObjects.size() <= 1u ); // We do not support child array fields yet
|
||||
|
||||
if ( childObjects.size() == 1u )
|
||||
{
|
||||
childObject = childObjects.front();
|
||||
}
|
||||
else if ( childObjects.empty() )
|
||||
{
|
||||
childObject = emplaceChildField( pdmChildFieldHandle );
|
||||
}
|
||||
CAF_ASSERT( childObject );
|
||||
if ( childObject )
|
||||
{
|
||||
assignPdmObjectValues( childObject, subMessage, parameter );
|
||||
}
|
||||
}
|
||||
else if ( pdmValueFieldHandle )
|
||||
{
|
||||
assignPdmFieldValue( pdmValueFieldHandle, subMessage, parameter );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaGrpcCommandService::assignGrpcFieldValue( Message* reply,
|
||||
const FieldDescriptor* fieldDescriptor,
|
||||
const caf::PdmValueField* pdmValueField )
|
||||
{
|
||||
if ( fieldDescriptor->is_repeated() )
|
||||
{
|
||||
auto reflection = reply->GetReflection();
|
||||
QVariant qValue = pdmValueField->toQVariant();
|
||||
if ( fieldDescriptor->type() == FieldDescriptor::TYPE_STRING )
|
||||
{
|
||||
MutableRepeatedFieldRef<std::string> repeatedField =
|
||||
reflection->GetMutableRepeatedFieldRef<std::string>( reply, fieldDescriptor );
|
||||
QStringList stringList = qValue.toStringList();
|
||||
for ( QString stringValue : stringList )
|
||||
{
|
||||
repeatedField.Add( stringValue.toStdString() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CAF_ASSERT( false && "Assigning vector results to Command Results is only implemented for strings" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
FieldDescriptor::Type fieldDataType = fieldDescriptor->type();
|
||||
QVariant qValue = pdmValueField->toQVariant();
|
||||
|
||||
auto reflection = reply->GetReflection();
|
||||
switch ( fieldDataType )
|
||||
{
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
{
|
||||
reflection->SetBool( reply, fieldDescriptor, qValue.toBool() );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
{
|
||||
reflection->SetInt32( reply, fieldDescriptor, qValue.toInt() );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
{
|
||||
reflection->SetUInt32( reply, fieldDescriptor, qValue.toUInt() );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
{
|
||||
reflection->SetInt64( reply, fieldDescriptor, qValue.toLongLong() );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
{
|
||||
reflection->SetUInt64( reply, fieldDescriptor, qValue.toULongLong() );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
{
|
||||
reflection->SetString( reply, fieldDescriptor, qValue.toString().toStdString() );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
{
|
||||
reflection->SetFloat( reply, fieldDescriptor, qValue.toFloat() );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
{
|
||||
reflection->SetDouble( reply, fieldDescriptor, qValue.toDouble() );
|
||||
break;
|
||||
}
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
{
|
||||
reflection->SetEnumValue( reply, fieldDescriptor, qValue.toInt() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaGrpcCommandService::assignResultToReply( const caf::PdmObject* result, CommandReply* reply )
|
||||
{
|
||||
if ( !result )
|
||||
{
|
||||
reply->set_allocated_emptyresult( new Empty );
|
||||
return;
|
||||
}
|
||||
|
||||
QString resultType = result->classKeyword();
|
||||
|
||||
auto replyDescriptor = reply->GetDescriptor();
|
||||
auto oneofDescriptor = replyDescriptor->FindOneofByName( "result" );
|
||||
const FieldDescriptor* matchingOneOf = nullptr;
|
||||
for ( int fieldIndex = 0; fieldIndex < oneofDescriptor->field_count(); ++fieldIndex )
|
||||
{
|
||||
auto fieldDescriptor = oneofDescriptor->field( fieldIndex );
|
||||
if ( fieldDescriptor->name() == resultType.toStdString() )
|
||||
{
|
||||
matchingOneOf = fieldDescriptor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CAF_ASSERT( matchingOneOf );
|
||||
Message* message = reply->GetReflection()->MutableMessage( reply, matchingOneOf );
|
||||
CAF_ASSERT( message );
|
||||
auto resultDescriptor = message->GetDescriptor();
|
||||
|
||||
for ( int fieldIndex = 0; fieldIndex < resultDescriptor->field_count(); ++fieldIndex )
|
||||
{
|
||||
auto fieldDescriptor = resultDescriptor->field( fieldIndex );
|
||||
const auto pdmField = dynamic_cast<const caf::PdmValueField*>(
|
||||
result->findField( QString::fromStdString( fieldDescriptor->name() ) ) );
|
||||
assignGrpcFieldValue( message, fieldDescriptor, pdmField );
|
||||
}
|
||||
}
|
||||
|
||||
static bool RiaGrpcCommandService_init = RiaGrpcServiceFactory::instance()->registerCreator<RiaGrpcCommandService>(
|
||||
typeid( RiaGrpcCommandService ).hash_code() );
|
||||
71
GrpcInterface/RiaGrpcCommandService.h
Normal file
71
GrpcInterface/RiaGrpcCommandService.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "RiaGrpcServiceInterface.h"
|
||||
|
||||
#include "Commands.grpc.pb.h"
|
||||
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <vector>
|
||||
|
||||
namespace caf
|
||||
{
|
||||
class PdmChildFieldHandle;
|
||||
class PdmValueField;
|
||||
class PdmObject;
|
||||
class PdmObjectHandle;
|
||||
template <typename T>
|
||||
class PdmField;
|
||||
} // namespace caf
|
||||
|
||||
namespace google
|
||||
{
|
||||
namespace protobuf
|
||||
{
|
||||
class FieldDescriptor;
|
||||
class Message;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
class RiaGrpcCallbackInterface;
|
||||
|
||||
class RiaGrpcCommandService : public rips::Commands::AsyncService, public RiaGrpcServiceInterface
|
||||
{
|
||||
public:
|
||||
grpc::Status
|
||||
Execute( grpc::ServerContext* context, const rips::CommandParams* request, rips::CommandReply* reply ) override;
|
||||
std::vector<RiaGrpcCallbackInterface*> createCallbacks() override;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
static caf::PdmField<T>* dataValueField( caf::PdmValueField* valueField );
|
||||
template <typename T>
|
||||
static const caf::PdmField<T>* constDataValueField( const caf::PdmValueField* valueField );
|
||||
void assignPdmFieldValue( caf::PdmValueField* pdmValueField,
|
||||
const google::protobuf::Message& params,
|
||||
const google::protobuf::FieldDescriptor* paramDescriptor );
|
||||
void assignPdmObjectValues( caf::PdmObjectHandle* pdmObject,
|
||||
const google::protobuf::Message& params,
|
||||
const google::protobuf::FieldDescriptor* paramDescriptor );
|
||||
|
||||
void assignGrpcFieldValue( google::protobuf::Message* reply,
|
||||
const google::protobuf::FieldDescriptor* fieldDescriptor,
|
||||
const caf::PdmValueField* pdmValueField );
|
||||
void assignResultToReply( const caf::PdmObject* result, rips::CommandReply* reply );
|
||||
};
|
||||
208
GrpcInterface/RiaGrpcGridService.cpp
Normal file
208
GrpcInterface/RiaGrpcGridService.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#include "RiaGrpcGridService.h"
|
||||
|
||||
#include "RiaGrpcCallbacks.h"
|
||||
#include "RiaGrpcHelper.h"
|
||||
|
||||
#include "RigCell.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigMainGrid.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
|
||||
using namespace rips;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaCellCenterStateHandler::RiaCellCenterStateHandler()
|
||||
: m_request( nullptr )
|
||||
, m_eclipseCase( nullptr )
|
||||
, m_grid( nullptr )
|
||||
, m_currentCellIdx( 0u )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaCellCenterStateHandler::init( const rips::GridRequest* request )
|
||||
{
|
||||
CAF_ASSERT( request );
|
||||
m_request = request;
|
||||
|
||||
RimCase* rimCase = RiaGrpcServiceInterface::findCase( m_request->case_request().id() );
|
||||
m_eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
|
||||
|
||||
if ( !m_eclipseCase )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case not found" );
|
||||
}
|
||||
|
||||
size_t gridIndex = (size_t)request->grid_index();
|
||||
if ( gridIndex >= m_eclipseCase->mainGrid()->gridCount() )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Grid not found" );
|
||||
}
|
||||
|
||||
m_grid = m_eclipseCase->mainGrid()->gridByIndex( gridIndex );
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaCellCenterStateHandler::assignReply( rips::CellCenters* reply )
|
||||
{
|
||||
const size_t packageSize = RiaGrpcServiceInterface::numberOfDataUnitsInPackage( sizeof( rips::Vec3d ) );
|
||||
size_t indexInPackage = 0u;
|
||||
reply->mutable_centers()->Reserve( (int)packageSize );
|
||||
for ( ; indexInPackage < packageSize && m_currentCellIdx < m_grid->cellCount(); ++indexInPackage )
|
||||
{
|
||||
cvf::Vec3d center = m_grid->cell( m_currentCellIdx ).center();
|
||||
|
||||
RiaGrpcHelper::convertVec3dToPositiveDepth( ¢er );
|
||||
|
||||
Vec3d* cellCenter = reply->add_centers();
|
||||
cellCenter->set_x( center.x() );
|
||||
cellCenter->set_y( center.y() );
|
||||
cellCenter->set_z( center.z() );
|
||||
m_currentCellIdx++;
|
||||
}
|
||||
if ( indexInPackage > 0u )
|
||||
{
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaCellCenterStateHandler::assignCornersReply( rips::CellCornersArray* reply )
|
||||
{
|
||||
const size_t packageSize = RiaGrpcServiceInterface::numberOfDataUnitsInPackage( sizeof( rips::CellCorners ) );
|
||||
size_t indexInPackage = 0u;
|
||||
reply->mutable_cells()->Reserve( (int)packageSize );
|
||||
|
||||
cvf::Vec3d cornerVerts[8];
|
||||
for ( ; indexInPackage < packageSize && m_currentCellIdx < m_grid->cellCount(); ++indexInPackage )
|
||||
{
|
||||
m_grid->cellCornerVertices( m_currentCellIdx, cornerVerts );
|
||||
for ( cvf::Vec3d& corner : cornerVerts )
|
||||
{
|
||||
RiaGrpcHelper::convertVec3dToPositiveDepth( &corner );
|
||||
}
|
||||
|
||||
rips::CellCorners* corners = reply->add_cells();
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c0(), cornerVerts[0] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c1(), cornerVerts[1] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c2(), cornerVerts[2] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c3(), cornerVerts[3] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c4(), cornerVerts[4] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c5(), cornerVerts[5] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c6(), cornerVerts[6] );
|
||||
RiaGrpcHelper::setCornerValues( corners->mutable_c7(), cornerVerts[7] );
|
||||
|
||||
m_currentCellIdx++;
|
||||
}
|
||||
if ( indexInPackage > 0u )
|
||||
{
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcGridService::GetDimensions( grpc::ServerContext* context,
|
||||
const rips::GridRequest* request,
|
||||
rips::GridDimensions* reply )
|
||||
{
|
||||
RimCase* rimCase = findCase( request->case_request().id() );
|
||||
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
|
||||
if ( eclipseCase )
|
||||
{
|
||||
size_t gridIndex = (size_t)request->grid_index();
|
||||
if ( gridIndex < eclipseCase->mainGrid()->gridCount() )
|
||||
{
|
||||
const RigGridBase* grid = eclipseCase->mainGrid()->gridByIndex( gridIndex );
|
||||
Vec3i* dimensions = new Vec3i;
|
||||
dimensions->set_i( (int)grid->cellCountI() );
|
||||
dimensions->set_j( (int)grid->cellCountJ() );
|
||||
dimensions->set_k( (int)grid->cellCountK() );
|
||||
|
||||
reply->set_allocated_dimensions( dimensions );
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
return grpc::Status( grpc::NOT_FOUND, "Grid not found" );
|
||||
}
|
||||
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case not found" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcGridService::GetCellCenters( grpc::ServerContext* context,
|
||||
const rips::GridRequest* request,
|
||||
rips::CellCenters* reply,
|
||||
RiaCellCenterStateHandler* stateHandler )
|
||||
{
|
||||
return stateHandler->assignReply( reply );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcGridService::GetCellCorners( grpc::ServerContext* context,
|
||||
const rips::GridRequest* request,
|
||||
rips::CellCornersArray* reply,
|
||||
RiaCellCenterStateHandler* stateHandler )
|
||||
{
|
||||
return stateHandler->assignCornersReply( reply );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaGrpcCallbackInterface*> RiaGrpcGridService::createCallbacks()
|
||||
{
|
||||
typedef RiaGrpcGridService Self;
|
||||
|
||||
return {
|
||||
|
||||
new RiaGrpcServerToClientStreamCallback<Self, GridRequest, CellCenters, RiaCellCenterStateHandler>( this,
|
||||
&Self::GetCellCenters,
|
||||
&Self::RequestGetCellCenters,
|
||||
new RiaCellCenterStateHandler ),
|
||||
|
||||
new RiaGrpcServerToClientStreamCallback<Self, GridRequest, CellCornersArray, RiaCellCenterStateHandler>( this,
|
||||
&Self::GetCellCorners,
|
||||
&Self::RequestGetCellCorners,
|
||||
new RiaCellCenterStateHandler ),
|
||||
|
||||
new RiaGrpcUnaryCallback<Self, GridRequest, GridDimensions>( this, &Self::GetDimensions, &Self::RequestGetDimensions ) };
|
||||
}
|
||||
|
||||
static bool RiaGrpcGridService_init =
|
||||
RiaGrpcServiceFactory::instance()->registerCreator<RiaGrpcGridService>( typeid( RiaGrpcGridService ).hash_code() );
|
||||
76
GrpcInterface/RiaGrpcGridService.h
Normal file
76
GrpcInterface/RiaGrpcGridService.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "Grid.grpc.pb.h"
|
||||
|
||||
#include "RiaGrpcServiceInterface.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RigGridBase;
|
||||
class RimEclipseCase;
|
||||
|
||||
namespace rips
|
||||
{
|
||||
class GridRequest;
|
||||
class CellCenters;
|
||||
class GridDimensions;
|
||||
}; // namespace rips
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// State handler for streaming of active cell info
|
||||
//
|
||||
//==================================================================================================
|
||||
class RiaCellCenterStateHandler
|
||||
{
|
||||
typedef grpc::Status Status;
|
||||
|
||||
public:
|
||||
RiaCellCenterStateHandler();
|
||||
grpc::Status init( const rips::GridRequest* request );
|
||||
grpc::Status assignReply( rips::CellCenters* reply );
|
||||
grpc::Status assignCornersReply( rips::CellCornersArray* reply );
|
||||
|
||||
protected:
|
||||
const rips::GridRequest* m_request;
|
||||
RimEclipseCase* m_eclipseCase;
|
||||
size_t m_currentCellIdx;
|
||||
const RigGridBase* m_grid;
|
||||
};
|
||||
|
||||
class RiaGrpcGridService final : public rips::Grid::AsyncService, public RiaGrpcServiceInterface
|
||||
{
|
||||
public:
|
||||
grpc::Status GetCellCenters( grpc::ServerContext* context,
|
||||
const rips::GridRequest* request,
|
||||
rips::CellCenters* reply,
|
||||
RiaCellCenterStateHandler* stateHandler );
|
||||
|
||||
grpc::Status GetCellCorners( grpc::ServerContext* context,
|
||||
const rips::GridRequest* request,
|
||||
rips::CellCornersArray* reply,
|
||||
RiaCellCenterStateHandler* stateHandler );
|
||||
|
||||
grpc::Status GetDimensions( grpc::ServerContext* context,
|
||||
const rips::GridRequest* request,
|
||||
rips::GridDimensions* reply ) override;
|
||||
|
||||
std::vector<RiaGrpcCallbackInterface*> createCallbacks() override;
|
||||
};
|
||||
37
GrpcInterface/RiaGrpcHelper.cpp
Normal file
37
GrpcInterface/RiaGrpcHelper.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RiaGrpcHelper.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Convert internal ResInsight representation of cells with negative depth to positive depth.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaGrpcHelper::convertVec3dToPositiveDepth( cvf::Vec3d* vec )
|
||||
{
|
||||
double& z = vec->z();
|
||||
z *= -1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaGrpcHelper::setCornerValues( rips::Vec3d* out, const cvf::Vec3d& in )
|
||||
{
|
||||
out->set_x( in.x() );
|
||||
out->set_y( in.y() );
|
||||
out->set_z( in.z() );
|
||||
}
|
||||
34
GrpcInterface/RiaGrpcHelper.h
Normal file
34
GrpcInterface/RiaGrpcHelper.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "Definitions.grpc.pb.h"
|
||||
|
||||
#include "cvfVector3.h"
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Various gRPC helper methods
|
||||
//
|
||||
//==================================================================================================
|
||||
class RiaGrpcHelper
|
||||
{
|
||||
public:
|
||||
static void convertVec3dToPositiveDepth( cvf::Vec3d* vec );
|
||||
static void setCornerValues( rips::Vec3d* out, const cvf::Vec3d& in );
|
||||
};
|
||||
531
GrpcInterface/RiaGrpcNNCPropertiesService.cpp
Normal file
531
GrpcInterface/RiaGrpcNNCPropertiesService.cpp
Normal file
@@ -0,0 +1,531 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RiaGrpcNNCPropertiesService.h"
|
||||
|
||||
#include "RiaGrpcCallbacks.h"
|
||||
#include "RiaGrpcCaseService.h"
|
||||
|
||||
#include "RigCaseCellResultsData.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseResultAddress.h"
|
||||
#include "RigEclipseResultInfo.h"
|
||||
#include "RigMainGrid.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseCellColors.h"
|
||||
#include "RimEclipseInputCase.h"
|
||||
#include "RimEclipseInputProperty.h"
|
||||
#include "RimEclipseInputPropertyCollection.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimIntersectionCollection.h"
|
||||
|
||||
using namespace rips;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaNNCConnectionsStateHandler::RiaNNCConnectionsStateHandler()
|
||||
: m_request( nullptr )
|
||||
, m_eclipseCase( nullptr )
|
||||
, m_currentIdx( 0u )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaNNCConnectionsStateHandler::init( const rips::CaseRequest* request )
|
||||
{
|
||||
CAF_ASSERT( request );
|
||||
m_request = request;
|
||||
|
||||
RimCase* rimCase = RiaGrpcServiceInterface::findCase( m_request->id() );
|
||||
m_eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
|
||||
|
||||
if ( !( m_eclipseCase && m_eclipseCase->eclipseCaseData() && m_eclipseCase->eclipseCaseData()->mainGrid() ) )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case not found" );
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
rips::Vec3i* createConnectionVec3i( const RigCell& cell )
|
||||
{
|
||||
RigGridBase* hostGrid = cell.hostGrid();
|
||||
size_t gridLocalCellIndex = cell.gridLocalCellIndex();
|
||||
size_t i, j, k;
|
||||
hostGrid->ijkFromCellIndex( gridLocalCellIndex, &i, &j, &k );
|
||||
|
||||
rips::Vec3i* vec = new rips::Vec3i;
|
||||
vec->set_i( i );
|
||||
vec->set_j( j );
|
||||
vec->set_k( k );
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaNNCConnectionsStateHandler::assignReply( rips::NNCConnections* reply )
|
||||
{
|
||||
RigMainGrid* mainGrid = m_eclipseCase->eclipseCaseData()->mainGrid();
|
||||
const RigConnectionContainer& connections = mainGrid->nncData()->connections();
|
||||
|
||||
size_t connectionCount = connections.size();
|
||||
const size_t packageSize = RiaGrpcServiceInterface::numberOfDataUnitsInPackage( sizeof( rips::NNCConnection ) );
|
||||
size_t indexInPackage = 0u;
|
||||
reply->mutable_connections()->Reserve( (int)packageSize );
|
||||
for ( ; indexInPackage < packageSize && m_currentIdx < connectionCount; ++indexInPackage )
|
||||
{
|
||||
const RigConnection& connection = connections[m_currentIdx];
|
||||
const RigCell& cell1 = mainGrid->globalCellArray()[connection.c1GlobIdx()];
|
||||
const RigCell& cell2 = mainGrid->globalCellArray()[connection.c2GlobIdx()];
|
||||
|
||||
NNCConnection* nncConnection = reply->add_connections();
|
||||
nncConnection->set_allocated_cell1( createConnectionVec3i( cell1 ) );
|
||||
nncConnection->set_allocated_cell2( createConnectionVec3i( cell2 ) );
|
||||
nncConnection->set_cell_grid_index1( cell1.hostGrid()->gridIndex() );
|
||||
nncConnection->set_cell_grid_index2( cell2.hostGrid()->gridIndex() );
|
||||
|
||||
m_currentIdx++;
|
||||
}
|
||||
|
||||
if ( indexInPackage > 0u )
|
||||
{
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcNNCPropertiesService::GetNNCConnections( grpc::ServerContext* context,
|
||||
const rips::CaseRequest* request,
|
||||
rips::NNCConnections* reply,
|
||||
RiaNNCConnectionsStateHandler* stateHandler )
|
||||
{
|
||||
return stateHandler->assignReply( reply );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaNNCValuesStateHandler::RiaNNCValuesStateHandler()
|
||||
: m_request( nullptr )
|
||||
, m_eclipseCase( nullptr )
|
||||
, m_currentIdx( 0u )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaNNCValuesStateHandler::init( const rips::NNCValuesRequest* request )
|
||||
{
|
||||
CAF_ASSERT( request );
|
||||
m_request = request;
|
||||
|
||||
RimCase* rimCase = RiaGrpcServiceInterface::findCase( m_request->case_id() );
|
||||
m_eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
|
||||
|
||||
if ( !( m_eclipseCase && m_eclipseCase->eclipseCaseData() && m_eclipseCase->eclipseCaseData()->mainGrid() ) )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Eclipse Case not found" );
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>* getScalarResultByName( const RigNNCData* nncData,
|
||||
RigNNCData::NNCResultType resultType,
|
||||
const QString& propertyName,
|
||||
size_t timeStep )
|
||||
{
|
||||
if ( resultType == RigNNCData::NNC_STATIC )
|
||||
{
|
||||
return nncData->staticConnectionScalarResultByName( propertyName );
|
||||
}
|
||||
|
||||
if ( resultType == RigNNCData::NNC_DYNAMIC )
|
||||
{
|
||||
return nncData->dynamicConnectionScalarResultByName( propertyName, timeStep );
|
||||
}
|
||||
|
||||
if ( resultType == RigNNCData::NNC_GENERATED )
|
||||
{
|
||||
return nncData->generatedConnectionScalarResultByName( propertyName, timeStep );
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaNNCValuesStateHandler::assignReply( rips::NNCValues* reply )
|
||||
{
|
||||
RigMainGrid* mainGrid = m_eclipseCase->eclipseCaseData()->mainGrid();
|
||||
auto connections = mainGrid->nncData()->connections();
|
||||
|
||||
QString propertyName = QString::fromStdString( m_request->property_name() );
|
||||
RigNNCData::NNCResultType propertyType = static_cast<RigNNCData::NNCResultType>( m_request->property_type() );
|
||||
size_t timeStep = m_request->time_step();
|
||||
|
||||
const std::vector<double>* nncValues =
|
||||
getScalarResultByName( mainGrid->nncData(), propertyType, propertyName, timeStep );
|
||||
if ( !nncValues )
|
||||
{
|
||||
return Status( grpc::NOT_FOUND, "No values found" );
|
||||
}
|
||||
|
||||
size_t connectionCount = connections.size();
|
||||
const size_t packageSize = RiaGrpcServiceInterface::numberOfDataUnitsInPackage( sizeof( double ) );
|
||||
size_t indexInPackage = 0u;
|
||||
reply->mutable_values()->Reserve( (int)packageSize );
|
||||
for ( ; indexInPackage < packageSize && m_currentIdx < connectionCount; ++indexInPackage )
|
||||
{
|
||||
reply->add_values( nncValues->at( m_currentIdx ) );
|
||||
m_currentIdx++;
|
||||
}
|
||||
|
||||
if ( indexInPackage > 0u )
|
||||
{
|
||||
return Status::OK;
|
||||
}
|
||||
return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcNNCPropertiesService::GetNNCValues( grpc::ServerContext* context,
|
||||
const rips::NNCValuesRequest* request,
|
||||
rips::NNCValues* reply,
|
||||
RiaNNCValuesStateHandler* stateHandler )
|
||||
{
|
||||
return stateHandler->assignReply( reply );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcNNCPropertiesService::GetAvailableNNCProperties( grpc::ServerContext* context,
|
||||
const CaseRequest* request,
|
||||
AvailableNNCProperties* reply )
|
||||
{
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( RiaGrpcServiceInterface::findCase( request->id() ) );
|
||||
if ( eclipseCase && eclipseCase->eclipseCaseData() && eclipseCase->eclipseCaseData()->mainGrid() )
|
||||
{
|
||||
RigNNCData* nncData = eclipseCase->eclipseCaseData()->mainGrid()->nncData();
|
||||
|
||||
std::vector<RigNNCData::NNCResultType> resultTypes;
|
||||
resultTypes.push_back( RigNNCData::NNC_DYNAMIC );
|
||||
resultTypes.push_back( RigNNCData::NNC_STATIC );
|
||||
resultTypes.push_back( RigNNCData::NNC_GENERATED );
|
||||
|
||||
for ( size_t rtIdx = 0; rtIdx < resultTypes.size(); ++rtIdx )
|
||||
{
|
||||
std::vector<QString> availableParameters = nncData->availableProperties( resultTypes[rtIdx] );
|
||||
|
||||
for ( const QString& parameter : availableParameters )
|
||||
{
|
||||
AvailableNNCProperty* property = reply->add_properties();
|
||||
property->set_name( parameter.toStdString() );
|
||||
property->set_property_type( static_cast<NNCPropertyType>( resultTypes[rtIdx] ) );
|
||||
}
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
return grpc::Status( grpc::NOT_FOUND, "No such case" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
static bool scalarResultExistsOrCreate( RigCaseCellResultsData* results, QString propertyName )
|
||||
{
|
||||
RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::GENERATED, propertyName );
|
||||
|
||||
if ( !results->ensureKnownResultLoaded( resAddr ) )
|
||||
{
|
||||
results->createResultEntry( resAddr, true );
|
||||
}
|
||||
|
||||
std::vector<std::vector<double>>* scalarResultFrames = results->modifiableCellScalarResultTimesteps( resAddr );
|
||||
size_t timeStepCount = results->maxTimeStepCount();
|
||||
scalarResultFrames->resize( timeStepCount );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
static bool createIJKCellResults( RigCaseCellResultsData* results, QString propertyName )
|
||||
{
|
||||
bool ok;
|
||||
ok = scalarResultExistsOrCreate( results, QString( "%1IJK" ).arg( propertyName ) );
|
||||
if ( !ok ) return false;
|
||||
ok = scalarResultExistsOrCreate( results, QString( "%1I" ).arg( propertyName ) );
|
||||
if ( !ok ) return false;
|
||||
ok = scalarResultExistsOrCreate( results, QString( "%1J" ).arg( propertyName ) );
|
||||
if ( !ok ) return false;
|
||||
ok = scalarResultExistsOrCreate( results, QString( "%1K" ).arg( propertyName ) );
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaNNCInputValuesStateHandler::RiaNNCInputValuesStateHandler( bool )
|
||||
: m_eclipseCase( nullptr )
|
||||
, m_streamedValueCount( 0u )
|
||||
, m_cellCount( 0u )
|
||||
, m_timeStep( 0u )
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<double>* getOrCreateConnectionScalarResultByName( RigNNCData* nncData, const QString propertyName, int timeStep )
|
||||
{
|
||||
std::vector<double>* resultsToAdd = nncData->generatedConnectionScalarResultByName( propertyName, timeStep );
|
||||
if ( resultsToAdd )
|
||||
{
|
||||
return resultsToAdd;
|
||||
}
|
||||
else
|
||||
{
|
||||
nncData->makeGeneratedConnectionScalarResult( propertyName, timeStep + 1 );
|
||||
return nncData->generatedConnectionScalarResultByName( propertyName, timeStep );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaNNCInputValuesStateHandler::init( const NNCValuesInputRequest* request )
|
||||
{
|
||||
int caseId = request->case_id();
|
||||
m_eclipseCase = dynamic_cast<RimEclipseCase*>( RiaGrpcServiceInterface::findCase( caseId ) );
|
||||
|
||||
if ( m_eclipseCase && m_eclipseCase->eclipseCaseData() && m_eclipseCase->eclipseCaseData()->mainGrid() )
|
||||
{
|
||||
auto caseData = m_eclipseCase->eclipseCaseData();
|
||||
auto m_porosityModel = static_cast<RiaDefines::PorosityModelType>( request->porosity_model() );
|
||||
m_timeStep = request->time_step();
|
||||
m_propertyName = QString::fromStdString( request->property_name() );
|
||||
|
||||
RigNNCData* nncData = m_eclipseCase->eclipseCaseData()->mainGrid()->nncData();
|
||||
std::vector<double>* resultsToAdd = getOrCreateConnectionScalarResultByName( nncData, m_propertyName, m_timeStep );
|
||||
if ( !resultsToAdd )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "No results for scalar results found." );
|
||||
}
|
||||
|
||||
if ( !m_eclipseCase->results( m_porosityModel ) )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "No results for porosity model." );
|
||||
}
|
||||
|
||||
bool ok = createIJKCellResults( m_eclipseCase->results( m_porosityModel ), m_propertyName );
|
||||
if ( !ok )
|
||||
{
|
||||
return grpc::Status( grpc::NOT_FOUND, "Could not find the property results." );
|
||||
}
|
||||
|
||||
RigEclipseResultAddress resAddr( QString( "%1IJK" ).arg( m_propertyName ) );
|
||||
m_eclipseCase->results( m_porosityModel )->ensureKnownResultLoaded( resAddr );
|
||||
nncData->setEclResultAddress( m_propertyName, resAddr );
|
||||
|
||||
m_cellCount = caseData->mainGrid()->nncData()->connections().size();
|
||||
|
||||
resultsToAdd->resize( m_cellCount, HUGE_VAL );
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
return grpc::Status( grpc::NOT_FOUND, "Couldn't find an Eclipse case matching the case Id" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaNNCInputValuesStateHandler::init( const rips::NNCValuesChunk* chunk )
|
||||
{
|
||||
if ( chunk->has_params() )
|
||||
{
|
||||
return init( &( chunk->params() ) );
|
||||
}
|
||||
return grpc::Status( grpc::INVALID_ARGUMENT, "Need to have PropertyRequest parameters in first message" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaNNCInputValuesStateHandler::receiveStreamRequest( const NNCValuesChunk* request,
|
||||
ClientToServerStreamReply* reply )
|
||||
{
|
||||
if ( request->has_values() )
|
||||
{
|
||||
auto values = request->values().values();
|
||||
if ( !values.empty() )
|
||||
{
|
||||
RigNNCData* nncData = m_eclipseCase->eclipseCaseData()->mainGrid()->nncData();
|
||||
|
||||
std::vector<std::vector<double>>* resultsToAdd =
|
||||
nncData->generatedConnectionScalarResultByName( m_propertyName );
|
||||
|
||||
size_t currentCellIdx = m_streamedValueCount;
|
||||
m_streamedValueCount += values.size();
|
||||
|
||||
for ( int i = 0; i < values.size() && currentCellIdx < m_cellCount; ++i, ++currentCellIdx )
|
||||
{
|
||||
resultsToAdd->at( m_timeStep )[currentCellIdx] = values[i];
|
||||
}
|
||||
|
||||
if ( m_streamedValueCount > m_cellCount )
|
||||
{
|
||||
return grpc::Status( grpc::OUT_OF_RANGE, "Attempting to write out of bounds" );
|
||||
}
|
||||
reply->set_accepted_value_count( static_cast<int64_t>( currentCellIdx ) );
|
||||
return Status::OK;
|
||||
}
|
||||
}
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RiaNNCInputValuesStateHandler::totalValueCount() const
|
||||
{
|
||||
return m_cellCount;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RiaNNCInputValuesStateHandler::streamedValueCount() const
|
||||
{
|
||||
return m_streamedValueCount;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaNNCInputValuesStateHandler::finish()
|
||||
{
|
||||
if ( m_eclipseCase != nullptr )
|
||||
{
|
||||
// Create a new input property if we have an input reservoir
|
||||
RimEclipseInputCase* inputRes = dynamic_cast<RimEclipseInputCase*>( m_eclipseCase );
|
||||
if ( inputRes )
|
||||
{
|
||||
RimEclipseInputProperty* inputProperty =
|
||||
inputRes->inputPropertyCollection()->findInputProperty( m_propertyName );
|
||||
if ( !inputProperty )
|
||||
{
|
||||
inputProperty = new RimEclipseInputProperty;
|
||||
inputProperty->resultName = m_propertyName;
|
||||
inputProperty->eclipseKeyword = "";
|
||||
inputProperty->fileName = QString( "" );
|
||||
inputRes->inputPropertyCollection()->inputProperties.push_back( inputProperty );
|
||||
inputRes->inputPropertyCollection()->updateConnectedEditors();
|
||||
}
|
||||
inputProperty->resolvedState = RimEclipseInputProperty::RESOLVED_NOT_SAVED;
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < m_eclipseCase->reservoirViews.size(); ++i )
|
||||
{
|
||||
if ( m_eclipseCase->reservoirViews[i] )
|
||||
{
|
||||
// As new result might have been introduced, update all editors connected
|
||||
m_eclipseCase->reservoirViews[i]->cellResult()->updateConnectedEditors();
|
||||
|
||||
// It is usually not needed to create new display model, but if any derived geometry based on
|
||||
// generated data (from Octave) a full display model rebuild is required
|
||||
m_eclipseCase->reservoirViews[i]->scheduleCreateDisplayModelAndRedraw();
|
||||
m_eclipseCase->reservoirViews[i]->intersectionCollection()->scheduleCreateDisplayModelAndRedraw2dIntersectionViews();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
grpc::Status RiaGrpcNNCPropertiesService::SetNNCValues( grpc::ServerContext* context,
|
||||
const rips::NNCValuesChunk* chunk,
|
||||
rips::ClientToServerStreamReply* reply,
|
||||
RiaNNCInputValuesStateHandler* stateHandler )
|
||||
{
|
||||
return stateHandler->receiveStreamRequest( chunk, reply );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaGrpcCallbackInterface*> RiaGrpcNNCPropertiesService::createCallbacks()
|
||||
{
|
||||
typedef RiaGrpcNNCPropertiesService Self;
|
||||
|
||||
std::vector<RiaGrpcCallbackInterface*> callbacks;
|
||||
callbacks =
|
||||
{ new RiaGrpcUnaryCallback<Self, CaseRequest, AvailableNNCProperties>( this,
|
||||
&Self::GetAvailableNNCProperties,
|
||||
&Self::RequestGetAvailableNNCProperties ),
|
||||
new RiaGrpcServerToClientStreamCallback<Self,
|
||||
CaseRequest,
|
||||
rips::NNCConnections,
|
||||
RiaNNCConnectionsStateHandler>( this,
|
||||
&Self::GetNNCConnections,
|
||||
&Self::RequestGetNNCConnections,
|
||||
new RiaNNCConnectionsStateHandler ),
|
||||
new RiaGrpcServerToClientStreamCallback<Self,
|
||||
NNCValuesRequest,
|
||||
rips::NNCValues,
|
||||
RiaNNCValuesStateHandler>( this,
|
||||
&Self::GetNNCValues,
|
||||
&Self::RequestGetNNCValues,
|
||||
new RiaNNCValuesStateHandler ),
|
||||
|
||||
new RiaGrpcClientToServerStreamCallback<Self,
|
||||
NNCValuesChunk,
|
||||
ClientToServerStreamReply,
|
||||
RiaNNCInputValuesStateHandler>( this,
|
||||
&Self::SetNNCValues,
|
||||
&Self::RequestSetNNCValues,
|
||||
new RiaNNCInputValuesStateHandler(
|
||||
true ) ) };
|
||||
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
static bool RiaGrpcNNCPropertiesService_init =
|
||||
RiaGrpcServiceFactory::instance()->registerCreator<RiaGrpcNNCPropertiesService>(
|
||||
typeid( RiaGrpcNNCPropertiesService ).hash_code() );
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user