diff --git a/docs/geos_pv_docs/processing.rst b/docs/geos_pv_docs/processing.rst
index 726100fd..36800919 100644
--- a/docs/geos_pv_docs/processing.rst
+++ b/docs/geos_pv_docs/processing.rst
@@ -47,28 +47,10 @@ PVClipToMainFrame
Geos output pre-processing
+++++++++++++++++++++++++++++
-PVExtractMergeBlocksVolume plugin
--------------------------------------------
-
-.. automodule:: geos.pv.plugins.PVExtractMergeBlocksVolume
-
-
-PVExtractMergeBlocksVolumeSurface plugin
---------------------------------------------------
-
-.. automodule:: geos.pv.plugins.PVExtractMergeBlocksVolumeSurface
-
-
-PVExtractMergeBlocksVolumeSurfaceWell plugin
-------------------------------------------------------
-
-.. automodule:: geos.pv.plugins.PVExtractMergeBlocksVolumeSurfaceWell
-
-
-PVExtractMergeBlocksVolumeWell plugin
------------------------------------------------
+PVGeosBlockExtractAndMerge plugin
+----------------------------------
-.. automodule:: geos.pv.plugins.PVExtractMergeBlocksVolumeWell
+.. automodule:: geos.pv.plugins.PVGeosBlockExtractAndMerge
diff --git a/docs/geos_pv_docs/utils.rst b/docs/geos_pv_docs/utils.rst
index 3a868de5..31443918 100644
--- a/docs/geos_pv_docs/utils.rst
+++ b/docs/geos_pv_docs/utils.rst
@@ -24,6 +24,14 @@ geos.pv.utils.paraviewTreatments module
---------------------------------------------
.. automodule:: geos.pv.utils.paraviewTreatments
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+geos.pv.utils.workflowFunctions module
+---------------------------------------
+
+.. automodule:: geos.pv.utils.workflowFunctions
:members:
:undoc-members:
:show-inheritance:
\ No newline at end of file
diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py
index dcaf110e..09efe6a6 100644
--- a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py
+++ b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py
@@ -201,7 +201,7 @@ def computePhaseNames( self: Self ) -> None:
"""Get the names of the phases in the mesh from Cell attributes."""
# All the phase attributes are on cells
for name in getAttributeSet( self.inputMesh, False ):
- if PHASE_SEP in name:
+ if PHASE_SEP in name and "dofIndex" not in name:
phaseName: str
suffixName: str
phaseName, suffixName = name.split( PHASE_SEP )
diff --git a/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolume.py b/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolume.py
deleted file mode 100644
index 382f8bc8..00000000
--- a/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolume.py
+++ /dev/null
@@ -1,315 +0,0 @@
-# SPDX-License-Identifier: Apache-2.0
-# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
-# SPDX-FileContributor: Martin Lemay
-# ruff: noqa: E402 # disable Module level import not at top of file
-import sys
-from pathlib import Path
-import numpy as np
-import numpy.typing as npt
-from typing_extensions import Self
-from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector
-from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet
-
-# update sys.path to load all GEOS Python Package dependencies
-geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent
-sys.path.insert( 0, str( geos_pv_path / "src" ) )
-from geos.pv.utils.config import update_paths
-
-update_paths()
-
-from geos.utils.GeosOutputsConstants import (
- GeosMeshOutputsEnum,
- getAttributeToTransferFromInitialTime,
-)
-from geos.utils.Logger import ERROR, INFO, Logger, getLogger
-from geos.processing.post_processing.GeosBlockExtractor import GeosBlockExtractor
-from geos.processing.post_processing.GeosBlockMerge import GeosBlockMerge
-from geos.mesh.utils.arrayModifiers import (
- copyAttribute,
- createCellCenterAttribute,
-)
-from geos.pv.utils.paraviewTreatments import getTimeStepIndex
-from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
-)
-from paraview.detail.loghandler import ( # type: ignore[import-not-found]
- VTKHandler,
-) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py
-
-__doc__ = """
-PVExtractMergeBlocksVolume is a Paraview plugin that allows to merge ranks
-of a Geos output objects containing only a volumic mesh.
-
-Input and output types are vtkMultiBlockDataSet.
-
-This filter results in a single output pipeline that contains the volume mesh.
-If multiple regions were defined in the volume mesh, they are preserved as
-distinct blocks.
-
-To use it:
-
-* Load the module in Paraview: Tools>Manage Plugins...>Load new>PVExtractMergeBlocksVolume.
-* Select the Geos output .pvd file loaded in Paraview.
-* Search and Apply PVExtractMergeBlocksVolume Filter.
-
-"""
-
-
-@smproxy.filter(
- name="PVExtractMergeBlocksVolume",
- label="Geos Extract And Merge Blocks - Volume Only",
-)
-@smhint.xml( """
-
-
- """ )
-@smproperty.input( name="Input", port_index=0 )
-@smdomain.datatype( dataTypes=[ "vtkMultiBlockDataSet" ], composite_data_supported=True )
-class PVExtractMergeBlocksVolume( VTKPythonAlgorithmBase ):
-
- def __init__( self: Self ) -> None:
- """Paraview plugin to extract and merge ranks from Geos output Mesh.
-
- To apply in the case of output ".pvd" file contains only a Volume.
- """
- super().__init__(
- nInputPorts=1,
- nOutputPorts=1,
- inputType="vtkMultiBlockDataSet",
- outputType="vtkMultiBlockDataSet",
- )
-
- #: all time steps from input
- self.m_timeSteps: npt.NDArray[ np.float64 ] = np.array( [] )
- #: displayed time step in the IHM
- self.m_currentTime: float = 0.0
- #: time step index of displayed time step
- self.m_currentTimeStepIndex: int = 0
- #: request data processing step - incremented each time RequestUpdateExtent is called
- self.m_requestDataStep: int = -1
-
- #: saved object at initial time step
- self.m_outputT0: vtkMultiBlockDataSet = vtkMultiBlockDataSet()
-
- #: set logger
- self.m_logger: Logger = getLogger( "Extract and merge block Filter" )
-
- def SetLogger( self: Self, logger: Logger ) -> None:
- """Set filter logger.
-
- Args:
- logger (Logger): logger
- """
- self.m_logger = logger
-
- def FillInputPortInformation( self: Self, port: int, info: vtkInformation ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestInformation.
-
- Args:
- port (int): input port
- info (vtkInformationVector): info
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- if port == 0:
- info.Set( self.INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet" )
- return 1
-
- def RequestInformation(
- self: Self,
- request: vtkInformation, # noqa: F841
- inInfoVec: list[ vtkInformationVector ], # noqa: F841
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestInformation.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- executive = self.GetExecutive() # noqa: F841
- outInfo = outInfoVec.GetInformationObject( 0 ) # noqa: F841
- return 1
-
- def RequestDataObject(
- self: Self,
- request: vtkInformation,
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestDataObject.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- inData = self.GetInputData( inInfoVec, 0, 0 )
- outData = self.GetOutputData( outInfoVec, 0 )
- assert inData is not None
- if outData is None or ( not outData.IsA( inData.GetClassName() ) ):
- outData = inData.NewInstance()
- outInfoVec.GetInformationObject( 0 ).Set( outData.DATA_OBJECT(), outData )
- return super().RequestDataObject( request, inInfoVec, outInfoVec ) # type: ignore[no-any-return]
-
- def RequestUpdateExtent(
- self: Self,
- request: vtkInformation, # noqa: F841
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestUpdateExtent.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- executive = self.GetExecutive()
- inInfo = inInfoVec[ 0 ]
- # get displayed time step info before updating time
- if self.m_requestDataStep == -1:
- self.m_logger.info( f"Apply filter {__name__}" )
- self.m_timeSteps = inInfo.GetInformationObject( 0 ).Get( executive.TIME_STEPS() # type: ignore
- )
- self.m_currentTime = inInfo.GetInformationObject( 0 ).Get( executive.UPDATE_TIME_STEP() # type: ignore
- )
- self.m_currentTimeStepIndex = getTimeStepIndex( self.m_currentTime, self.m_timeSteps )
- # update requestDataStep
- self.m_requestDataStep += 1
-
- # update time according to requestDataStep iterator
- inInfo.GetInformationObject( 0 ).Set(
- executive.UPDATE_TIME_STEP(),
- self.m_timeSteps[ self.m_requestDataStep ] # type: ignore
- )
- outInfoVec.GetInformationObject( 0 ).Set(
- executive.UPDATE_TIME_STEP(),
- self.m_timeSteps[ self.m_requestDataStep ] # type: ignore
- )
-
- # update all objects according to new time info
- self.Modified()
- return 1
-
- def RequestData(
- self: Self,
- request: vtkInformation,
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestData.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- try:
- input: vtkMultiBlockDataSet = vtkMultiBlockDataSet.GetData( inInfoVec[ 0 ] )
- output: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 0 )
-
- assert input is not None, "Input object is null."
- assert output is not None, "Output object is null."
-
- # time controller
- executive = self.GetExecutive()
- if self.m_requestDataStep == 0:
- # first time step
- # do extraction and merge (do not display phase info)
- self.m_logger.setLevel( ERROR )
- self.doExtractAndMerge( input, output )
- self.m_logger.setLevel( INFO )
- # save input mesh to copy later
- self.m_outputT0.ShallowCopy( output )
- request.Set( executive.CONTINUE_EXECUTING(), 1 ) # type: ignore
- if self.m_requestDataStep >= self.m_currentTimeStepIndex:
- # displayed time step, no need to go further
- request.Remove( executive.CONTINUE_EXECUTING() ) # type: ignore
- # reinitialize requestDataStep if filter is recalled later
- self.m_requestDataStep = -1
- # do extraction and merge
- self.doExtractAndMerge( input, output )
- # copy attributes from initial time step
- for (
- attributeName,
- attributeNewName,
- ) in getAttributeToTransferFromInitialTime().items():
- copyAttribute( self.m_outputT0, output, attributeName, attributeNewName )
- # create elementCenter attribute if needed
- cellCenterAttributeName: str = ( GeosMeshOutputsEnum.ELEMENT_CENTER.attributeName )
- createCellCenterAttribute( output, cellCenterAttributeName )
-
- # TODO add ForceStaticMesh filter https://gitlab.kitware.com/paraview/plugins/staticmeshplugin
-
- except AssertionError as e:
- mess: str = "Block extraction and merge failed due to:"
- self.m_logger.error( mess )
- self.m_logger.error( str( e ) )
- return 0
- except Exception as e:
- mess1: str = "Block extraction and merge failed due to:"
- self.m_logger.critical( mess1 )
- self.m_logger.critical( e, exc_info=True )
- return 0
-
- return 1
-
- def doExtractAndMerge( self: Self, input: vtkMultiBlockDataSet, output: vtkMultiBlockDataSet ) -> bool:
- """Apply block extraction and merge.
-
- Args:
- input (vtkMultiBlockDataSet): input multi block
- output (vtkMultiBlockDataSet): output volume mesh
-
- Returns:
- bool: True if extraction and merge successfully ended, False otherwise
- """
- # extract blocks
- blockExtractor: GeosBlockExtractor = GeosBlockExtractor( input )
- blockExtractor.applyFilter()
-
- # recover output objects from GeosBlockExtractor filter
- volumeBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.volume
- assert volumeBlockExtracted is not None, "Extracted Volume mesh is null."
-
- # merge internal blocks
- output.ShallowCopy( self.mergeBlocksFilter( volumeBlockExtracted, False ) )
- output.Modified()
- self.m_logger.info( "Ranks were successfully merged together." )
- return True
-
- def mergeBlocksFilter( self: Self,
- input: vtkMultiBlockDataSet,
- convertSurfaces: bool = False ) -> vtkMultiBlockDataSet:
- """Apply vtk merge block filter on input multi block mesh.
-
- Args:
- input (vtkMultiBlockDataSet): multiblock mesh to merge
- convertSurfaces (bool, optional): True to convert surface from vtkUnstructuredGrid to
- vtkPolyData. Defaults to False.
-
- Returns:
- vtkMultiBlockDataSet: Multiblock mesh composed of internal merged blocks.
- """
- mergeBlockFilter: GeosBlockMerge = GeosBlockMerge( input, convertSurfaces, True )
- if not mergeBlockFilter.logger.hasHandlers():
- mergeBlockFilter.setLoggerHandler( VTKHandler() )
- mergeBlockFilter.applyFilter()
- mergedBlocks: vtkMultiBlockDataSet = mergeBlockFilter.getOutput()
- assert mergedBlocks is not None, "Final merged MultiBlockDataSet is null."
- return mergedBlocks
diff --git a/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolumeSurface.py b/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolumeSurface.py
deleted file mode 100644
index a670df2b..00000000
--- a/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolumeSurface.py
+++ /dev/null
@@ -1,337 +0,0 @@
-# SPDX-License-Identifier: Apache-2.0
-# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
-# SPDX-FileContributor: Martin Lemay
-# ruff: noqa: E402 # disable Module level import not at top of file
-import sys
-from pathlib import Path
-
-import numpy as np
-import numpy.typing as npt
-from typing_extensions import Self
-from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector
-from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet
-
-# update sys.path to load all GEOS Python Package dependencies
-geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent
-sys.path.insert( 0, str( geos_pv_path / "src" ) )
-from geos.pv.utils.config import update_paths
-
-update_paths()
-
-from geos.utils.GeosOutputsConstants import (
- GeosMeshOutputsEnum,
- getAttributeToTransferFromInitialTime,
-)
-from geos.utils.Logger import ERROR, INFO, Logger, getLogger
-from geos.processing.post_processing.GeosBlockExtractor import GeosBlockExtractor
-from geos.processing.post_processing.GeosBlockMerge import GeosBlockMerge
-from geos.mesh.utils.arrayModifiers import (
- copyAttribute,
- createCellCenterAttribute,
-)
-from geos.pv.utils.paraviewTreatments import getTimeStepIndex
-from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
-)
-from paraview.detail.loghandler import ( # type: ignore[import-not-found]
- VTKHandler,
-) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py
-
-__doc__ = """
-PVExtractMergeBlocksVolumeSurface is a Paraview plugin that allows to merge
-ranks of a Geos output objects containing a volumic mesh and surfaces.
-
-Input and output types are vtkMultiBlockDataSet.
-
-This filter results in 2 output pipelines:
-
-* first pipeline contains the volume mesh. If multiple regions were defined in
- the volume mesh, they are preserved as distinct blocks.
-* second pipeline contains surfaces. If multiple surfaces were used, they are
- preserved as distinct blocks.
-
-To use it:
-
-* Load the module in Paraview: Tools>Manage Plugins...>Load new>PVExtractMergeBlocksVolumeSurface.
-* Select the Geos output .pvd file loaded in Paraview.
-* Search and Apply PVExtractMergeBlocksVolumeSurface Filter.
-
-"""
-
-
-@smproxy.filter(
- name="PVExtractMergeBlocksVolumeSurface",
- label="Geos Extract And Merge Blocks - Volume/Surface",
-)
-@smhint.xml( """
-
-
-
- """ )
-@smproperty.input( name="Input", port_index=0 )
-@smdomain.datatype( dataTypes=[ "vtkMultiBlockDataSet" ], composite_data_supported=True )
-class PVExtractMergeBlocksVolumeSurface( VTKPythonAlgorithmBase ):
-
- def __init__( self: Self ) -> None:
- """Paraview plugin to extract and merge ranks from Geos output Mesh.
-
- To apply in the case of output ".pvd" file contains Volume and Fault
- elements.
- """
- super().__init__(
- nInputPorts=1,
- nOutputPorts=2,
- inputType="vtkMultiBlockDataSet",
- outputType="vtkMultiBlockDataSet",
- )
-
- #: all time steps from input
- self.m_timeSteps: npt.NDArray[ np.float64 ] = np.array( [] )
- #: displayed time step in the IHM
- self.m_currentTime: float = 0.0
- #: time step index of displayed time step
- self.m_currentTimeStepIndex: int = 0
- #: request data processing step - incremented each time RequestUpdateExtent is called
- self.m_requestDataStep: int = -1
-
- # saved object at initial time step
- self.m_outputT0: vtkMultiBlockDataSet = vtkMultiBlockDataSet()
-
- # set logger
- self.m_logger: Logger = getLogger( "Extract and merge block Filter" )
-
- def SetLogger( self: Self, logger: Logger ) -> None:
- """Set filter logger.
-
- Args:
- logger (Logger): logger
- """
- self.m_logger = logger
-
- def FillInputPortInformation( self: Self, port: int, info: vtkInformation ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestInformation.
-
- Args:
- port (int): input port
- info (vtkInformationVector): info
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- if port == 0:
- info.Set( self.INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet" )
- return 1
-
- def RequestInformation(
- self: Self,
- request: vtkInformation, # noqa: F841
- inInfoVec: list[ vtkInformationVector ], # noqa: F841
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestInformation.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- executive = self.GetExecutive() # noqa: F841
- outInfo = outInfoVec.GetInformationObject( 0 ) # noqa: F841
- return 1
-
- def RequestDataObject(
- self: Self,
- request: vtkInformation,
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestDataObject.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- inData = self.GetInputData( inInfoVec, 0, 0 )
- outDataCells = self.GetOutputData( outInfoVec, 0 )
- outDataFaults = self.GetOutputData( outInfoVec, 1 )
- assert inData is not None
- if outDataCells is None or ( not outDataCells.IsA( "vtkMultiBlockDataSet" ) ):
- outDataCells = vtkMultiBlockDataSet()
- outInfoVec.GetInformationObject( 0 ).Set( outDataCells.DATA_OBJECT(), outDataCells ) # type: ignore
- if outDataFaults is None or ( not outDataFaults.IsA( "vtkMultiBlockDataSet" ) ):
- outDataFaults = vtkMultiBlockDataSet()
- outInfoVec.GetInformationObject( 1 ).Set( outDataFaults.DATA_OBJECT(), outDataFaults ) # type: ignore
-
- return super().RequestDataObject( request, inInfoVec, outInfoVec ) # type: ignore[no-any-return]
-
- def RequestUpdateExtent(
- self: Self,
- request: vtkInformation, # noqa: F841
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestUpdateExtent.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- executive = self.GetExecutive()
- inInfo = inInfoVec[ 0 ]
- # get displayed time step info before updating time
- if self.m_requestDataStep == -1:
- self.m_logger.info( f"Apply filter {__name__}" )
- self.m_timeSteps = inInfo.GetInformationObject( 0 ).Get( executive.TIME_STEPS() ) # type: ignore
- self.m_currentTime = inInfo.GetInformationObject( 0 ).Get( executive.UPDATE_TIME_STEP() ) # type: ignore
- self.m_currentTimeStepIndex = getTimeStepIndex( self.m_currentTime, self.m_timeSteps )
- # update requestDataStep
- self.m_requestDataStep += 1
-
- # update time according to requestDataStep iterator
- inInfo.GetInformationObject( 0 ).Set(
- executive.UPDATE_TIME_STEP(), # type: ignore
- self.m_timeSteps[ self.m_requestDataStep ],
- )
- outInfoVec.GetInformationObject( 0 ).Set(
- executive.UPDATE_TIME_STEP(), # type: ignore
- self.m_timeSteps[ self.m_requestDataStep ],
- )
-
- # update all objects according to new time info
- self.Modified()
- return 1
-
- def RequestData(
- self: Self,
- request: vtkInformation,
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestData.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- try:
- input: vtkMultiBlockDataSet = vtkMultiBlockDataSet.GetData( inInfoVec[ 0 ] )
- outputCells: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 0 )
- outputFaults: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 1 )
-
- assert input is not None, "Input MultiBlockDataSet is null."
- assert outputCells is not None, "Output volum mesh is null."
- assert outputFaults is not None, "Output surface mesh is null."
-
- # time controller
- executive = self.GetExecutive()
- if self.m_requestDataStep == 0:
- # first time step
- # do extraction and merge (do not display phase info)
- outputFaults0: vtkMultiBlockDataSet = vtkMultiBlockDataSet()
- self.m_logger.setLevel( ERROR )
- self.doExtractAndMerge( input, self.m_outputT0, outputFaults0 )
- self.m_logger.setLevel( INFO )
- request.Set( executive.CONTINUE_EXECUTING(), 1 ) # type: ignore
-
- if self.m_requestDataStep >= self.m_currentTimeStepIndex:
- # displayed time step, no need to go further
- request.Remove( executive.CONTINUE_EXECUTING() ) # type: ignore
- # reinitialize requestDataStep if filter is recalled later
- self.m_requestDataStep = -1
- # do extraction and merge
- self.doExtractAndMerge( input, outputCells, outputFaults )
- # copy attributes from initial time step
- for (
- attributeName,
- attributeNewName,
- ) in getAttributeToTransferFromInitialTime().items():
- copyAttribute( self.m_outputT0, outputCells, attributeName, attributeNewName )
- # create elementCenter attribute if needed
- cellCenterAttributeName: str = ( GeosMeshOutputsEnum.ELEMENT_CENTER.attributeName )
- createCellCenterAttribute( outputCells, cellCenterAttributeName )
-
- except AssertionError as e:
- mess: str = "Block extraction and merge failed due to:"
- self.m_logger.error( mess )
- self.m_logger.error( str( e ) )
- return 0
- except Exception as e:
- mess1: str = "Block extraction and merge failed due to:"
- self.m_logger.critical( mess1 )
- self.m_logger.critical( e, exc_info=True )
- return 0
-
- return 1
-
- def doExtractAndMerge(
- self: Self,
- input: vtkMultiBlockDataSet,
- outputCells: vtkMultiBlockDataSet,
- outputFaults: vtkMultiBlockDataSet,
- ) -> bool:
- """Apply block extraction and merge.
-
- Args:
- input (vtkMultiBlockDataSet): input multi block
- outputCells (vtkMultiBlockDataSet): output volume mesh
- outputFaults (vtkMultiBlockDataSet): output surface mesh
-
- Returns:
- bool: True if extraction and merge successfully eneded, False otherwise
- """
- # extract blocks
- blockExtractor: GeosBlockExtractor = GeosBlockExtractor( input, extractFault=True )
- blockExtractor.applyFilter()
-
- # recover output objects from GeosBlockExtractor filter
- volumeBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.volume
- faultBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.fault
-
- # rename attributes and merge blocks
- assert volumeBlockExtracted is not None, "Extracted Volume mesh is null."
- outputCells.ShallowCopy( self.mergeBlocksFilter( volumeBlockExtracted, False ) )
- outputCells.Modified()
-
- assert faultBlockExtracted is not None, "Extracted Fault mesh is null."
- outputFaults.ShallowCopy( self.mergeBlocksFilter( faultBlockExtracted, True ) )
- outputFaults.Modified()
-
- self.m_logger.info( "Volume blocks were successfully splitted from surfaces" +
- " and ranks were merged together." )
- return True
-
- def mergeBlocksFilter( self: Self,
- input: vtkMultiBlockDataSet,
- convertSurfaces: bool = False ) -> vtkMultiBlockDataSet:
- """Apply vtk merge block filter on input multi block mesh.
-
- Args:
- input (vtkMultiBlockDataSet): multiblock mesh to merge
- convertSurfaces (bool, optional): True to convert surface from vtkUnstructuredGrid to
- vtkPolyData. Defaults to False.
-
- Returns:
- vtkMultiBlockDataSet: Multiblock mesh composed of internal merged blocks.
- """
- mergeBlockFilter: GeosBlockMerge = GeosBlockMerge( input, convertSurfaces, True )
- if not mergeBlockFilter.logger.hasHandlers():
- mergeBlockFilter.setLoggerHandler( VTKHandler() )
- mergeBlockFilter.applyFilter()
- mergedBlocks: vtkMultiBlockDataSet = mergeBlockFilter.getOutput()
- assert mergedBlocks is not None, "Final merged MultiBlockDataSet is null."
- return mergedBlocks
diff --git a/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolumeSurfaceWell.py b/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolumeSurfaceWell.py
deleted file mode 100644
index d3eff7af..00000000
--- a/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolumeSurfaceWell.py
+++ /dev/null
@@ -1,365 +0,0 @@
-# SPDX-License-Identifier: Apache-2.0
-# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
-# SPDX-FileContributor: Martin Lemay
-# ruff: noqa: E402 # disable Module level import not at top of file
-import sys
-from pathlib import Path
-
-import numpy as np
-import numpy.typing as npt
-from typing_extensions import Self
-from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector
-from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet
-
-# update sys.path to load all GEOS Python Package dependencies
-geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent
-sys.path.insert( 0, str( geos_pv_path / "src" ) )
-from geos.pv.utils.config import update_paths
-
-update_paths()
-
-from geos.utils.GeosOutputsConstants import (
- GeosMeshOutputsEnum,
- getAttributeToTransferFromInitialTime,
-)
-from geos.utils.Logger import ERROR, INFO, Logger, getLogger
-from geos.processing.post_processing.GeosBlockExtractor import GeosBlockExtractor
-from geos.processing.post_processing.GeosBlockMerge import GeosBlockMerge
-from geos.mesh.utils.arrayModifiers import (
- copyAttribute,
- createCellCenterAttribute,
-)
-from geos.pv.utils.paraviewTreatments import getTimeStepIndex
-from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
-)
-from paraview.detail.loghandler import ( # type: ignore[import-not-found]
- VTKHandler,
-) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py
-
-__doc__ = """
-PVExtractMergeBlocksVolumeSurfaceWell is a Paraview plugin that allows to merge
-ranks of a Geos output objects containing a volumic mesh, surfaces, and wells.
-
-Input and output types are vtkMultiBlockDataSet.
-
-This filter results in 3 output pipelines:
-
-* first pipeline contains the volume mesh. If multiple regions were defined in
- the volume mesh, they are preserved as distinct blocks.
-* second pipeline contains surfaces. If multiple surfaces were used, they are
- preserved as distinct blocks.
-* third pipeline contains wells. If multiple wells were used, they are preserved
- as distinct blocks.
-
-To use it:
-
-* Load the module in Paraview: Tools>Manage Plugins...>Load new>PVExtractMergeBlocksVolumeSurfaceWell.
-* Select the Geos output .pvd file loaded in Paraview.
-* Search and Apply PVExtractMergeBlocksVolumeSurfaceWell Filter.
-
-"""
-
-
-@smproxy.filter(
- name="PVExtractMergeBlocksVolumeSurfaceWell",
- label="Geos Extract And Merge Blocks - Volume/Surface/Well",
-)
-@smhint.xml( """
-
-
-
-
- """ )
-@smproperty.input( name="Input", port_index=0 )
-@smdomain.datatype( dataTypes=[ "vtkMultiBlockDataSet" ], composite_data_supported=True )
-class PVExtractMergeBlocksVolumeSurfaceWell( VTKPythonAlgorithmBase ):
-
- def __init__( self: Self ) -> None:
- """Paraview plugin to extract and merge ranks from Geos output Mesh.
-
- To apply in the case of output ".pvd" file contains Volume, Fault and
- Well elements.
- """
- super().__init__(
- nInputPorts=1,
- nOutputPorts=3,
- inputType="vtkMultiBlockDataSet",
- outputType="vtkMultiBlockDataSet",
- )
-
- #: all time steps from input
- self.m_timeSteps: npt.NDArray[ np.float64 ] = np.array( [] )
- #: displayed time step in the IHM
- self.m_currentTime: float = 0.0
- #: time step index of displayed time step
- self.m_currentTimeStepIndex: int = 0
- #: request data processing step - incremented each time RequestUpdateExtent is called
- self.m_requestDataStep: int = -1
-
- # saved object at initial time step
- self.m_outputT0: vtkMultiBlockDataSet = vtkMultiBlockDataSet()
-
- # set logger
- self.m_logger: Logger = getLogger( "Extract and merge block Filter" )
-
- def SetLogger( self: Self, logger: Logger ) -> None:
- """Set filter logger.
-
- Args:
- logger (Logger): logger
- """
- self.m_logger = logger
-
- def FillInputPortInformation( self: Self, port: int, info: vtkInformation ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestInformation.
-
- Args:
- port (int): input port
- info (vtkInformationVector): info
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- if port == 0:
- info.Set( self.INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet" )
- return 1
-
- def RequestInformation(
- self: Self,
- request: vtkInformation, # noqa: F841
- inInfoVec: list[ vtkInformationVector ], # noqa: F841
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestInformation.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- executive = self.GetExecutive() # noqa: F841
- outInfo = outInfoVec.GetInformationObject( 0 ) # noqa: F841
- return 1
-
- def RequestDataObject(
- self: Self,
- request: vtkInformation,
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestDataObject.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- inData = self.GetInputData( inInfoVec, 0, 0 )
- outDataCells = self.GetOutputData( outInfoVec, 0 )
- outDataFaults = self.GetOutputData( outInfoVec, 1 )
- outDataWells = self.GetOutputData( outInfoVec, 2 )
- assert inData is not None
- if outDataCells is None or ( not outDataCells.IsA( "vtkMultiBlockDataSet" ) ):
- outDataCells = vtkMultiBlockDataSet()
- outInfoVec.GetInformationObject( 0 ).Set(
- outDataCells.DATA_OBJECT(),
- outDataCells # type: ignore
- )
-
- if outDataFaults is None or ( not outDataFaults.IsA( "vtkMultiBlockDataSet" ) ):
- outDataFaults = vtkMultiBlockDataSet()
- outInfoVec.GetInformationObject( 1 ).Set(
- outDataFaults.DATA_OBJECT(),
- outDataFaults # type: ignore
- )
-
- if outDataWells is None or ( not outDataWells.IsA( "vtkMultiBlockDataSet" ) ):
- outDataWells = vtkMultiBlockDataSet()
- outInfoVec.GetInformationObject( 2 ).Set(
- outDataWells.DATA_OBJECT(),
- outDataWells # type: ignore
- )
-
- return super().RequestDataObject( request, inInfoVec, outInfoVec ) # type: ignore[no-any-return]
-
- def RequestUpdateExtent(
- self: Self,
- request: vtkInformation, # noqa: F841
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestUpdateExtent.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- executive = self.GetExecutive()
- inInfo = inInfoVec[ 0 ]
- # get displayed time step info before updating time
- if self.m_requestDataStep == -1:
- self.m_logger.info( f"Apply filter {__name__}" )
- self.m_timeSteps = inInfo.GetInformationObject( 0 ).Get( executive.TIME_STEPS() # type: ignore
- )
- self.m_currentTime = inInfo.GetInformationObject( 0 ).Get( executive.UPDATE_TIME_STEP() # type: ignore
- )
- self.m_currentTimeStepIndex = getTimeStepIndex( self.m_currentTime, self.m_timeSteps )
- # update requestDataStep
- self.m_requestDataStep += 1
-
- # update time according to requestDataStep iterator
- inInfo.GetInformationObject( 0 ).Set(
- executive.UPDATE_TIME_STEP(),
- self.m_timeSteps[ self.m_requestDataStep ] # type: ignore
- )
- outInfoVec.GetInformationObject( 0 ).Set(
- executive.UPDATE_TIME_STEP(),
- self.m_timeSteps[ self.m_requestDataStep ] # type: ignore
- )
-
- # update all objects according to new time info
- self.Modified()
- return 1
-
- def RequestData(
- self: Self,
- request: vtkInformation,
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestData.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- try:
- input: vtkMultiBlockDataSet = vtkMultiBlockDataSet.GetData( inInfoVec[ 0 ] )
- outputCells: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 0 )
- outputFaults: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 1 )
- outputWells: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 2 )
-
- assert input is not None, "Input MultiBlockDataSet is null."
- assert outputCells is not None, "Output volum mesh is null."
- assert outputFaults is not None, "Output surface mesh is null."
- assert outputWells is not None, "Output well mesh is null."
-
- # time controller
- executive = self.GetExecutive()
- if self.m_requestDataStep == 0:
- # first time step
- # do extraction and merge (do not display phase info)
- self.m_logger.setLevel( ERROR )
- outputFaults0: vtkMultiBlockDataSet = vtkMultiBlockDataSet()
- outputWells0: vtkMultiBlockDataSet = vtkMultiBlockDataSet()
- self.doExtractAndMerge( input, outputCells, outputFaults0, outputWells0 )
- self.m_logger.setLevel( INFO )
- # save input mesh to copy later
- self.m_outputT0.ShallowCopy( outputCells )
- request.Set( executive.CONTINUE_EXECUTING(), 1 ) # type: ignore
- if self.m_requestDataStep >= self.m_currentTimeStepIndex:
- # displayed time step, no need to go further
- request.Remove( executive.CONTINUE_EXECUTING() ) # type: ignore
- # reinitialize requestDataStep if filter is recalled later
- self.m_requestDataStep = -1
- # do extraction and merge
- self.doExtractAndMerge( input, outputCells, outputFaults, outputWells )
- # copy attributes from initial time step
- for (
- attributeName,
- attributeNewName,
- ) in getAttributeToTransferFromInitialTime().items():
- copyAttribute( self.m_outputT0, outputCells, attributeName, attributeNewName )
- # create elementCenter attribute in the volume mesh if needed
- cellCenterAttributeName: str = ( GeosMeshOutputsEnum.ELEMENT_CENTER.attributeName )
- createCellCenterAttribute( outputCells, cellCenterAttributeName )
- except AssertionError as e:
- mess: str = "Block extraction and merge failed due to:"
- self.m_logger.error( mess )
- self.m_logger.error( str( e ) )
- return 0
- except Exception as e:
- mess1: str = "Block extraction and merge failed due to:"
- self.m_logger.critical( mess1 )
- self.m_logger.critical( e, exc_info=True )
- return 0
- return 1
-
- def doExtractAndMerge(
- self: Self,
- input: vtkMultiBlockDataSet,
- outputCells: vtkMultiBlockDataSet,
- outputFaults: vtkMultiBlockDataSet,
- outputWells: vtkMultiBlockDataSet,
- ) -> bool:
- """Apply block extraction and merge.
-
- Args:
- input (vtkMultiBlockDataSet): input multi block
- outputCells (vtkMultiBlockDataSet): output volume mesh
- outputFaults (vtkMultiBlockDataSet): output surface mesh
- outputWells (vtkMultiBlockDataSet): output well mesh
-
- Returns:
- bool: True if extraction and merge successfully eneded, False otherwise
- """
- # extract blocks
- blockExtractor: GeosBlockExtractor = GeosBlockExtractor( input, extractFaults=True, extractWells=True )
- blockExtractor.applyFilter()
-
- # recover output objects from GeosBlockExtractor filter and merge internal blocks
- volumeBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.volume
- assert volumeBlockExtracted is not None, "Extracted Volume mesh is null."
- outputCells.ShallowCopy( self.mergeBlocksFilter( volumeBlockExtracted, False ) )
-
- faultBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.fault
- assert faultBlockExtracted is not None, "Extracted Fault mesh is null."
- outputFaults.ShallowCopy( self.mergeBlocksFilter( faultBlockExtracted, True ) )
-
- wellBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.well
- assert wellBlockExtracted is not None, "Extracted Well mesh is null."
- outputWells.ShallowCopy( self.mergeBlocksFilter( wellBlockExtracted, False ) )
-
- outputCells.Modified()
- outputFaults.Modified()
- outputWells.Modified()
-
- self.m_logger.info( "Volume blocks were successfully splitted from surfaces" +
- " and wells, and ranks were merged together." )
- return True
-
- def mergeBlocksFilter( self: Self,
- input: vtkMultiBlockDataSet,
- convertSurfaces: bool = False ) -> vtkMultiBlockDataSet:
- """Apply vtk merge block filter on input multi block mesh.
-
- Args:
- input (vtkMultiBlockDataSet): multiblock mesh to merge
- convertSurfaces (bool, optional): True to convert surface from vtkUnstructuredGrid to
- vtkPolyData. Defaults to False.
-
- Returns:
- vtkMultiBlockDataSet: Multiblock mesh composed of internal merged blocks.
- """
- mergeBlockFilter: GeosBlockMerge = GeosBlockMerge( input, convertSurfaces, True )
- if not mergeBlockFilter.logger.hasHandlers():
- mergeBlockFilter.setLoggerHandler( VTKHandler() )
- mergeBlockFilter.applyFilter()
- mergedBlocks: vtkMultiBlockDataSet = mergeBlockFilter.getOutput()
- assert mergedBlocks is not None, "Final merged MultiBlockDataSet is null."
- return mergedBlocks
diff --git a/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolumeWell.py b/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolumeWell.py
deleted file mode 100644
index d1da166b..00000000
--- a/geos-pv/src/geos/pv/plugins/PVExtractMergeBlocksVolumeWell.py
+++ /dev/null
@@ -1,346 +0,0 @@
-# SPDX-License-Identifier: Apache-2.0
-# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
-# SPDX-FileContributor: Martin Lemay
-# ruff: noqa: E402 # disable Module level import not at top of file
-import sys
-from pathlib import Path
-
-import numpy as np
-import numpy.typing as npt
-from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
-)
-from paraview.detail.loghandler import ( # type: ignore[import-not-found]
- VTKHandler,
-) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py
-from typing_extensions import Self
-from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector
-from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet
-
-# update sys.path to load all GEOS Python Package dependencies
-geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent
-sys.path.insert( 0, str( geos_pv_path / "src" ) )
-from geos.pv.utils.config import update_paths
-
-update_paths()
-
-from geos.utils.GeosOutputsConstants import (
- GeosMeshOutputsEnum,
- getAttributeToTransferFromInitialTime,
-)
-from geos.utils.Logger import ERROR, INFO, Logger, getLogger
-from geos.processing.post_processing.GeosBlockExtractor import GeosBlockExtractor
-from geos.processing.post_processing.GeosBlockMerge import GeosBlockMerge
-from geos.mesh.utils.arrayModifiers import (
- copyAttribute,
- createCellCenterAttribute,
-)
-from geos.pv.utils.paraviewTreatments import getTimeStepIndex
-
-__doc__ = """
-PVExtractMergeBlocksVolumeWell is a Paraview plugin that allows to merge
-ranks of a Geos output objects containing a volumic mesh and wells.
-
-Input and output types are vtkMultiBlockDataSet.
-
-This filter results in 2 output pipelines:
-
-* first pipeline contains the volume mesh. If multiple regions were defined in
- the volume mesh, they are preserved as distinct blocks.
-* second pipeline contains wells. If multiple wells were used, they are preserved
- as distinct blocks.
-
-To use it:
-
-* Load the module in Paraview: Tools>Manage Plugins...>Load new>PVExtractMergeBlocksVolumeWell.
-* Select the Geos output .pvd file loaded in Paraview.
-* Search and Apply PVExtractMergeBlocksVolumeWell Filter.
-
-"""
-
-
-@smproxy.filter(
- name="PVExtractMergeBlocksVolumeWell",
- label="Geos Extract And Merge Blocks - Volume/Well",
-)
-@smhint.xml( """
-
-
-
- """ )
-@smproperty.input( name="Input", port_index=0 )
-@smdomain.datatype( dataTypes=[ "vtkMultiBlockDataSet" ], composite_data_supported=True )
-class PVExtractMergeBlocksVolumeWell( VTKPythonAlgorithmBase ):
-
- def __init__( self: Self ) -> None:
- """Paraview plugin to extract and merge ranks from Geos output Mesh.
-
- To apply in the case of output ".pvd" file contains Volume and Well
- elements.
- """
- super().__init__(
- nInputPorts=1,
- nOutputPorts=2,
- inputType="vtkMultiBlockDataSet",
- outputType="vtkMultiBlockDataSet",
- )
-
- #: all time steps from input
- self.m_timeSteps: npt.NDArray[ np.float64 ] = np.array( [] )
- #: displayed time step in the IHM
- self.m_currentTime: float = 0.0
- #: time step index of displayed time step
- self.m_currentTimeStepIndex: int = 0
- #: request data processing step - incremented each time RequestUpdateExtent is called
- self.m_requestDataStep: int = -1
-
- # saved object at initial time step
- self.m_outputT0: vtkMultiBlockDataSet = vtkMultiBlockDataSet()
-
- # set logger
- self.m_logger: Logger = getLogger( "Extract and merge block Filter" )
-
- def SetLogger( self: Self, logger: Logger ) -> None:
- """Set filter logger.
-
- Args:
- logger (Logger): logger
- """
- self.m_logger = logger
-
- def FillInputPortInformation( self: Self, port: int, info: vtkInformation ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestInformation.
-
- Args:
- port (int): input port
- info (vtkInformationVector): info
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- if port == 0:
- info.Set( self.INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet" )
- return 1
-
- def RequestInformation(
- self: Self,
- request: vtkInformation, # noqa: F841
- inInfoVec: list[ vtkInformationVector ], # noqa: F841
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestInformation.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- executive = self.GetExecutive() # noqa: F841
- outInfo = outInfoVec.GetInformationObject( 0 ) # noqa: F841
- return 1
-
- def RequestDataObject(
- self: Self,
- request: vtkInformation,
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestDataObject.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- inData = self.GetInputData( inInfoVec, 0, 0 )
- outDataCells = self.GetOutputData( outInfoVec, 0 )
- outDataWells = self.GetOutputData( outInfoVec, 1 )
- assert inData is not None
- if outDataCells is None or ( not outDataCells.IsA( "vtkMultiBlockDataSet" ) ):
- outDataCells = vtkMultiBlockDataSet()
- outInfoVec.GetInformationObject( 0 ).Set(
- outDataCells.DATA_OBJECT(),
- outDataCells # type: ignore
- )
-
- if outDataWells is None or ( not outDataWells.IsA( "vtkMultiBlockDataSet" ) ):
- outDataWells = vtkMultiBlockDataSet()
- outInfoVec.GetInformationObject( 1 ).Set(
- outDataWells.DATA_OBJECT(),
- outDataWells # type: ignore
- )
-
- return super().RequestDataObject( request, inInfoVec, outInfoVec ) # type: ignore[no-any-return]
-
- def RequestUpdateExtent(
- self: Self,
- request: vtkInformation, # noqa: F841
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestUpdateExtent.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- executive = self.GetExecutive()
- inInfo = inInfoVec[ 0 ]
- # get displayed time step info before updating time
- if self.m_requestDataStep == -1:
- self.m_logger.info( f"Apply filter {__name__}" )
- self.m_timeSteps = inInfo.GetInformationObject( 0 ).Get( executive.TIME_STEPS() # type: ignore
- )
- self.m_currentTime = inInfo.GetInformationObject( 0 ).Get( executive.UPDATE_TIME_STEP() # type: ignore
- )
- self.m_currentTimeStepIndex = getTimeStepIndex( self.m_currentTime, self.m_timeSteps )
- # update requestDataStep
- self.m_requestDataStep += 1
-
- # update time according to requestDataStep iterator
- inInfo.GetInformationObject( 0 ).Set(
- executive.UPDATE_TIME_STEP(),
- self.m_timeSteps[ self.m_requestDataStep ] # type: ignore
- )
- outInfoVec.GetInformationObject( 0 ).Set(
- executive.UPDATE_TIME_STEP(),
- self.m_timeSteps[ self.m_requestDataStep ] # type: ignore
- )
-
- # update all objects according to new time info
- self.Modified()
- return 1
-
- def RequestData(
- self: Self,
- request: vtkInformation,
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestData.
-
- Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- try:
- input: vtkMultiBlockDataSet = vtkMultiBlockDataSet.GetData( inInfoVec[ 0 ] )
- outputCells: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 0 )
- outputWells: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 1 )
-
- assert input is not None, "Input MultiBlockDataSet is null."
- assert outputCells is not None, "Output volum mesh is null."
- assert outputWells is not None, "Output well mesh is null."
-
- # time controller
- executive = self.GetExecutive()
- if self.m_requestDataStep == 0:
- # first time step
- # do extraction and merge (do not display phase info)
- self.m_logger.setLevel( ERROR )
- outputWells0: vtkMultiBlockDataSet = vtkMultiBlockDataSet()
- self.doExtractAndMerge( input, outputCells, outputWells0 )
- self.m_logger.setLevel( INFO )
- # save input mesh to copy later
- self.m_outputT0.ShallowCopy( outputCells )
- request.Set( executive.CONTINUE_EXECUTING(), 1 ) # type: ignore
- if self.m_requestDataStep >= self.m_currentTimeStepIndex:
- # displayed time step, no need to go further
- request.Remove( executive.CONTINUE_EXECUTING() ) # type: ignore
- # reinitialize requestDataStep if filter is recalled later
- self.m_requestDataStep = -1
- # do extraction and merge
- self.doExtractAndMerge( input, outputCells, outputWells )
- # copy attributes from initial time step
- for (
- attributeName,
- attributeNewName,
- ) in getAttributeToTransferFromInitialTime().items():
- copyAttribute( self.m_outputT0, outputCells, attributeName, attributeNewName )
- # create elementCenter attribute if needed
- cellCenterAttributeName: str = ( GeosMeshOutputsEnum.ELEMENT_CENTER.attributeName )
- createCellCenterAttribute( outputCells, cellCenterAttributeName )
-
- except AssertionError as e:
- mess: str = "Block extraction and merge failed due to:"
- self.m_logger.error( mess )
- self.m_logger.error( str( e ) )
- return 0
- except Exception as e:
- mess1: str = "Block extraction and merge failed due to:"
- self.m_logger.critical( mess1 )
- self.m_logger.critical( e, exc_info=True )
- return 0
-
- return 1
-
- def doExtractAndMerge(
- self: Self,
- input: vtkMultiBlockDataSet,
- outputCells: vtkMultiBlockDataSet,
- outputWells: vtkMultiBlockDataSet,
- ) -> bool:
- """Apply block extraction and merge.
-
- Args:
- input (vtkMultiBlockDataSet): input multi block
- outputCells (vtkMultiBlockDataSet): output volume mesh
- outputWells (vtkMultiBlockDataSet): output well mesh
-
- Returns:
- bool: True if extraction and merge successfully eneded, False otherwise
- """
- # extract blocks
- blockExtractor: GeosBlockExtractor = GeosBlockExtractor( input, extractWells=True )
- blockExtractor.applyFilter()
-
- # recover output objects from GeosBlockExtractor filter and merge internal blocks
- volumeBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.volume
- assert volumeBlockExtracted is not None, "Extracted Volume mesh is null."
- outputCells.ShallowCopy( self.mergeBlocksFilter( volumeBlockExtracted, False ) )
-
- wellBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.well
- assert wellBlockExtracted is not None, "Extracted Well mesh is null."
- outputWells.ShallowCopy( self.mergeBlocksFilter( wellBlockExtracted, False ) )
-
- outputCells.Modified()
- outputWells.Modified()
-
- self.m_logger.info( "Volume blocks were successfully splitted from " +
- "wells, and ranks were merged together." )
- return True
-
- def mergeBlocksFilter( self: Self,
- input: vtkMultiBlockDataSet,
- convertSurfaces: bool = False ) -> vtkMultiBlockDataSet:
- """Apply vtk merge block filter on input multi block mesh.
-
- Args:
- input (vtkMultiBlockDataSet): multiblock mesh to merge
- convertSurfaces (bool, optional): True to convert surface from vtkUnstructuredGrid to
- vtkPolyData. Defaults to False.
-
- Returns:
- vtkMultiBlockDataSet: Multiblock mesh composed of internal merged blocks.
- """
- mergeBlockFilter: GeosBlockMerge = GeosBlockMerge( input, convertSurfaces, True )
- if not mergeBlockFilter.logger.hasHandlers():
- mergeBlockFilter.setLoggerHandler( VTKHandler() )
- mergeBlockFilter.applyFilter()
- mergedBlocks: vtkMultiBlockDataSet = mergeBlockFilter.getOutput()
- assert mergedBlocks is not None, "Final merged MultiBlockDataSet is null."
- return mergedBlocks
diff --git a/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolume.py b/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolume.py
index 50a6a0f3..7c550c37 100644
--- a/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolume.py
+++ b/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolume.py
@@ -30,7 +30,7 @@
VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
)
-from geos.pv.plugins.PVExtractMergeBlocksVolume import PVExtractMergeBlocksVolume
+from geos.pv.plugins.PVGeosBlockExtractAndMerge import PVGeosBlockExtractAndMerge
from geos.pv.plugins.PVGeomechanicsCalculator import PVGeomechanicsCalculator
__doc__ = """
@@ -353,12 +353,12 @@ def doExtractAndMerge( self: Self ) -> bool:
Returns:
bool: True if extraction and merge successfully eneded, False otherwise
"""
- filter: PVExtractMergeBlocksVolume = PVExtractMergeBlocksVolume()
+ filter: PVGeosBlockExtractAndMerge = PVGeosBlockExtractAndMerge()
filter.SetInputConnection( self.GetInputConnection( 0, 0 ) )
filter.SetLogger( self.m_logger )
filter.Update()
- # recover output objects from PVExtractMergeBlocksVolume
+ # recover output objects from PVGeosBlockExtractAndMerge
self.m_volumeMesh.ShallowCopy( filter.GetOutputDataObject( 0 ) )
self.m_volumeMesh.Modified()
return True
diff --git a/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeSurface.py b/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeSurface.py
index c1370de6..d383c457 100644
--- a/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeSurface.py
+++ b/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeSurface.py
@@ -30,8 +30,7 @@
DEFAULT_ROCK_COHESION,
WATER_DENSITY,
)
-from geos.pv.plugins.PVExtractMergeBlocksVolumeSurface import (
- PVExtractMergeBlocksVolumeSurface, )
+from geos.pv.plugins.PVGeosBlockExtractAndMerge import PVGeosBlockExtractAndMerge
from geos.pv.plugins.PVGeomechanicsCalculator import PVGeomechanicsCalculator
from geos.pv.plugins.PVSurfaceGeomechanics import PVSurfaceGeomechanics
@@ -352,12 +351,12 @@ def doExtractAndMerge( self: Self ) -> bool:
Returns:
bool: True if extraction and merge successfully eneded, False otherwise
"""
- filter: PVExtractMergeBlocksVolumeSurface = PVExtractMergeBlocksVolumeSurface()
+ filter: PVGeosBlockExtractAndMerge = PVGeosBlockExtractAndMerge()
filter.SetInputConnection( self.GetInputConnection( 0, 0 ) )
filter.SetLogger( self.m_logger )
filter.Update()
- # recover output objects from PVExtractMergeBlocksVolumeSurface
+ # recover output objects from PVGeosBlockExtractAndMerge
self.m_volumeMesh.ShallowCopy( filter.GetOutputDataObject( 0 ) )
self.m_surfaceMesh.ShallowCopy( filter.GetOutputDataObject( 1 ) )
self.m_volumeMesh.Modified()
diff --git a/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeSurfaceWell.py b/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeSurfaceWell.py
index 693c6055..3c8ac8fb 100644
--- a/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeSurfaceWell.py
+++ b/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeSurfaceWell.py
@@ -30,8 +30,7 @@
DEFAULT_ROCK_COHESION,
WATER_DENSITY,
)
-from geos.pv.plugins.PVExtractMergeBlocksVolumeSurfaceWell import (
- PVExtractMergeBlocksVolumeSurfaceWell, )
+from geos.pv.plugins.PVGeosBlockExtractAndMerge import PVGeosBlockExtractAndMerge
from geos.pv.plugins.PVGeomechanicsCalculator import PVGeomechanicsCalculator
from geos.pv.plugins.PVSurfaceGeomechanics import PVSurfaceGeomechanics
@@ -359,12 +358,12 @@ def doExtractAndMerge( self: Self ) -> bool:
Returns:
bool: True if extraction and merge successfully eneded, False otherwise
"""
- filter: PVExtractMergeBlocksVolumeSurfaceWell = ( PVExtractMergeBlocksVolumeSurfaceWell() )
+ filter: PVGeosBlockExtractAndMerge = PVGeosBlockExtractAndMerge()
filter.SetInputConnection( self.GetInputConnection( 0, 0 ) )
filter.SetLogger( self.m_logger )
filter.Update()
- # recover output objects from PVExtractMergeBlocksVolumeSurfaceWell
+ # recover output objects from PVGeosBlockExtractAndMerge
self.m_volumeMesh.ShallowCopy( filter.GetOutputDataObject( 0 ) )
self.m_surfaceMesh.ShallowCopy( filter.GetOutputDataObject( 1 ) )
self.m_wells.ShallowCopy( filter.GetOutputDataObject( 2 ) )
diff --git a/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeWell.py b/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeWell.py
index 1e7c9980..44aeb977 100644
--- a/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeWell.py
+++ b/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflowVolumeWell.py
@@ -31,8 +31,7 @@
WATER_DENSITY,
)
-from geos.pv.plugins.PVExtractMergeBlocksVolumeWell import (
- PVExtractMergeBlocksVolumeWell, )
+from geos.pv.plugins.PVGeosBlockExtractAndMerge import PVGeosBlockExtractAndMerge
from geos.pv.plugins.PVGeomechanicsCalculator import PVGeomechanicsCalculator
__doc__ = """
@@ -366,12 +365,12 @@ def doExtractAndMerge( self: Self ) -> bool:
Returns:
bool: True if extraction and merge successfully eneded, False otherwise
"""
- filter: PVExtractMergeBlocksVolumeWell = PVExtractMergeBlocksVolumeWell()
+ filter: PVGeosBlockExtractAndMerge = PVGeosBlockExtractAndMerge()
filter.SetInputConnection( self.GetInputConnection( 0, 0 ) )
filter.SetLogger( self.m_logger )
filter.Update()
- # recover output objects from PVExtractMergeBlocksVolumeWell
+ # recover output objects from PVGeosBlockExtractAndMerge
self.m_volumeMesh.ShallowCopy( filter.GetOutputDataObject( 0 ) )
self.m_wells.ShallowCopy( filter.GetOutputDataObject( 1 ) )
self.m_volumeMesh.Modified()
diff --git a/geos-pv/src/geos/pv/plugins/PVGeosBlockExtractAndMerge.py b/geos-pv/src/geos/pv/plugins/PVGeosBlockExtractAndMerge.py
new file mode 100644
index 00000000..beea5400
--- /dev/null
+++ b/geos-pv/src/geos/pv/plugins/PVGeosBlockExtractAndMerge.py
@@ -0,0 +1,302 @@
+# SPDX-License-Identifier: Apache-2.0
+# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
+# SPDX-FileContributor: Martin Lemay, Romain Baville
+# ruff: noqa: E402 # disable Module level import not at top of file
+import sys
+import logging
+import numpy as np
+import numpy.typing as npt
+
+from pathlib import Path
+from typing_extensions import Self
+
+# update sys.path to load all GEOS Python Package dependencies
+geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent
+sys.path.insert( 0, str( geos_pv_path / "src" ) )
+from geos.pv.utils.config import update_paths
+
+update_paths()
+
+from geos.mesh.utils.arrayHelpers import getAttributeSet
+from geos.mesh.utils.arrayModifiers import ( copyAttribute, createCellCenterAttribute )
+from geos.mesh.utils.multiblockHelpers import getBlockNames
+
+from geos.utils.GeosOutputsConstants import ( GeosMeshOutputsEnum, GeosDomainNameEnum,
+ getAttributeToTransferFromInitialTime )
+
+from geos.pv.utils.paraviewTreatments import getTimeStepIndex
+from geos.pv.utils.workflowFunctions import doExtractAndMerge
+
+from vtkmodules.vtkCommonCore import ( vtkInformation, vtkInformationVector )
+from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet
+
+from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
+ VTKPythonAlgorithmBase, smdomain, smproperty, smproxy )
+from paraview.detail.loghandler import ( # type: ignore[import-not-found]
+ VTKHandler )
+
+__doc__ = """
+PVGeosBlockExtractAndMerge is a Paraview plugin processing the input mesh at the current time in two steps:
+ 1. Extraction of domains (volume, fault and well) from a GEOS output multiBlockDataSet mesh
+ 2. Actions on each region of a GEOS output domain (volume, fault, wells) to:
+ * Merge Ranks
+ * Identify "Fluids" and "Rock" phases
+ * Rename "Rock" attributes depending on the phase they refer to for more clarity
+ * Convert volume meshes to surface if needed
+ * Copy "geomechanics" attributes from the initial timestep to the current one if they exist
+
+This filter results in 3 output pipelines with the vtkMultiBlockDataSet:
+ - "Volume" contains the volume domain
+ - "Fault" contains the fault domain if it exist
+ - "Well" contains the well domain if it exist
+
+Input and output meshes are vtkMultiBlockDataSet.
+
+.. Important::
+ - The input mesh must be an output of a GEOS simulation or contain at least three blocks labeled with the same domain names:
+ * "CellElementRegion" for volume domain
+ * "SurfaceElementRegion" for fault domain if the input contains fault
+ * "WellElementRegion" for well domain if the input contains well
+ * See more https://geosx-geosx.readthedocs-hosted.com/en/latest/docs/sphinx/datastructure/ElementRegions.html?_sm_au_=iVVT5rrr5fN00R8sQ0WpHK6H8sjL6#xml-element-elementregions
+ - The filter detected automatically the three domains. If one of them if not in the input mesh, the associated output pipeline will be empty
+
+To use it:
+
+* Load the module in Paraview: Tools>Manage Plugins...>Load new>PVGeosBlockExtractAndMerge.
+* Select the Geos output .pvd file loaded in Paraview.
+* Search and Apply PVGeosBlockExtractAndMerge Filter.
+"""
+
+loggerTitle: str = "Extract & Merge GEOS Block"
+
+
+@smproxy.filter(
+ name="PVGeosBlockExtractAndMerge",
+ label="Geos Extract and Merge Blocks",
+)
+@smproperty.xml( """
+
+
+
+
+
+
+
+
+
+ """ )
+@smproperty.input( name="Input", port_index=0 )
+@smdomain.datatype( dataTypes=[ "vtkMultiBlockDataSet" ], composite_data_supported=True )
+class PVGeosBlockExtractAndMerge( VTKPythonAlgorithmBase ):
+
+ def __init__( self: Self ) -> None:
+ """Paraview plugin to extract and merge ranks from Geos output Mesh.
+
+ To apply in the case of output ".pvd" file contains Volume, Fault or
+ Well elements.
+ """
+ super().__init__(
+ nInputPorts=1,
+ nOutputPorts=3,
+ inputType="vtkMultiBlockDataSet",
+ outputType="vtkMultiBlockDataSet",
+ )
+
+ self.extractFault: bool = True
+ self.extractWell: bool = True
+
+ # All time steps from input
+ self.timeSteps: npt.NDArray[ np.float64 ] = np.array( [] )
+ # The time step of the input when the plugin is called or updated
+ self.currentTimeStepIndex: int = 0
+ # The time step studies. It is incremental -1 during the initialization, from 0 to self.currentTimeStepIndex during the computation and -2 at the end of the computation
+ self.requestDataStep: int = -1
+
+ self.outputCellsT0: vtkMultiBlockDataSet = vtkMultiBlockDataSet()
+
+ self.logger = logging.getLogger( loggerTitle )
+ self.logger.setLevel( logging.INFO )
+ self.logger.addHandler( VTKHandler() )
+
+ def RequestDataObject(
+ self: Self,
+ request: vtkInformation,
+ inInfoVec: list[ vtkInformationVector ],
+ outInfoVec: vtkInformationVector,
+ ) -> int:
+ """Inherited from VTKPythonAlgorithmBase::RequestDataObject.
+
+ Args:
+ request (vtkInformation): request
+ inInfoVec (list[vtkInformationVector]): input objects
+ outInfoVec (vtkInformationVector): output objects
+
+ Returns:
+ int: 1 if calculation successfully ended, 0 otherwise.
+ """
+ inData = self.GetInputData( inInfoVec, 0, 0 )
+ assert inData is not None
+
+ outDataCells = self.GetOutputData( outInfoVec, 0 )
+ if outDataCells is None or ( not outDataCells.IsA( "vtkMultiBlockDataSet" ) ):
+ outDataCells = vtkMultiBlockDataSet()
+ outInfoVec.GetInformationObject( 0 ).Set( outDataCells.DATA_OBJECT(), outDataCells ) # type: ignore
+
+ outDataFaults = self.GetOutputData( outInfoVec, 1 )
+ if outDataFaults is None or ( not outDataFaults.IsA( "vtkMultiBlockDataSet" ) ):
+ outDataFaults = vtkMultiBlockDataSet()
+ outInfoVec.GetInformationObject( 1 ).Set( outDataFaults.DATA_OBJECT(), outDataFaults ) # type: ignore
+
+ outDataWells = self.GetOutputData( outInfoVec, 2 )
+ if outDataWells is None or ( not outDataWells.IsA( "vtkMultiBlockDataSet" ) ):
+ outDataWells = vtkMultiBlockDataSet()
+ outInfoVec.GetInformationObject( 2 ).Set( outDataWells.DATA_OBJECT(), outDataWells ) # type: ignore
+
+ return super().RequestDataObject( request, inInfoVec, outInfoVec ) # type: ignore[no-any-return]
+
+ def RequestInformation(
+ self: Self,
+ request: vtkInformation,
+ inInfoVec: list[ vtkInformationVector ],
+ outInfoVec: vtkInformationVector,
+ ) -> int:
+ """Inherited from VTKPythonAlgorithmBase::RequestInformation.
+
+ Args:
+ request (vtkInformation): request
+ inInfoVec (list[vtkInformationVector]): input objects
+ outInfoVec (vtkInformationVector): output objects
+
+ Returns:
+ int: 1 if calculation successfully ended, 0 otherwise.
+ """
+ self.logger.info( f"Apply plugin { self.logger.name }." )
+
+ executive = self.GetExecutive()
+ inInfo = inInfoVec[ 0 ]
+ self.timeSteps = inInfo.GetInformationObject( 0 ).Get( executive.TIME_STEPS() )
+
+ # The time of the input mesh
+ currentTime = inInfo.GetInformationObject( 0 ).Get( executive.UPDATE_TIME_STEP() )
+
+ self.currentTimeStepIndex = getTimeStepIndex( currentTime, self.timeSteps )
+
+ inputMesh: vtkMultiBlockDataSet = vtkMultiBlockDataSet.GetData( inInfo )
+ blockNames: list[ str ] = getBlockNames( inputMesh )
+ if GeosDomainNameEnum.FAULT_DOMAIN_NAME.value not in blockNames:
+ self.extractFault = False
+ self.logger.warning(
+ f"The mesh to process does not contains the block named { GeosDomainNameEnum.FAULT_DOMAIN_NAME.value }. The output 'Fault' will be an empty mesh."
+ )
+
+ if GeosDomainNameEnum.WELL_DOMAIN_NAME.value not in blockNames:
+ self.extractWell = False
+ self.logger.warning(
+ f"The mesh to process does not contains the block named { GeosDomainNameEnum.WELL_DOMAIN_NAME.value }. The output 'Well' will be an empty mesh."
+ )
+
+ return 1
+
+ def RequestUpdateExtent(
+ self: Self,
+ request: vtkInformation,
+ inInfoVec: list[ vtkInformationVector ],
+ outInfoVec: vtkInformationVector,
+ ) -> int:
+ """Inherited from VTKPythonAlgorithmBase::RequestUpdateExtent.
+
+ This function is call at each change of time:
+ on Paraview with the widget Time
+ if request.Set( self.GetExecutive.CONTINUE_EXECUTING(), 1 ) is set (time steps iterator)
+
+ Args:
+ request (vtkInformation): request
+ inInfoVec (list[vtkInformationVector]): input objects
+ outInfoVec (vtkInformationVector): output objects
+
+ Returns:
+ int: 1 if calculation successfully ended, 0 otherwise.
+ """
+ executive = self.GetExecutive()
+ inInfo = inInfoVec[ 0 ]
+
+ # Get update time step from Paraview
+ if self.requestDataStep == -2:
+ currentTime = inInfo.GetInformationObject( 0 ).Get( executive.UPDATE_TIME_STEP() )
+ self.currentTimeStepIndex = getTimeStepIndex( currentTime, self.timeSteps )
+ self.requestDataStep = self.currentTimeStepIndex
+
+ # Update requestDataStep
+ else:
+ self.requestDataStep += 1
+
+ # Update time according to requestDataStep iterator
+ inInfo.GetInformationObject( 0 ).Set( executive.UPDATE_TIME_STEP(), self.timeSteps[ self.requestDataStep ] )
+
+ return 1
+
+ def RequestData(
+ self: Self,
+ request: vtkInformation,
+ inInfoVec: list[ vtkInformationVector ],
+ outInfoVec: vtkInformationVector,
+ ) -> int:
+ """Inherited from VTKPythonAlgorithmBase::RequestData.
+
+ Args:
+ request (vtkInformation): request
+ inInfoVec (list[vtkInformationVector]): input objects
+ outInfoVec (vtkInformationVector): output objects
+
+ Returns:
+ int: 1 if calculation successfully ended, 0 otherwise.
+ """
+ try:
+ inputMesh: vtkMultiBlockDataSet = vtkMultiBlockDataSet.GetData( inInfoVec[ 0 ] )
+ executive = self.GetExecutive()
+
+ # First time step, compute the initial properties (useful for geomechanics analyses)
+ if self.requestDataStep == 0:
+ self.logger.info( "Apply the plugin for the first time step to get the initial properties." )
+ doExtractAndMerge( inputMesh, self.outputCellsT0, vtkMultiBlockDataSet(), vtkMultiBlockDataSet(),
+ self.extractFault, self.extractWell )
+ request.Set( executive.CONTINUE_EXECUTING(), 1 )
+
+ # Current time step, extract, merge, rename and transfer properties
+ if self.requestDataStep == self.currentTimeStepIndex:
+ self.logger.info( f"Apply the filter for the current time step: { self.currentTimeStepIndex }." )
+ outputCells: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 0 )
+ outputFaults: vtkMultiBlockDataSet = self.GetOutputData(
+ outInfoVec, 1 ) if self.extractFault else vtkMultiBlockDataSet()
+ outputWells: vtkMultiBlockDataSet = self.GetOutputData(
+ outInfoVec, 2 ) if self.extractWell else vtkMultiBlockDataSet()
+ doExtractAndMerge( inputMesh, outputCells, outputFaults, outputWells, self.extractFault,
+ self.extractWell )
+
+ # Copy attributes from the initial time step
+ meshAttributes: set[ str ] = getAttributeSet( self.outputCellsT0, False )
+ for ( attributeName, attributeNewName ) in getAttributeToTransferFromInitialTime().items():
+ if attributeName in meshAttributes:
+ copyAttribute( self.outputCellsT0, outputCells, attributeName, attributeNewName, False,
+ self.logger )
+
+ # Create elementCenter attribute in the volume mesh if needed
+ cellCenterAttributeName: str = GeosMeshOutputsEnum.ELEMENT_CENTER.attributeName
+ createCellCenterAttribute( outputCells, cellCenterAttributeName )
+
+ # Stop the time step iteration
+ request.Remove( executive.CONTINUE_EXECUTING() )
+
+ # Set to -2 in case time changes on Paraview
+ self.requestDataStep = -2
+
+ self.logger.info( f"The plugin { self.logger.name } succeeded." )
+ except AssertionError as e:
+ self.logger.error( f"The plugin failed.\n{e}" )
+ return 0
+ except Exception as e:
+ mess1: str = "Block extraction and merge failed due to:"
+ self.logger.critical( mess1 )
+ self.logger.critical( e, exc_info=True )
+ return 0
+ return 1
diff --git a/geos-pv/src/geos/pv/utils/workflowFunctions.py b/geos-pv/src/geos/pv/utils/workflowFunctions.py
new file mode 100644
index 00000000..39ae35ee
--- /dev/null
+++ b/geos-pv/src/geos/pv/utils/workflowFunctions.py
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: Apache-2.0
+# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
+# SPDX-FileContributor: Romain Baville
+# ruff: noqa: E402 # disable Module level import not at top of file
+
+
+from geos.processing.post_processing.GeosBlockExtractor import GeosBlockExtractor
+from geos.processing.post_processing.GeosBlockMerge import GeosBlockMerge
+
+from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet
+
+from paraview.detail.loghandler import ( VTKHandler ) # type: ignore[import-not-found]
+
+
+def doExtractAndMerge(
+ mesh: vtkMultiBlockDataSet,
+ outputCells: vtkMultiBlockDataSet,
+ outputFaults: vtkMultiBlockDataSet,
+ outputWells: vtkMultiBlockDataSet,
+ extractFault: bool,
+ extractWell: bool,
+) -> None:
+ """Apply block extraction and merge.
+
+ Args:
+ mesh (vtkMultiBlockDataSet): Mesh to process.
+ outputCells (vtkMultiBlockDataSet): Output volume mesh.
+ outputFaults (vtkMultiBlockDataSet): Output surface mesh.
+ outputWells (vtkMultiBlockDataSet): Output well mesh.
+ """
+ # Extract blocks
+ blockExtractor: GeosBlockExtractor = GeosBlockExtractor( mesh, extractFault=extractFault, extractWell=extractWell, speHandler=True )
+ if not blockExtractor.logger.hasHandlers():
+ blockExtractor.setLoggerHandler( VTKHandler() )
+ blockExtractor.applyFilter()
+
+ # recover output objects from GeosBlockExtractor filter and merge internal blocks
+ volumeBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.volume
+ outputCells.ShallowCopy( mergeBlocksFilter( volumeBlockExtracted, False ) )
+ outputCells.Modified()
+
+ if extractFault:
+ faultBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.fault
+ outputFaults.ShallowCopy( mergeBlocksFilter( faultBlockExtracted, True ) )
+ outputFaults.Modified()
+
+ if extractWell:
+ wellBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.well
+ outputWells.ShallowCopy( mergeBlocksFilter( wellBlockExtracted, False ) )
+ outputWells.Modified()
+
+ return
+
+def mergeBlocksFilter( mesh: vtkMultiBlockDataSet,
+ convertSurfaces: bool = False, ) -> vtkMultiBlockDataSet:
+ """Apply vtk merge block filter on input multi block mesh.
+
+ Args:
+ mesh (vtkMultiBlockDataSet): Mesh to merge.
+ convertSurfaces (bool, optional): True to convert surface from vtkUnstructuredGrid to vtkPolyData.
+ Defaults to False.
+
+ Returns:
+ vtkMultiBlockDataSet: Mesh composed of internal merged blocks.
+ """
+ mergeBlockFilter: GeosBlockMerge = GeosBlockMerge( mesh, convertSurfaces, True )
+ if not mergeBlockFilter.logger.hasHandlers():
+ mergeBlockFilter.setLoggerHandler( VTKHandler() )
+ mergeBlockFilter.applyFilter()
+ mergedBlocks: vtkMultiBlockDataSet = vtkMultiBlockDataSet()
+ mergedBlocks.ShallowCopy( mergeBlockFilter.getOutput() )
+ return mergedBlocks
diff --git a/geos-utils/src/geos/utils/GeosOutputsConstants.py b/geos-utils/src/geos/utils/GeosOutputsConstants.py
index 52d50a3f..0dc0e691 100644
--- a/geos-utils/src/geos/utils/GeosOutputsConstants.py
+++ b/geos-utils/src/geos/utils/GeosOutputsConstants.py
@@ -12,7 +12,6 @@
.. WARNING::
Names may need to be updated when modifications occur in the GEOS code.
-
.. todo::
If possible, link GEOS names directly with GEOS code instead of redefining
@@ -95,17 +94,33 @@ class GeosMeshSuffixEnum( Enum ):
STRAIN_SUFFIX = "strain"
PERMEABILITY_SUFFIX = "_permeability"
POROSITY_SUFFIX = "_porosity"
+ POROSITY_INIT_SUFFIX = "_initialPorosity"
POROSITY_REF_SUFFIX = "_referencePorosity"
BULK_MODULUS_SUFFIX = "_bulkModulus"
SHEAR_MODULUS_SUFFIX = "_shearModulus"
GRAIN_BULK_MODULUS_SUFFIX = "_grainBulkModulus"
BIOT_COEFFICIENT_SUFFIX = "_biotCoefficient"
- # fluid attributes suffix
- PHASE_DENSITY_SUFFIX = "_density"
- PHASE_MASS_DENSITY_SUFFIX = "_phaseMassDensity"
- PHASE_VISCOSITY_SUFFIX = "_viscosity"
+ # fluid attributes suffix multiPhases
+ TOTAL_FLUID_DENSITY_SUFFIX = "_totalDensity"
+ PHASE_DENSITY_SUFFIX = "_phaseDensity"
PHASE_FRACTION_SUFFIX = "_phaseFraction"
+ PHASE_MASS_DENSITY_SUFFIX = "_phaseMassDensity"
+ PHASE_VISCOSITY_SUFFIX = "_phaseViscosity"
+ PHASE_INTERNAL_ENERGY_SUFFIX = "_phaseInternalEnergy"
+ PHASE_COMP_FRACTION_SUFFIX = "_phaseCompFraction"
+ PHASE_REAL_PERM_SUFFIX = "_phaseRelPerm"
+ PHASE_TRAP_VOL_FRACTION_SUFFIX = "_phaseTrappedVolFraction"
+
+ # fluid attributes suffix singlePhase
+ FLUID_DENSITY_SUFFIX = "_density"
+ FLUID_VISCOSITY_SUFFIX = "_viscosity"
+ FLUID_DENSITY_DERIVATE_SUFFIX = "_dDensity"
+ FLUID_VISCOSITY_DERIVATE_SUFFIX = "_dViscosity"
+ FLUID_INTERNAL_ENERGY_SUFFIX = "_internalEnergy"
+ FLUID_INTERNAL_ENERGY_DERIVATE_SUFFIX = "_dInternalEnergy"
+ FLUID_ENTHALPY_SUFFIX = "_enthalpy"
+ FLUID_ENTHALPY_DERIVATE_SUFFIX = "_dEnthalpy"
# surface attribute transfer suffix
SURFACE_PLUS_SUFFIX = "_Plus"
@@ -220,20 +235,36 @@ def __init__( self: Self, phaseType: str, attributes: tuple[ str, ...] ) -> None
(
GeosMeshSuffixEnum.DENSITY_SUFFIX.value,
GeosMeshSuffixEnum.STRESS_SUFFIX.value,
- GeosMeshSuffixEnum.BULK_MODULUS_SUFFIX.value,
- GeosMeshSuffixEnum.SHEAR_MODULUS_SUFFIX.value,
+ GeosMeshSuffixEnum.PERMEABILITY_SUFFIX.value,
GeosMeshSuffixEnum.POROSITY_SUFFIX.value,
+ GeosMeshSuffixEnum.POROSITY_INIT_SUFFIX.value,
GeosMeshSuffixEnum.POROSITY_REF_SUFFIX.value,
- GeosMeshSuffixEnum.PERMEABILITY_SUFFIX.value,
+ GeosMeshSuffixEnum.BULK_MODULUS_SUFFIX.value,
+ GeosMeshSuffixEnum.SHEAR_MODULUS_SUFFIX.value,
+ GeosMeshSuffixEnum.GRAIN_BULK_MODULUS_SUFFIX.value,
+ GeosMeshSuffixEnum.BIOT_COEFFICIENT_SUFFIX.value,
),
)
FLUID = (
"Fluid",
(
+ GeosMeshSuffixEnum.TOTAL_FLUID_DENSITY_SUFFIX.value,
GeosMeshSuffixEnum.PHASE_DENSITY_SUFFIX.value,
- GeosMeshSuffixEnum.PHASE_VISCOSITY_SUFFIX.value,
GeosMeshSuffixEnum.PHASE_FRACTION_SUFFIX.value,
GeosMeshSuffixEnum.PHASE_MASS_DENSITY_SUFFIX.value,
+ GeosMeshSuffixEnum.PHASE_VISCOSITY_SUFFIX.value,
+ GeosMeshSuffixEnum.PHASE_INTERNAL_ENERGY_SUFFIX.value,
+ GeosMeshSuffixEnum.PHASE_COMP_FRACTION_SUFFIX.value,
+ GeosMeshSuffixEnum.PHASE_REAL_PERM_SUFFIX.value,
+ GeosMeshSuffixEnum.PHASE_TRAP_VOL_FRACTION_SUFFIX.value,
+ GeosMeshSuffixEnum.FLUID_DENSITY_SUFFIX.value,
+ GeosMeshSuffixEnum.FLUID_VISCOSITY_SUFFIX.value,
+ GeosMeshSuffixEnum.FLUID_DENSITY_DERIVATE_SUFFIX.value,
+ GeosMeshSuffixEnum.FLUID_VISCOSITY_DERIVATE_SUFFIX.value,
+ GeosMeshSuffixEnum.FLUID_INTERNAL_ENERGY_SUFFIX.value,
+ GeosMeshSuffixEnum.FLUID_INTERNAL_ENERGY_DERIVATE_SUFFIX.value,
+ GeosMeshSuffixEnum.FLUID_ENTHALPY_SUFFIX.value,
+ GeosMeshSuffixEnum.FLUID_ENTHALPY_DERIVATE_SUFFIX.value,
),
)
UNKNOWN = ( "Other", () )