Split generation of surface vertices and fault vertices for getGirdSurface

This commit is contained in:
Jørgen Herje
2024-03-22 15:37:30 +01:00
parent 4df9eabf9c
commit 985e2e21ee
12 changed files with 291 additions and 30 deletions

View File

@@ -73,7 +73,7 @@ RivGridPartMgr::RivGridPartMgr( RivCellSetEnum cellSetType, RimEclipseCase* ecli
: m_surfaceGenerator( grid, RiaRegressionTestRunner::instance()->useOpenMPForGeometryCreation() )
, m_gridIdx( gridIdx )
, m_grid( grid )
, m_surfaceFaceFilter( grid, false )
, m_surfaceFaceFilter( grid )
, m_opacityLevel( 1.0f )
, m_defaultColor( cvf::Color3::WHITE )
, m_eclipseCase( eclipseCase )

View File

@@ -572,7 +572,7 @@ bool RigGridCellFaceVisibilityFilter::isFaceVisible( size_t
const RigFault* fault = m_grid->mainGrid()->findFaultFromCellIndexAndCellFace( nativeResvCellIndex, face );
if ( fault )
{
return m_includeFaultFaces;
return false;
}
// If the neighbour cell is invisible, we need to draw the face

View File

@@ -128,9 +128,8 @@ private:
class RigGridCellFaceVisibilityFilter : public cvf::CellFaceVisibilityFilter
{
public:
explicit RigGridCellFaceVisibilityFilter( const RigGridBase* const grid, bool includeFaultFaces )
explicit RigGridCellFaceVisibilityFilter( const RigGridBase* const grid )
: m_grid( grid )
, m_includeFaultFaces( includeFaultFaces )
{
}
@@ -138,5 +137,4 @@ public:
private:
const RigGridBase* const m_grid;
const bool m_includeFaultFaces;
};

View File

@@ -50,6 +50,7 @@ set(SOURCE_GROUP_HEADER_FILES
RiaGrpcPdmObjectService.h
RiaGrpcApplicationInterface.h
RiaGrpcGridGeometryExtractionService.h
RiaGrpcGridGeometryExtractionServiceHelper.h
)
set(SOURCE_GROUP_SOURCE_FILES
@@ -67,6 +68,7 @@ set(SOURCE_GROUP_SOURCE_FILES
RiaGrpcPdmObjectService.cpp
RiaGrpcApplicationInterface.cpp
RiaGrpcGridGeometryExtractionService.cpp
RiaGrpcGridGeometryExtractionServiceHelper.cpp
)
# Find Protobuf installation Looks for protobuf-config.cmake file installed by

View File

@@ -43,7 +43,8 @@ norne_case_single_segment_poly_line_utm_xy = [457150, 7.32106e06, 456885, 7.3217
norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.32477e06]
fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy
# fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy
fence_poly_line_utm_xy = norne_case_single_segment_poly_line_gap_utm_xy
cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest(
gridFilename=grid_file_name,

View File

@@ -43,7 +43,7 @@ norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.3
fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy
num_calls = 20
num_calls = 1000
sleep_time_s = 0.5
for i in range(num_calls):
@@ -56,6 +56,8 @@ for i in range(num_calls):
GridGeometryExtraction__pb2.CutAlongPolylineResponse
) = grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request)
time.sleep(sleep_time_s)
# fence_mesh_sections = cut_along_polyline_response.fenceMeshSections
# print(f"Number of fence mesh sections: {len(fence_mesh_sections)}")
# time.sleep(sleep_time_s)
print("Done!")

View File

@@ -0,0 +1,62 @@
import numpy as np
import plotly.graph_objects as go
from rips.instance import *
from rips.generated.GridGeometryExtraction_pb2_grpc import *
from rips.generated.GridGeometryExtraction_pb2 import *
# from ..instance import *
# from ..generated.GridGeometryExtraction_pb2_grpc import *
# from ..generated.GridGeometryExtraction_pb2 import *
rips_instance = Instance.find()
grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel)
grid_file_name = (
"D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID"
)
# grid_file_name = "MOCKED_TEST_GRID"
# grid_file_name = "D:/ResInsight/GRID__SNORRE_BASECASEGRID.roff"
ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter(
iMin=-1, iMax=-1, jMin=-1, jMax=-1, kMin=1, kMax=12
)
ijk_index_filter = None
get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest(
gridFilename=grid_file_name,
ijkIndexFilter=ijk_index_filter,
cellIndexFilter=None,
propertyFilter=None,
)
get_grid_surface_response: GridGeometryExtraction__pb2.GetGridSurfaceResponse = (
grid_geometry_extraction_stub.GetGridSurface(get_grid_surface_request)
)
total_time_elapsed = get_grid_surface_response.timeElapsedInfo.totalTimeElapsedMs
named_events_and_time_elapsed = (
get_grid_surface_response.timeElapsedInfo.namedEventsAndTimeElapsedMs
)
vertex_array = get_grid_surface_response.vertexArray
quad_indices_array = get_grid_surface_response.quadIndicesArr
origin_utm_xy = get_grid_surface_response.originUtmXy
source_cell_indices_arr = get_grid_surface_response.sourceCellIndicesArr
grid_dimensions = get_grid_surface_response.gridDimensions
num_vertex_coords = 3 # [x, y, z]
num_vertices_per_quad = 4 # [v1, v2, v3, v4]
num_quads = len(vertex_array) / (num_vertex_coords * num_vertices_per_quad)
print(f"Number of quads: {num_quads}")
print(f"Source cell indices array length: {len(source_cell_indices_arr)}")
print(f"Origin UTM coordinates [x, y]: [{origin_utm_xy.x}, {origin_utm_xy.y}]")
print(
f"Grid dimensions [I, J, K]: [{grid_dimensions.i}, {grid_dimensions.j}, {grid_dimensions.k}]"
)
print(f"Total time elapsed: {total_time_elapsed} ms")
# print(f"Time elapsed per event [ms]: {named_events_and_time_elapsed}")
for message, time_elapsed in named_events_and_time_elapsed.items():
print(f"{message}: {time_elapsed}")

View File

@@ -17,11 +17,12 @@ grid_file_name = (
"D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID"
)
# grid_file_name = "MOCKED_TEST_GRID"
# grid_file_name = "D:/ResInsight/GRID__SNORRE_BASECASEGRID.roff"
ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter(
iMin=-1, iMax=-1, jMin=-1, jMax=-1, kMin=-1, kMax=-1
iMin=15, iMax=30, jMin=30, jMax=90, kMin=1, kMax=12
)
# ijk_index_filter = None
ijk_index_filter = None
get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest(
gridFilename=grid_file_name,

View File

@@ -32,11 +32,13 @@
#include "RigGeoMechCaseData.h"
#include "RigGridBase.h"
#include "RigMainGrid.h"
#include "RigNNCData.h"
#include "RimCase.h"
#include "RimCellFilterCollection.h"
#include "RimCellRangeFilter.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimFaultInViewCollection.h"
#include "RimGeoMechCase.h"
#include "RimGridView.h"
#include "RimProject.h"
@@ -112,6 +114,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC
return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse view found" );
}
eclipseView->setShowInactiveCells( true );
eclipseView->faultCollection()->setActive( false ); // TODO: Check if this is correct??
// Apply ijk-filtering - assuming 0-indexing from gRPC
if ( request->has_ijkindexfilter() )
@@ -125,15 +128,19 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC
// Configure eclipse view
// - Ensure static geometry parts created for grid part manager in view
// - Initialize grid geometry generator
// - To include inactive cells and activate requested filter for view
auto createGridGeometryPartsTimeCount = ElapsedTimeCount();
eclipseView->createGridGeometryParts();
m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridGeometryParts"] =
static_cast<std::uint32_t>( createGridGeometryPartsTimeCount.elapsedMsCount() );
const bool useOpenMP = false;
auto gridGeometryGenerator = cvf::StructGridGeometryGenerator( eclipseView->mainGrid(), useOpenMP );
status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( gridGeometryGenerator, eclipseView );
// Set visibility
const bool useOpenMP = false;
auto surfaceGridGeometryGenerator = cvf::StructGridGeometryGenerator( eclipseView->mainGrid(), useOpenMP );
auto faultGridGeometryGenerator = cvf::StructGridGeometryGenerator( eclipseView->mainGrid(), useOpenMP );
status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( surfaceGridGeometryGenerator,
faultGridGeometryGenerator,
eclipseView );
if ( status.error_code() != grpc::StatusCode::OK )
{
return status;
@@ -141,14 +148,24 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC
// Create grid surface vertices
auto createVerticesTimeCount = ElapsedTimeCount();
auto* gridSurfaceVertices = gridGeometryGenerator.getOrCreateVertices();
auto* gridSurfaceVertices = surfaceGridGeometryGenerator.getOrCreateVertices();
if ( gridSurfaceVertices == nullptr )
{
return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid vertices found" );
return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid surface vertices found" );
}
m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridSurfaceVertices"] =
static_cast<std::uint32_t>( createVerticesTimeCount.elapsedMsCount() );
// Create grid fault vertices
auto createFaultVerticesTimeCount = ElapsedTimeCount();
auto* gridFaultVertices = faultGridGeometryGenerator.getOrCreateVertices();
if ( gridFaultVertices == nullptr )
{
return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid fault vertices found" );
}
m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridFaultVertices"] =
static_cast<std::uint32_t>( createFaultVerticesTimeCount.elapsedMsCount() );
// Retrieve the UTM offset
const auto mainGridModelOffset = m_eclipseCase->mainGrid()->displayModelOffset();
@@ -165,6 +182,18 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC
response->add_quadindicesarr( static_cast<google::protobuf::uint32>( i ) );
}
const auto indexOffset = gridSurfaceVertices->size();
for ( size_t i = 0; i < gridFaultVertices->size(); ++i )
{
const auto& vertex = gridFaultVertices->get( i );
response->add_vertexarray( vertex.x() );
response->add_vertexarray( vertex.y() );
response->add_vertexarray( vertex.z() + zAxisOffset );
auto index = indexOffset + i;
response->add_quadindicesarr( static_cast<google::protobuf::uint32>( index ) );
}
// Origin is the UTM offset
rips::Vec2d* originUtmXy = new rips::Vec2d;
originUtmXy->set_x( mainGridModelOffset.x() );
@@ -173,9 +202,19 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC
// Source cell indices from main grid part manager
std::vector<size_t> sourceCellIndicesArray = std::vector<size_t>();
if ( gridGeometryGenerator.quadToCellFaceMapper() != nullptr )
if ( surfaceGridGeometryGenerator.quadToCellFaceMapper() != nullptr )
{
sourceCellIndicesArray = gridGeometryGenerator.quadToCellFaceMapper()->quadToCellIndicesArray();
for ( const auto& elm : surfaceGridGeometryGenerator.quadToCellFaceMapper()->quadToCellIndicesArray() )
{
sourceCellIndicesArray.push_back( elm );
}
}
if ( faultGridGeometryGenerator.quadToCellFaceMapper() != nullptr )
{
for ( const auto& elm : faultGridGeometryGenerator.quadToCellFaceMapper()->quadToCellIndicesArray() )
{
sourceCellIndicesArray.push_back( elm );
}
}
if ( sourceCellIndicesArray.empty() )
{
@@ -524,7 +563,8 @@ grpc::Status RiaGrpcGridGeometryExtractionService::applyIJKCellFilterToEclipseVi
///
//--------------------------------------------------------------------------------------------------
grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGeneratorWithEclipseViewCellVisibility(
cvf::StructGridGeometryGenerator& generator,
cvf::StructGridGeometryGenerator& surfaceGeometryGenerator,
cvf::StructGridGeometryGenerator& faultGeometryGenerator,
RimEclipseView* view )
{
if ( view == nullptr )
@@ -541,15 +581,19 @@ grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGenerat
// Cell visibilities
const int firstTimeStep = 0;
auto* cellVisibilities = new cvf::UByteArray( mainGrid->cellCount() );
view->calculateCurrentTotalCellVisibility( cellVisibilities, firstTimeStep );
view->calculateCurrentTotalCellVisibility( cellVisibilities, firstTimeStep ); // TODO: Check if this is correct way
// to get cell visibilities
// Face visibility filter
const bool includeFaultFaces = true;
m_faceVisibilityFilter = std::make_unique<RigGridCellFaceVisibilityFilter>(
RigGridCellFaceVisibilityFilter( mainGrid, includeFaultFaces ) );
m_surfaceFaceVisibilityFilter =
std::make_unique<RigGridCellFaceVisibilityFilter>( RigGridCellFaceVisibilityFilter( mainGrid ) );
surfaceGeometryGenerator.setCellVisibility( cellVisibilities ); // Ownership transferred
surfaceGeometryGenerator.addFaceVisibilityFilter( m_surfaceFaceVisibilityFilter.get() );
generator.setCellVisibility( cellVisibilities ); // Ownership transferred
generator.addFaceVisibilityFilter( m_faceVisibilityFilter.get() );
m_faultFaceVisibilityFilter =
std::make_unique<RigGridCellFaultFaceVisibilityFilter>( RigGridCellFaultFaceVisibilityFilter( mainGrid ) );
faultGeometryGenerator.setCellVisibility( cellVisibilities ); // Ownership transferred
faultGeometryGenerator.addFaceVisibilityFilter( m_faultFaceVisibilityFilter.get() );
return grpc::Status::OK;
}
@@ -637,6 +681,24 @@ grpc::Status
return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "More than one grid case found for project" );
}
m_eclipseCase = eclipseCases.front();
// Set nncData for main grid
// TODO: Do not perform if calling intersection endpoint only
if ( m_eclipseCase && m_eclipseCase->eclipseCaseData() && m_eclipseCase->eclipseCaseData()->mainGrid() &&
m_eclipseCase->eclipseCaseData()->mainGrid()->nncData() )
{
auto createNncDataForGrid = ElapsedTimeCount();
const bool includeInactiveCells = true;
m_eclipseCase->eclipseCaseData()
->mainGrid()
->nncData()
->setSourceDataForProcessing( m_eclipseCase->eclipseCaseData()->mainGrid(),
m_eclipseCase->eclipseCaseData()->activeCellInfo(
RiaDefines::PorosityModelType::MATRIX_MODEL ),
includeInactiveCells );
m_elapsedTimeInfo.elapsedTimePerEventMs["CreateNncDataForGrid"] =
static_cast<std::uint32_t>( createNncDataForGrid.elapsedMsCount() );
}
}
if ( m_eclipseCase == nullptr )

