fenicsx_cosim.adapters package

Submodules

fenicsx_cosim.adapters.abaqus_adapter module

AbaqusFileAdapter — File-based staggered coupling for Abaqus.

Abaqus does not provide a live Python API that can easily integrate with ZeroMQ communication during an implicit timestep. Instead, this adapter facilitates a file-based staggered coupling approach.

The FEniCSx solver (or a Python wrapper running alongside Abaqus) uses this adapter to read/write Numpy .npy files in a designated exchange directory.

Workflow

  1. A pre-processing step writes boundary coordinates to <exch_dir>/boundary_coords.npy.

  2. During the time loop, Abaqus writes its output (e.g. TEMPERATURE) to <exch_dir>/TEMPERATURE_out.npy.

  3. The coupling interface extracts this parameter and sends it to FEniCSx.

  4. FEniCSx sends back its output (e.g. DISPLACEMENT).

  5. The adapter injects (writes) this parameter to <exch_dir>/DISPLACEMENT_in.npy.

  6. The Abaqus script reads the _in.npy file to apply boundary conditions for the next step.

fenicsx_cosim.adapters.abaqus_adapter.exchange_dir

Directory where data files are exchanged.

Type:

Path

class fenicsx_cosim.adapters.abaqus_adapter.AbaqusFileAdapter(exchange_dir: str | Path, timeout_s: float = 60.0)[source]

Bases: SolverAdapter

Adapter for file-based coupling with Abaqus.

Parameters:
  • exchange_dir (str | Path) – Path to the shared directory where .npy files are written/read.

  • timeout_s (float, optional) – Maximum time to wait for expected files to appear. Currently unused as exact file presence is checked instantly for simplicity, but could be extended for polling file locks.

advance() None[source]

No-op — File synchronization handles step progression implicitly.

extract_field(field_name: str) ndarray[source]

Read field from ‘<field_name>_out.npy’.

Parameters:

field_name (str) – Name of the field.

Returns:

Shape (N,) or (N, 3).

Return type:

np.ndarray

get_boundary_coordinates() ndarray[source]

Read coordinates from ‘boundary_coords.npy’.

Returns:

Shape (N, 3).

Return type:

np.ndarray

Raises:

FileNotFoundError – If the coordinates file does not exist.

get_metadata() dict[str, str][source]

Return solver metadata (mesh info, solver name, etc.).

Override to provide metadata that the partner solver can inspect.

inject_field(field_name: str, values: ndarray) None[source]

Write field to ‘<field_name>_in.npy’.

Parameters:
  • field_name (str) – Name of the field.

  • values (np.ndarray) – Values to write.

fenicsx_cosim.adapters.base module

SolverAdapter — Abstract base class for multi-solver coupling.

Every external solver that participates in a fenicsx-cosim coupling must provide a concrete SolverAdapter. The adapter’s job is to translate the solver’s native data structures (e.g. Kratos ModelPart, Abaqus ODB, MOOSE variables) into plain NumPy arrays that the Communicator can serialize and transmit over ZeroMQ.

This is the “last mile” abstraction — everything before it (ZMQ transport, nearest-neighbour mapping, synchronization) is solver-agnostic.

class fenicsx_cosim.adapters.base.SolverAdapter[source]

Bases: ABC

Bridge between any solver’s native data structures and fenicsx-cosim.

Subclasses must implement the four abstract methods below. The adapter is then passed to CouplingInterface.from_adapter() (or used standalone with a raw Communicator).

Design principles

  • No FEniCSx dependency — adapters for external solvers must not import dolfinx. Only the FEniCSxAdapter needs DOLFINx.

  • NumPy is the lingua franca — all data is exchanged as NumPy arrays (coordinates as (N, 3) float64, scalar fields as (N,) float64, vector fields as (N, dim) float64).

  • Thin wrappers — adapters should delegate to solver APIs, not re-implement solver logic.

abstractmethod advance() None[source]

Advance the solver by one time step.

This is called by CouplingInterface.advance_in_time() after data exchange is complete. Implement as a no-op if the solver’s time-stepping is managed externally.

abstractmethod extract_field(field_name: str) ndarray[source]

Extract a field’s values at coupling boundary nodes.

Parameters:

field_name (str) – Solver-native field identifier (e.g. "TEMPERATURE").

Returns:

Shape (N,) for scalar or (N, dim) for vector fields.

Return type:

np.ndarray

abstractmethod get_boundary_coordinates() ndarray[source]

Return coordinates of coupling boundary nodes.

Returns:

Shape (N, 3), dtype float64. Each row is (x, y, z) for a boundary node.

Return type:

np.ndarray

get_field_names() list[str][source]

Return a list of available field names for export.

Override to advertise which fields the solver can provide. The default returns an empty list (metadata exchange is optional).

