cyprecice module

precice

The python module precice offers python language bindings to the C++ coupling library precice. Please refer to precice.org for further information.

class cyprecice.Participant

Bases: object

Main Application Programming Interface of preCICE. To adapt a solver to preCICE, follow the following main structure:

  • Create an object of Participant with Participant()

  • Initialize preCICE with Participant::initialize()

  • Advance to the next (time)step with Participant::advance()

  • Finalize preCICE with Participant::finalize()

  • We use solver, simulation code, and participant as synonyms.

  • The preferred name in the documentation is participant.

advance(computed_timestep_length)

Advances preCICE after the solver has computed one timestep.

Parameters

computed_timestep_lengthdouble

Length of timestep used by the solver.

Notes

Previous calls:

initialize() has been called successfully. The solver has computed one timestep. The solver has written all coupling data. finalize() has not yet been called.

Tasks completed:

Coupling data values specified in the configuration are exchanged. Coupling scheme state (computed time, computed timesteps, …) is updated. The coupling state is logged. Configured data mapping schemes are applied. [Second Participant] Configured post processing schemes are applied. Meshes with data are exported to files if configured.

finalize()

Finalizes preCICE.

Notes

Previous calls:

initialize() has been called successfully.

Tasks completed:

Communication channels are closed. Meshes and data are deallocated.

get_data_dimensions(mesh_name, data_name)

Returns the spatial dimensionality of the given data on the given mesh.

Parameters

mesh_namestring

Name of the mesh.

data_namestring

Name of the data.

Returns

dimensionint

The dimensions of the given data.

get_max_time_step_size()

Get the maximum allowed time step size of the current window.

Allows the user to query the maximum allowed time step size in the current window. This should be used to compute the actual time step that the solver uses.

Returns

tagdouble

Maximum size of time step to be computed by solver.

Notes

Previous calls:

initialize() has been called successfully.

get_mesh_dimensions(mesh_name)

Returns the spatial dimensionality of the given mesh.

Parameters

mesh_namestring

Name of the mesh.

Returns

dimensionint

The dimensions of the given mesh.

get_mesh_vertex_ids_and_coordinates(mesh_name)

Iterating over the region of interest defined by bounding boxes and reading the corresponding coordinates omitting the mapping. This function is still experimental.

Parameters

mesh_namestr

Corresponding mesh name

Returns

idsnumpy.ndarray

Vertex IDs corresponding to the coordinates

coordinatesnumpy.ndarray

he coordinates associated to the IDs and corresponding data values (dim * size)

get_mesh_vertex_size(mesh_name)

Returns the number of vertices of a mesh

Parameters

mesh_namestr

Name of the mesh.

Returns

sumint

Number of vertices of the mesh.

initialize()

Fully initializes preCICE and initializes coupling data. The starting values for coupling data are zero by default. To provide custom values, first set the data using the Data Access methods before calling this method to finally exchange the data.

This function handles:
  • Parallel communication to the coupling partner/s is setup.

  • Meshes are exchanged between coupling partners and the parallel partitions are created.

  • [Serial Coupling Scheme] If the solver is not starting the simulation, coupling data is received

    from the coupling partner’s first computation.

Returns

max_timestepdouble

Maximum length of first timestep to be computed by the solver.

is_coupling_ongoing()

Checks if the coupled simulation is still ongoing. A coupling is ongoing as long as

  • the maximum number of timesteps has not been reached, and

  • the final time has not been reached.

The user should call finalize() after this function returns false.

Returns

tagbool

Whether the coupling is ongoing.

Notes

Previous calls:

initialize() has been called successfully.

is_time_window_complete()

Checks if the current coupling timewindow is completed. The following reasons require several solver time steps per coupling time step:

  • A solver chooses to perform subcycling.

  • An implicit coupling timestep iteration is not yet converged.

Returns

tagbool

Whether the timestep is complete.

Notes

Previous calls:

initialize() has been called successfully.

read_data(mesh_name, data_name, vertex_ids, relative_read_time)

Reads data into a provided block. This function reads values of specified vertices from a dataID. Values are read into a block of continuous memory.

Parameters

mesh_namestr

Name of the mesh to write to.

data_namestr

ID to read from.

vertex_idsarray_like

Indices of the vertices.

relative_read_timedouble

Point in time where data is read relative to the beginning of the current time step

Returns

valuesnumpy.ndarray

Contains the read data.

Notes

Previous calls:

count of available elements at values matches the configured dimension * size count of available elements at vertex_ids matches the given size initialize() has been called

Examples

Read scalar data for a 2D problem with 5 vertices: >>> mesh_name = “MeshOne” >>> data_name = “DataOne” >>> vertex_ids = [1, 2, 3, 4, 5] >>> dt = 1.0 >>> values = read_data(mesh_name, data_name, vertex_ids, dt) >>> values.shape >>> (5, )

