Dear preCICE developers,
I am currently working on a coupled setup with three participants using a bi-coupling strategy. Let me call the solvers A, B, and C. Due to the characteristics of the application, each pair (A–B, B–C, and A–C) is required to use a different time window size in the coupling.
To investigate this, I constructed a minimal example using the dummy solvers. In this simplified setup, I configured three participants (Solver A, Solver B, Solver C) and assigned different time window sizes for each pair-wise coupling (AB, BC, AC) in the precice-config.xml. However, when I run this configuration, the simulation ends up in a deadlock.
Before posting, I tried to carefully check the configuration, but I could not identify whether the issue comes from a mistake on my side or from a limitation in the current design of preCICE. Therefore, I would like to ask:
-
Is it in principle supported in the current version of preCICE to have three participants in a bi-coupling setup, where each pair of participants uses a different time window size?
-
If it is supposed to be supported, are there known constraints or best practices for configuring such a case in
precice-config.xmlto avoid deadlocks? -
If it is not supported by design, could you please confirm that this use case is currently outside the intended scope of preCICE? In that case, any suggestions for possible workarounds or alternative coupling strategies would be very helpful.
I am happy to provide my precice-config.xml, the dummy solver configuration, and log files if needed for debugging. Thank you very much in advance for your time and for maintaining preCICE.
Best regards,
Seongju Do
<?xml version="1.0" encoding="UTF-8" ?>
<precice-configuration>
<log>
<sink
type="stream"
output="stdout"
filter="%Severity% > debug"
format="preCICE:%ColorizedSeverity% %Message%"
enabled="true" />
</log>
<!-- 6 data fields: bidirectional for all 3 pairs -->
<data:scalar name="Data-AB" />
<data:scalar name="Data-BA" />
<data:scalar name="Data-AC" />
<data:scalar name="Data-CA" />
<data:scalar name="Data-BC" />
<data:scalar name="Data-CB" />
<!-- SolverA-Mesh: A-B and A-C data -->
<mesh name="SolverA-Mesh" dimensions="2">
<use-data name="Data-AB" />
<use-data name="Data-BA" />
<use-data name="Data-AC" />
<use-data name="Data-CA" />
</mesh>
<!-- SolverB-Mesh: A-B and B-C data -->
<mesh name="SolverB-Mesh" dimensions="2">
<use-data name="Data-AB" />
<use-data name="Data-BA" />
<use-data name="Data-BC" />
<use-data name="Data-CB" />
</mesh>
<!-- SolverC-Mesh: A-C and B-C data -->
<mesh name="SolverC-Mesh" dimensions="2">
<use-data name="Data-AC" />
<use-data name="Data-CA" />
<use-data name="Data-BC" />
<use-data name="Data-CB" />
</mesh>
<!-- SolverA: controller (hub) -->
<participant name="SolverA">
<provide-mesh name="SolverA-Mesh" />
<write-data name="Data-AB" mesh="SolverA-Mesh" />
<write-data name="Data-AC" mesh="SolverA-Mesh" />
<read-data name="Data-BA" mesh="SolverA-Mesh" />
<read-data name="Data-CA" mesh="SolverA-Mesh" />
</participant>
<!-- SolverB: maps B-Mesh <-> A-Mesh for A-B data, provides B-Mesh for B-C data -->
<participant name="SolverB">
<provide-mesh name="SolverB-Mesh" />
<receive-mesh name="SolverA-Mesh" from="SolverA" />
<mapping:nearest-neighbor
direction="write"
from="SolverB-Mesh"
to="SolverA-Mesh"
constraint="consistent" />
<mapping:nearest-neighbor
direction="read"
from="SolverA-Mesh"
to="SolverB-Mesh"
constraint="consistent" />
<write-data name="Data-BA" mesh="SolverB-Mesh" />
<write-data name="Data-BC" mesh="SolverB-Mesh" />
<read-data name="Data-AB" mesh="SolverB-Mesh" />
<read-data name="Data-CB" mesh="SolverB-Mesh" />
</participant>
<!-- SolverC: maps C-Mesh <-> A-Mesh for A-C data, maps C-Mesh <-> B-Mesh for B-C data -->
<participant name="SolverC">
<provide-mesh name="SolverC-Mesh" />
<receive-mesh name="SolverA-Mesh" from="SolverA" />
<receive-mesh name="SolverB-Mesh" from="SolverB" />
<mapping:nearest-neighbor
direction="write"
from="SolverC-Mesh"
to="SolverA-Mesh"
constraint="consistent" />
<mapping:nearest-neighbor
direction="read"
from="SolverA-Mesh"
to="SolverC-Mesh"
constraint="consistent" />
<mapping:nearest-neighbor
direction="write"
from="SolverC-Mesh"
to="SolverB-Mesh"
constraint="consistent" />
<mapping:nearest-neighbor
direction="read"
from="SolverB-Mesh"
to="SolverC-Mesh"
constraint="consistent" />
<write-data name="Data-CA" mesh="SolverC-Mesh" />
<write-data name="Data-CB" mesh="SolverC-Mesh" />
<read-data name="Data-AC" mesh="SolverC-Mesh" />
<read-data name="Data-BC" mesh="SolverC-Mesh" />
</participant>
<!-- m2n: full mesh - all pairs connected -->
<m2n:sockets acceptor="SolverA" connector="SolverB" exchange-directory=".." />
<m2n:sockets acceptor="SolverA" connector="SolverC" exchange-directory=".." />
<m2n:sockets acceptor="SolverB" connector="SolverC" exchange-directory=".." />
<!-- A <-> B -->
<coupling-scheme:serial-explicit>
<participants first="SolverA" second="SolverB" />
<max-time value="10" />
<time-window-size value="1.0" />
<exchange data="Data-AB" mesh="SolverA-Mesh" from="SolverA" to="SolverB" />
<exchange data="Data-BA" mesh="SolverA-Mesh" from="SolverB" to="SolverA" />
</coupling-scheme:serial-explicit>
<!-- A <-> C -->
<coupling-scheme:serial-explicit>
<participants first="SolverA" second="SolverC" />
<max-time value="10" />
<time-window-size value="0.5" />
<exchange data="Data-AC" mesh="SolverA-Mesh" from="SolverA" to="SolverC" />
<exchange data="Data-CA" mesh="SolverA-Mesh" from="SolverC" to="SolverA" />
</coupling-scheme:serial-explicit>
<!-- B <-> C (direct) -->
<coupling-scheme:serial-explicit>
<participants first="SolverB" second="SolverC" />
<max-time value="10" />
<time-window-size value="0.3" />
<exchange data="Data-BC" mesh="SolverB-Mesh" from="SolverB" to="SolverC" />
<exchange data="Data-CB" mesh="SolverB-Mesh" from="SolverC" to="SolverB" />
</coupling-scheme:serial-explicit>
</precice-configuration>
SolverA_20260415_134408.log (12.4 KB)
SolverC_20260415_134408.log (5.7 KB)
SolverB_20260415_134408.log (5.0 KB)