External coupling¶
OpenPFC can run as a library inside a host solver (FEM, another PDE code, or a custom orchestrator). The stable surface is small on purpose.
Runnable sketch: examples/22_external_coupling.cpp.
What is stable¶
Piece |
Header |
Role |
|---|---|---|
|
|
Non-owning host export: name, |
|
same |
Build a handle from |
|
|
Free-function time loop the host can own or call step-by-step |
|
|
dt negotiation: the host proposes a step; OpenPFC clips to |
|
|
Opt-in |
|
|
Restart owned by OpenPFC; coordinate checkpoints with the host clock via |
FieldHandle is a read export. Write a source or boundary back through
SimulationState (typically get_field<double>(name).apply(...)) or a
FieldModifier-shaped adapter apply(SimulationState&, double) as in the
example header. Do not treat FieldView as mutable.
pfc::coupling::FieldHandle is not pfc::FieldHandle<T> (the typed index
inside SimulationState).
What is not stable¶
Device-resident fields (
CUDASpace/HIPSpace): this export is host-only.Gen-1
Model/Simulatoraccessors.Stage buffers, FFT plans, operator caches, stepper rollback scratch.
Halo cells: the handle’s
owned_boxis the owned index box; ghost values need a halo exchange after the host writes owned cells.Changing the MPI rank map or global grid between checkpoint and restore.
dt negotiation¶
The host owns the outer loop. Before an attempt:
const double dt = time.clip_attempt_dt(host_proposed_dt);
time.begin_attempt(dt);
source.apply(state, time.get_accepted_time());
// ... host physics / OpenPFC step ...
time.commit_attempt();
clip_attempt_dt never lengthens the proposal. Reject with
time.reject_attempt() if the host step fails.
Restart coordination¶
Use one OpenPFC bundle, not a second host-side dump of the same field:
{
"restart_from": "results/ckpt/step_10",
"checkpoint": { "every": 10, "directory": "results/ckpt" }
}
CheckpointService::restore_from_config loads fields, accepted time,
increment, result counter, and method identity. The host must restart at the
same accepted time; mismatch of grid or method is a hard error. See
checkpoint_publish.md.
Communicator isolation¶
If the host already uses MPI_COMM_WORLD for its own halo or reductions,
duplicate before constructing OpenPFC exchanges:
pfc::mpi::communicator world;
auto isolated = world.duplicate();
Pass MPI_Comm(isolated) into stacks, CheckpointService, and
BinaryReader. Destroying the wrapper frees the duplicate.