Read vector data for a 2D problem with 5 vertices: >>> mesh_name = “MeshOne” >>> data_name = “DataOne” >>> vertex_ids = [1, 2, 3, 4, 5] >>> dt = 1.0 >>> values = read_data(mesh_name, data_name, vertex_ids, dt) >>> values.shape >>> (5, 2)

Read vector data for a 3D system with 5 vertices: >>> mesh_name = “MeshOne” >>> data_name = “DataOne” >>> vertex_ids = [1, 2, 3, 4, 5] >>> dt = 1.0 >>> values = read_data(mesh_name, data_name, vertex_ids, dt) >>> values.shape >>> (5, 3)

requires_gradient_data_for(mesh_name, data_name)

Checks if the given data set requires gradient data. We check if the data object has been intialized with the gradient flag.

Parameters

mesh_namestr

Mesh name to check.

data_namestr

Data name to check.

Returns

bool

True if gradient data is required for a data.

Examples

Check if gradient data is required for a data: >>> mesh_name = “MeshOne” >>> data_name = “DataOne” >>> participant.is_gradient_data_required(mesh_name, data_name)

requires_initial_data()

Checks if the participant is required to provide initial data. If true, then the participant needs to write initial data to defined vertices prior to calling initialize().

Returns

tagbool

Returns True if inital data is required.

Notes

Previous calls:

initialize() has not yet been called

requires_mesh_connectivity_for(mesh_name)

Checks if the given mesh requires connectivity.

Parameters

mesh_namestring

Name of the mesh.

Returns

tagbool

True if mesh connectivity is required.

requires_reading_checkpoint()

Checks if the participant is required to read an iteration checkpoint.

If true, the participant is required to read an iteration checkpoint before calling advance().

preCICE refuses to proceed if reading a checkpoint is required, but this method isn’t called prior to advance().

Notes

This function returns false before the first call to advance().

Previous calls:

initialize() has been called

requires_writing_checkpoint()

Checks if the participant is required to write an iteration checkpoint.

If true, the participant is required to write an iteration checkpoint before calling advance().

preCICE refuses to proceed if writing a checkpoint is required, but this method isn’t called prior to advance().

Notes

Previous calls:

initialize() has been called

set_mesh_access_region(mesh_name, bounding_box)

This function is required if you don’t want to use the mapping schemes in preCICE, but rather want to use your own solver for data mapping. As opposed to the usual preCICE mapping, only a single mesh (from the other participant) is now involved in this situation since an ‘own’ mesh defined by the participant itself is not required any more. In order to re-partition the received mesh, the participant needs to define the mesh region it wants read data from and write data to. The mesh region is specified through an axis-aligned bounding box given by the lower and upper [min and max] bounding-box limits in each space dimension [x, y, z]. This function is still experimental

Parameters

mesh_namestr

Name of the mesh you want to access through the bounding box

bounding_boxarray_like

Axis aligned bounding box. Example for 3D the format: [x_min, x_max, y_min, y_max, z_min, z_max]

Notes

Defining a bounding box for serial runs of the solver (not to be confused with serial coupling mode) is valid. However, a warning is raised in case vertices are filtered out completely on the receiving side, since the associated data values of the filtered vertices are filled with zero data.

This function can only be called once per participant and rank and trying to call it more than once results in an error.

If you combine the direct access with a mapping (say you want to read data from a defined mesh, as usual, but you want to directly access and write data on a received mesh without a mapping) you may not need this function at all since the region of interest is already defined through the defined mesh used for data reading. This is the case if you define any mapping involving the directly accessed mesh on the receiving participant. (In parallel, only the cases read-consistent and write-conservative are relevant, as usual).

The safety factor scaling (see safety-factor in the configuration file) is not applied to the defined access region and a specified safety will be ignored in case there is no additional mapping involved. However, in case a mapping is in addition to the direct access involved, you will receive (and gain access to) vertices inside the defined access region plus vertices inside the safety factor region resulting from the mapping. The default value of the safety factor is 0.5, i.e. the defined access region as computed through the involved provided mesh is by 50% enlarged.

set_mesh_edge(mesh_name, first_vertex_id, second_vertex_id)

Sets mesh edge from vertex IDs, returns edge ID.

Parameters

mesh_namestr

Name of the mesh to add the edge to.

first_vertex_idint

ID of the first vertex of the edge.

second_vertex_idint

ID of the second vertex of the edge.

Returns

edge_idint

ID of the edge.

Notes

Previous calls:

vertices with firstVertexID and secondVertexID were added to the mesh with name mesh_name

set_mesh_edges(mesh_name, vertices)

Creates multiple mesh edges

