Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
a8a6b9b
add the VTK filter to fill a partial arrays of an input mesh
Jun 16, 2025
e948b20
add the pv plugin to fill a partial arrays of an input mesh
Jun 16, 2025
35c3b74
fixing bugs by removing the use of the abstract class
Jun 16, 2025
5633fce
Add the possibility to choose the atribute to fill without using para…
Jun 16, 2025
919351b
add the possibility to choose the value to fill in the function fillp…
Jun 18, 2025
10bfc75
add the possibility to choose a value to fill the partial array
Jun 18, 2025
839821a
add the possibility to choose the value to fill in the partial attrib…
Jun 18, 2025
870fb25
Update the documentation and upgrade the name of the variables
Jun 18, 2025
798003c
Small modifications of the doc
Jun 20, 2025
1494d5b
Update of the tests
Jun 20, 2025
f69e853
Formatting for the ci
Jun 20, 2025
4d9468e
Add the test file for the FillPartialArrays vtk filter
Jun 20, 2025
d44bc56
Formatting for the ci
Jun 20, 2025
5e0da35
Fix the lin with yapft issue
Jun 20, 2025
0ca3fe5
add a function to get the type of a vtk array
Jun 24, 2025
a905450
uptade the function createAttribute to preserve the type of the vtk a…
Jun 24, 2025
ec0302f
update the typing in the test of the function createAttribute
Jun 24, 2025
6c501c4
Update createAttribute and createConstantAttributeDataSet
Jun 26, 2025
510887d
Merge branch 'main' into RomainBaville/feature/update_geos-mesh_utils
Jun 26, 2025
490135c
update fillPartialAttribute and fillAllPartialAttributes
Jun 27, 2025
15a67fa
Add a function to get the vtk data type of an attribute of a multiblo…
Jun 27, 2025
5b17644
Formating for the CI
Jun 27, 2025
bd63003
Uptade functions calling utils functions
Jun 30, 2025
19ffa8d
Fix the doc issue
Jun 30, 2025
a0a2092
Apply suggestions from code review
RomainBaville Jun 30, 2025
bcdf4bd
Apply suggestions from code review
RomainBaville Jul 15, 2025
e79f5ab
Generalize error message of copyAttribute
Jul 15, 2025
b17e2e5
Add a raise assertion error in case of the mesh doen't have the attri…
Jul 15, 2025
5941980
Update the default value for uint case for fillpartialattribute
Jul 15, 2025
f46fde5
Cleen and add logger to manadge output messages
Jul 16, 2025
614cafa
clear the tests and functions of arrayModifiers
Jul 18, 2025
1423482
Clean fillpartialattribute and its test
Jul 22, 2025
0e2ded2
clean the code and add a funtion to test if an attribute is partial.
Jul 22, 2025
68d6c3c
fix the test of isAttributeGlobal
Jul 22, 2025
57c9bd2
Clean the code
Jul 22, 2025
b4ff24e
Clean for ci
Jul 23, 2025
7da8f9b
Clean for the ci
Jul 23, 2025
3c8f5d6
Clean doc
Jul 23, 2025
1d16852
Clean for ci
Jul 23, 2025
b4e2084
Clean For ci
Jul 23, 2025
f052c14
Clean For ci
Jul 23, 2025
6fc4f5d
Apply suggestions from Paloma's code review
RomainBaville Jul 28, 2025
80c08ae
Merge branch 'main' into RomainBaville/feature/update_geos-mesh_utils
Jul 28, 2025
36d715f
fix error in transferAttributes
Jul 28, 2025
8f0ed47
Merge branch 'main' into RomainBaville/feature/update_geos-mesh_utils
Jul 30, 2025
aa989f3
Merge branch 'main' into RomainBaville/feature/VTK_filter_and_PVFillP…
Jul 30, 2025
96f2237
Clean variables name and typing
Aug 6, 2025
2ac03bc
Remove the AsDF function
Aug 6, 2025
a021fa7
Change variables iter to iterator
Aug 6, 2025
f100bb8
Clean for ci
Aug 6, 2025
aeba4ba
move the plugin file in the new folder
Aug 6, 2025
065d6ff
update the doc with the new filter
Aug 6, 2025
20120be
remove the use of VTKPythonAlgorythmBase
Aug 6, 2025
9ca8b56
Fix logger
Aug 6, 2025
eb29afd
Update to the last version of the geos-mesh utils function
Aug 6, 2025
68b29f5
update FillPartialArrays to deals with multiple component
Aug 6, 2025
729f58c
update do set a value per component
Aug 6, 2025
b51bff1
Update to main
Aug 7, 2025
d23fc0a
clean for ci
Aug 7, 2025
0709b43
Update the test and the typing
Aug 7, 2025
e58f957
Apply suggestions from Paloma's code review
RomainBaville Aug 12, 2025
28bf48b
Update to main
Aug 12, 2025
71535ed
Update the doc
Aug 12, 2025
94219b3
Apply suggestions from Paloma's review
Aug 12, 2025
b58ded3
Fix doc
Aug 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions geos-mesh/src/geos/mesh/processing/FillPartialArrays.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
# SPDX-FileContributor: Romain Baville, Martin Lemay