View File

@@ -19,6 +19,7 @@
#include "GridGeometryExtraction.grpc.pb.h"
#include "RiaApplication.h"
#include "RiaGrpcGridGeometryExtractionServiceHelper.h"
#include "RiaGrpcServiceInterface.h"
#include "RigGridBase.h"
#include "RimEclipseCase.h"
@@ -71,12 +72,15 @@ private:
grpc::Status applyIJKCellFilterToEclipseView( const rips::IJKIndexFilter& filter, RimEclipseView* view );
grpc::Status initializeApplicationAndEclipseCaseFromAbsoluteFilePath( const std::string filePath );
grpc::Status initializeGridGeometryGeneratorWithEclipseViewCellVisibility( cvf::StructGridGeometryGenerator& generator,
RimEclipseView* view );
grpc::Status initializeGridGeometryGeneratorWithEclipseViewCellVisibility(
cvf::StructGridGeometryGenerator& surfaceGeometryGenerator,
cvf::StructGridGeometryGenerator& faultGeometryGenerator,
RimEclipseView* view );
RiaApplication* m_application = nullptr;
RimEclipseCase* m_eclipseCase = nullptr;
std::unique_ptr<RigGridCellFaceVisibilityFilter> m_faceVisibilityFilter = nullptr;
RiaApplication* m_application = nullptr;
RimEclipseCase* m_eclipseCase = nullptr;
std::unique_ptr<RigGridCellFaceVisibilityFilter> m_surfaceFaceVisibilityFilter = nullptr;
std::unique_ptr<RigGridCellFaultFaceVisibilityFilter> m_faultFaceVisibilityFilter = nullptr;
struct ElapsedTimeInfo
{

View File

@@ -0,0 +1,91 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024- 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 "RiaGrpcGridGeometryExtractionServiceHelper.h"
#include "RigMainGrid.h"
#include "RigNNCData.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigGridCellFaultFaceVisibilityFilter::isFaceVisible( size_t i,
size_t j,
size_t k,
cvf::StructGridInterface::FaceType face,
const cvf::UByteArray* cellVisibility ) const
{
CVF_TIGHT_ASSERT( m_grid );
size_t cellIndex = m_grid->cellIndexFromIJK( i, j, k );
size_t nativeResvCellIndex = m_grid->reservoirCellIndex( cellIndex );
const RigFault* fault = m_grid->mainGrid()->findFaultFromCellIndexAndCellFace( nativeResvCellIndex, face );
if ( fault )
{
// TODO: REMOVE EARLY RETURN
return true; // TMP: Until we have a better way to determine if a fault face should be visible
// If no nnc data is generated, include fault face based on the flag
auto* nncData = m_grid->mainGrid()->nncData();
if ( nncData == nullptr || nncData->allConnections().empty() )
{
return true;
}
// Do not show fault if inside the grid
const auto& faultConnectionIndices = fault->connectionIndices();
for ( const auto& connectionIndex : faultConnectionIndices )
{
if ( connectionIndex >= nncData->allConnections().size() )
{
continue;
}
const RigConnection& connection = nncData->allConnections()[connectionIndex];
size_t oppositeCellIndex = std::numeric_limits<size_t>::max();
if ( connection.c1GlobIdx() == cellIndex )
{
oppositeCellIndex = connection.c2GlobIdx();
}
else if ( connection.c2GlobIdx() == cellIndex )
{
oppositeCellIndex = connection.c1GlobIdx();
}
if ( oppositeCellIndex >= cellVisibility->size() )
{
continue;
}
// TODO: This gives false for all fault faces, is cellVisibility incorrect?
// - Only want to include faults on the boundary of the surface, not the ones inside the grid
// - Now it excludes all, as all opposite cells are visible
// - Seems not to work if fault is on the boundary of the grid?
auto isOppositeCellVisible = ( *cellVisibility )[oppositeCellIndex] != 0;
if ( !isOppositeCellVisible )
{
return true;
}
}
// All opposite cells are visible, do not show the fault face
return false;
}
return false;
}

View File

@@ -0,0 +1,38 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024- 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 "RigGridBase.h"
class RigGridCellFaultFaceVisibilityFilter : public cvf::CellFaceVisibilityFilter
{
public:
explicit RigGridCellFaultFaceVisibilityFilter( const RigGridBase* const grid )
: m_grid( grid )
{
}
bool isFaceVisible( size_t i,
size_t j,
size_t k,
cvf::StructGridInterface::FaceType face,
const cvf::UByteArray* cellVisibility ) const override;
private:
const RigGridBase* const m_grid;
};