Parameters

mesh_namestr

Name of the mesh to add the vertices to.

verticesarray_like

The IDs of the vertices in a numpy array [N x 2] where N = number of edges and D = dimensions of geometry.

Examples

Set mesh edges for a problem with 4 mesh vertices in the form of a square with both diagonals which are fully interconnected.

>>> vertices = np.array([[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]])
>>> vertices.shape
(6, 2)
>>> participant.set_mesh_edges(mesh_name, vertices)
set_mesh_quad(mesh_name, first_vertex_id, second_vertex_id, third_vertex_id, fourth_vertex_id)

Set a mesh Quad from vertex IDs.

Parameters

mesh_namestr

Name of the mesh to add the quad to.

first_vertex_idint

ID of the first vertex of the quad.

second_vertex_idint

ID of the second vertex of the quad.

third_vertex_idint

ID of the third vertex of the quad.

fourth_vertex_idint

ID of the third vertex of the quad.

Notes

Previous calls:

vertices with first_vertex_id, second_vertex_id, third_vertex_id, and fourth_vertex_id were added to the mesh with the name mesh_name

set_mesh_quads(mesh_name, vertices)

Creates multiple mesh quads

Parameters

mesh_namestr

Name of the mesh to add the quads to.

verticesarray_like

The IDs of the vertices in a numpy array [N x 4] where N = number of quads and D = dimensions of geometry.

Examples

Set mesh quads for a problem with 4 mesh vertices in the form of a square with both diagonals which are fully interconnected.

>>> vertices = np.array([[1, 2, 3, 4]])
>>> vertices.shape
(1, 2)
>>> participant.set_mesh_quads(mesh_name, vertices)
set_mesh_tetrahedra(mesh_name, vertices)

Creates multiple mesh tetdrahedrons

Parameters

mesh_namestr

Name of the mesh to add the tetrahedrons to.

verticesarray_like

The IDs of the vertices in a numpy array [N x 4] where N = number of quads and D = dimensions of geometry.

Examples

Set mesh tetrahedrons for a problem with 4 mesh vertices.

>>> vertices = np.array([[1, 2, 3, 4]])
>>> vertices.shape
(1, 2)
>>> participant.set_mesh_tetradehra(mesh_name, vertices)
set_mesh_tetrahedron(mesh_name, first_vertex_id, second_vertex_id, third_vertex_id, fourth_vertex_id)

Sets a mesh tetrahedron from vertex IDs.

Parameters

mesh_namestr

Name of the mesh to add the tetrahedron to.

first_vertex_idint

ID of the first vertex of the tetrahedron.

second_vertex_idint

ID of the second vertex of the tetrahedron.

third_vertex_idint

ID of the third vertex of the tetrahedron.

fourth_vertex_idint

ID of the third vertex of the tetrahedron.

Notes

Previous calls:

vertices with first_vertex_id, second_vertex_id, third_vertex_id, and fourth_vertex_id were added to the mesh with the name mesh_name

set_mesh_triangle(mesh_name, first_vertex_id, second_vertex_id, third_vertex_id)

Set a mesh triangle from edge IDs

Parameters

mesh_namestr

Name of the mesh to add the triangle to.

first_vertex_idint

ID of the first vertex of the triangle.

second_vertex_idint

ID of the second vertex of the triangle.

third_vertex_idint

ID of the third vertex of the triangle.

Notes

Previous calls:

vertices with first_vertex_id, second_vertex_id, and third_vertex_id were added to the mesh with the name mesh_name

set_mesh_triangles(mesh_name, vertices)

Creates multiple mesh triangles

Parameters

mesh_namestr

Name of the mesh to add the triangles to.

verticesarray_like

The IDs of the vertices in a numpy array [N x 3] where N = number of triangles and D = dimensions of geometry.

Examples

Set mesh triangles for a problem with 4 mesh vertices in the form of a square with both diagonals which are fully interconnected.

>>> vertices = np.array([[1, 2, 3], [1, 3, 4], [1, 2, 4], [1, 3, 4]])
>>> vertices.shape
(4, 2)
>>> participant.set_mesh_triangles(mesh_name, vertices)
set_mesh_vertex(mesh_name, position)

Creates a mesh vertex

Parameters

mesh_namestr

Name of the mesh to add the vertex to.

positionarray_like

The coordinates of the vertex.

Returns

vertex_idint

ID of the vertex which is set.

Notes

Previous calls:

Count of available elements at position matches the configured dimension

set_mesh_vertices(mesh_name, positions)

Creates multiple mesh vertices

Parameters

mesh_namestr

Name of the mesh to add the vertices to.

positionsarray_like

The coordinates of the vertices in a numpy array [N x D] where N = number of vertices and D = dimensions of geometry.

Returns