from typing_extensions import Self
from typing import Union, Tuple
from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase

from geos.utils.Logger import Logger, getLogger
from geos.mesh.utils.arrayModifiers import fillPartialAttributes
from geos.mesh.utils.arrayHelpers import (
getNumberOfComponents,
isAttributeInObject,
)

from vtkmodules.vtkCommonCore import (
vtkInformation,
vtkInformationVector,
)

from vtkmodules.vtkCommonDataModel import (
vtkMultiBlockDataSet, )

import numpy as np

__doc__ = """
Fill partial arrays of input mesh with values (defaults to nan).
Several attributes can be fill in the same time but with the same value.
Comment thread
RomainBaville marked this conversation as resolved.
Outdated

Input and output mesh are vtkMultiBlockDataSet.
Comment thread
RomainBaville marked this conversation as resolved.
Outdated

To use it:

.. code-block:: python

from geos.mesh.processing.FillPartialArrays import FillPartialArrays

# filter inputs
input_mesh: vtkMultiBlockDataSet
input_attributesNameList: list[str]
input_valueToFill: float, optional defaults to nan

# Instanciate the filter
filter: FillPartialArrays = FillPartialArrays()
# Set the list of the partial atributes to fill
filter._SetAttributesNameList( input_attributesNameList )
# Set the value to fill in the partial attributes if not nan
filter._SetValueToFill( input_valueToFill )
# Set the mesh
filter.SetInputDataObject( input_mesh )
# Do calculations
filter.Update()

# get output object
output: vtkMultiBlockDataSet = filter.GetOutputDataObject( 0 ) )
"""


class FillPartialArrays( VTKPythonAlgorithmBase ):

def __init__( self: Self ) -> None:
"""Map the properties of a server mesh to a client mesh."""
super().__init__( nInputPorts=1,
nOutputPorts=1,
inputType="vtkMultiBlockDataSet",
outputType="vtkMultiBlockDataSet" )

# Initialisation of an empty list of the attribute's name
self._SetAttributesNameList()

# Initialisation of the value (nan) to fill in the partial attributes
self._SetValueToFill()

# Logger
self.m_logger: Logger = getLogger( "Fill Partial Attributes" )

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 RequestData(
self: Self,
request: vtkInformation, # noqa: F841
inInfoVec: list[ vtkInformationVector ],
outInfoVec: vtkInformationVector,
) -> int:
"""Inherited from VTKPythonAlgorithmBase::RequestData.

Args:
request (vtkInformation): request
inInfoVec (list[vtkInformationVector]): input objects
outInfoVec (vtkInformationVector): output objects
Comment thread
RomainBaville marked this conversation as resolved.
Outdated

Returns:
int: 1 if calculation successfully ended, 0 otherwise.
"""
self.m_logger.info( f"Apply filter {__name__}" )
try:
inputMesh: vtkMultiBlockDataSet = self.GetInputData( inInfoVec, 0, 0 )
outData: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 0 )

assert inputMesh is not None, "Input mesh is null."
assert outData is not None, "Output pipeline is null."

outData.ShallowCopy( inputMesh )
for attributeName in self._attributesNameList:
# cell and point arrays
for onPoints in ( False, True ):
if isAttributeInObject( outData, attributeName, onPoints ):
nbComponents = getNumberOfComponents( outData, attributeName, onPoints )
fillPartialAttributes( outData, attributeName, nbComponents, onPoints, self._valueToFill )
outData.Modified()

