Transfer module
The maia.transfer contains functions that exchange data between the
partitioned and distributed meshes.
Fields transfer
High level APIs allow to exchange data at CGNS Tree or Zone level. All the provided functions take similar parameters: a distributed tree (resp. zone), the corresponding partitioned tree (resp. list of zones), the MPI communicator and optionally a filtering parameter.
The following kind of data are supported: FlowSolution_t, DiscreteData_t, ArbitraryGridMotion_t, ZoneSubRegion_t and BCDataSet_t.
When transferring from distributed meshes to partitioned meshes, fields are supposed to be known on the source mesh across all the ranks (according to disttree definition). Geometric patches (such as ZoneSubRegion or BCDataSet) must exists on the relevant partitions, meaning that only fields are transfered.
When transferring from partitioned meshes to distributed meshes, geometric patches may or may not exist on the distributed zone: they will be created if needed. This allows to transfer fields that have been created on the partitioned meshes. It is however assumed that global data (e.g. FlowSolution) are defined on every partition.
Tree level
All the functions of this section operate inplace and require the following parameters:
dist_tree (CGNSTree) – Distributed CGNS Tree
part_tree (CGNSTree) – Corresponding partitioned CGNS Tree
comm (MPIComm) – MPI communicator
- dist_tree_to_part_tree_all(dist_tree, part_tree, comm)
Transfer all the data fields from a distributed tree to the corresponding partitioned tree.
Example
from mpi4py import MPI import os import maia import maia.pytree as PT from maia.utils.test_utils import sample_mesh_dir filename = os.path.join(sample_mesh_dir, 'quarter_crown_square_8.yaml') dist_tree = maia.io.file_to_dist_tree(filename, MPI.COMM_WORLD) part_tree = maia.factory.partition_dist_tree(dist_tree, MPI.COMM_WORLD) maia.transfer.dist_tree_to_part_tree_all(dist_tree, part_tree, MPI.COMM_WORLD) zone = PT.get_all_Zone_t(part_tree)[0] assert PT.get_node_from_path(zone, 'FlowSolution/DataX') is not None assert PT.get_node_from_path(zone, 'ZoneSubRegion/Tata') is not None assert PT.get_node_from_path(zone, 'ZoneBC/Bnd2/BCDataSet/DirichletData/TutuZ') is not None
- part_tree_to_dist_tree_all(dist_tree, part_tree, comm)
Transfer all the data fields from the partitioned tree to the corresponding distributed tree.
- Parameters
dist_tree (CGNSDistTree) – Distributed tree to receive data
part_tree (CGNSPartTree) – Partitioned tree to transfer from
comm (MPIComm) – MPI communicator
In addition, the next two methods expect the parameter labels (list of str) which allow to pick one or more kind of data to transfer from the supported labels.
- dist_tree_to_part_tree_only_labels(dist_tree, part_tree, labels, comm)
Transfer all the data fields of the specified labels from a distributed tree to the corresponding partitioned tree.
Example
from mpi4py import MPI import os import maia import maia.pytree as PT from maia.utils.test_utils import sample_mesh_dir comm = MPI.COMM_WORLD filename = os.path.join(sample_mesh_dir, 'quarter_crown_square_8.yaml') dist_tree = maia.io.file_to_dist_tree(filename, comm) part_tree = maia.factory.partition_dist_tree(dist_tree, comm) maia.transfer.dist_tree_to_part_tree_only_labels(dist_tree, part_tree, ['FlowSolution_t', 'ZoneSubRegion_t'], comm) zone = PT.get_all_Zone_t(part_tree)[0] assert PT.get_node_from_path(zone, 'FlowSolution/DataX') is not None assert PT.get_node_from_path(zone, 'ZoneSubRegion/Tata') is not None assert PT.get_node_from_path(zone, 'ZoneBC/Bnd2/BCDataSet/DirichletData/TutuZ') is None maia.transfer.dist_tree_to_part_tree_only_labels(dist_tree, part_tree, ['BCDataSet_t'], comm) assert PT.get_node_from_path(zone, 'ZoneBC/Bnd2/BCDataSet/DirichletData/TutuZ') is not None
- part_tree_to_dist_tree_only_labels(dist_tree, part_tree, labels, comm)
Transfer only the data fields matching the provided labels from the partitioned tree to the corresponding distributed tree.
- Parameters
dist_tree – Distributed tree to receive data
part_tree – Partitioned tree to transfer from
labels – List of labels to transfer
comm – MPI communicator
Zone level
All the functions of this section operate inplace and require the following parameters:
dist_zone (CGNSTree) – Distributed CGNS Zone
part_zones (list of CGNSTree) – Corresponding partitioned CGNS Zones
comm (MPIComm) – MPI communicator
In addition, filtering is possible with the use of the
include_dict or exclude_dict dictionaries. These dictionaries map
each supported label to a list of cgns paths to include (or exclude). Paths
starts from the Zone_t node and ends at the targeted DataArray_t node.
Wildcard * are allowed in paths : for example, considering the following tree
structure,
Zone (Zone_t)
├── FirstSolution (FlowSolution_t)
│ ├── Pressure (DataArray_t)
│ ├── MomentumX (DataArray_t)
│ └── MomentumY (DataArray_t)
├── SecondSolution (FlowSolution_t)
│ ├── Pressure (DataArray_t)
│ ├── MomentumX (DataArray_t)
│ └── MomentumY (DataArray_t)
└── SpecialSolution (FlowSolution_t)
├── Density (DataArray_t)
└── MomentumZ (DataArray_t)
"FirstSolution/Momentum*" maps to ["FirstSolution/MomentumX", "FirstSolution/MomentumY"],"*/Pressure maps to ["FirstSolution/Pressure", "SecondSolution/Pressure"], and"S*/M*" maps to ["SecondSolution/MomentumX", "SecondSolution/MomentumY", "SpecialSolution/MomentumZ"].For convenience, we also provide the magic path ['*'] meaning “everything related to this
label”.
Lastly, we use the following rules to manage missing label keys in dictionaries:
For _only functions, we do not transfer any field related to the missing labels;
For _all functions, we do transfer all the fields related to the missing labels.
- dist_zone_to_part_zones_only(dist_zone, part_zones, comm, include_dict)
Transfer the data fields specified in include_dict from a distributed zone to the corresponding partitioned zones.
Example
from mpi4py import MPI import os import maia import maia.pytree as PT from maia.utils.test_utils import sample_mesh_dir comm = MPI.COMM_WORLD filename = os.path.join(sample_mesh_dir, 'quarter_crown_square_8.yaml') dist_tree = maia.io.file_to_dist_tree(filename, comm) dist_zone = PT.get_all_Zone_t(dist_tree)[0] part_tree = maia.factory.partition_dist_tree(dist_tree, comm) part_zones = PT.get_all_Zone_t(part_tree) include_dict = {'FlowSolution_t' : ['FlowSolution/DataX', 'FlowSolution/DataZ'], 'BCDataSet_t' : ['*']} maia.transfer.dist_zone_to_part_zones_only(dist_zone, part_zones, comm, include_dict) for zone in part_zones: assert PT.get_node_from_path(zone, 'FlowSolution/DataX') is not None assert PT.get_node_from_path(zone, 'ZoneSubRegion/Tata') is None assert PT.get_node_from_path(zone, 'ZoneBC/Bnd2/BCDataSet/DirichletData/TutuZ') is not None
- part_zones_to_dist_zone_only(dist_zone, part_zones, comm, include_dict)
Transfer the data fields specified in include_dict from the partitioned zones to the corresponding distributed zone.
- Parameters
dist_zone – Distributed zone to receive data
part_zones – List of partitioned zones to transfer from
comm – MPI communicator
include_dict – Dictionary mapping labels to paths to include
- dist_zone_to_part_zones_all(dist_zone, part_zones, comm, exclude_dict={})
Transfer all the data fields, excepted those specified in exclude_dict, from a distributed zone to the corresponding partitioned zones.
Example
from mpi4py import MPI import os import maia import maia.pytree as PT from maia.utils.test_utils import sample_mesh_dir comm = MPI.COMM_WORLD filename = os.path.join(sample_mesh_dir, 'quarter_crown_square_8.yaml') dist_tree = maia.io.file_to_dist_tree(filename, comm) dist_zone = PT.get_all_Zone_t(dist_tree)[0] part_tree = maia.factory.partition_dist_tree(dist_tree, comm) part_zones = PT.get_all_Zone_t(part_tree) exclude_dict = {'FlowSolution_t' : ['FlowSolution/DataX', 'FlowSolution/DataZ'], 'BCDataSet_t' : ['*']} maia.transfer.dist_zone_to_part_zones_all(dist_zone, part_zones, comm, exclude_dict) for zone in part_zones: assert PT.get_node_from_path(zone, 'FlowSolution/DataX') is None assert PT.get_node_from_path(zone, 'FlowSolution/DataY') is not None assert PT.get_node_from_path(zone, 'ZoneSubRegion/Tata') is not None assert PT.get_node_from_path(zone, 'ZoneBC/Bnd2/BCDataSet/DirichletData/TutuZ') is None
- part_zones_to_dist_zone_all(dist_zone, part_zones, comm, exclude_dict={})
Transfer all the data fields, excepted those specified in exclude_dict, from the partitioned zone to the corresponding distributed zone.
- Parameters
dist_zone – Distributed zone to receive data
part_zones – List of partitioned zones to transfer from
comm – MPI communicator
exclude_dict – Dictionary mapping labels to paths to exclude
Metadata transfer
The functions described in the previous section allows to transfer local data (ie fields defined on entities of the mesh such as cells, vertices, etc.).
In addition, we provide two functions helping users to copy global data between their meshes. Nodes are simply copied from one tree to the other, regardless of their content. These functions are suited to transfer metadata (such as Family_t nodes) or UserDefinedData nodes storing global data.
For these two functions, predicates must be a pattern leading to the nodes to copy, starting
from the root of the dist_tree (see maia.pytree corresponding section).
When nodes names are used in predicates, they should by provided in their original version,
without maia splitting conventions. For example,
"Base/AIRFOIL/ZoneBC_t/BC_t/.Solver#Property"will transfer nodes named.Solver#Propertyfound under any BC, only for zoneAIRFOIL,
"CGNSBase_t/Zone_t/ZoneBC_t/BC_t/.Solver#Property"will do the same for all the zones of the mesh,
["CGNSBase_t", "Family_t", lambda n: PT.get_name(n).startswith('.Solver#')]will transfer any node whose names starts with.Solver#under all the families of the tree.
If requested nodes already exists on the target tree, they will be updated.
- dist_tree_to_part_tree_copy(dist_tree, part_tree, predicates, comm)
Copy nodes matching the input predicates chain from dist_tree to part_tree
- Parameters
dist_tree (CGNSDistTree) – Distributed tree
part_tree (CGNSPartTree) – Corresponding partitioned tree
predicates (str or list) – Predicates chain, starting from tree level
comm (MPIComm) – MPI communicator
Example
from mpi4py.MPI import COMM_WORLD import maia import maia.pytree as PT dist_tree = maia.factory.generate_dist_block(11, 'HEXA_8', COMM_WORLD) part_tree = maia.factory.partition_dist_tree(dist_tree, COMM_WORLD) dist_base = PT.get_node_from_label(dist_tree, 'CGNSBase_t') PT.new_Family('BCWall', family_bc='BCWall', parent=dist_base) maia.transfer.dist_tree_to_part_tree_copy(dist_tree, part_tree, 'CGNSBase_t/Family_t', COMM_WORLD) assert len(PT.get_nodes_from_label(part_tree, 'Family_t')) == 1
- part_tree_to_dist_tree_copy(dist_tree, part_tree, predicates, comm)
Copy nodes matching the input predicates chain from part_tree to dist_tree
- Parameters
dist_tree (CGNSDistTree) – Distributed tree
part_tree (CGNSPartTree) – Corresponding partitioned tree
predicates (str or list) – Predicates chain, starting from tree level
comm (MPIComm) – MPI communicator
Example
from mpi4py.MPI import COMM_WORLD import maia import maia.pytree as PT dist_tree = maia.factory.generate_dist_block(11, 'TRI_3', COMM_WORLD) part_tree = maia.factory.partition_dist_tree(dist_tree, COMM_WORLD) for bc in PT.iter_nodes_from_label(part_tree, 'BC_t'): PT.new_UserDefinedData('.solver#BC', parent=bc) PT.new_UserDefinedData('.solver#Property', parent=bc) maia.transfer.part_tree_to_dist_tree_copy(dist_tree, part_tree, 'Base/zone/ZoneBC/*max/.solver#*', COMM_WORLD) assert len(PT.get_nodes_from_name(dist_tree, '.solver#*')) == 4