vertex_idsnumpy.ndarray

IDs of the created vertices.

Notes

Previous calls:

initialize() has not yet been called count of available elements at positions matches the configured dimension * size count of available elements at ids matches size

Examples

Set mesh vertices for a 2D problem with 5 mesh vertices.

>>> positions = np.array([[1, 1], [2, 2], [3, 3], [4, 4], [5, 5]])
>>> positions.shape
(5, 2)
>>> mesh_name = "MeshOne"
>>> vertex_ids = participant.set_mesh_vertices(mesh_name, positions)
>>> vertex_ids.shape
(5,)

Set mesh vertices for a 3D problem with 5 mesh vertices.

>>> positions = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4], [5, 5, 5]])
>>> positions.shape
(5, 3)
>>> mesh_name = "MeshOne"
>>> vertex_ids = participant.set_mesh_vertices(mesh_name, positions)
>>> vertex_ids.shape
(5,)
write_data(mesh_name, data_name, vertex_ids, values)

This function writes values of specified vertices to data of a mesh. Values are provided as a block of continuous memory defined by values. Values are stored in a numpy array [N x D] where N = number of vertices and D = dimensions of geometry. The order of the provided data follows the order specified by vertices.

Parameters

mesh_namestr

name of the mesh to write to.

data_namestr

Data name to write to.

vertex_idsarray_like

Indices of the vertices.

valuesarray_like

Values of data

Notes

Previous calls:

count of available elements at values matches the configured dimension * size count of available elements at vertex_ids matches the given size initialize() has been called

Examples

Write scalar data for a 2D problem with 5 vertices: >>> mesh_name = “MeshOne” >>> data_name = “DataOne” >>> vertex_ids = [1, 2, 3, 4, 5] >>> values = np.array([v1, v2, v3, v4, v5]) >>> participant.write_data(mesh_name, data_name, vertex_ids, values)

Write vector data for a 2D problem with 5 vertices: >>> mesh_name = “MeshOne” >>> data_name = “DataOne” >>> vertex_ids = [1, 2, 3, 4, 5] >>> values = np.array([[v1_x, v1_y], [v2_x, v2_y], [v3_x, v3_y], [v4_x, v4_y], [v5_x, v5_y]]) >>> participant.write_data(mesh_name, data_name, vertex_ids, values)

Write vector data for a 3D (D=3) problem with 5 (N=5) vertices: >>> mesh_name = “MeshOne” >>> data_name = “DataOne” >>> vertex_ids = [1, 2, 3, 4, 5] >>> values = np.array([[v1_x, v1_y, v1_z], [v2_x, v2_y, v2_z], [v3_x, v3_y, v3_z], [v4_x, v4_y, v4_z], [v5_x, v5_y, v5_z]]) >>> participant.write_data(mesh_name, data_name, vertex_ids, values)

write_gradient_data(mesh_name, data_name, vertex_ids, gradients)

Writes gradient data given as block. This function writes gradient values of specified vertices to a dataID. Values are provided as a block of continuous memory. Values are stored in a numpy array [N x D] where N = number of vertices and D = number of gradient components.

Parameters

mesh_namestr

Name of the mesh to write to.

data_namestr

Data name to write to.

vertex_idsarray_like

Indices of the vertices.

gradientsarray_like

Gradient values differentiated in the spacial direction (dx, dy) for 2D space, (dx, dy, dz) for 3D space

Notes

Previous calls:

Count of available elements at values matches the configured dimension Count of available elements at vertex_ids matches the given size Initialize() has been called Data with dataID has attribute hasGradient = true

Examples

Write gradient vector data for a 2D problem with 2 vertices: >>> mesh_name = “MeshOne” >>> data_name = “DataOne” >>> vertex_ids = [1, 2] >>> gradients = np.array([[v1x_dx, v1y_dx, v1x_dy, v1y_dy], [v2x_dx, v2y_dx, v2x_dy, v2y_dy]]) >>> participant.write_gradient_data(mesh_name, data_name, vertex_ids, gradients)

Write vector data for a 3D problem with 2 vertices: >>> mesh_name = “MeshOne” >>> data_name = “DataOne” >>> vertex_ids = [1, 2] >>> gradients = np.array([[v1x_dx, v1y_dx, v1z_dx, v1x_dy, v1y_dy, v1z_dy, v1x_dz, v1y_dz, v1z_dz], [v2x_dx, v2y_dx, v2z_dx, v2x_dy, v2y_dy, v2z_dy, v2x_dz, v2y_dz, v2z_dz]]) >>> participant.write_gradient_data(mesh_name, data_name, vertex_ids, gradients)

cyprecice.check_array_like(argument, argument_name, function_name)
cyprecice.get_version_information()

Returns

Current preCICE version information