diff --git a/.gitignore b/.gitignore
index 9989d6d..e69b617 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,3 +38,6 @@ pip-log.txt
pip-delete-this-directory.txt
.tox
+
+# macOS
+.DS_Store
\ No newline at end of file
diff --git a/docs/Nodes.md b/docs/Nodes.md
index 96dffbb..f17da4e 100644
--- a/docs/Nodes.md
+++ b/docs/Nodes.md
@@ -1,16 +1,24 @@
# Nodes
-This project builds a graph based on a precice-config.xml file. The nodes in the graph correspond to the specified XML
+This project builds a graph based on a `precice-config.xml` file. The nodes in the graph correspond to the specified XML
elements and tags.
-The documentation for preCICE's config tags can be read
-at [preCICE XML reference](https://precice.org/configuration-XML-reference.html)
+The documentation for preCICE's config tags can be read at
+the [preCICE XML reference](https://precice.org/configuration-XML-reference.html).
> [!NOTE]
-> This graph is built for the [preCICE logic checker](https://github.com/precice-forschungsprojekt/config-checker). This
-> means that there may be redundancies or “inconsistencies” in the building of the graph itself.
+> This graph is built for both [preCICE config check](https://github.com/precice/config-check/)
+> and [preCICE case-generate](https://github.com/precice/case-generate).
+> This means that there may be redundancies or “inconsistencies” in the building of the graph itself.
Here you will find a list with brief explanations of each node and its parameters.
+> [!NOTE]
+> Please note that since version 1.1, each node additionally has a method `to_xml()`,
+> to convert it back to a `precice-config.xml` element (string).
+> To allow this conversion to be as thorough as possible, additional, _optional_ attributes were added to many nodes,
+> which are not listed here and _not_ required for using the graph. Their meaning can be inferred from their name or
+> the [preCICE XML reference](https://precice.org/configuration-xml-reference.html).
+
## Participant
The participant is the center of the graph. It saves references to all connected meshes, written and read data,
@@ -63,8 +71,9 @@ A coupling-scheme node represents a coupling-scheme element of the XML file.
- `first_participant`: The participant of the coupling-scheme that gets referred to as `first=“”`.
- `second_participant`: The participant of the coupling-scheme that gets referred to as `second=“”`.
- `exchanges`: A list of exchanges between the participants. This links to `Exchange` nodes for further references.
-- `accelerations`: A list of accelerations that are intended to accelerate data in exchanges.
-- `convergence_measures`: A list of convergence-measure. Defines the convergence criterion of certain data of a mesh in a coupling-scheme.
+- `accelerations`: The acceleration node that will contain references to all data-accelerations of the coupling-scheme.
+- `convergence_measures`: A list of convergence-measure. Defines the convergence criterion of certain data of a mesh in
+ a coupling-scheme.
- `line`: The line number where the coupling-scheme is defined in the config.xml.
## MultiCouplingScheme
@@ -76,8 +85,9 @@ coupling-scheme to allow for more than two participants.
- `participants`: A list of all participants taking part in the multi-coupling-scheme.
This does _not_ include the control participant.
- `exchanges`: A list of all exchanges being used to exchange data in this multi-coupling-scheme.
-- `accelerations`: A list of accelerations that are intended to accelerate data in exchanges.
-- `convergence_measures`: A list of convergence-measure. Defines the convergence criterion of certain data of a mesh in a multi-coupling-scheme.
+- `accelerations`: The acceleration node that will contain references to all data-accelerations of the coupling-scheme.
+- `convergence_measures`: A list of convergence-measure. Defines the convergence criterion of certain data of a mesh in
+ a multi-coupling-scheme.
- `line`: The line number where the multi-coupling-scheme is defined in the config.xml.
## Data
@@ -206,7 +216,8 @@ Data is accelerated in a mesh in an exchange in the same coupling scheme.
Defines the convergence criterion of certain data of a mesh in a coupling-scheme.
- `coupling_scheme`: The coupling-scheme who the convergence-measure belongs to.
-- `type`: The type of the convergence-measure node. Possible values are `absolute`, `absolute-or-relative`, `relative` and `residual-relative`.
+- `type`: The type of the convergence-measure node. Possible values are `absolute`, `absolute-or-relative`, `relative`
+ and `residual-relative`.
- `data`: Which data should converge by type.
- `mesh`: In which mesh the data is to be converged according to the type.
- `line`: The line number where the convergence-measure is defined in the config.xml.
diff --git a/precice_config_graph/enums.py b/precice_config_graph/enums.py
new file mode 100644
index 0000000..3b4df34
--- /dev/null
+++ b/precice_config_graph/enums.py
@@ -0,0 +1,141 @@
+"""
+This graph is intended for the preCICE logical-checker https://github.com/precice-forschungsprojekt/config-checker.
+
+You can find documentation under README.md, docs/Nodes.md and docs/Edges.md.
+
+This graph was developed by Simon Wazynski, Alexander Hutter and Orlando Ackermann as part of https://github.com/precice-forschungsprojekt.
+"""
+
+from __future__ import annotations
+
+from enum import Enum
+
+
+class MappingMethod(Enum):
+ NEAREST_NEIGHBOR = "nearest-neighbor"
+ NEAREST_PROJECTION = "nearest-projection"
+ NEAREST_NEIGHBOR_GRADIENT = "nearest-neighbor-gradient"
+ LINEAR_CELL_INTERPOLATION = "linear-cell-interpolation"
+ RBF_GLOBAL_ITERATIVE = "rbf-global-iterative"
+ RBF_GLOBAL_DIRECT = "rbf-global-direct"
+ RBF_PUM_DIRECT = "rbf-pum-direct"
+ RBF = "rbf"
+ AXIAL_GEOMETRIC_MULTISCALE = "axial-geometric-multiscale"
+ RADIAL_GEOMETRIC_MULTISCALE = "radial-geometric-multiscale"
+
+
+class MappingConstraint(Enum):
+ CONSERVATIVE = "conservative"
+ CONSISTENT = "consistent"
+ SCALED_CONSISTENT_SURFACE = "scaled-consistent-surface"
+ SCALED_CONSISTENT_VOLUME = "scaled-consistent-volume"
+
+
+class M2NType(Enum):
+ SOCKETS = "sockets"
+ MPI = "mpi"
+ MPI_MULTIPLE_PORTS = "mpi-multiple-ports"
+
+
+class Direction(Enum):
+ READ = "read"
+ WRITE = "write"
+
+
+class DataType(Enum):
+ SCALAR = "scalar"
+ VECTOR = "vector"
+
+
+class TimingType(Enum):
+ WRITE_MAPPING_POST = "write-mapping-post"
+ READ_MAPPING_POST = "read-mapping-post"
+
+
+class CouplingSchemeType(Enum):
+ SERIAL_EXPLICIT = "serial-explicit"
+ PARALLEL_EXPLICIT = "parallel-explicit"
+ SERIAL_IMPLICIT = "serial-implicit"
+ PARALLEL_IMPLICIT = "parallel-implicit"
+ # This enum does not include coupling-scheme:multi, since it is modeled with a different node type
+
+
+class ActionType(Enum):
+ MULTIPLY_BY_AREA = "multiply-by-area"
+ DIVIDE_BY_AREA = "divide-by-area"
+ SUMMATION = "summation"
+ PYTHON = "python"
+ RECORDER = "recorder"
+
+
+class ExportFormat(Enum):
+ VTK = "vtk"
+ VTU = "vtu"
+ VTP = "vtp"
+ CSV = "csv"
+
+
+class AccelerationType(Enum):
+ AITKEN = "aitken"
+ IQN_ILS = "IQN-ILS"
+ IQN_IMVJ = "IQN-IMVJ"
+ CONSTANT = "constant"
+
+
+class ConvergenceMeasureType(Enum):
+ ABSOLUTE = "absolute"
+ ABSOLUTE_OR_RELATIVE = "absolute-or-relative"
+ RELATIVE = "relative"
+ RESIDUAL_RELATIVE = "residual-relative"
+
+
+class MappingExecutorType(Enum):
+ CPU = "cpu"
+ CUDA = "cuda"
+ OPENMP = "openmp"
+ HIP = "hip"
+
+
+class PreconditionerType(Enum):
+ CONSTANT = "constant"
+ VALUE = "value"
+ RESIDUAL = "residual"
+ RESIDUAL_SUM = "residual-sum"
+
+
+class AccelerationFilterType(Enum):
+ QR1 = "QR1"
+ QR1ABSOLUTE = "QR1-absolute"
+ QR2 = "QR2"
+ QR3 = "QR3"
+
+
+class MappingBasisFunctionType(Enum):
+ COMPACT_POLYNOMIAL_C0 = "compact-polynomial-c0"
+ COMPACT_POLYNOMIAL_C2 = "compact-polynomial-c2"
+ COMPACT_POLYNOMIAL_C4 = "compact-polynomial-c4"
+ COMPACT_POLYNOMIAL_C6 = "compact-polynomial-c6"
+ COMPACT_POLYNOMIAL_C8 = "compact-polynomial-c8"
+ COMPACT_TPS_C2 = "compact-tps-c2"
+ MULTIQUADRICS = "multiquadrics"
+ INVERSE_MULTIQUADRICS = "inverse-multiquadrics"
+ GAUSSIAN = "gaussian"
+ THIN_PLATE_SPLINE = "thin-plate-spline"
+ VOLUME_SPLINE = "volume-spline"
+
+
+class MappingMultiscaleType(Enum):
+ SPREAD = "spread"
+ COLLECT = "collect"
+
+
+class MappingMultiscaleAxis(Enum):
+ X = "x"
+ Y = "y"
+ Z = "z"
+
+
+class MappingPolynomialType(Enum):
+ SEPARATE = "separate"
+ ON = "on"
+ OFF = "off"
diff --git a/precice_config_graph/graph.py b/precice_config_graph/graph.py
index 96c6785..c9dbb75 100644
--- a/precice_config_graph/graph.py
+++ b/precice_config_graph/graph.py
@@ -14,6 +14,7 @@
from . import nodes as n
from .edges import Edge
+from . import enums as e
from .xml_processing import convert_string_to_bool
LINK_GRAPH_ISSUES: str = "'\033[1;36mhttps://github.com/precice-forschungsprojekt/config-graph/issues\033[0m'"
@@ -105,12 +106,12 @@ def get_attribute(e: etree.Element, key: str):
for (data_el, kind) in find_all_with_prefix(root, "data"):
name = get_attribute(data_el, "name")
try:
- type = n.DataType(kind)
+ type = e.DataType(kind)
except ValueError:
- possible_types_list = get_enum_values(n.DataType)
+ possible_types_list = get_enum_values(e.DataType)
error_unknown_type(data_el, kind, possible_types_list)
line: int = data_el.sourceline
- node = n.DataNode(name, type, line)
+ node = n.DataNode(name, type, line=line)
data_nodes[name] = node
# Meshes –
@@ -149,7 +150,7 @@ def get_attribute(e: etree.Element, key: str):
mesh = mesh_nodes[mesh_name]
line: int = write_data_el.sourceline
- write_data = n.WriteDataNode(participant, data, mesh, line)
+ write_data = n.WriteDataNode(participant, data, mesh, line=line)
participant.write_data.append(write_data)
write_data_nodes.append(write_data)
@@ -162,7 +163,7 @@ def get_attribute(e: etree.Element, key: str):
mesh = mesh_nodes[mesh_name]
line: int = read_data_el.sourceline
- read_data = n.ReadDataNode(participant, data, mesh, line)
+ read_data = n.ReadDataNode(participant, data, mesh, line=line)
participant.read_data.append(read_data)
read_data_nodes.append(read_data)
@@ -177,9 +178,9 @@ def get_attribute(e: etree.Element, key: str):
to_mesh = mesh_nodes[to_mesh_name] if to_mesh_name else None
try:
- method = n.MappingMethod(kind)
+ method = e.MappingMethod(kind)
except ValueError:
- possible_method_list = get_enum_values(n.MappingMethod)
+ possible_method_list = get_enum_values(e.MappingMethod)
possible_methods: str = list_to_string(possible_method_list)
message: str = (
'Unknown method "'
@@ -190,7 +191,7 @@ def get_attribute(e: etree.Element, key: str):
+ possible_methods
)
error(message)
- constraint = n.MappingConstraint(get_attribute(mapping_el, "constraint"))
+ constraint = e.MappingConstraint(get_attribute(mapping_el, "constraint"))
if not from_mesh and not to_mesh:
error_missing_attribute(mapping_el, 'from" or "to')
@@ -199,13 +200,13 @@ def get_attribute(e: etree.Element, key: str):
mapping = n.MappingNode(
participant,
- n.Direction(direction),
+ e.Direction(direction),
just_in_time,
method,
constraint,
from_mesh,
to_mesh,
- line,
+ line=line,
)
participant.mappings.append(mapping)
@@ -215,19 +216,19 @@ def get_attribute(e: etree.Element, key: str):
#
for (_, kind) in find_all_with_prefix(participant_el, "export"):
try:
- type = n.ExportFormat(kind)
+ type = e.ExportFormat(kind)
except ValueError:
- possible_types_list = get_enum_values(n.ExportFormat)
+ possible_types_list = get_enum_values(e.ExportFormat)
error_unknown_type(_, kind, possible_types_list)
line: int = _.sourceline
- export = n.ExportNode(participant, type, line)
+ export = n.ExportNode(participant, type, line=line)
export_nodes.append(export)
# Actions
#
for (action_el, kind) in find_all_with_prefix(participant_el, "action"):
mesh = mesh_nodes[get_attribute(action_el, "mesh")]
- timing = n.TimingType(get_attribute(action_el, "timing"))
+ timing = e.TimingType(get_attribute(action_el, "timing"))
target_data = None
if kind in ["multiply-by-area", "divide-by-area", "summation", "python"]:
@@ -244,14 +245,14 @@ def get_attribute(e: etree.Element, key: str):
)
try:
- type = n.ActionType(kind)
+ type = e.ActionType(kind)
except ValueError:
- possible_types_list = get_enum_values(n.ActionType)
+ possible_types_list = get_enum_values(e.ActionType)
error_unknown_type(action_el, kind, possible_types_list)
line: int = action_el.sourceline
action = n.ActionNode(
- participant, type, mesh, timing, target_data, source_data, line
+ participant, type, mesh, timing, target_data, source_data, line=line
)
action_nodes.append(action)
@@ -262,7 +263,7 @@ def get_attribute(e: etree.Element, key: str):
mesh = mesh_nodes[get_attribute(watch_point_el, "mesh")]
line: int = watch_point_el.sourceline
- watch_point = n.WatchPointNode(point_name, participant, mesh, line)
+ watch_point = n.WatchPointNode(point_name, participant, mesh, line=line)
watch_point_nodes.append(watch_point)
# Watch-Integral
@@ -272,7 +273,7 @@ def get_attribute(e: etree.Element, key: str):
mesh = mesh_nodes[get_attribute(watch_integral_el, "mesh")]
line: int = watch_integral_el.sourceline
- watch_integral = n.WatchIntegralNode(integral_name, participant, mesh, line)
+ watch_integral = n.WatchIntegralNode(integral_name, participant, mesh, line=line)
watch_integral_nodes.append(watch_integral)
# Now that participant_node is completely built, add it and children to the graph and our dictionary
@@ -303,7 +304,7 @@ def get_attribute(e: etree.Element, key: str):
line: int = receive_mesh_el.sourceline
receive_mesh = n.ReceiveMeshNode(
- participant, mesh, from_participant, api_access, line
+ participant, mesh, from_participant, api_access, line=line
)
participant.receive_meshes.append(receive_mesh)
receive_mesh_nodes.append(receive_mesh)
@@ -331,7 +332,7 @@ def get_attribute(e: etree.Element, key: str):
second_participant_name = get_attribute(participants, "second")
second_participant = participant_nodes[second_participant_name]
- type = n.CouplingSchemeType(kind)
+ type = e.CouplingSchemeType(kind)
coupling_scheme = n.CouplingSchemeNode(
type, first_participant, second_participant, line=line
@@ -389,7 +390,7 @@ def get_attribute(e: etree.Element, key: str):
line: int = exchange_el.sourceline
exchange = n.ExchangeNode(
- coupling_scheme, data, mesh, from_participant, to_participant, line
+ coupling_scheme, data, mesh, from_participant, to_participant, line=line
)
coupling_scheme.exchanges.append(exchange)
exchange_nodes.append(exchange)
@@ -409,9 +410,9 @@ def get_attribute(e: etree.Element, key: str):
error(message)
try:
- type = n.AccelerationType(a_kind)
+ type = e.AccelerationType(a_kind)
except ValueError:
- possible_types_list = get_enum_values(n.AccelerationType)
+ possible_types_list = get_enum_values(e.AccelerationType)
error_unknown_type(acceleration_el, a_kind, possible_types_list)
line: int = acceleration_el.sourceline
@@ -435,11 +436,11 @@ def get_attribute(e: etree.Element, key: str):
a_mesh_name = get_attribute(a_data, "mesh")
mesh = mesh_nodes[a_mesh_name]
line: int = a_data.sourceline
- a_data_node = n.AccelerationDataNode(acceleration, data, mesh, line)
+ a_data_node = n.AccelerationDataNode(acceleration, data, mesh, line=line)
acceleration.data.append(a_data_node)
acceleration_data_nodes.append(a_data_node)
- coupling_scheme.accelerations.append(acceleration)
+ coupling_scheme.acceleration = acceleration
acceleration_nodes.append(acceleration)
for (convergence_measure_el, c_kind) in find_all_with_postfix(
@@ -448,9 +449,9 @@ def get_attribute(e: etree.Element, key: str):
match kind:
case "serial-implicit" | "parallel-implicit" | "multi":
try:
- type = n.ConvergenceMeasureType(c_kind)
+ type = e.ConvergenceMeasureType(c_kind)
except ValueError:
- possible_types_list = get_enum_values(n.ConvergenceMeasureType)
+ possible_types_list = get_enum_values(e.ConvergenceMeasureType)
error_unknown_type(
convergence_measure_el, c_kind, possible_types_list
)
@@ -462,7 +463,7 @@ def get_attribute(e: etree.Element, key: str):
line: int = convergence_measure_el.sourceline
convergence_measure = n.ConvergenceMeasureNode(
- coupling_scheme, type, c_data, c_mesh, line
+ coupling_scheme, type, c_data, c_mesh, line=line
)
coupling_scheme.convergence_measures.append(convergence_measure)
convergence_measure_nodes.append(convergence_measure)
@@ -487,9 +488,9 @@ def get_attribute(e: etree.Element, key: str):
# M2N –
for (m2n_el, kind) in find_all_with_prefix(root, "m2n"):
try:
- type = n.M2NType(kind)
+ type = e.M2NType(kind)
except ValueError:
- possible_types_list = get_enum_values(n.M2NType)
+ possible_types_list = get_enum_values(e.M2NType)
error_unknown_type(m2n_el, kind, possible_types_list)
acceptor_name = get_attribute(m2n_el, "acceptor")
acceptor = participant_nodes[acceptor_name]
@@ -497,7 +498,7 @@ def get_attribute(e: etree.Element, key: str):
connector = participant_nodes[connector_name]
line: int = m2n_el.sourceline
- m2n = n.M2NNode(type, acceptor, connector, line)
+ m2n = n.M2NNode(type, acceptor, connector, line=line)
m2n_nodes.append(m2n)
# BUILD GRAPH
diff --git a/precice_config_graph/nodes.py b/precice_config_graph/nodes.py
index ab4862e..992f041 100644
--- a/precice_config_graph/nodes.py
+++ b/precice_config_graph/nodes.py
@@ -8,101 +8,23 @@
from __future__ import annotations
-from enum import Enum
-
-
-class MappingMethod(Enum):
- NEAREST_NEIGHBOR = "nearest-neighbor"
- NEAREST_PROJECTION = "nearest-projection"
- NEAREST_NEIGHBOR_GRADIENT = "nearest-neighbor-gradient"
- LINEAR_CELL_INTERPOLATION = "linear-cell-interpolation"
- RBF_GLOBAL_ITERATIVE = "rbf-global-iterative"
- RBF_GLOBAL_DIRECT = "rbf-global-direct"
- RBF_PUM_DIRECT = "rbf-pum-direct"
- RBF = "rbf"
- AXIAL_GEOMETRIC_MULTISCALE = "axial-geometric-multiscale"
- RADIAL_GEOMETRIC_MULTISCALE = "radial-geometric-multiscale"
-
-
-class MappingConstraint(Enum):
- CONSERVATIVE = "conservative"
- CONSISTENT = "consistent"
- SCALED_CONSISTENT_SURFACE = "scaled-consistent-surface"
- SCALED_CONSISTENT_VOLUME = "scaled-consistent-volume"
-
-
-class M2NType(Enum):
- SOCKETS = "sockets"
- MPI = "mpi"
- MPI_MULTIPLE_PORTS = "mpi-multiple-ports"
-
-
-class Direction(Enum):
- READ = "read"
- WRITE = "write"
-
-
-class DataType(Enum):
- SCALAR = "scalar"
- VECTOR = "vector"
-
-
-class TimingType(Enum):
- WRITE_MAPPING_POST = "write-mapping-post"
- READ_MAPPING_POST = "read-mapping-post"
-
-
-class CouplingSchemeType(Enum):
- SERIAL_EXPLICIT = "serial-explicit"
- PARALLEL_EXPLICIT = "parallel-explicit"
- SERIAL_IMPLICIT = "serial-implicit"
- PARALLEL_IMPLICIT = "parallel-implicit"
- # This enum does not include coupling-scheme:multi, since it is modeled with a different node type
-
-
-class ActionType(Enum):
- MULTIPLY_BY_AREA = "multiply-by-area"
- DIVIDE_BY_AREA = "divide-by-area"
- SUMMATION = "summation"
- PYTHON = "python"
- RECORDER = "recorder"
-
-
-class ExportFormat(Enum):
- VTK = "vtk"
- VTU = "vtu"
- VTP = "vtp"
- CSV = "csv"
-
-
-class AccelerationType(Enum):
- AITKEN = "aitken"
- IQN_ILS = "IQN-ILS"
- IQN_IMVJ = "IQN-IMVJ"
- CONSTANT = "constant"
-
-
-class ConvergenceMeasureType(Enum):
- ABSOLUTE = "absolute"
- ABSOLUTE_OR_RELATIVE = "absolute-or-relative"
- RELATIVE = "relative"
- RESIDUAL_RELATIVE = "residual-relative"
+from . import enums as e
class ParticipantNode:
def __init__(
- self,
- name: str,
- write_data: list[WriteDataNode] = None,
- read_data: list[ReadDataNode] = None,
- receive_meshes: list[ReceiveMeshNode] = None,
- provide_meshes: list[MeshNode] = None,
- mappings: list[MappingNode] = None,
- exports: list[ExportNode] = None,
- actions: list[ActionNode] = None,
- watchpoints: list[WatchPointNode] = None,
- watch_integrals: list[WatchIntegralNode] = None,
- line: int = None,
+ self,
+ name: str,
+ write_data: list[WriteDataNode] = None,
+ read_data: list[ReadDataNode] = None,
+ receive_meshes: list[ReceiveMeshNode] = None,
+ provide_meshes: list[MeshNode] = None,
+ mappings: list[MappingNode] = None,
+ exports: list[ExportNode] = None,
+ actions: list[ActionNode] = None,
+ watchpoints: list[WatchPointNode] = None,
+ watch_integrals: list[WatchIntegralNode] = None,
+ line: int = None,
):
self.name = name
@@ -153,27 +75,59 @@ def __init__(
self.line = line
+ def to_xml(self):
+ xml_str: str = f"\n"
+ for provide_mesh in self.provide_meshes:
+ xml_str += f" \n"
+ for receive_mesh in self.receive_meshes:
+ xml_str += f" {receive_mesh.to_xml()}\n"
+ for write_data in self.write_data:
+ xml_str += f" {write_data.to_xml()}\n"
+ for read_data in self.read_data:
+ xml_str += f" {read_data.to_xml()}\n"
+ for mapping in self.mappings:
+ xml_str += f" {mapping.to_xml()}\n"
+
+ for action in self.actions:
+ xml_str += f" {action.to_xml()}\n"
+ for export in self.exports:
+ xml_str += f" {export.to_xml()}\n"
+ for watchpoint in self.watchpoints:
+ xml_str += f" {watchpoint.to_xml()}\n"
+ for watch_integral in self.watch_integrals:
+ xml_str += f" {watch_integral.to_xml()}\n"
+
+ xml_str += f"\n"
+ return xml_str
+
class MeshNode:
- def __init__(self, name: str, use_data: list[DataNode] = None, line: int = None):
+ def __init__(self, name: str, use_data: list[DataNode] = None, line: int = None, dimensions: int = 3):
self.name = name
if use_data is None:
self.use_data = []
else:
self.use_data = use_data
-
+ self.dimensions = dimensions
self.line = line
+ def to_xml(self):
+ xml_str: str = f"\n"
+ for data in self.use_data:
+ xml_str += f" \n"
+ xml_str += f"\n"
+ return xml_str
+
class ReceiveMeshNode:
def __init__(
- self,
- participant: ParticipantNode,
- mesh: MeshNode,
- from_participant: ParticipantNode,
- api_access: bool,
- line: int = None,
+ self,
+ participant: ParticipantNode,
+ mesh: MeshNode,
+ from_participant: ParticipantNode,
+ api_access: bool,
+ line: int = None,
):
self.participant = participant
self.mesh = mesh
@@ -181,17 +135,24 @@ def __init__(
self.api_access = api_access
self.line = line
+ def to_xml(self):
+ api_access_str: str = "api-access=\"true\" " if self.api_access else ""
+ xml_str: str = f""
+ return xml_str
+
class CouplingSchemeNode:
def __init__(
- self,
- type: CouplingSchemeType,
- first_participant: ParticipantNode,
- second_participant: ParticipantNode,
- exchanges: list[ExchangeNode] = None,
- accelerations: list[AccelerationNode] = None,
- convergence_measures: list[ConvergenceMeasureNode] = None,
- line: int = None,
+ self,
+ type: e.CouplingSchemeType,
+ first_participant: ParticipantNode,
+ second_participant: ParticipantNode,
+ exchanges: list[ExchangeNode] = None,
+ acceleration: AccelerationNode = None,
+ convergence_measures: list[ConvergenceMeasureNode] = None,
+ line: int = None,
+ max_time_windows: int = 10,
+ time_window_size: float = 1e-1,
):
self.type = type
self.first_participant = first_participant
@@ -202,10 +163,7 @@ def __init__(
else:
self.exchanges = exchanges
- if accelerations is None:
- self.accelerations = []
- else:
- self.accelerations = accelerations
+ self.acceleration = acceleration
if convergence_measures is None:
self.convergence_measures = []
@@ -213,17 +171,33 @@ def __init__(
self.convergence_measures = convergence_measures
self.line = line
+ self.max_time_windows = max_time_windows
+ self.time_window_size = time_window_size
+
+ def to_xml(self):
+ xml_str: str = f"\n"
+ xml_str += f" \n"
+ xml_str += f" \n"
+ xml_str += f" \n"
+ for exchange in self.exchanges:
+ xml_str += f" {exchange.to_xml()}\n"
+ if self.acceleration is not None:
+ xml_str += f" {self.acceleration.to_xml()}\n"
+ for convergence in self.convergence_measures:
+ xml_str += f" {convergence.to_xml()}\n"
+ xml_str += f"\n"
+ return xml_str
class MultiCouplingSchemeNode:
def __init__(
- self,
- control_participant: ParticipantNode,
- participants: list[ParticipantNode] = None,
- exchanges: list[ExchangeNode] = None,
- accelerations: list[AccelerationNode] = None,
- convergence_measures: list[ConvergenceMeasureNode] = None,
- line: int = None,
+ self,
+ control_participant: ParticipantNode,
+ participants: list[ParticipantNode] = None,
+ exchanges: list[ExchangeNode] = None,
+ acceleration: AccelerationNode = None,
+ convergence_measures: list[ConvergenceMeasureNode] = None,
+ line: int = None,
):
self.control_participant = control_participant
@@ -237,10 +211,7 @@ def __init__(
else:
self.exchanges = exchanges
- if accelerations is None:
- self.accelerations = []
- else:
- self.accelerations = accelerations
+ self.acceleration = acceleration
if convergence_measures is None:
self.convergence_measures = []
@@ -249,25 +220,58 @@ def __init__(
self.line = line
+ def to_xml(self):
+ xml_str: str = f"\n"
+ for participant in self.participants:
+ if participant == self.control_participant:
+ xml_str += f" \n"
+ else:
+ xml_str += f" \n"
+ for exchange in self.exchanges:
+ xml_str += f" {exchange.to_xml()}\n"
+ if self.acceleration is not None:
+ xml_str += f" {self.acceleration.to_xml()}\n"
+ for convergence in self.convergence_measures:
+ xml_str += f" {convergence.to_xml()}\n"
+
+ xml_str += f"\n"
+ return xml_str
+
class DataNode:
- def __init__(self, name: str, data_type: DataType, line: int = None):
+ def __init__(self, name: str, data_type: e.DataType, line: int = None):
self.name = name
self.data_type = data_type
self.line = line
+ def to_xml(self) -> str:
+ return f""
+
class MappingNode:
def __init__(
- self,
- parent_participant: ParticipantNode,
- direction: Direction,
- just_in_time: bool,
- method: MappingMethod,
- constraint: MappingConstraint,
- from_mesh: MeshNode | None = None,
- to_mesh: MeshNode | None = None,
- line: int = None,
+ self,
+ parent_participant: ParticipantNode,
+ direction: e.Direction,
+ just_in_time: bool,
+ method: e.MappingMethod,
+ constraint: e.MappingConstraint,
+ from_mesh: MeshNode | None = None,
+ to_mesh: MeshNode | None = None,
+ polynomial: e.MappingPolynomialType = e.MappingPolynomialType.SEPARATE,
+ x_dead: bool = False,
+ y_dead: bool = False,
+ z_dead: bool = False,
+ solver_rtol: float = 1e-9,
+ vertices_per_cluster: int = 50,
+ relative_overlap: float = 0.15,
+ project_to_input: bool = True,
+ multiscale_type: e.MappingMultiscaleType = e.MappingMultiscaleType.COLLECT,
+ multiscale_axis: e.MappingMultiscaleAxis = e.MappingMultiscaleAxis.X,
+ multiscale_radius: float = 1,
+ basisfunction: MappingBasisFunctionNode = None,
+ executor: MappingExecutorNode = None,
+ line: int = None,
):
self.parent_participant = parent_participant
self.direction = direction
@@ -276,46 +280,112 @@ def __init__(
self.constraint = constraint
self.from_mesh = from_mesh
self.to_mesh = to_mesh
+
+ self.polynomial = polynomial
+ self.x_dead = x_dead
+ self.y_dead = y_dead
+ self.z_dead = z_dead
+ self.solver_rtol = solver_rtol
+ self.vertices_per_cluster = vertices_per_cluster
+ self.relative_overlap = relative_overlap
+ self.project_to_input = project_to_input
+ self.multiscale_type = multiscale_type
+ self.multiscale_axis = multiscale_axis
+ self.multiscale_radius = multiscale_radius
+ if basisfunction is None:
+ self.basisfunction = MappingBasisFunctionNode(mapping=self,
+ type=e.MappingBasisFunctionType.COMPACT_POLYNOMIAL_C0)
+ else:
+ self.basisfunction = basisfunction
+ if executor is None:
+ self.executor = MappingExecutorNode(mapping=self, type=e.MappingExecutorType.CPU)
+ else:
+ self.executor = executor
+
self.line = line
+ def to_xml(self) -> str:
+ # General tags
+ xml_str: str = f"\n" # close opening element brace
+ xml_str += f" {self.executor.to_xml()}\n"
+ xml_str += f" {self.basisfunction.to_xml()}\n"
+ xml_str += f""
+ else:
+ xml_str += f"/>"
+ return xml_str
+
class WriteDataNode:
def __init__(
- self,
- participant: ParticipantNode,
- data: DataNode,
- mesh: MeshNode,
- line: int = None,
+ self,
+ participant: ParticipantNode,
+ data: DataNode,
+ mesh: MeshNode,
+ line: int = None,
):
self.participant = participant
self.data = data
self.mesh = mesh
self.line = line
+ def to_xml(self) -> str:
+ xml_str: str = f""
+ return xml_str
+
class ReadDataNode:
def __init__(
- self,
- participant: ParticipantNode,
- data: DataNode,
- mesh: MeshNode,
- line: int = None,
+ self,
+ participant: ParticipantNode,
+ data: DataNode,
+ mesh: MeshNode,
+ line: int = None,
):
self.participant = participant
self.data = data
self.mesh = mesh
self.line = line
+ def to_xml(self) -> str:
+ xml_str: str = f""
+ return xml_str
+
class ExchangeNode:
def __init__(
- self,
- coupling_scheme: CouplingSchemeNode | MultiCouplingSchemeNode,
- data: DataNode,
- mesh: MeshNode,
- from_participant: ParticipantNode,
- to_participant: ParticipantNode,
- line: int = None,
+ self,
+ coupling_scheme: CouplingSchemeNode | MultiCouplingSchemeNode,
+ data: DataNode,
+ mesh: MeshNode,
+ from_participant: ParticipantNode,
+ to_participant: ParticipantNode,
+ line: int = None,
):
self.coupling_scheme = coupling_scheme
self.data = data
@@ -324,26 +394,37 @@ def __init__(
self.to_participant = to_participant
self.line = line
+ def to_xml(self) -> str:
+ xml_str: str = (f" ")
+ return xml_str
+
class ExportNode:
def __init__(
- self, participant: ParticipantNode, format: ExportFormat, line: int = None
+ self, participant: ParticipantNode, format: e.ExportFormat, line: int = None, directory: str = "."
):
self.participant = participant
self.format = format
self.line = line
+ self.directory = directory
+
+ def to_xml(self) -> str:
+ xml_str: str = f""
+ return xml_str
class ActionNode:
def __init__(
- self,
- participant: ParticipantNode,
- type: ActionType,
- mesh: MeshNode,
- timing: TimingType,
- target_data: DataNode | None = None,
- source_data: list[DataNode] = None,
- line: int = None,
+ self,
+ participant: ParticipantNode,
+ type: e.ActionType,
+ mesh: MeshNode,
+ timing: e.TimingType,
+ target_data: DataNode | None = None,
+ source_data: list[DataNode] = None,
+ python_module_name: str = "",
+ line: int = None,
):
self.participant = participant
self.type = type
@@ -356,64 +437,104 @@ def __init__(
else:
self.source_data = source_data
+ self.python_module_name = python_module_name
+
self.line = line
+ def to_xml(self) -> str:
+ xml_str: str = f"\n"
+ if self.type != e.ActionType.RECORDER and self.target_data is not None:
+ xml_str += f" \n"
+ if self.type == e.ActionType.PYTHON:
+ xml_str += f" \n"
+ for source_data in self.source_data:
+ xml_str += f" \n"
+ xml_str += f"\n"
+ return xml_str
+
class WatchPointNode:
def __init__(
- self, name: str, participant: ParticipantNode, mesh: MeshNode, line: int = None
+ self, name: str, participant: ParticipantNode, mesh: MeshNode, line: int = None,
+ coordinate: list[float] = None
):
self.name = name
self.participant = participant
self.mesh = mesh
+ if coordinate is None:
+ self.coordinate = [0] * self.mesh.dimensions # create a 2-d or 3-d coordinate
+ elif len(coordinate) != self.mesh.dimensions:
+ self.coordinate = [0] * self.mesh.dimensions # create a 2-d or 3-d coordinate
+ else:
+ self.coordinate = coordinate
self.line = line
+ def to_xml(self) -> str:
+ coordinate = ";".join(map(str, self.coordinate)) # Coordinate of the form 0;1;2 ...
+ xml_str: str = f""
+ return xml_str
+
class WatchIntegralNode:
def __init__(
- self, name: str, participant: ParticipantNode, mesh: MeshNode, line: int = None
+ self, name: str, participant: ParticipantNode, mesh: MeshNode, scale_with_connectivity: bool = False,
+ line: int = None
):
self.name = name
self.participant = participant
self.mesh = mesh
+ self.scale_with_connectivity = scale_with_connectivity
self.line = line
+ def to_xml(self) -> str:
+ xml_str: str = f""
+ return xml_str
+
class M2NNode:
def __init__(
- self,
- type: M2NType,
- acceptor: ParticipantNode,
- connector: ParticipantNode,
- line: int = None,
+ self,
+ type: e.M2NType,
+ acceptor: ParticipantNode,
+ connector: ParticipantNode,
+ line: int = None,
):
self.type = type
self.acceptor = acceptor
self.connector = connector
self.line = line
+ def to_xml(self) -> str:
+ return f"\n"
+
class AccelerationDataNode:
def __init__(
- self,
- acceleration: AccelerationNode,
- data: DataNode,
- mesh: MeshNode,
- line: int = None,
+ self,
+ acceleration: AccelerationNode,
+ data: DataNode,
+ mesh: MeshNode,
+ line: int = None,
):
self.acceleration = acceleration
self.data = data
self.mesh = mesh
self.line = line
+ def to_xml(self) -> str:
+ xml_str: str = f""
+ return xml_str
+
class AccelerationNode:
def __init__(
- self,
- coupling_scheme: CouplingSchemeNode | MultiCouplingSchemeNode,
- type: AccelerationType,
- data: list[AccelerationDataNode] = None,
- line: int = None,
+ self,
+ coupling_scheme: CouplingSchemeNode | MultiCouplingSchemeNode,
+ type: e.AccelerationType,
+ data: list[AccelerationDataNode] = None,
+ preconditioner: PreconditionerNode = None,
+ filter: AccelerationFilterNode = None,
+ line: int = None,
):
self.coupling_scheme = coupling_scheme
self.type = type
@@ -423,20 +544,142 @@ def __init__(
else:
self.data = data
+ self.preconditioner = preconditioner
+ self.filter = filter
+
self.line = line
+ def to_xml(self) -> str:
+ xml_str: str = f"\n"
+ if self.type == e.AccelerationType.CONSTANT:
+ xml_str += f" \n"
+ for accelerated_data in self.data:
+ xml_str += f" {accelerated_data.to_xml()}\n"
+ if self.preconditioner is not None:
+ xml_str += f" {self.preconditioner.to_xml()}\n"
+ if self.filter is not None:
+ xml_str += f" {self.filter.to_xml()}"
+ xml_str += f""
+ return xml_str
+
class ConvergenceMeasureNode:
def __init__(
- self,
- coupling_scheme: CouplingSchemeNode | MultiCouplingSchemeNode,
- type: ConvergenceMeasureType,
- data: DataNode,
- mesh: MeshNode,
- line: int = None,
+ self,
+ coupling_scheme: CouplingSchemeNode | MultiCouplingSchemeNode,
+ type: e.ConvergenceMeasureType,
+ data: DataNode,
+ mesh: MeshNode,
+ line: int = None,
+ limit: float = 0.1, # functions as absolute and residual limit (they cannot appear together)
+ rel_limit: float = 0.1,
):
self.type = type
self.coupling_scheme = coupling_scheme
self.data = data
self.mesh = mesh
self.line = line
+ self.limit = limit
+ self.rel_limit = rel_limit
+
+ def to_xml(self) -> str:
+ limit_str: str = ""
+ if self.type == e.ConvergenceMeasureType.ABSOLUTE:
+ limit_str = f"limit=\"{self.limit}\" "
+ elif self.type == e.ConvergenceMeasureType.RELATIVE:
+ limit_str = f"limit=\"{self.rel_limit}\" "
+ elif self.type == e.ConvergenceMeasureType.ABSOLUTE_OR_RELATIVE:
+ limit_str = f"abs-limit=\"{self.limit}\" rel-limit=\"{self.rel_limit}\" "
+ elif self.type == e.ConvergenceMeasureType.RESIDUAL_RELATIVE:
+ limit_str = f"limit=\"{self.limit}\" "
+ xml_str: str = f"<{self.type.value}-convergence-measure data=\"{self.data.name}\" mesh=\"{self.mesh.name}\" {limit_str}/>"
+ return xml_str
+
+
+class PreconditionerNode:
+ def __init__(
+ self,
+ type: e.PreconditionerType,
+ acceleration: AccelerationNode,
+ freeze_after: int = -1,
+ update_on_threshold: bool = True
+ ):
+ self.type = type
+ self.acceleration = acceleration
+ self.freeze_after = freeze_after
+ self.update_on_threshold = update_on_threshold
+
+ def to_xml(self) -> str:
+ threshold_str: str = ""
+ if self.acceleration.type != e.AccelerationType.AITKEN:
+ threshold_str = f"update-on-threshold=\"{self.update_on_threshold}\" "
+
+ xml_str: str = f""
+ return xml_str
+
+
+class AccelerationFilterNode:
+ def __init__(
+ self,
+ acceleration: AccelerationNode,
+ type: e.AccelerationFilterType = e.AccelerationFilterType.QR3,
+ limit: float = 1e-16,
+ ):
+ self.acceleration = acceleration
+ self.type = type
+ self.limit = limit
+
+ def to_xml(self) -> str:
+ xml_str: str = f""
+ return xml_str
+
+
+class MappingBasisFunctionNode:
+ def __init__(
+ self,
+ type: e.MappingBasisFunctionType,
+ mapping: MappingNode,
+ support_radius: float = 0.5,
+ shape_parameter: float = 1,
+ ):
+ self.type = type
+ self.mapping = mapping
+ self.support_radius = support_radius
+ self.shape_parameter = shape_parameter
+
+ def to_xml(self) -> str:
+ support_radius: str = ""
+ if self.type in [e.MappingBasisFunctionType.COMPACT_POLYNOMIAL_C0,
+ e.MappingBasisFunctionType.COMPACT_POLYNOMIAL_C2,
+ e.MappingBasisFunctionType.COMPACT_POLYNOMIAL_C4,
+ e.MappingBasisFunctionType.COMPACT_POLYNOMIAL_C6,
+ e.MappingBasisFunctionType.COMPACT_POLYNOMIAL_C8,
+ e.MappingBasisFunctionType.COMPACT_TPS_C2,
+ e.MappingBasisFunctionType.GAUSSIAN,
+ ]:
+ support_radius += f"support-radius=\"{self.support_radius}\" "
+ shape_parameter_str: str = ""
+ if self.type in [e.MappingBasisFunctionType.MULTIQUADRICS,
+ e.MappingBasisFunctionType.INVERSE_MULTIQUADRICS,
+ e.MappingBasisFunctionType.GAUSSIAN]:
+ shape_parameter_str = f"shape-parameter=\"{self.shape_parameter}\" "
+ xml_str: str = f""
+ return xml_str
+
+
+class MappingExecutorNode:
+ def __init__(self, type: e.MappingExecutorType, mapping: MappingNode, gpu_device_id: int = 0, n_threads: int = 0):
+ self.type = type
+ self.mapping = mapping
+ self.gpu_device_id = gpu_device_id
+ self.n_threads = n_threads
+
+ def to_xml(self) -> str:
+ gpu_device_id_str: str = ""
+ if self.type in [e.MappingExecutorType.CUDA, e.MappingExecutorType.HIP]:
+ gpu_device_id_str += f"gpu-device-id=\"{self.gpu_device_id}\" "
+ n_threads_str: str = ""
+ if self.type == e.MappingExecutorType.OPENMP:
+ n_threads_str += f"n-threads=\"{self.n_threads}\" "
+ xml_str: str = f""
+ return xml_str
diff --git a/tests/example-configs/actions/actions_test.py b/tests/example-configs/actions/actions_test.py
index e6f5264..6b9d6bc 100644
--- a/tests/example-configs/actions/actions_test.py
+++ b/tests/example-configs/actions/actions_test.py
@@ -3,7 +3,7 @@
from precice_config_graph import graph, xml_processing
from precice_config_graph import nodes as n
from precice_config_graph.edges import Edge
-from precice_config_graph.nodes import (
+from precice_config_graph.enums import (
DataType,
Direction,
TimingType,
diff --git a/tests/example-configs/multi-coupling/multi-coupling_test.py b/tests/example-configs/multi-coupling/multi-coupling_test.py
index fc3096d..0b970de 100644
--- a/tests/example-configs/multi-coupling/multi-coupling_test.py
+++ b/tests/example-configs/multi-coupling/multi-coupling_test.py
@@ -3,13 +3,7 @@
from precice_config_graph import graph, xml_processing
from precice_config_graph import nodes as n
from precice_config_graph.edges import Edge
-from precice_config_graph.nodes import (
- DataType,
- Direction,
- M2NType,
- MappingMethod,
- MappingConstraint,
-)
+from precice_config_graph import enums as e
def test_graph():
@@ -21,12 +15,12 @@ def test_graph():
edges = []
# Data
- n_data_forces1 = n.DataNode("Forces1", DataType.VECTOR)
- n_data_forces2 = n.DataNode("Forces2", DataType.VECTOR)
- n_data_forces3 = n.DataNode("Forces3", DataType.VECTOR)
- n_data_displacements1 = n.DataNode("Displacements1", DataType.VECTOR)
- n_data_displacements2 = n.DataNode("Displacements2", DataType.VECTOR)
- n_data_displacements3 = n.DataNode("Displacements3", DataType.VECTOR)
+ n_data_forces1 = n.DataNode("Forces1", e.DataType.VECTOR)
+ n_data_forces2 = n.DataNode("Forces2", e.DataType.VECTOR)
+ n_data_forces3 = n.DataNode("Forces3", e.DataType.VECTOR)
+ n_data_displacements1 = n.DataNode("Displacements1", e.DataType.VECTOR)
+ n_data_displacements2 = n.DataNode("Displacements2", e.DataType.VECTOR)
+ n_data_displacements3 = n.DataNode("Displacements3", e.DataType.VECTOR)
# Meshes
n_mesh_nastin1 = n.MeshNode("NASTIN_Mesh1", [n_data_forces1])
@@ -131,10 +125,10 @@ def test_graph():
n_participant_nastin.mappings = [
n.MappingNode(
parent_participant=n_participant_nastin,
- direction=Direction.WRITE,
+ direction=e.Direction.WRITE,
just_in_time=False,
- method=MappingMethod.NEAREST_NEIGHBOR,
- constraint=MappingConstraint.CONSERVATIVE,
+ method=e.MappingMethod.NEAREST_NEIGHBOR,
+ constraint=e.MappingConstraint.CONSERVATIVE,
from_mesh=from_mesh,
to_mesh=to_mesh,
)
@@ -159,94 +153,94 @@ def test_graph():
]
edges += (
- [
- (read_data, participant, Edge.READ_DATA__PARTICIPANT__BELONGS_TO)
- for participant in participants
- for read_data in participant.read_data
- ]
- + [
- (read_data, read_data.data, Edge.READ_DATA__DATA_READ_BY)
- for participant in participants
- for read_data in participant.read_data
- ]
- + [
- (read_data, read_data.mesh, Edge.READ_DATA__MESH_READ_BY)
- for participant in participants
- for read_data in participant.read_data
- ]
+ [
+ (read_data, participant, Edge.READ_DATA__PARTICIPANT__BELONGS_TO)
+ for participant in participants
+ for read_data in participant.read_data
+ ]
+ + [
+ (read_data, read_data.data, Edge.READ_DATA__DATA_READ_BY)
+ for participant in participants
+ for read_data in participant.read_data
+ ]
+ + [
+ (read_data, read_data.mesh, Edge.READ_DATA__MESH_READ_BY)
+ for participant in participants
+ for read_data in participant.read_data
+ ]
)
edges += (
- [
- (
- receive_mesh,
- n_participant_nastin,
- Edge.RECEIVE_MESH__PARTICIPANT__BELONGS_TO,
- )
- for participant in participants
- for receive_mesh in participant.receive_meshes
- ]
- + [
- (receive_mesh, receive_mesh.mesh, Edge.RECEIVE_MESH__MESH)
- for participant in participants
- for receive_mesh in participant.receive_meshes
- ]
- + [
- (
- receive_mesh,
- receive_mesh.from_participant,
- Edge.RECEIVE_MESH__PARTICIPANT_RECEIVED_FROM,
- )
- for participant in participants
- for receive_mesh in participant.receive_meshes
- ]
+ [
+ (
+ receive_mesh,
+ n_participant_nastin,
+ Edge.RECEIVE_MESH__PARTICIPANT__BELONGS_TO,
+ )
+ for participant in participants
+ for receive_mesh in participant.receive_meshes
+ ]
+ + [
+ (receive_mesh, receive_mesh.mesh, Edge.RECEIVE_MESH__MESH)
+ for participant in participants
+ for receive_mesh in participant.receive_meshes
+ ]
+ + [
+ (
+ receive_mesh,
+ receive_mesh.from_participant,
+ Edge.RECEIVE_MESH__PARTICIPANT_RECEIVED_FROM,
+ )
+ for participant in participants
+ for receive_mesh in participant.receive_meshes
+ ]
)
edges += (
- [
- (write_data, participant, Edge.WRITE_DATA__PARTICIPANT__BELONGS_TO)
- for participant in participants
- for write_data in participant.write_data
- ]
- + [
- (write_data, write_data.data, Edge.WRITE_DATA__WRITES_TO_DATA)
- for participant in participants
- for write_data in participant.write_data
- ]
- + [
- (write_data, write_data.mesh, Edge.WRITE_DATA__WRITES_TO_MESH)
- for participant in participants
- for write_data in participant.write_data
- ]
+ [
+ (write_data, participant, Edge.WRITE_DATA__PARTICIPANT__BELONGS_TO)
+ for participant in participants
+ for write_data in participant.write_data
+ ]
+ + [
+ (write_data, write_data.data, Edge.WRITE_DATA__WRITES_TO_DATA)
+ for participant in participants
+ for write_data in participant.write_data
+ ]
+ + [
+ (write_data, write_data.mesh, Edge.WRITE_DATA__WRITES_TO_MESH)
+ for participant in participants
+ for write_data in participant.write_data
+ ]
)
edges += (
- [
- (mapping, n_participant_nastin, Edge.MAPPING__PARTICIPANT__BELONGS_TO)
- for participant in participants
- for mapping in participant.mappings
- ]
- + [
- (mapping, mapping.from_mesh, Edge.MAPPING__FROM_MESH)
- for participant in participants
- for mapping in participant.mappings
- ]
- + [
- (mapping, mapping.to_mesh, Edge.MAPPING__TO_MESH)
- for participant in participants
- for mapping in participant.mappings
- ]
+ [
+ (mapping, n_participant_nastin, Edge.MAPPING__PARTICIPANT__BELONGS_TO)
+ for participant in participants
+ for mapping in participant.mappings
+ ]
+ + [
+ (mapping, mapping.from_mesh, Edge.MAPPING__FROM_MESH)
+ for participant in participants
+ for mapping in participant.mappings
+ ]
+ + [
+ (mapping, mapping.to_mesh, Edge.MAPPING__TO_MESH)
+ for participant in participants
+ for mapping in participant.mappings
+ ]
)
# M2N nodes
m2n_nastin_solidz1 = n.M2NNode(
- M2NType.SOCKETS, n_participant_nastin, n_participant_solizd1
+ e.M2NType.SOCKETS, n_participant_nastin, n_participant_solizd1
)
m2n_nastin_solidz2 = n.M2NNode(
- M2NType.SOCKETS, n_participant_nastin, n_participant_solizd2
+ e.M2NType.SOCKETS, n_participant_nastin, n_participant_solizd2
)
m2n_nastin_solidz3 = n.M2NNode(
- M2NType.SOCKETS, n_participant_nastin, n_participant_solizd3
+ e.M2NType.SOCKETS, n_participant_nastin, n_participant_solizd3
)
edges += [
@@ -274,15 +268,15 @@ def test_graph():
)
edges += [
- (n_coupling_scheme, participant, Edge.MULTI_COUPLING_SCHEME__PARTICIPANT)
- for participant in n_coupling_scheme.participants
- ] + [
- (
- n_coupling_scheme,
- n_participant_nastin,
- Edge.MULTI_COUPLING_SCHEME__PARTICIPANT__CONTROL,
- )
- ]
+ (n_coupling_scheme, participant, Edge.MULTI_COUPLING_SCHEME__PARTICIPANT)
+ for participant in n_coupling_scheme.participants
+ ] + [
+ (
+ n_coupling_scheme,
+ n_participant_nastin,
+ Edge.MULTI_COUPLING_SCHEME__PARTICIPANT__CONTROL,
+ )
+ ]
n_exchange_forces1 = n.ExchangeNode(
coupling_scheme=n_coupling_scheme,
@@ -337,24 +331,24 @@ def test_graph():
n_coupling_scheme.exchanges = exchanges
edges += (
- [
- (exchange, n_coupling_scheme, Edge.EXCHANGE__COUPLING_SCHEME__BELONGS_TO)
- for exchange in exchanges
- ]
- + [(exchange, exchange.data, Edge.EXCHANGE__DATA) for exchange in exchanges]
- + [(exchange, exchange.mesh, Edge.EXCHANGE__MESH) for exchange in exchanges]
- + [
- (exchange, exchange.from_participant, Edge.EXCHANGE__EXCHANGED_FROM)
- for exchange in exchanges
- ]
- + [
- (exchange, exchange.to_participant, Edge.EXCHANGE__EXCHANGES_TO)
- for exchange in exchanges
- ]
+ [
+ (exchange, n_coupling_scheme, Edge.EXCHANGE__COUPLING_SCHEME__BELONGS_TO)
+ for exchange in exchanges
+ ]
+ + [(exchange, exchange.data, Edge.EXCHANGE__DATA) for exchange in exchanges]
+ + [(exchange, exchange.mesh, Edge.EXCHANGE__MESH) for exchange in exchanges]
+ + [
+ (exchange, exchange.from_participant, Edge.EXCHANGE__EXCHANGED_FROM)
+ for exchange in exchanges
+ ]
+ + [
+ (exchange, exchange.to_participant, Edge.EXCHANGE__EXCHANGES_TO)
+ for exchange in exchanges
+ ]
)
- acceleration = n.AccelerationNode(n_coupling_scheme, n.AccelerationType.IQN_ILS)
- n_coupling_scheme.accelerations.append(acceleration)
+ acceleration = n.AccelerationNode(n_coupling_scheme, e.AccelerationType.IQN_ILS)
+ n_coupling_scheme.acceleration = acceleration
acceleration_data1 = n.AccelerationDataNode(
acceleration, n_data_forces1, n_mesh_solidz1
)
@@ -369,95 +363,95 @@ def test_graph():
acceleration.data.append(acceleration_data3)
edges += (
- [
- (
- acceleration,
- acceleration.coupling_scheme,
- Edge.ACCELERATION__COUPLING_SCHEME__BELONGS_TO,
- )
- ]
- + [
- (
- data_node,
- data_node.acceleration,
- Edge.ACCELERATION_DATA__ACCELERATION__BELONGS_TO,
- )
- for data_node in acceleration.data
- ]
- + [
- (data_node, data_node.data, Edge.ACCELERATION_DATA__DATA)
- for data_node in acceleration.data
- ]
- + [
- (data_node, data_node.mesh, Edge.ACCELERATION_DATA__MESH)
- for data_node in acceleration.data
- ]
+ [
+ (
+ acceleration,
+ acceleration.coupling_scheme,
+ Edge.ACCELERATION__COUPLING_SCHEME__BELONGS_TO,
+ )
+ ]
+ + [
+ (
+ data_node,
+ data_node.acceleration,
+ Edge.ACCELERATION_DATA__ACCELERATION__BELONGS_TO,
+ )
+ for data_node in acceleration.data
+ ]
+ + [
+ (data_node, data_node.data, Edge.ACCELERATION_DATA__DATA)
+ for data_node in acceleration.data
+ ]
+ + [
+ (data_node, data_node.mesh, Edge.ACCELERATION_DATA__MESH)
+ for data_node in acceleration.data
+ ]
)
convergence_measures = [
n.ConvergenceMeasureNode(
n_coupling_scheme,
- n.ConvergenceMeasureType.RELATIVE,
+ e.ConvergenceMeasureType.RELATIVE,
n_data_displacements1,
n_mesh_solidz1,
),
n.ConvergenceMeasureNode(
n_coupling_scheme,
- n.ConvergenceMeasureType.RELATIVE,
+ e.ConvergenceMeasureType.RELATIVE,
n_data_displacements2,
n_mesh_solidz2,
),
n.ConvergenceMeasureNode(
n_coupling_scheme,
- n.ConvergenceMeasureType.RELATIVE,
+ e.ConvergenceMeasureType.RELATIVE,
n_data_displacements3,
n_mesh_solidz3,
),
n.ConvergenceMeasureNode(
n_coupling_scheme,
- n.ConvergenceMeasureType.RELATIVE,
+ e.ConvergenceMeasureType.RELATIVE,
n_data_forces1,
n_mesh_solidz1,
),
n.ConvergenceMeasureNode(
n_coupling_scheme,
- n.ConvergenceMeasureType.RELATIVE,
+ e.ConvergenceMeasureType.RELATIVE,
n_data_forces2,
n_mesh_solidz2,
),
n.ConvergenceMeasureNode(
n_coupling_scheme,
- n.ConvergenceMeasureType.RELATIVE,
+ e.ConvergenceMeasureType.RELATIVE,
n_data_forces3,
n_mesh_solidz3,
),
]
edges += (
- [
- (
- convergence_measure,
- convergence_measure.coupling_scheme,
- Edge.CONVERGENCE_MEASURE__COUPLING_SCHEME__BELONGS_TO,
- )
- for convergence_measure in convergence_measures
- ]
- + [
- (
- convergence_measure,
- convergence_measure.data,
- Edge.CONVERGENCE_MEASURE__DATA,
- )
- for convergence_measure in convergence_measures
- ]
- + [
- (
- convergence_measure,
- convergence_measure.mesh,
- Edge.CONVERGENCE_MEASURE__MESH,
- )
- for convergence_measure in convergence_measures
- ]
+ [
+ (
+ convergence_measure,
+ convergence_measure.coupling_scheme,
+ Edge.CONVERGENCE_MEASURE__COUPLING_SCHEME__BELONGS_TO,
+ )
+ for convergence_measure in convergence_measures
+ ]
+ + [
+ (
+ convergence_measure,
+ convergence_measure.data,
+ Edge.CONVERGENCE_MEASURE__DATA,
+ )
+ for convergence_measure in convergence_measures
+ ]
+ + [
+ (
+ convergence_measure,
+ convergence_measure.mesh,
+ Edge.CONVERGENCE_MEASURE__MESH,
+ )
+ for convergence_measure in convergence_measures
+ ]
)
G_expected = nx.Graph()
@@ -473,8 +467,8 @@ def edge_match(edge_a, edge_b):
assert nx.is_isomorphic(
G_expected, G_actual, node_match=node_match, edge_match=edge_match
), (
- f"Graphs did not match. Some stats: Expected: (num nodes: {len(G_expected.nodes)}, num edges: {len(G_expected.edges)}), "
- + f"Actual: (num nodes: {len(G_actual.nodes)}, num edges: {len(G_actual.edges)})"
+ f"Graphs did not match. Some stats: Expected: (num nodes: {len(G_expected.nodes)}, num edges: {len(G_expected.edges)}), "
+ + f"Actual: (num nodes: {len(G_actual.nodes)}, num edges: {len(G_actual.edges)})"
)
print("\nGraphs are isomorphic.")
diff --git a/tests/example-configs/simple-good/simple-good_test.py b/tests/example-configs/simple-good/simple-good_test.py
index 6ef77a9..bd14854 100644
--- a/tests/example-configs/simple-good/simple-good_test.py
+++ b/tests/example-configs/simple-good/simple-good_test.py
@@ -3,7 +3,7 @@
from precice_config_graph import graph, xml_processing
from precice_config_graph import nodes as n
from precice_config_graph.edges import Edge
-from precice_config_graph.nodes import (
+from precice_config_graph.enums import (
DataType,
Direction,
CouplingSchemeType,