get_metadata() dict[str, Any][source]

Return solver metadata (mesh info, solver name, etc.).

Override to provide metadata that the partner solver can inspect.

abstractmethod inject_field(field_name: str, values: ndarray) None[source]

Set field values at coupling boundary nodes.

Parameters:
  • field_name (str) – Solver-native field identifier.

  • values (np.ndarray) – Same shape convention as extract_field().

fenicsx_cosim.adapters.fenicsx_adapter module

FEniCSxAdapter — wraps MeshExtractor in the SolverAdapter interface.

This adapter allows existing FEniCSx-based workflows to use the new unified adapter API. CouplingInterface uses this internally when register_interface() is called.

It also serves as the canonical reference implementation for writing new adapters for other solvers.

class fenicsx_cosim.adapters.fenicsx_adapter.FEniCSxAdapter(mesh: dolfinx.mesh.Mesh, facet_tags: dolfinx.mesh.MeshTags | None = None, marker_id: int = 1, function_space: dolfinx.fem.FunctionSpace | None = None, locator_fn=None)[source]

Bases: SolverAdapter

Adapter that bridges FEniCSx data structures to fenicsx-cosim.

Wraps the existing MeshExtractor to provide the standardised SolverAdapter interface.

Parameters:
  • mesh (dolfinx.mesh.Mesh) – The computational mesh.

  • facet_tags (dolfinx.mesh.MeshTags, optional) – Mesh tags labelling boundary facets.

  • marker_id (int, optional) – The coupling boundary marker. Default 1.

  • function_space (dolfinx.fem.FunctionSpace, optional) – If None, a Lagrange-1 scalar space is created.

  • locator_fn (callable, optional) – Alternative to facet_tags: a geometric locator function.

advance() None[source]

No-op — FEniCSx time-stepping is managed by the user script.

extract_boundary_values(function: dolfinx.fem.Function) ndarray[source]

Direct passthrough to MeshExtractor (for backward compat).

extract_field(field_name: str) ndarray[source]

Extract boundary values from a registered FEniCSx Function.

The field_name is used to look up the function in the internal registry (set via register_function()).

property extractor: MeshExtractor

The underlying MeshExtractor.

property function_space: dolfinx.fem.FunctionSpace

The function space used for boundary extraction.

get_boundary_coordinates() ndarray[source]

Return boundary DoF coordinates — shape (N, 3).

get_field_names() list[str][source]

Return names of all registered fields.

inject_boundary_values(function: dolfinx.fem.Function, values: ndarray) None[source]

Direct passthrough to MeshExtractor (for backward compat).

inject_field(field_name: str, values: ndarray) None[source]

Inject values into a registered FEniCSx Function at boundary DoFs.

register_function(field_name: str, function: dolfinx.fem.Function) None[source]

Register a FEniCSx Function for a named field.

Parameters:
  • field_name (str) – Name to associate with this function (e.g. "TEMPERATURE").

  • function (dolfinx.fem.Function) – The FEniCSx function.

fenicsx_cosim.adapters.kratos_adapter module

KratosAdapter — SolverAdapter for Kratos Multiphysics.

Bridges the Kratos Multiphysics Python API to fenicsx-cosim, enabling bidirectional coupling between FEniCSx and Kratos solvers.

This adapter operates on a Kratos ModelPart and its sub-model-parts (which define coupling interfaces). It translates between Kratos’ node-based data structures and the NumPy arrays expected by the fenicsx-cosim communication layer.

Requirements

  • KratosMultiphysics Python package must be importable.

  • The Kratos model must be set up with a sub-model-part defining the coupling boundary (e.g. "coupling_interface").

Typical usage

>>> import KratosMultiphysics
>>> from fenicsx_cosim.adapters import KratosAdapter
>>> from fenicsx_cosim import CouplingInterface
>>>
>>> # Set up Kratos model (simplified)
>>> model = KratosMultiphysics.Model()
>>> model_part = model.CreateModelPart("Structure")
>>> # ... populate mesh, define interface sub-model-part ...
>>>
>>> adapter = KratosAdapter(model_part, "coupling_interface")
>>> cosim = CouplingInterface.from_adapter(
...     adapter, name="KratosSolver", partner_name="FEniCSxSolver"
... )
>>> cosim.register_adapter_interface()
>>> cosim.export_via_adapter("TEMPERATURE")
>>> cosim.import_via_adapter("DISPLACEMENT_X")
class fenicsx_cosim.adapters.kratos_adapter.KratosAdapter(model_part: KratosMultiphysics.ModelPart, interface_sub_model_part_name: str, variable_map: dict[str, Any] | None = None)[source]

Bases: SolverAdapter

Adapter for coupling Kratos Multiphysics solvers via fenicsx-cosim.