mess: str = "Fill Partial arrays were successfully completed. " + str(
self._attributesNameList ) + " filled with value " + str( self._valueToFill )
self.m_logger.info( mess )
except AssertionError as e:
mess1: str = "Partial arrays filling failed due to:"
self.m_logger.error( mess1 )
self.m_logger.error( e, exc_info=True )
return 0
except Exception as e:
mess0: str = "Partial arrays filling failed due to:"
self.m_logger.critical( mess0 )
self.m_logger.critical( e, exc_info=True )
return 0

return 1

def _SetAttributesNameList( self: Self, attributesNameList: Union[ list[ str ], Tuple ] = () ) -> None:
"""Set the list of the partial attributes to fill.

Args:
attributesNameList (Union[list[str], Tuple], optional): list of all the attributes name.
Comment thread
RomainBaville marked this conversation as resolved.
Outdated
Defaults to a empty list
"""
self._attributesNameList: Union[ list[ str ], Tuple ] = attributesNameList

def _SetValueToFill( self: Self, valueToFill: float = np.nan ) -> None:
"""Set the value to fill in the partial attribute.

Args:
valueToFill (float, optional): value to fill in the partial attribute.
Comment thread
RomainBaville marked this conversation as resolved.
Outdated
Defaults to nan.
"""
self._valueToFill: float = valueToFill
46 changes: 22 additions & 24 deletions geos-mesh/src/geos/mesh/utils/arrayModifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,56 +39,54 @@
"""


def fillPartialAttributes(
multiBlockMesh: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet, vtkDataObject ],
attributeName: str,
nbComponents: int,
onPoints: bool = False,
) -> bool:
"""Fill input partial attribute of multiBlockMesh with nan values.
def fillPartialAttributes( multiBlockMesh: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet, vtkDataObject ],
attributeName: str,
nbComponents: int,
onPoints: bool = False,
value: float = np.nan ) -> bool:
"""Fill input partial attribute of multiBlockMesh with values (defaults to nan).

Args:
multiBlockMesh (vtkMultiBlockDataSet | vtkCompositeDataSet | vtkDataObject): multiBlock
mesh where to fill the attribute
attributeName (str): attribute name
nbComponents (int): number of components
onPoints (bool, optional): Attribute is on Points (False) or
on Cells.

mesh where to fill the attribute.
attributeName (str): attribute name.
nbComponents (int): number of components.
onPoints (bool, optional): Attribute is on Points (True) or on Cells (False).
Defaults to False.
value (float, optional): value to fill in the partial atribute.
Comment thread
RomainBaville marked this conversation as resolved.
Outdated
Defaults to nan.

Returns:
bool: True if calculation successfully ended, False otherwise
bool: True if calculation successfully ended, False otherwise.
"""
componentNames: tuple[ str, ...] = ()
if nbComponents > 1:
componentNames = getComponentNames( multiBlockMesh, attributeName, onPoints )
values: list[ float ] = [ np.nan for _ in range( nbComponents ) ]
values: list[ float ] = [ value for _ in range( nbComponents ) ]
createConstantAttribute( multiBlockMesh, values, attributeName, componentNames, onPoints )
multiBlockMesh.Modified()
return True


def fillAllPartialAttributes(
multiBlockMesh: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet, vtkDataObject ],
onPoints: bool = False,
) -> bool:
"""Fill all the partial attributes of multiBlockMesh with nan values.
def fillAllPartialAttributes( multiBlockMesh: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet, vtkDataObject ],
onPoints: bool = False,
value: float = np.nan ) -> bool:
"""Fill all the partial attributes of multiBlockMesh with values (defaults to nan).

Args:
multiBlockMesh (vtkMultiBlockDataSet | vtkCompositeDataSet | vtkDataObject):
multiBlockMesh where to fill the attribute
onPoints (bool, optional): Attribute is on Points (False) or
on Cells.

onPoints (bool, optional): Attribute is on Points (True) or on Cells (False).
Defaults to False.
value (float, optional): value to fill in all the partial atributes.
Comment thread
RomainBaville marked this conversation as resolved.
Outdated
Defaults to nan.

