Gracefully Finalizing the Coupling in Asynchronous Termination Scenario

Dear preCICE community,

I am currently working on coupling two in-house codes using preCICE. For clarity, let me refer to them as Code A and Code B.

In our setup, Code A has its own convergence criteria, and it may terminate its computation before reaching the maximum simulation time defined in the precice-config.xml. When this occurs, Code A calls precice.finalize() as expected.

However, the issue arises on the side of Code B, which continues execution under the assumption that the coupling is still ongoing. It proceeds to the next time step and calls readData(), waiting indefinitely for data that Code A will no longer send.

I would like to ask the community:

Is there a recommended or clean way to notify Code B that the coupling has ended, so it can finalize properly without getting stuck in a waiting state?

Any shared experiences, technical advice, or suggested implementation patterns would be greatly appreciated.

Thank you in advance for your support!

1 Like

Hi,

This has been on our agenda for quite some time now.
It’s always good to let us know in preCICE issues that a feature is needed.

In this case, Code A should close communication channels to Code B.
If Code B is waiting for data, then it should throw an error.
This you can catch after preCICE version v3.2

There is currently no clean way of handling this outside of fast-forwarding to the end of the simulation with:

void forwardToEnd(precice::Participant& p) {
  while (p.isCouplingOnGoing()) {
    p.requiresWritingCheckpoint();
    p.advance(precice.getMaxTimeStepSize());
    p.requiresReadingCheckpoint();
  }
}

Thank you very much for the quick response.

The idea of applying the fast forwarding approach indeed looks like a very reasonable solution. For Code A, it seems sufficient to simply call the forwardToEnd function at the point where early termination is required.

However, could you clarify when exactly this function should be invoked for Code B? In this case, Code B is a computationally expensive solver, and running a “null calculation” until the end time is not feasible. Therefore, I believe forwardToEnd should also be called at an appropriate point in Code B.

Sending a signal to second participant could work.

To do this in preCICE, define a pseudo mesh for A and B, and a pseudo scalar data

On one rank of A, set one vertex e.g. (0, 0) and then write 0 to it the simulation runs and 1 if it is supposed to stop.
On all ranks of B, set a vertex e.g (0, rank), map the pseudo scalar to it with a consistent nearest-neighbor mapping and then read the data from the local vertex.
If Code B received 1, it knows that A is done, and you call forwardToEnd.

1 Like

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.