Parameters:
  • model_part (KratosMultiphysics.ModelPart) – The main Kratos model part containing the simulation data.

  • interface_sub_model_part_name (str) – Name of the sub-model-part that defines the coupling boundary. All coordinate/field extraction happens on this sub-model-part’s nodes.

  • variable_map (dict[str, Any], optional) – Mapping from string field names to Kratos variable objects. If None (default), variables are looked up dynamically via KratosMultiphysics.KratosGlobals.GetVariable(field_name).

Examples

>>> adapter = KratosAdapter(model_part, "interface_boundary")
>>> coords = adapter.get_boundary_coordinates()  # (N, 3) array
>>> temp = adapter.extract_field("TEMPERATURE")   # (N,) array
>>> adapter.inject_field("DISPLACEMENT_X", disp_x) # set values
advance() None[source]

No-op — Kratos time-stepping is managed by the user script.

extract_field(field_name: str) ndarray[source]

Extract a scalar field from interface nodes.

Parameters:

field_name (str) – Kratos variable name (e.g. "TEMPERATURE", "DISPLACEMENT_X").

Returns:

Shape (N,) — one value per interface node.

Return type:

np.ndarray

extract_vector_field(field_name: str) ndarray[source]

Extract a vector field (e.g. DISPLACEMENT, VELOCITY).

Parameters:

field_name (str) – Kratos vector variable name.

Returns:

Shape (N, 3)(x, y, z) components per node.

Return type:

np.ndarray

get_boundary_coordinates() ndarray[source]

Return coupling boundary node coordinates.

Returns:

Shape (N, 3)(x, y, z) for each interface node, in the same order as node_ids.

Return type:

np.ndarray

get_field_names() list[str][source]

Return user-registered field names.

get_metadata() dict[str, Any][source]

Return summary metadata about the Kratos interface.

inject_field(field_name: str, values: ndarray) None[source]

Set a scalar field at interface nodes.

Parameters:
  • field_name (str) – Kratos variable name.

  • values (np.ndarray) – Shape (N,) — one value per interface node.

Raises:

ValueError – If values length doesn’t match the number of interface nodes.

inject_vector_field(field_name: str, values: ndarray) None[source]

Set a vector field at interface nodes.

Parameters:
  • field_name (str) – Kratos vector variable name.

  • values (np.ndarray) – Shape (N, 3).

property node_ids: list[int]

Interface node IDs in consistent order.

property num_nodes: int

Number of coupling boundary nodes.

Module contents

Solver adapters for fenicsx-cosim.

This subpackage provides adapter classes that bridge external solvers (Kratos, Abaqus, etc.) to the fenicsx-cosim communication layer.

Each adapter implements the SolverAdapter ABC, which standardizes how boundary coordinates and field data are extracted/injected regardless of the underlying solver.

class fenicsx_cosim.adapters.SolverAdapter[source]

Bases: ABC

Bridge between any solver’s native data structures and fenicsx-cosim.

Subclasses must implement the four abstract methods below. The adapter is then passed to CouplingInterface.from_adapter() (or used standalone with a raw Communicator).

Design principles

  • No FEniCSx dependency — adapters for external solvers must not import dolfinx. Only the FEniCSxAdapter needs DOLFINx.

  • NumPy is the lingua franca — all data is exchanged as NumPy arrays (coordinates as (N, 3) float64, scalar fields as (N,) float64, vector fields as (N, dim) float64).

  • Thin wrappers — adapters should delegate to solver APIs, not re-implement solver logic.

abstractmethod advance() None[source]

Advance the solver by one time step.

This is called by CouplingInterface.advance_in_time() after data exchange is complete. Implement as a no-op if the solver’s time-stepping is managed externally.

abstractmethod extract_field(field_name: str) ndarray[source]

Extract a field’s values at coupling boundary nodes.

Parameters:

field_name (str) – Solver-native field identifier (e.g. "TEMPERATURE").

Returns:

Shape (N,) for scalar or (N, dim) for vector fields.

Return type:

np.ndarray

abstractmethod get_boundary_coordinates() ndarray[source]

Return coordinates of coupling boundary nodes.

Returns:

Shape (N, 3), dtype float64. Each row is (x, y, z) for a boundary node.

Return type:

np.ndarray

get_field_names() list[str][source]

Return a list of available field names for export.

Override to advertise which fields the solver can provide. The default returns an empty list (metadata exchange is optional).

get_metadata() dict[str, Any][source]

Return solver metadata (mesh info, solver name, etc.).

Override to provide metadata that the partner solver can inspect.

abstractmethod inject_field(field_name: str, values: ndarray) None[source]

Set field values at coupling boundary nodes.

Parameters:
  • field_name (str) – Solver-native field identifier.

  • values (np.ndarray) – Same shape convention as extract_field().