Returns:
bool: True if calculation successfully ended, False otherwise
"""
attributes: dict[ str, int ] = getAttributesWithNumberOfComponents( multiBlockMesh, onPoints )
for attributeName, nbComponents in attributes.items():
fillPartialAttributes( multiBlockMesh, attributeName, nbComponents, onPoints )
fillPartialAttributes( multiBlockMesh, attributeName, nbComponents, onPoints, value )
multiBlockMesh.Modified()
return True

Expand Down
2 changes: 1 addition & 1 deletion geos-mesh/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ def _get_dataset( datasetType: str ):

return reader.GetOutput()

return _get_dataset
return _get_dataset
75 changes: 75 additions & 0 deletions geos-mesh/tests/test_FillPartialArrays.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
# SPDX-FileContributor: Romain Baville
# SPDX-License-Identifier: Apache 2.0
# ruff: noqa: E402 # disable Module level import not at top of file
# mypy: disable-error-code="operator"
import pytest
from typing import Union, Tuple, cast

import numpy as np
import numpy.typing as npt

import vtkmodules.util.numpy_support as vnp
from vtkmodules.vtkCommonDataModel import ( vtkDataSet, vtkMultiBlockDataSet, vtkPointData, vtkCellData )

from geos.mesh.processing.FillPartialArrays import FillPartialArrays


@pytest.mark.parametrize( "onpoints, attributesList, value_test", [
Comment thread
paloma-martinez marked this conversation as resolved.
Outdated
( False, ( ( 0, "PORO", 1 ), ), np.nan ),
( True, ( ( 0, "PointAttribute", 3 ), ( 1, "collocated_nodes", 2 ) ), 2. ),
( False, ( ( 0, "CELL_MARKERS", 1 ), ( 0, "CellAttribute", 3 ), ( 0, "FAULT", 1 ), ( 0, "PERM", 3 ),
( 0, "PORO", 1 ) ), 2. ),
( False, ( ( 0, "PORO", 1 ), ), 2.0 ),
( True, ( ( 0, "PointAttribute", 3 ), ( 1, "collocated_nodes", 2 ) ), np.nan ),
( False, ( ( 0, "CELL_MARKERS", 1 ), ( 0, "CellAttribute", 3 ), ( 0, "FAULT", 1 ), ( 0, "PERM", 3 ),
( 0, "PORO", 1 ) ), np.nan ),
] )
def test_FillPartialArrays(
dataSetTest: vtkMultiBlockDataSet,
onpoints: bool,
attributesList: Tuple[ Tuple[ int, str, int ], ...],
value_test: float,
) -> None:
"""Test FillPartialArrays vtk filter."""
vtkMultiBlockDataSetTestRef: vtkMultiBlockDataSet = dataSetTest( "multiblock" )
vtkMultiBlockDataSetTest: vtkMultiBlockDataSet = dataSetTest( "multiblock" )
attributesNameList: list[ str ] = [ attributesList[ i ][ 1 ] for i in range( len( attributesList ) ) ]

filter: FillPartialArrays = FillPartialArrays()
filter._SetAttributesNameList( attributesNameList )
filter._SetValueToFill( value_test )
filter.SetInputDataObject( vtkMultiBlockDataSetTest )
filter.Update()

nbBlock: int = vtkMultiBlockDataSetTestRef.GetNumberOfBlocks()
for block_id in range( nbBlock ):
datasetRef: vtkDataSet = cast( vtkDataSet, vtkMultiBlockDataSetTestRef.GetBlock( block_id ) )
dataset: vtkDataSet = cast( vtkDataSet, filter.GetOutputDataObject( 0 ).GetBlock( block_id ) )
expected_array: npt.NDArray[ np.float64 ]
array: npt.NDArray[ np.float64 ]
dataRef: Union[ vtkPointData, vtkCellData ]
data: Union[ vtkPointData, vtkCellData ]
nbElements: list[ int ]
if onpoints:
dataRef = datasetRef.GetPointData()
data = dataset.GetPointData()
nbElements = [ 212, 4092 ]
else:
dataRef = datasetRef.GetCellData()
data = dataset.GetCellData()
nbElements = [ 156, 1740 ]

for inBlock, attribute, nbComponents in attributesList:
array = vnp.vtk_to_numpy( data.GetArray( attribute ) )
if block_id == inBlock:
expected_array = vnp.vtk_to_numpy( dataRef.GetArray( attribute ) )
assert ( array == expected_array ).all()
else:
expected_array = np.array( [ [ value_test for i in range( nbComponents ) ]
for _ in range( nbElements[ inBlock ] ) ] )
if np.isnan( value_test ):
assert np.all( np.isnan( array ) == np.isnan( expected_array ) )
else:
assert ( array == expected_array ).all()
Loading