diff --git a/ApplicationLibCode/ReservoirDataModel/RigFault.cpp b/ApplicationLibCode/ReservoirDataModel/RigFault.cpp index 626b2c106d4..ec1b8245e02 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigFault.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigFault.cpp @@ -231,3 +231,28 @@ void RigFaultsPrCellAccumulator::setFaultIdx( size_t reservoirCellIndex, cvf::St { m_faultIdxForCellFace[reservoirCellIndex][face] = faultIdx; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RigFault::minimumDistanceToPoint( const cvf::Vec3d& point, const RigMainGrid* mainGrid ) const +{ + double minDistance = std::numeric_limits::max(); + cvf::StructGridInterface::FaceType minFace = cvf::StructGridInterface::NO_FACE; + for ( const FaultFace& ff : m_faultFaces ) + { + const RigCell& cell = mainGrid->cell( ff.m_nativeReservoirCellIndex ); + if ( cell.isInvalid() ) continue; + + for ( auto& c : cell.faceCorners( ff.m_nativeFace ) ) + { + double distance = ( c - point ).length(); + if ( distance < minDistance ) + { + minDistance = distance; + minFace = ff.m_nativeFace; + } + } + } + return std::make_pair( minDistance, minFace ); +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigFault.h b/ApplicationLibCode/ReservoirDataModel/RigFault.h index cb60a9188a1..10dc51a3203 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigFault.h +++ b/ApplicationLibCode/ReservoirDataModel/RigFault.h @@ -97,6 +97,8 @@ class RigFault : public cvf::Object static bool ordering( CellAndFace first, CellAndFace second ); + std::pair minimumDistanceToPoint( const cvf::Vec3d& point, const RigMainGrid* mainGrid ) const; + private: QString m_name; diff --git a/ApplicationLibCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationLibCode/ReservoirDataModel/RigMainGrid.cpp index a4ad490e91c..89901737cc3 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigMainGrid.cpp @@ -809,6 +809,28 @@ const RigFault* RigMainGrid::findFaultFromCellIndexAndCellFace( size_t reservoir return nullptr; } +//-------------------------------------------------------------------------------------------------- +/// Returns the name of the closest fault, the distance to the fault, and the face type of the closest face +//-------------------------------------------------------------------------------------------------- +std::tuple RigMainGrid::minimumDistanceFaultToPoint( const cvf::Vec3d& point ) const +{ + double minDistance = std::numeric_limits::max(); + cvf::StructGridInterface::FaceType minFace = cvf::StructGridInterface::FaceType::NO_FACE; + QString minFaultName; + for ( const auto& fault : m_faults ) + { + auto [faultMinDistance, faultMinFace] = fault->minimumDistanceToPoint( point, this ); + + if ( faultMinDistance < minDistance ) + { + minDistance = faultMinDistance; + minFace = faultMinFace; + minFaultName = fault->name(); + } + } + return { minFaultName, minDistance, minFace }; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ReservoirDataModel/RigMainGrid.h b/ApplicationLibCode/ReservoirDataModel/RigMainGrid.h index 1df5dcd042a..dc401f997ee 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigMainGrid.h +++ b/ApplicationLibCode/ReservoirDataModel/RigMainGrid.h @@ -27,6 +27,8 @@ #include "cvfBoundingBox.h" #include "cvfCollection.h" +#include + #include class RigActiveCellInfo; @@ -116,6 +118,8 @@ class RigMainGrid : public RigGridBase // invalidate all cells with I > iLimit (0 based index) void invalidateCellsAboveI( size_t iLimit ); + std::tuple minimumDistanceFaultToPoint( const cvf::Vec3d& point ) const; + protected: // only for use by file readers and internal services. TODO: replace with a better API friend class RigGridBase; friend class RigReservoirBuilder; @@ -124,7 +128,7 @@ class RigMainGrid : public RigGridBase friend class RifReaderEclipseOutput; friend class RifReaderOpmCommon; friend class RiaGrpcCaseService; - friend class RiaActiveCellInfoStateHandler; + friend class RiaGrpcActiveCellInfoStateHandler; friend class RicCreateTemporaryLgrFeature; friend class RimCornerPointCase; std::vector& reservoirCells(); diff --git a/GrpcInterface/CMakeLists.txt b/GrpcInterface/CMakeLists.txt index 703bc9ca7cd..8c2bdb3a358 100644 --- a/GrpcInterface/CMakeLists.txt +++ b/GrpcInterface/CMakeLists.txt @@ -39,6 +39,8 @@ set(SOURCE_GROUP_HEADER_FILES RiaGrpcApplicationInterface.h RiaGrpcWellPathService.h RiaWellPathDataToGrpcConverter.h + RiaGrpcActiveCellInfoStateHandler.h + RiaGrpcSelectedCellsStateHandler.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -58,6 +60,8 @@ set(SOURCE_GROUP_SOURCE_FILES RiaGrpcApplicationInterface.cpp RiaGrpcWellPathService.cpp RiaWellPathDataToGrpcConverter.cpp + RiaGrpcActiveCellInfoStateHandler.cpp + RiaGrpcSelectedCellsStateHandler.cpp ) # Find Protobuf installation Looks for protobuf-config.cmake file installed by diff --git a/GrpcInterface/GrpcProtos/Case.proto b/GrpcInterface/GrpcProtos/Case.proto index 076028612ff..77aedf1174f 100644 --- a/GrpcInterface/GrpcProtos/Case.proto +++ b/GrpcInterface/GrpcProtos/Case.proto @@ -21,6 +21,7 @@ service Case { rpc GetCaseInfo(CaseRequest) returns (CaseInfo) {} rpc GetPdmObject(CaseRequest) returns (PdmObject) {} rpc GetReservoirBoundingBox(CaseRequest) returns (BoundingBox) {} + rpc GetDistanceToClosestFault(ClosestFaultRequest) returns (ClosestFault) {} } message CaseRequest { int32 id = 1; } @@ -103,3 +104,14 @@ message SelectedCell { } message SelectedCells { repeated SelectedCell cells = 1; } + +message ClosestFaultRequest { + CaseRequest case_request = 1; + Vec3d point = 2; +} + +message ClosestFault { + string fault_name = 1; + double distance = 2; + string face_name = 3; +} diff --git a/GrpcInterface/Python/rips/PythonExamples/case_and_grid_operations/fault_distance.py b/GrpcInterface/Python/rips/PythonExamples/case_and_grid_operations/fault_distance.py new file mode 100644 index 00000000000..27014746e23 --- /dev/null +++ b/GrpcInterface/Python/rips/PythonExamples/case_and_grid_operations/fault_distance.py @@ -0,0 +1,35 @@ +################################################################################### +# This example prints the distance to and the name of the fault closest to a point +################################################################################### + +import rips + +resinsight = rips.Instance.find() +if resinsight is None: + exit(1) + +cases = resinsight.project.cases() +if len(cases) == 0: + exit(1) + +case = cases[0] +print("Using case: " + case.name) + +# random test point (positive Z for depth) +point_x = 5039.84 +point_y = 6303.76 +point_z = 4144.21 + +print("Looking for closest fault to point %f, %f, %f:" % (point_x, point_y, point_z)) + +faultname, distance, facename = case.distance_to_closest_fault( + point_x, point_y, point_z +) + +if facename == "": + print("- No fault found!") +else: + print( + "- Distance to closest fault %s is %f, closest face direction is %s" + % (faultname, distance, facename) + ) diff --git a/GrpcInterface/Python/rips/case.py b/GrpcInterface/Python/rips/case.py index 6fd49c26088..9123c369a27 100644 --- a/GrpcInterface/Python/rips/case.py +++ b/GrpcInterface/Python/rips/case.py @@ -43,6 +43,7 @@ import Case_pb2_grpc import Commands_pb2 as Cmd import PdmObject_pb2 as PdmObject_pb2 +import Definitions_pb2 import Properties_pb2 import Properties_pb2_grpc @@ -300,6 +301,17 @@ def reservoir_boundingbox(self): return self.__case_stub.GetReservoirBoundingBox(self.__request()) +@add_method(Case) +def distance_to_closest_fault(self, x: float, y: float, z: float): + """Find the closest fault to the given point and return the distance, fault name and fault face""" + request = Case_pb2.ClosestFaultRequest( + case_request=self.__request(), point=Definitions_pb2.Vec3d(x=x, y=y, z=z) + ) + reply = self.__case_stub.GetDistanceToClosestFault(request) + + return (reply.fault_name, reply.distance, reply.face_name) + + @add_method(Case) def reservoir_depth_range(self) -> Tuple[float, float]: """Get the reservoir depth range diff --git a/GrpcInterface/Python/rips/tests/test_faults.py b/GrpcInterface/Python/rips/tests/test_faults.py new file mode 100644 index 00000000000..ff2a31087fb --- /dev/null +++ b/GrpcInterface/Python/rips/tests/test_faults.py @@ -0,0 +1,30 @@ +import sys +import os +import math +import pytest + +sys.path.insert(1, os.path.join(sys.path[0], "../../")) +import rips + +import dataroot + + +def test_faultDistance(rips_instance, initialize_test): + case = rips_instance.project.load_case( + dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + ) + + # a test point + point_x = 4817.84 + point_y = 5204.76 + point_z = 4137.21 + + faultname, distance, facename = case.distance_to_closest_fault( + point_x, point_y, point_z + ) + + # Fault name is unstable between grid readers, so we skip this check + # assert faultname == "Undefined Grid Faults" + + assert facename == "I+" + assert math.isclose(distance, 53.84, abs_tol=0.1) diff --git a/GrpcInterface/RiaGrpcActiveCellInfoStateHandler.cpp b/GrpcInterface/RiaGrpcActiveCellInfoStateHandler.cpp new file mode 100644 index 00000000000..23ee35e6a9e --- /dev/null +++ b/GrpcInterface/RiaGrpcActiveCellInfoStateHandler.cpp @@ -0,0 +1,359 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025 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 +// for more details. +// +////////////////////////////////////////////////////////////////////////////////// +#include "RiaGrpcActiveCellInfoStateHandler.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" + +#include + +using namespace rips; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGrpcActiveCellInfoStateHandler::RiaGrpcActiveCellInfoStateHandler() + : m_request( nullptr ) + , m_eclipseCase( nullptr ) + , m_activeCellInfo( nullptr ) + , m_currentCellIdx( 0u ) + , m_porosityModel( RiaDefines::PorosityModelType::MATRIX_MODEL ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcActiveCellInfoStateHandler::init( const rips::CellInfoRequest* request ) +{ + CAF_ASSERT( request ); + m_request = request; + + m_porosityModel = RiaDefines::PorosityModelType( m_request->porosity_model() ); + RimCase* rimCase = RiaGrpcHelper::findCase( m_request->case_request().id() ); + m_eclipseCase = dynamic_cast( 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 RiaGrpcActiveCellInfoStateHandler::assignNextActiveCellInfoData( rips::CellInfo* cellInfo ) +{ + const std::vector& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->reservoirCells(); + + 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 RiaGrpcActiveCellInfoStateHandler::assignCellInfoData( rips::CellInfo* cellInfo, + const std::vector& 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( 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* RiaGrpcActiveCellInfoStateHandler::activeCellInfo() const +{ + return m_activeCellInfo; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RiaGrpcActiveCellInfoStateHandler::reservoirCells() const +{ + const std::vector& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->reservoirCells(); + return reservoirCells; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcActiveCellInfoStateHandler::assignReply( rips::CellInfoArray* reply ) +{ + const size_t packageSize = RiaGrpcHelper::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 RiaGrpcActiveCellInfoStateHandler::assignNextActiveCellCenter( rips::Vec3d* cellCenter ) +{ + const std::vector& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->reservoirCells(); + + 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 RiaGrpcActiveCellInfoStateHandler::assignCellCenter( rips::Vec3d* cellCenter, + const std::vector& 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 RiaGrpcActiveCellInfoStateHandler::assignCellCentersReply( rips::CellCenters* reply ) +{ + const size_t packageSize = RiaGrpcHelper::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 RiaGrpcActiveCellInfoStateHandler::assignNextActiveCellCorners( rips::CellCorners* cellCorners ) +{ + const std::vector& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->reservoirCells(); + + 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 RiaGrpcActiveCellInfoStateHandler::assignCellCorners( rips::CellCorners* corners, + const std::vector& reservoirCells, + size_t cellIdx ) +{ + RigGridBase* grid = m_eclipseCase->eclipseCaseData()->mainGrid(); + std::array cornerVerts = grid->cellCornerVertices( cellIdx ); + 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 RiaGrpcActiveCellInfoStateHandler::assignCellCornersReply( rips::CellCornersArray* reply ) +{ + const size_t packageSize = RiaGrpcHelper::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" ); +} diff --git a/GrpcInterface/RiaGrpcActiveCellInfoStateHandler.h b/GrpcInterface/RiaGrpcActiveCellInfoStateHandler.h new file mode 100644 index 00000000000..5566ae981eb --- /dev/null +++ b/GrpcInterface/RiaGrpcActiveCellInfoStateHandler.h @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025 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 +// for more details. +// +////////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "Case.grpc.pb.h" + +#include "RiaPorosityModel.h" + +#include + +class RigCell; +class RigActiveCellInfo; +class RimEclipseCase; + +//================================================================================================== +// +// State handler for streaming of active cell info +// +//================================================================================================== +class RiaGrpcActiveCellInfoStateHandler +{ + using Status = grpc::Status; + +public: + RiaGrpcActiveCellInfoStateHandler(); + + Status init( const rips::CellInfoRequest* request ); + + RigActiveCellInfo* activeCellInfo() const; + const std::vector& reservoirCells() const; + + // For cell info: + Status assignNextActiveCellInfoData( rips::CellInfo* cellInfo ); + void assignCellInfoData( rips::CellInfo* cellInfo, const std::vector& 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& 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& 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 m_globalCoarseningBoxIndexStart; + size_t m_currentCellIdx; +}; diff --git a/GrpcInterface/RiaGrpcCaseService.cpp b/GrpcInterface/RiaGrpcCaseService.cpp index fcf789d1190..1e74209dbed 100644 --- a/GrpcInterface/RiaGrpcCaseService.cpp +++ b/GrpcInterface/RiaGrpcCaseService.cpp @@ -17,8 +17,10 @@ ////////////////////////////////////////////////////////////////////////////////// #include "RiaGrpcCaseService.h" +#include "RiaGrpcActiveCellInfoStateHandler.h" #include "RiaGrpcCallbacks.h" #include "RiaGrpcHelper.h" +#include "RiaGrpcSelectedCellsStateHandler.h" #include "RiaSocketTools.h" #include "RigActiveCellInfo.h" @@ -36,327 +38,6 @@ 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 = RiaGrpcHelper::findCase( m_request->case_request().id() ); - m_eclipseCase = dynamic_cast( 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& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->reservoirCells(); - - 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& 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( 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& RiaActiveCellInfoStateHandler::reservoirCells() const -{ - const std::vector& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->reservoirCells(); - return reservoirCells; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -grpc::Status RiaActiveCellInfoStateHandler::assignReply( rips::CellInfoArray* reply ) -{ - const size_t packageSize = RiaGrpcHelper::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& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->reservoirCells(); - - 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& 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 = RiaGrpcHelper::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& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->reservoirCells(); - - 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& reservoirCells, - size_t cellIdx ) -{ - RigGridBase* grid = m_eclipseCase->eclipseCaseData()->mainGrid(); - std::array cornerVerts = grid->cellCornerVertices( cellIdx ); - 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 = RiaGrpcHelper::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" ); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -502,10 +183,10 @@ grpc::Status RiaGrpcCaseService::GetPdmObject( grpc::ServerContext* context, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcCaseService::GetCellInfoForActiveCells( grpc::ServerContext* context, - const rips::CellInfoRequest* request, - rips::CellInfoArray* reply, - RiaActiveCellInfoStateHandler* stateHandler ) +grpc::Status RiaGrpcCaseService::GetCellInfoForActiveCells( grpc::ServerContext* context, + const rips::CellInfoRequest* request, + rips::CellInfoArray* reply, + RiaGrpcActiveCellInfoStateHandler* stateHandler ) { return stateHandler->assignReply( reply ); } @@ -513,10 +194,10 @@ grpc::Status RiaGrpcCaseService::GetCellInfoForActiveCells( grpc::ServerContext* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcCaseService::GetCellCenterForActiveCells( grpc::ServerContext* context, - const rips::CellInfoRequest* request, - rips::CellCenters* reply, - RiaActiveCellInfoStateHandler* stateHandler ) +grpc::Status RiaGrpcCaseService::GetCellCenterForActiveCells( grpc::ServerContext* context, + const rips::CellInfoRequest* request, + rips::CellCenters* reply, + RiaGrpcActiveCellInfoStateHandler* stateHandler ) { return stateHandler->assignCellCentersReply( reply ); } @@ -524,10 +205,10 @@ grpc::Status RiaGrpcCaseService::GetCellCenterForActiveCells( grpc::ServerContex //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcCaseService::GetCellCornersForActiveCells( grpc::ServerContext* context, - const rips::CellInfoRequest* request, - rips::CellCornersArray* reply, - RiaActiveCellInfoStateHandler* stateHandler ) +grpc::Status RiaGrpcCaseService::GetCellCornersForActiveCells( grpc::ServerContext* context, + const rips::CellInfoRequest* request, + rips::CellCornersArray* reply, + RiaGrpcActiveCellInfoStateHandler* stateHandler ) { return stateHandler->assignCellCornersReply( reply ); } @@ -535,128 +216,10 @@ grpc::Status RiaGrpcCaseService::GetCellCornersForActiveCells( grpc::ServerConte //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -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 = RiaGrpcHelper::findCase( m_request->id() ); - m_eclipseCase = dynamic_cast( 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& 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 items; - Riu3dSelectionManager::instance()->selectedItems( items ); - - // Only eclipse cases are currently supported. Also filter by case. - std::vector eclipseItems; - for ( auto item : items ) - { - RiuEclipseSelectionItem* eclipseItem = dynamic_cast( item ); - if ( eclipseItem && eclipseItem->m_resultDefinition->eclipseCase()->caseId() == m_request->id() ) - { - eclipseItems.push_back( eclipseItem ); - } - } - - const size_t packageSize = RiaGrpcHelper::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 ) +grpc::Status RiaGrpcCaseService::GetSelectedCells( grpc::ServerContext* context, + const rips::CaseRequest* request, + rips::SelectedCells* reply, + RiaGrpcSelectedCellsStateHandler* stateHandler ) { return stateHandler->assignReply( reply ); } @@ -723,6 +286,30 @@ grpc::Status RiaGrpcCaseService::GetCoarseningInfoArray( grpc::ServerContext* return Status( grpc::NOT_FOUND, "Case not found" ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcCaseService::GetDistanceToClosestFault( grpc::ServerContext* context, + const rips::ClosestFaultRequest* request, + rips::ClosestFault* reply ) +{ + RimCase* rimCase = RiaGrpcHelper::findCase( request->case_request().id() ); + if ( auto eCase = dynamic_cast( rimCase ) ) + { + cvf::Vec3d point( request->point() ); + point.z() = -point.z(); // Convert to internal coordinate system + + auto [faultName, distance, faceType] = eCase->mainGrid()->minimumDistanceFaultToPoint( point ); + + reply->set_distance( distance ); + reply->set_face_name( RiaGrpcHelper::faceTypeToString( faceType ) ); + reply->set_fault_name( faultName.toStdString() ); + + return grpc::Status::OK; + } + return Status( grpc::NOT_FOUND, "Eclipse Case not found" ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -741,38 +328,42 @@ std::vector RiaGrpcCaseService::createCallbacks() new RiaGrpcServerToClientStreamCallback( this, - &Self::GetCellInfoForActiveCells, - &Self::RequestGetCellInfoForActiveCells, - new RiaActiveCellInfoStateHandler ), + RiaGrpcActiveCellInfoStateHandler>( this, + &Self::GetCellInfoForActiveCells, + &Self::RequestGetCellInfoForActiveCells, + new RiaGrpcActiveCellInfoStateHandler ), new RiaGrpcServerToClientStreamCallback( this, - &Self::GetCellCenterForActiveCells, - &Self::RequestGetCellCenterForActiveCells, - new RiaActiveCellInfoStateHandler ), + RiaGrpcActiveCellInfoStateHandler>( this, + &Self::GetCellCenterForActiveCells, + &Self::RequestGetCellCenterForActiveCells, + new RiaGrpcActiveCellInfoStateHandler ), new RiaGrpcServerToClientStreamCallback( this, - &Self::GetCellCornersForActiveCells, - &Self::RequestGetCellCornersForActiveCells, - new RiaActiveCellInfoStateHandler ), + RiaGrpcActiveCellInfoStateHandler>( this, + &Self::GetCellCornersForActiveCells, + &Self::RequestGetCellCornersForActiveCells, + new RiaGrpcActiveCellInfoStateHandler ), new RiaGrpcServerToClientStreamCallback( this, - &Self::GetSelectedCells, - &Self::RequestGetSelectedCells, - new RiaSelectedCellsStateHandler ), + RiaGrpcSelectedCellsStateHandler>( this, + &Self::GetSelectedCells, + &Self::RequestGetSelectedCells, + new RiaGrpcSelectedCellsStateHandler ), new RiaGrpcUnaryCallback( this, &Self::GetReservoirBoundingBox, &Self::RequestGetReservoirBoundingBox ), new RiaGrpcUnaryCallback( this, &Self::GetCoarseningInfoArray, - &Self::RequestGetCoarseningInfoArray ) }; + &Self::RequestGetCoarseningInfoArray ), + + new RiaGrpcUnaryCallback( this, + &Self::GetDistanceToClosestFault, + &Self::RequestGetDistanceToClosestFault ) }; } static bool RiaGrpcCaseService_init = diff --git a/GrpcInterface/RiaGrpcCaseService.h b/GrpcInterface/RiaGrpcCaseService.h index f21b3ef29cb..53a868651ae 100644 --- a/GrpcInterface/RiaGrpcCaseService.h +++ b/GrpcInterface/RiaGrpcCaseService.h @@ -28,77 +28,15 @@ namespace rips { class CaseRequest; class PdmObject; +class CaseInfo; } // namespace rips class RiaGrpcCallbackInterface; class RigCell; class RigActiveCellInfo; class RimEclipseCase; -class RiuEclipseSelectionItem; - -//================================================================================================== -// -// State handler for streaming of active cell info -// -//================================================================================================== -class RiaActiveCellInfoStateHandler -{ - using Status = grpc::Status; - -public: - RiaActiveCellInfoStateHandler(); - - Status init( const rips::CellInfoRequest* request ); - - RigActiveCellInfo* activeCellInfo() const; - const std::vector& reservoirCells() const; - - // For cell info: - Status assignNextActiveCellInfoData( rips::CellInfo* cellInfo ); - void assignCellInfoData( rips::CellInfo* cellInfo, const std::vector& 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& 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& 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 m_globalCoarseningBoxIndexStart; - size_t m_currentCellIdx; -}; - -//================================================================================================== -// -// State handler for streaming of selected cells -// -//================================================================================================== -class RiaSelectedCellsStateHandler -{ - using Status = grpc::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& items ); - -protected: - const rips::CaseRequest* m_request; - RimEclipseCase* m_eclipseCase; - size_t m_currentItem; -}; +class RiaGrpcActiveCellInfoStateHandler; +class RiaGrpcSelectedCellsStateHandler; //================================================================================================== // @@ -122,22 +60,22 @@ class RiaGrpcCaseService final : public rips::Case::AsyncService, public RiaGrpc 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 GetCellInfoForActiveCells( grpc::ServerContext* context, + const rips::CellInfoRequest* request, + rips::CellInfoArray* reply, + RiaGrpcActiveCellInfoStateHandler* stateHandler ); + grpc::Status GetCellCenterForActiveCells( grpc::ServerContext* context, + const rips::CellInfoRequest* request, + rips::CellCenters* reply, + RiaGrpcActiveCellInfoStateHandler* stateHandler ); + grpc::Status GetCellCornersForActiveCells( grpc::ServerContext* context, + const rips::CellInfoRequest* request, + rips::CellCornersArray* reply, + RiaGrpcActiveCellInfoStateHandler* stateHandler ); + grpc::Status GetSelectedCells( grpc::ServerContext* context, + const rips::CaseRequest* request, + rips::SelectedCells* reply, + RiaGrpcSelectedCellsStateHandler* stateHandler ); grpc::Status GetReservoirBoundingBox( grpc::ServerContext* context, const rips::CaseRequest* request, rips::BoundingBox* reply ) override; @@ -145,5 +83,9 @@ class RiaGrpcCaseService final : public rips::Case::AsyncService, public RiaGrpc const rips::CaseRequest* request, rips::CoarseningInfoArray* reply ) override; + grpc::Status GetDistanceToClosestFault( grpc::ServerContext* context, + const rips::ClosestFaultRequest* request, + rips::ClosestFault* reply ) override; + std::vector createCallbacks() override; }; diff --git a/GrpcInterface/RiaGrpcHelper.cpp b/GrpcInterface/RiaGrpcHelper.cpp index 2775706663c..6e9a1f80cae 100644 --- a/GrpcInterface/RiaGrpcHelper.cpp +++ b/GrpcInterface/RiaGrpcHelper.cpp @@ -105,3 +105,25 @@ RimCase* RiaGrpcHelper::findCase( int caseId ) } return nullptr; } + +std::string RiaGrpcHelper::faceTypeToString( cvf::StructGridInterface::FaceType faceType ) +{ + switch ( faceType ) + { + case cvf::StructGridInterface::POS_I: + return "I+"; + case cvf::StructGridInterface::NEG_I: + return "I-"; + case cvf::StructGridInterface::POS_J: + return "J+"; + case cvf::StructGridInterface::NEG_J: + return "J-"; + case cvf::StructGridInterface::POS_K: + return "K+"; + case cvf::StructGridInterface::NEG_K: + return "K-"; + default: + break; + } + return ""; +} diff --git a/GrpcInterface/RiaGrpcHelper.h b/GrpcInterface/RiaGrpcHelper.h index b027876fd60..545e1810767 100644 --- a/GrpcInterface/RiaGrpcHelper.h +++ b/GrpcInterface/RiaGrpcHelper.h @@ -19,6 +19,7 @@ #include "Definitions.grpc.pb.h" +#include "cvfStructGrid.h" #include "cvfVector3.h" #include @@ -51,4 +52,6 @@ class RiaGrpcHelper static size_t numberOfDataUnitsInPackage( size_t dataUnitSize, size_t packageByteCount = 64 * 1024u ); static RimCase* findCase( int caseId ); + + static std::string faceTypeToString( cvf::StructGridInterface::FaceType ); }; diff --git a/GrpcInterface/RiaGrpcSelectedCellsStateHandler.cpp b/GrpcInterface/RiaGrpcSelectedCellsStateHandler.cpp new file mode 100644 index 00000000000..cf1c7b0ca0b --- /dev/null +++ b/GrpcInterface/RiaGrpcSelectedCellsStateHandler.cpp @@ -0,0 +1,155 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +////////////////////////////////////////////////////////////////////////////////// +#include "RiaGrpcSelectedCellsStateHandler.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" + +#include + +using namespace rips; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGrpcSelectedCellsStateHandler::RiaGrpcSelectedCellsStateHandler() + : m_request( nullptr ) + , m_eclipseCase( nullptr ) + , m_currentItem( 0u ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Status RiaGrpcSelectedCellsStateHandler::init( const rips::CaseRequest* request ) +{ + CAF_ASSERT( request ); + m_request = request; + + RimCase* rimCase = RiaGrpcHelper::findCase( m_request->id() ); + m_eclipseCase = dynamic_cast( 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 RiaGrpcSelectedCellsStateHandler::assignNextSelectedCell( rips::SelectedCell* cell, + const std::vector& 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 RiaGrpcSelectedCellsStateHandler::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 RiaGrpcSelectedCellsStateHandler::assignReply( rips::SelectedCells* reply ) +{ + std::vector items; + Riu3dSelectionManager::instance()->selectedItems( items ); + + // Only eclipse cases are currently supported. Also filter by case. + std::vector eclipseItems; + for ( auto item : items ) + { + RiuEclipseSelectionItem* eclipseItem = dynamic_cast( item ); + if ( eclipseItem && eclipseItem->m_resultDefinition->eclipseCase()->caseId() == m_request->id() ) + { + eclipseItems.push_back( eclipseItem ); + } + } + + const size_t packageSize = RiaGrpcHelper::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" ); +} diff --git a/GrpcInterface/RiaGrpcSelectedCellsStateHandler.h b/GrpcInterface/RiaGrpcSelectedCellsStateHandler.h new file mode 100644 index 00000000000..d850d34a9f0 --- /dev/null +++ b/GrpcInterface/RiaGrpcSelectedCellsStateHandler.h @@ -0,0 +1,55 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025 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 +// for more details. +// +////////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "Case.grpc.pb.h" + +#include "RiaGrpcServiceInterface.h" + +#include + +namespace rips +{ +class CaseRequest; +} // namespace rips + +class RimEclipseCase; +class RiuEclipseSelectionItem; + +//================================================================================================== +// +// State handler for streaming of selected cells +// +//================================================================================================== +class RiaGrpcSelectedCellsStateHandler +{ + using Status = grpc::Status; + +public: + RiaGrpcSelectedCellsStateHandler(); + + 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& items ); + +protected: + const rips::CaseRequest* m_request; + RimEclipseCase* m_eclipseCase; + size_t m_currentItem; +};