preCICE API
The following is a diff of how an adapter-port could look like. The guide continues underneath the code.
- #include "precice/SolverInterface.hpp"
+ #include "precice/precice.hpp"
turnOnSolver(); //e.g. setup and partition mesh
- precice::SolverInterface participant("FluidSolver","precice-config.xml",rank,size); // constructor
+ precice::Participant participant("FluidSolver","precice-config.xml",rank,size); // constructor
- const std::string& coric = precice::constants::actionReadIterationCheckpoint();
- const std::string& cowic = precice::constants::actionWriteIterationCheckpoint();
- const std::string& cowid = precice::constants::actionWriteInitialData();
- int dim = participant.getDimension();
+ int dim = participant.getMeshDimensions("FluidMesh");
- int meshID = precice.getMeshID("FluidMesh");
int vertexSize; // number of vertices at wet surface
// determine vertex count
std::vector<double> coords(vertexSize*dim); // coords of vertices at wet surface
// determine coordinates
std::vector<int> vertexIDs(vertexSize);
- precice.setMeshVertices(meshID, vertexSize, coords.data(), vertexIDs.data());
+ precice.setMeshVertices("FluidMesh", coords, vertexIDs);
- int displID = precice.getDataID("Displacements", meshID);
- int forceID = precice.getDataID("Forces", meshID);
- std::vector<double> forces(vertexSize*dim);
- std::vector<double> displacements(vertexSize*dim);
+ const int forceDim = participant.getDataDimensions("FluidMesh", "Forces")
+ const int displDim = participant.getDataDimensions("FluidMesh", "Displacements")
+ std::vector<double> forces(vertexSize*forceDimn);
+ std::vector<double> displacements(vertexSize*displDim);
double solverDt; // solver timestep size
double preciceDt; // maximum precice timestep size
double dt; // actual time step size
- preciceDt = participant.initialize();
- if (participant.isActionRequired(cowid)) {
- participant.writeBlockVectorData(forceID, vertexSize, vertexIDs.data(), forces.data());
- participant.markActionFulfilled(cowid);
- }
- participant.initializeData();
+ if (participant.requiresInitialData()) {
+ participant.writeData("FluidMesh", "Forces", vertexIDs, forces);
+ }
+ participant.initialize();
while (participant.isCouplingOngoing()){
- if(participant.isActionRequired(cowic)){
+ if(participant.requiresWritingCheckpoint()){
saveOldState(); // save checkpoint
- participant.markActionFulfilled(cowic);
}
+ preciceDt = participant.getMaxTimeStepSize();
solverDt = beginTimeStep(); // e.g. compute adaptive dt
dt = min(preciceDt, solverDt);
- participant.readBlockVectorData(displID, vertexSize, vertexIDs.data(), displacements.data());
+ participant.readData("FluidMesh", "Displacements", vertexIDs, dt, displacements);
setDisplacements(displacements);
solveTimeStep(dt);
computeForces(forces);
- participant.writeBlockVectorData(forceID, vertexSize, vertexIDs.data(), forces.data());
+ participant.writeData("FluidMesh", "Forces", vertexIDs, forces);
- preciceDt = participant.advance(dt);
+ participant.advance(dt);
- if (participant.isActionRequired(coric)) { // timestep not converged
+ if (participant.requiresReadingCheckpoint()) {
reloadOldState(); // set variables back to checkpoint
- participant.markActionFulfilled(coric);
}
else { // timestep converged
endTimeStep(); // e.g. update variables, increment time
}
}
participant.finalize(); // frees data structures and closes communication channels
turnOffSolver();
- The main preCICE header file and the main object was renamed. This means that you need to:
- Replace
#include "precice/SolverInterface.hpp"
with#include "precice/precice.hpp"
. - Where declaring a preCICE object, replace the
precice::SolverInterface
type withprecice::Participant
. - Where constructing a preCICE object, replace the
precice::SolverInterface( ... )
constructor withprecice::Participant( ... )
. - Consider renaming your objects from, e.g.,
interface
toparticipant
, to better reflect the purpose and to be consistent with the rest of the changes.
- Replace
- Steering methods
- Replace
double preciceDt = initialize()
anddouble preciceDt = advance(dt)
withinitialize()
andadvance(dt)
, as they no longer have a return value. - Use
double preciceDt = getMaxTimeStepSize()
, where you need the max time step size or the relative end of the time window.
- Replace
- Dimensions
- Replace
getDimensions()
withgetMeshDimensions(meshName)
- Replace any custom logic to determine the dimensionality of data with
getDataDimensions(meshName, dataName)
- Replace
- Migrate from using mesh and data ids to directly using names
- Remove the now obsolete calls to
getMeshID()
andgetDataID()
and any related variables / user-defined types. - Replace the use of mesh IDs with the mesh name.
- Replace the use of data IDs with the respective mesh and data names (both are needed).
- Remove the now obsolete calls to
- Migrate connectivity information to the vertex-only API. All
setMeshX
methods take vertex IDs as input and return nothing.- Directly define face elements or cells of your coupling mesh available in your solver by passing their vectices to preCICE, which automatically handles edges of triangles etc. See Mesh Connectivity for more information.
- Rename
setMeshTriangleWithEdges
tosetMeshTriangle
andsetMeshQuadWithEdges
tosetMeshQuad
. The edge-based implementation was removed. - Use the new bulk functions to reduce sanitization overhead:
setMeshEdges
,setMeshTriangles
,setMeshQuads
,setMeshTetrahedra
.
- Implicit coupling
- Remove
precice::constants::actionReadIterationCheckpoint()
andprecice::constants::actionWriteIterationCheckpoint()
- Replace
isActionRequired()
of the above actions withrequiresReadingCheckpoint()
orrequiresWritingCheckpoint()
. - Remove
markActionFulfilled()
of the above actions. It is now implied that arequires*()
is directly executed/fulfilled.
- Replace
- Remove
- Migrate data access
- Replace the commands to read data:
readBlockVectorData
,readVectorData
,readBlockScalarData
,readScalarData
with the single commandreadData
. - Replace the commands to write data:
writeBlockVectorData
,writeVectorData
,writeBlockScalarData
,writeScalarData
with the single commandwriteData
. - Replace the commands to write gradient data:
writeBlockVectorGradientData
,writeVectorGradientData
,writeBlockScalarGradientData
,writeScalarGradientData
with the single commandwriteGradientData
. - The signature of
readData
,writeData
andwriteGradientData
has changed fromconst int*
,const double*
, anddouble*
toprecice::span<const VertexID>
,precice::span<const double>
, andspan<double>
. The sizes of passed spans are checked by preCICE. spans can be constructed using a pointer and size, or by a contigous container. Examples for the latter arestd::vector
,std:array
,Eigen::VectorXd
, and alsostd::span
. - To simplify migration to
readData()
, usegetMaxTimeStepSize()
as relative read time for now to always read data at the end of the time window. Read up on time interpolation once you finished the port.
- Replace the commands to read data:
- Migrate data initialization
- Move the data initalization before the call to
initialize()
. You have to initialize the data ifrequiresInitialData()
returnstrue
. - Remove
initializeData()
. The functioninitializeData()
has been merged intoìnitialize()
. - Remove
precice::constants::actionWriteInitialData()
. - Remove
markActionFulfilled()
of write initial data. - Replace
isActionRequired()
of write initial data withrequiresInitialData()
.
- Move the data initalization before the call to
- Rename the functions:
- Replace
getMeshVerticesAndIDs
withgetMeshVertexIDsAndCoordinates
. Change the input argument meshID to meshName and swap the arguments for IDs and coordinates. - Replace
isMeshConnectivityRequired
withrequiresMeshConnectivityFor
. Instead of the input argumentmeshID
, pass themeshName
. - Replace
isGradientDataRequired
withrequiresGradientDataFor
. Instead of the input argumentdataID
, pass themeshName
anddataName
.
- Replace
- Remove the following without a replacement:
- Remove
mapWriteDataFrom()
andmapReadDataTo()
as custom timings were removed. - Remove
hasMesh()
andhasData()
as there is no real usecase for them. All errors are unrecoverable. - Remove
hasToEvaluateSurrogateModel()
andhasToEvaluateFineModel()
as they were stubs of a long-removed feature. - Remove
getMeshVertices()
andgetMeshVertexIDsFromPositions()
. This information is already known by the adapter. We docummented strategies on how to handle this in adapters. - Remove
isReadDataAvailable()
andisWriteDataRequired()
. Due to time interpolation, writing generates samples in time, and reading is always possible between the current time and the end of the current time window.
- Remove
Add relativeReadTime
for all read data calls
The previously optional argument relativeReadTime
is now mandatory for read data calls. This requires you to update all read data calls. See time interpolation for more details on this argument. If you don’t want to use subcycling or time interpolation, you can simply get the required relativeReadTime
by calling double preciceDt = getMaxTimeStepSize()
call. Change:
- couplingInterface.readBlockVectorData(meshName, dataReadName, numberOfVertices, vertexIDs.data(), readData.data());
+ preciceDt = participant.getMaxTimeStepSize();
+ participant.readData(meshName, dataReadName, vertexIDs, preciceDt, readData)
If you use subcycling, please do the following:
- couplingInterface.readBlockVectorData(meshName, dataReadName, numberOfVertices, vertexIDs.data(), readData.data());
+ preciceDt = participant.getMaxTimeStepSize();
double dt = min(preciceDt, solverDt);
+ participant.readData(meshName, dataReadName, vertexIDs, dt, readData)
Remove initializeData()
calls
The API function initializeData()
has been removed in #1350. initialize()
now takes care of all the initialization – including data initialization. This means, you have to call initialize()
, where you previously called initializeData()
. Be aware that this means that you have to write initial data before calling initialize()
. Change:
- double dt = 0;
- dt = couplingInterface.initialize();
std::vector<double> writeData(dimensions, writeValue);
// Write initial data before calling initialize()
- const std::string & cowid = actionWriteInitialData();
- if (couplingInterface.isActionRequired(cowid)) {
- couplingInterface.writeVectorData(writeDataID, vertexIDs, writeData.data());
- couplingInterface.markActionFulfilled(cowid);
+ if (participant.requiresInitialData()) {
+ participant.writeData(meshName, dataWriteName, vertexIDs, writeData);
}
// Move initialize to the place where you called initializeData() previously.
- couplingInterface.initializeData();
+ participant.initialize();
+ double dt = participant.getMaxTimeWindowSize();
Typical error message that should lead you here:
error: ‘class precice::Participant’ has no member named ‘initializeData’; did you mean ‘initialize’?
63 | participant.initializeData();
| ^~~~~~~~~~~~~~
| initialize
preCICE configuration file
- The XML tag
<solver-interface>
was removed and all underlying functionality was moved to the<precice-configuration>
tag. Remove the lines including<solver-interface>
and</solver-interface>
, and move any attributes (such asexperimental
) from thesolver-interface
to theprecice-configuration
tag. Move thesync-mode
attribute to the new<profiling>
tag (see below). - The
dimensions
configuration is now defined per mesh. Move thedimensions="2"
ordimensions="3"
from the<solver-interface>
tag to each<mesh>
tag:<mesh name="MeshOne" dimensions="3">
. - Rename the
<m2n: ... />
attributesfrom
->acceptor
andto
->connector
. -
You can now add
<profiling mode="all" />
after the<log>
tag if you need full profiling data. - Participants
- Replace
<use-mesh provide="true" ... />
with<provide-mesh ... />
, and<use-mesh provide="false" ... />
with<receive-mesh ... />
. - Move and rename the optional attribute
<read-data: ... waveform-order="1" />
to<data:scalar/vector ... waveform-degree="1"
. - Replace
<export:vtk />
for parallel participants with<export:vtu />
or<export:vtp />
. - Replace mapping constraint
scaled-consistent
withscaled-consistent-surface
. - Remove all timings in the mapping configuration
<mapping: ... timing="initial/onadvance/ondemand" />
. preCICE now fully controls the mapping. - Remove the preallocations in the mapping configuration
<mapping: ... preallocation="tree/compute/estimate/save/off" />
. We always use the superiortree
method. -
Replace all RBF related
<mapping:rbf-... />
tags. RBF mappings are now defined in terms of the applied solver (current options<mapping:rbf-global-direct ...
,<mapping:rbf-global-iterative
or<mapping:rbf-pum-direct ...
) and the applied basis function as a subtag of the solver. Users should use the additionally added auto selection of an appropriate solver, which omits the solver specification, as follows:<mapping:rbf ...> <basis-function:... /> </mapping:rbf>
Example:
preCICE version 2 RBF configuration:
<mapping:compact-polynomial-c0 direction="read" from= ... support-radius="0.3" />
corresponding preCICE version 3 RBF configuration (using the recommended auto selection):
<mapping:rbf direction="read" from= ...> <basis-function:compact-polynomial-c0 support-radius="0.3" /> </mapping:rbf>
A specific solver should only be configured if you want to force preCICE to use and stick to a certain solver, independent of your problem size and execution.
- Rename
<mapping:rbf... use-qr-decomposition="true" />
to<mapping:rbf-global-direct ... > <basis-function:... /> </mapping:rbf-global-direct>
. - We dropped quite some functionality concerning data actions as these were not used to the best of our knowledge and were hard to maintain:
- Removed deprecated action timings
regular-prior
,regular-post
,on-exchange-prior
, andon-exchange-post
. - Removed action timings
read-mapping-prior
,write-mapping-prior
, andon-time-window-complete-post
. - Removed
ComputeCurvatureAction
andScaleByDtAction
actions. - Removed callback functions
vertexCallback
andpostAction
fromPythonAction
interface. - Removed timewindowsize from the
performAction
signature ofPythonAction
. The new signature isperformAction(time, data)
- Using actions with multiple couping schemes and mixed time window sizes is not well defined!
- Removed deprecated action timings
- Replace
- Coupling schemes
- Remove
<extraplation-order value="..." />
in<coupling-scheme>
. Contact us if you need this feature. - Replace
<min-iteration-convergence-measure min-iterations="3" ... />
by<min-iterations value="3"/>
. Not defining convergence measures leads to iterations untilmax-iterations
is reached. - We removed the plain
Broyden
acceleration. You could useIQN-IMVJ
instead, which is a multi-vector Broyden variant.
- Remove
Building preCICE
Rename CMake configuration variables as follows:
PRECICE_PETScMapping
->PRECICE_FEATURE_PETSC_MAPPING
PRECICE_MPICommunication
->PRECICE_FEATURE_MPI_COMMUNICATION
PRECICE_Packages
->PRECICE_CONFIGURE_PACKAGE_GENERATION
PRECICE_PythonActions
->PRECICE_FEATURE_PYTHON_ACTIONS
PRECICE_ENABLE_C
->PRECICE_BINDINGS_C
PRECICE_ENABLE_FORTRAN
->PRECICE_BINDINGS_FORTRAN
PRECICE_ENABLE_LIBBACKTRACE
->PRECICE_FEATURE_LIBBACKTRACE_STACKTRACES
Language bindings
The renaming of the preCICE API from SolverInterface
to preCICE
also applies to all language bindings. The C++ header change precice/SolverInterface.hpp
to precice/precice.hpp
becomes:
- In C: Replace
#include "precice/SolverInterfaceC.h"
with#include "precice/preciceC.h"
andprecicec_createSolverInterface( ... )
withprecicec_createParticipant( ... )
. - In Julia: Replace
precicec_createSolverInterface( ... )
withprecicec_createParticipant( ... )
. - In Matlab: Replace
SolverInterface
withParticipant
everywhere. - In Fortran, Python: You don’t need to change anything.
Profiling
- There are three profiling modes now:
off
,fundamental
(default),all
. - Add
<profiling mode="all" />
inside the<precice-configuration>
tag if you need detailed profiling data. - If you relied on
sync-mode="on"
, remove it from<precice-configuration>
and add it to the profiling tag<profiling synchronize="true" />
.