#4477 Add python methods to get NNC values (dynamic, static and generated).

Equivalent to GetDynamicNNCValues and GetStaticNNCValues in Octave. Also adds
support for generated values which is currently not in Octave.
This commit is contained in:
Kristian Bendiksen 2020-02-21 20:40:26 +01:00 committed by Gaute Lindkvist
parent 1a05430123
commit 34d3785709
5 changed files with 250 additions and 2 deletions

View File

@ -9,6 +9,7 @@ service NNCProperties
{
rpc GetAvailableNNCProperties(CaseRequest) returns (AvailableNNCProperties) {}
rpc GetNNCConnections(CaseRequest) returns (stream NNCConnections) {}
rpc GetNNCValues(NNCValuesRequest) returns (stream NNCValues) {}
}
enum NNCPropertyType
@ -41,3 +42,16 @@ 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;
}

View File

@ -1013,3 +1013,81 @@ class Case(PdmObject):
for value in chunk.connections:
connections.append(value)
return connections
def __nnc_connections_values_async(self, property_name, property_type, time_step):
request = NNCProperties_pb2.NNCValuesRequest(case_id=self.case_id,
property_name=property_name,
property_type=property_type,
time_step=time_step)
return self.__nnc_properties_stub.GetNNCValues(request)
def __nnc_values_generator_to_list(self, generator):
"""Converts a NNC values generator to a list."""
vals = []
for chunk in generator:
for value in chunk.values:
vals.append(value)
return vals
def nnc_connections_static_values_async(self, property_name):
"""Get the static NNC values. Async, so returns an iterator.
Returns:
An iterator to a chunk object containing an list of doubles.
Loop through the chunks and then the values within the chunk to get values
for all the connections. The order of the list matches the list from
nnc_connections, i.e. the nth object of nnc_connections() refers to nth
value in this list.
"""
return self.__nnc_connections_values_async(property_name, NNCProperties_pb2.NNC_STATIC, 0)
def nnc_connections_static_values(self, property_name):
"""Get the static NNC values.
Returns:
A list of doubles. The order of the list matches the list from
nnc_connections, i.e. the nth object of nnc_connections() refers to nth
value in this list.
"""
generator = self.nnc_connections_static_values_async(property_name)
return self.__nnc_values_generator_to_list(generator)
def nnc_connections_dynamic_values_async(self, property_name, time_step):
"""Get the dynamic NNC values. Async, so returns an iterator.
Returns:
An iterator to a chunk object containing an list of doubles.
Loop through the chunks and then the values within the chunk to get values
for all the connections. The order of the list matches the list from
nnc_connections, i.e. the nth object of nnc_connections() refers to nth
value in this list.
"""
return self.__nnc_connections_values_async(property_name, NNCProperties_pb2.NNC_DYNAMIC, time_step)
def nnc_connections_dynamic_values(self, property_name, time_step):
"""Get the dynamic NNC values.
Returns:
A list of doubles. The order of the list matches the list from
nnc_connections, i.e. the nth object of nnc_connections() refers to nth
value in this list.
"""
generator = self.nnc_connections_dynamic_values_async(property_name, time_step)
return self.__nnc_values_generator_to_list(generator)
def nnc_connections_generated_values_async(self, property_name, time_step):
"""Get the generated NNC values. Async, so returns an iterator.
Returns:
An iterator to a chunk object containing an list of doubles.
Loop through the chunks and then the values within the chunk to get values
for all the connections. The order of the list matches the list from
nnc_connections, i.e. the nth object of nnc_connections() refers to nth
value in this list.
"""
return self.__nnc_connections_values_async(property_name, NNCProperties_pb2.NNC_GENERATED, time_step)
def nnc_connections_generated_values(self, property_name, time_step):
"""Get the generated NNC values.
Returns:
A list of doubles. The order of the list matches the list from
nnc_connections, i.e. the nth object of nnc_connections() refers to nth
value in this list.
"""
generator = self.nnc_connections_generated_values_async(property_name, time_step)
return self.__nnc_values_generator_to_list(generator)

View File

@ -23,7 +23,7 @@ def test_10kSync(rips_instance, initialize_test):
assert("Binary Formation Allen" == properties[1].name)
assert(NNCProperties_pb2.NNCPropertyType.NNC_GENERATED == properties[1].property_type)
assert("Formation Allen" == properties[2].name)
assert(NNCProperties_pb2.NNCPropertyType.NNC_GENERATED == properties[2].property_type)
assert(NNCProperties_pb2.NNCPropertyType.NNC_GENERATED == properties[2].property_type)
nnc_connections = case.nnc_connections()
assert(len(nnc_connections) == 84759)
@ -33,3 +33,28 @@ def test_10kSync(rips_instance, initialize_test):
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))
allen_vals = case.nnc_connections_generated_values("Formation Allen", 0)
assert(len(allen_vals) == len(nnc_connections))
for a in allen_vals:
assert(isinstance(a, float))
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 Allen", 9999)

View File

@ -121,6 +121,105 @@ grpc::Status RiaGrpcNNCPropertiesService::GetNNCConnections( grpc::ServerContext
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();
std::vector<RigConnection> 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 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -172,7 +271,15 @@ std::vector<RiaGrpcCallbackInterface*> RiaGrpcNNCPropertiesService::createCallba
RiaNNCConnectionsStateHandler>( this,
&Self::GetNNCConnections,
&Self::RequestGetNNCConnections,
new RiaNNCConnectionsStateHandler )};
new RiaNNCConnectionsStateHandler ),
new RiaGrpcServerToClientStreamCallback<Self,
NNCValuesRequest,
rips::NNCValues,
RiaNNCValuesStateHandler>( this,
&Self::GetNNCValues,
&Self::RequestGetNNCValues,
new RiaNNCValuesStateHandler )};
return callbacks;
}

View File

@ -45,6 +45,26 @@ protected:
size_t m_currentIdx;
};
//==================================================================================================
//
// State handler for streaming of NNC values
//
//==================================================================================================
class RiaNNCValuesStateHandler
{
typedef grpc::Status Status;
public:
RiaNNCValuesStateHandler();
grpc::Status init( const rips::NNCValuesRequest* request );
grpc::Status assignReply( rips::NNCValues* reply );
protected:
const rips::NNCValuesRequest* m_request;
RimEclipseCase* m_eclipseCase;
size_t m_currentIdx;
};
//==================================================================================================
//
// gRPC-service answering requests about NNC property information for a given case and time step
@ -60,6 +80,10 @@ public:
const rips::CaseRequest* request,
rips::NNCConnections* reply,
RiaNNCConnectionsStateHandler* stateHandler );
grpc::Status GetNNCValues( grpc::ServerContext* context,
const rips::NNCValuesRequest* request,
rips::NNCValues* reply,
RiaNNCValuesStateHandler* stateHandler );
std::vector<RiaGrpcCallbackInterface*> createCallbacks() override;
};