-
Notifications
You must be signed in to change notification settings - Fork 0
refactor: Move GeosBlockExtractor from geos-posp to geos-proccessing #142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
paloma-martinez
merged 30 commits into
main
from
RomainBaville/refactor/MoveGeosBlockExtractor
Oct 31, 2025
Merged
Changes from 23 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
e7447e4
Move GeosBlockExtractor to geos-mesh
RomainBaville 89c8f0c
Remove getBlockFromName
RomainBaville f9b2e3f
Refactor using vtkExtractBlock instead of vtkPythonAlgorithmBase
RomainBaville bcf5d59
Update and clean the doc
RomainBaville 889f59a
Update file using GeosExtractBlock
RomainBaville 22abd05
fix the ci
RomainBaville a524d2d
Merge branch 'main' into RomainBaville/refactor/MoveGeosBlockExtractor
RomainBaville 063ee86
Merge branch 'main' into RomainBaville/refactor/MoveGeosBlockExtractor
RomainBaville e577e07
Use dataclass for the extracted domain
RomainBaville 445711f
Update the doc
RomainBaville 7d79d28
Update de doc
RomainBaville e5835d0
fix AddGeosDomainIndex function
RomainBaville 57c29e2
Merge branch 'main' into RomainBaville/refactor/MoveGeosBlockExtractor
RomainBaville c81193d
Add the test file and the test mesh
RomainBaville c22e876
Clarify the variable names and the doc
RomainBaville 70b9358
Merge branch 'main' into RomainBaville/refactor/MoveGeosBlockExtractor
RomainBaville 6a922d3
Test CI labels identification and dispatch
alexbenedicto 14ea06c
Merge branch 'main' into RomainBaville/refactor/MoveGeosBlockExtractor
alexbenedicto 757732f
Fix docs
alexbenedicto 323b315
Revert Test CI labels identification and dispatch to create a dedicat…
alexbenedicto 4fbe721
add a mesh with a well only
RomainBaville 354dae9
Add a function to get the cell dimension of a mesh
RomainBaville e782d7e
Apply Palomas and Jacques suggestion
RomainBaville 86b09f5
Merge branch 'main' into RomainBaville/refactor/MoveGeosBlockExtractor
RomainBaville 28122b5
move GeosExtractBlock in geos-processing
RomainBaville 57fa533
fix bad move
RomainBaville 0161e2b
update the doc files
RomainBaville 70fcbfb
fix doc
RomainBaville b17ead9
Apply Jacques suggestion
RomainBaville 7aca9a8
Merge branch 'main' into RomainBaville/refactor/MoveGeosBlockExtractor
RomainBaville File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -396,4 +396,3 @@ jobs: | |
| echo "" | ||
| echo "✓ CI requirements satisfied - PR can be merged" | ||
| fi | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
215 changes: 215 additions & 0 deletions
215
geos-mesh/src/geos/mesh/processing/GeosBlockExtractor.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,215 @@ | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. | ||
| # SPDX-FileContributor: Martin Lemay, Romain Baville | ||
| import logging | ||
| from dataclasses import dataclass | ||
| from typing_extensions import Self | ||
|
|
||
| from geos.utils.Logger import ( Logger, getLogger ) | ||
| from geos.utils.GeosOutputsConstants import ( GeosDomainNameEnum ) | ||
| from geos.mesh.utils.arrayHelpers import ( getCellDimension ) | ||
| from geos.mesh.utils.multiblockHelpers import ( getBlockIndexFromName ) | ||
|
|
||
| from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet | ||
| from vtkmodules.vtkFiltersExtraction import vtkExtractBlock | ||
|
|
||
| __doc__ = """ | ||
| GeosBlockExtractor is a vtk filter that allows to extract the domain (volume, fault and well) from a GEOS output multiBlockDataset mesh. | ||
|
|
||
| .. 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 | ||
| "WellElementRegion" for well domain | ||
| See more https://geosx-geosx.readthedocs-hosted.com/en/latest/docs/sphinx/datastructure/ElementRegions.html?_sm_au_=iVVT5rrr5fN00R8sQ0WpHK6H8sjL6#xml-element-elementregions | ||
|
|
||
| .. Note:: | ||
| Volume domain is automatically extracted, by defaults Fault and Well domains are empty multiBlockDataSet. | ||
|
|
||
| To use the filter: | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| from geos.mesh.processing.GeosBlockExtractor import GeosBlockExtractor | ||
|
|
||
| # Filter inputs. | ||
| geosMesh: vtkMultiBlockDataSet | ||
| # Optional inputs. | ||
| extractFault: bool # Defaults to False | ||
| extractWell: bool # Defaults to False | ||
| speHandler: bool # Defaults to False | ||
|
|
||
| # Instantiate the filter | ||
| filter: GeosBlockExtractor = GeosBlockExtractor( geosMesh, extractFault, extractWell, speHandler ) | ||
|
|
||
| # Set the handler of yours (only if speHandler is True). | ||
| yourHandler: logging.Handler | ||
| filter.setLoggerHandler( yourHandler ) | ||
|
|
||
| # Do calculations | ||
| filter.applyFilter() | ||
|
|
||
| # Get the multiBlockDataSet with blocks of the extracted domain. | ||
| geosDomainExtracted: vtkMultiBlockDataSet | ||
| geosDomainExtracted = filter.extractedGeosDomain.volume # For volume domain | ||
| geosDomainExtracted = filter.extractedGeosDomain.fault # For fault domain | ||
| geosDomainExtracted = filter.extractedGeosDomain.well # For well domain | ||
| """ | ||
|
|
||
| loggerTitle: str = "Geos Block Extractor Filter" | ||
|
|
||
|
|
||
| class GeosExtractDomainBlock( vtkExtractBlock ): | ||
|
|
||
| def __init__( self: Self ) -> None: | ||
| """Extract blocks from a GEOS output multiBlockDataset mesh.""" | ||
|
|
||
| def AddGeosDomainName( self: Self, geosDomainName: GeosDomainNameEnum ) -> None: | ||
| """Add the index of the GEOS domain to extract from its name. | ||
|
|
||
| Args: | ||
| geosDomainName (GeosDomainNameEnum): Name of the GEOS domain to extract. | ||
| """ | ||
| domainBlockIndex: int = getBlockIndexFromName( self.GetInput(), geosDomainName.value ) | ||
| return super().AddIndex( domainBlockIndex ) | ||
|
|
||
|
|
||
| class GeosBlockExtractor: | ||
|
|
||
| @dataclass | ||
| class ExtractedGeosDomain: | ||
| """The dataclass with the three GEOS domain mesh.""" | ||
| _volume: vtkMultiBlockDataSet = vtkMultiBlockDataSet() | ||
| _fault: vtkMultiBlockDataSet = vtkMultiBlockDataSet() | ||
| _well: vtkMultiBlockDataSet = vtkMultiBlockDataSet() | ||
|
|
||
| @property | ||
| def volume( self: Self ) -> vtkMultiBlockDataSet: | ||
| """Get the mesh with the blocks of the GEOS CellElementRegion.""" | ||
| return self._volume | ||
|
|
||
| @volume.setter | ||
| def volume( self: Self, multiBlockDataSet: vtkMultiBlockDataSet ) -> None: | ||
| cellDim: set[ int ] = getCellDimension( multiBlockDataSet ) | ||
| if len( cellDim ) == 1 and 3 in cellDim: | ||
| self._volume.DeepCopy( multiBlockDataSet ) | ||
| else: | ||
| raise TypeError( "The input mesh must be a volume mesh with cells dimension equal to 3." ) | ||
|
|
||
| @property | ||
| def fault( self: Self ) -> vtkMultiBlockDataSet: | ||
| """Get the mesh with the blocks of the GEOS SurfaceElementRegion.""" | ||
| return self._fault | ||
|
|
||
| @fault.setter | ||
| def fault( self: Self, multiBlockDataSet: vtkMultiBlockDataSet ) -> None: | ||
| cellDim: set[ int ] = getCellDimension( multiBlockDataSet ) | ||
| if len( cellDim ) == 1 and 2 in cellDim: | ||
| self._fault.DeepCopy( multiBlockDataSet ) | ||
| else: | ||
| raise TypeError( "The input mesh must be a surface mesh with cells dimension equal to 2." ) | ||
|
|
||
| @property | ||
| def well( self: Self ) -> vtkMultiBlockDataSet: | ||
| """Get the mesh with the blocks of the GEOS WellElementRegion.""" | ||
| return self._well | ||
|
|
||
| @well.setter | ||
| def well( self: Self, multiBlockDataSet: vtkMultiBlockDataSet ) -> None: | ||
| cellDim: set[ int ] = getCellDimension( multiBlockDataSet ) | ||
| if len( cellDim ) == 1 and 1 in cellDim: | ||
| self._well.DeepCopy( multiBlockDataSet ) | ||
| else: | ||
| raise TypeError( "The input mesh must be a segment mesh with cells dimension equal to 1." ) | ||
|
|
||
| def setExtractedDomain( self: Self, geosDomainName: GeosDomainNameEnum, | ||
| multiBlockDataSet: vtkMultiBlockDataSet ) -> None: | ||
| """Set the mesh to the correct domain. | ||
|
|
||
| Args: | ||
| geosDomainName (GeosDomainNameEnum): Name of the GEOS domain. | ||
| multiBlockDataSet (vtkMultiBlockDataSet): The mesh to set. | ||
| """ | ||
| if geosDomainName.value == "CellElementRegion": | ||
| self.volume = multiBlockDataSet | ||
| elif geosDomainName.value == "SurfaceElementRegion": | ||
| self.fault = multiBlockDataSet | ||
| elif geosDomainName.value == "WellElementRegion": | ||
| self.well = multiBlockDataSet | ||
| else: | ||
| raise ValueError( | ||
| f"The GEOS extractable domains are { GeosDomainNameEnum.VOLUME_DOMAIN_NAME.value }, { GeosDomainNameEnum.FAULT_DOMAIN_NAME.value } and { GeosDomainNameEnum.WELL_DOMAIN_NAME.value }." | ||
| ) | ||
|
|
||
| extractedGeosDomain: ExtractedGeosDomain | ||
|
|
||
| def __init__( | ||
| self: Self, | ||
| geosMesh: vtkMultiBlockDataSet, | ||
| extractFault: bool = False, | ||
| extractWell: bool = False, | ||
| speHandler: bool = False, | ||
| ) -> None: | ||
| """Blocks from the ElementRegions from a GEOS output multiBlockDataset mesh. | ||
|
|
||
| Args: | ||
| geosMesh (vtkMultiBlockDataSet): The mesh from Geos. | ||
| extractFault (bool, Optional): True if SurfaceElementRegion needs to be extracted, False otherwise. | ||
| Defaults to False. | ||
| extractWell (bool, Optional): True if WellElementRegion needs to be extracted, False otherwise. | ||
| Defaults to False. | ||
| speHandler (bool, optional): True to use a specific handler, False to use the internal handler. | ||
| Defaults to False. | ||
| """ | ||
| self.geosMesh: vtkMultiBlockDataSet = geosMesh | ||
| self.extractedGeosDomain = self.ExtractedGeosDomain() | ||
|
|
||
| self.domainToExtract: list[ GeosDomainNameEnum ] = [ GeosDomainNameEnum.VOLUME_DOMAIN_NAME ] | ||
| if extractFault: | ||
| self.domainToExtract.append( GeosDomainNameEnum.FAULT_DOMAIN_NAME ) | ||
| if extractWell: | ||
| self.domainToExtract.append( GeosDomainNameEnum.WELL_DOMAIN_NAME ) | ||
|
|
||
| # Logger. | ||
| self.logger: Logger | ||
| if not speHandler: | ||
| self.logger = getLogger( loggerTitle, True ) | ||
| else: | ||
| self.logger = logging.getLogger( loggerTitle ) | ||
| self.logger.setLevel( logging.INFO ) | ||
|
|
||
| def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: | ||
| """Set a specific handler for the filter logger. | ||
|
|
||
| In this filter 4 log levels are use, .info, .error, .warning and .critical, be sure to have at least the same 4 levels. | ||
|
|
||
| Args: | ||
| handler (logging.Handler): The handler to add. | ||
| """ | ||
| if not self.logger.hasHandlers(): | ||
| self.logger.addHandler( handler ) | ||
| else: | ||
| self.logger.warning( | ||
| "The logger already has an handler, to use yours set the argument 'speHandler' to True during the filter initialization." | ||
| ) | ||
|
|
||
| def applyFilter( self: Self ) -> None: | ||
| """Extract the volume, the fault or the well domain of the mesh from GEOS.""" | ||
| self.logger.info( f"Apply filter { self.logger.name }." ) | ||
|
|
||
| try: | ||
| extractGeosDomain: GeosExtractDomainBlock = GeosExtractDomainBlock() | ||
| extractGeosDomain.SetInputData( self.geosMesh ) | ||
|
|
||
| for domain in self.domainToExtract: | ||
| extractGeosDomain.RemoveAllIndices() | ||
| extractGeosDomain.AddGeosDomainName( domain ) | ||
| extractGeosDomain.Update() | ||
| self.extractedGeosDomain.setExtractedDomain( domain, extractGeosDomain.GetOutput() ) | ||
|
|
||
| self.logger.info( "The filter succeeded." ) | ||
|
|
||
| except ValueError as ve: | ||
| self.logger.error( f"The filter failed.\n{ ve }." ) | ||
| except TypeError as te: | ||
| self.logger.error( f"The filter failed.\n{ te }." ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| <?xml version="1.0"?> | ||
| <VTKFile type="vtkMultiBlockDataSet" version="1.0"> | ||
| <vtkMultiBlockDataSet> | ||
| <Block name="CellElementRegion"> | ||
| <DataSet name="domain" file="domain_res5_id.vtu"/> | ||
| <DataSet name="emptyDomain" file="domain_res5_id_empty.vtu"/> | ||
| </Block> | ||
| <Block name="SurfaceElementRegion"> | ||
| <DataSet name="fracture" file="fracture_res5_id.vtu"/> | ||
| <DataSet name="emptyFracture" file="fracture_res5_id_empty.vtu"/> | ||
| </Block> | ||
| <Block name="WellElementRegion"> | ||
| <DataSet name="well" file="well.vtu"/> | ||
| </Block> | ||
| </vtkMultiBlockDataSet> | ||
| </VTKFile> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.