A participant needs to
use at least two meshes to define a mapping between both:
<participant name="MySolver1"> <use-mesh name="MyMesh1" provide="yes"/> <use-mesh name="MyMesh2" from="MySolver2"/> <write-data name="Forces" mesh="MyMesh1"/> <read-data name="Temperature" mesh="MyMesh1"/> <mapping:nearest-neighbor direction="read" from="MyMesh2" to="MyMesh1" constraint="consistent"/> <mapping:nearest-neighbor direction="write" from="MyMesh1" to="MyMesh2" constraint="conservative"/> </participant>
Mappings can be defined in two
readmappings are executed before you can read data from the mesh. In the example above,
Temperatureis received on
MyMesh2, then it is mapped from
MyMesh1and, finally, read from
writemappings are executed after you have written data.
Furthermore, mappings come int two types of
conservativemapping: Mapping between different meshes (example, from a fine to a coarse grid), the value at a coarse node is computed as an aggregation of the corresponding fine nodes, such that the total coupling value (in our example
Forces) on the coarse and fine mesh is the same. This is required for quantities that are absolute (extensive quantities, such as force, mass, etc.). An example for a nearest-neighbor mapping could look like this:
f=2 f=1 f=2 f=1 f=1 ------+------+------+------+------+------ \ | / | / -------------+-------------+------------- f=(2+1+2) f=(1+1)
consistentmapping: For quantities that are normalized (intensive quantities;
Temperaturein our example, or pressure, which is force per unit area), we need a consistent mapping. This means that the value at coarse nodes is the same as the value at the corresponding fine node. Again, an example for a nearest-neighbor mapping could look like this:
T=2 T=1 T=2 T=1 T=1 ------+------+------+------+------+------ | | -------------+-------------+------------- T=1 T=1
For a sequential participant, any combination of
consistent/conservative is valid. For a parallel participant (i.e. a
master tag is defined), only
conservative is possible. More details are given further below.
Furthermore, mappings have an optional parameter
timing, it can be:
initial(the default): The mapping is only computed once, the first time it is used. This is sufficient for stationary meshes (also including the reference mesh in an Lagrangian or an ALE description).
onadvance: The mapping is newly computed for every mapping of coupling data. This can be expensive and is only recommend if you know exactly why you want to do this.
Concerning mapping methods, preCICE offers four variants:
nearest-neighbor: A first-order method, which is fast, easy to use, but, of course, has numerical deficiencies.
nearest-projection: A (mostly) second-order method, which first projects onto mesh elements and, then, uses linear interpolation within each element (compare the figure below). The method is still relatively fast and numerically clearly superior to
nearest-neighbor. The downside is that mesh connectivity information needs to be defined, i.e. in the adapter, the participant needs to tell preCICE about edges in 2D and edges, triangles, or quads (see issue) in 3D. On the mesh connectivity page, we explain how to do that. If no connectivity information is provided,
nearest-projectionfalls back to an (expensive)
linear-cell-interpolation: A second-order method similar to
nearest-projection, but designed for volumetric coupling, where the coupling mesh is a region of space and not a domain boundary. It interpolates on triangles in 2D and on tetrahedra in 3D. If none are found, it falls back on
nearest-neighbor-gradient: A second-order method, which uses the same algorithm as nearest-neighbor with an additional linear approximation using gradient data. This method requires additional gradient data information. On the gradient data page, we explain how to add gradient data to the mesh. This method is only applicable with the
- Radial-basis function mapping. Here, the configuration is more involved, so keep reading.
Radial-basis function mapping
Radial basis function mapping computes a global interpolant on one mesh, which is then evaluated at the other mesh. The global interpolant is formed by a linear combination of radially-symmetric basis functions centered on each vertex, enriched by one global linear polynomial. For more information, please refer, e.g., to Florian’s thesis (pages 37 ff.) or to this paper and the reference therein.
To compute the interpolant, a linear equation system needs to be solved in every mapping of data. We use either:
- the external library Eigen and a QR decomposition, or
- the external library PETSc and a GMRES solver.
For small/medium size problems, the QR decomposition is enough and you don’t need to install anything else. However, this follows a gather-scatter approach, which limits the scalability. For large problems, the GMRES solver performs better than the QR decomposition. For this, you need to build preCICE with PETSc. If you built with PETSc, the default is always GMRES. If you still want to use the QR decomposition, you can use the option
Radial basis function mapping also behaves as a second-order method just as
nearest-projection, but without the need to define connectivity information. The downside is that it is normally more expensive to compute and that it shows numerical problems for large or highly irregular meshes.
The configuration might look like this:
<mapping:rbf-thin-plate-splines direction="read" from="MyMesh2" to="MyMesh1" constraint="consistent"/>
thin-plate-splines is the type of basis function used. preCICE offers basis function with global and local support:
- Basis function with global support (such as
thin-plate-splines) are easier to configure as no further parameter needs to be set. For larger meshes, however, such functions lead to performance issues in terms of algorithmic complexity, numerical condition, and scalability.
- Basis functions with local support need either the definition of a
support-radius(such as for
rbf-compact-tps-c2) or a
shape-parameter(such as for
gaussian). To have a good trade-off between accuracy and efficiency, the support of each basis function should cover three to five vertices in every direction. You can use the tool rbfShape.py to get a good estimate of
For a complete overview of all basis function, refer to this paper, page 5.
The interpolation problem might not be well-defined if you map along an axis-symmetric surface. This means, preCICE tries to compute, for example, a 3D interpolant out of 2D information. If so, preCICE throws an error
RBF linear system has not converged or
Interpolation matrix C is not invertible. In this case, you can restrict the interpolation problem by ignoring certain coordinates, e.g.
x-dead="true" to ignore the x coordinate.
advanceand not in
readBlockVectorDataetc., cf. the section on how to couple your own code.
Restrictions for parallel participants
As stated above, for parallel participants only
conservative are valid combinations. If want to find out why, have a look at Benjamin’s thesis, page 85. But what to do if you want a
consistent mapping? The trick is to move the mapping to the other participant, then
- Move the mapping, adjust
- Be sure that the other participant also uses both meshes. Probably you need an additional
<use-mesh name="MyMesh1" from="MySolver1"/>. This means another mesh is communicated at initialization, which can increase initialization time.
- Last, be sure to update the
exchangetags in the coupling scheme, compare the coupling scheme configuration (e.g. change which mesh is used for the exchange and acceleration)
After applying these changes, you can use the preCICE Config Visualizer to visually validate your updated configuration file.
Maybe an example helps. You find one in the preCICE Forum.