Extending OpenPFC¶
OpenPFC is designed so application-specific physics can live outside the
framework repository. A downstream project can add models, field modifiers,
writers, and spatial setup while linking the installed OpenPFC::openpfc
target.
Read Architecture first. It defines the stable kernel, runtime, and frontend boundaries used by this guide. For a complete out-of-tree executable, follow the Minimal custom application tutorial.
Choose the extension point¶
Goal |
Primary extension point |
Starting point |
|---|---|---|
Add a PDE or phase-field model |
|
|
Add a config-selected initial or boundary condition |
|
|
Apply programmatic field operations |
Namespace free functions and field iteration helpers |
|
Add an output format |
|
|
Add custom spatial interpretation |
Domain and coordinate helper functions |
|
Build a JSON/TOML-driven binary |
|
|
Add point-wise gradients or finite-difference physics |
Field/gradient primitives and halo policies |
The Examples catalog is the authoritative inventory of runnable examples.
API style¶
OpenPFC favors data-centric types and namespace free functions. Use inheritance
where the framework needs a runtime extension seam, such as Model,
FieldModifier, or ResultsWriter; keep the implementation behind that seam in
ordinary functions and small data types.
This keeps physics code testable and avoids deep class hierarchies. The complete conventions are in the Style guide.
Minimal config-driven project¶
A downstream application commonly contains:
File |
Responsibility |
|---|---|
|
Define the model fields, initialization, and time step |
|
Construct |
|
Find OpenPFC and link |
JSON or TOML input |
Define domain, time integration, planner options, modifiers, and writers |
The minimal CMake shape uses the same target as the packaging smoke test:
cmake_minimum_required(VERSION 3.21)
project(my_openpfc_app LANGUAGES C CXX)
find_package(OpenPFC REQUIRED)
add_executable(my_openpfc_app main.cpp your_model.cpp)
target_link_libraries(my_openpfc_app PRIVATE OpenPFC::openpfc)
Frontend headers may require additional packages used directly by the
application, such as nlohmann_json. The complete wiring and run command belong
in the custom application tutorial, not in
this overview.
Configuration and registration¶
The frontend converts JSON or TOML into a domain, decomposition, FFT stack, model, simulator, modifiers, and writers. The ownership and wiring order are described in Application pipeline. Exact keys belong in the Spectral App configuration reference.
For custom initial and boundary conditions, prefer an explicit local
FieldModifierCatalog in tests and reusable libraries. Process-wide registration
is convenient for simple applications but introduces shared mutable state.
Validation¶
A model can validate required parameters, types, ranges, units, and typical values before time integration begins. See Parameter validation and the tungsten application for a larger metadata-driven example.
Backend-specific work¶
Kernel code must remain independent of CUDA and HIP implementation headers. Backend-specific execution, memory, and FFT functionality belongs under the runtime layer. Review Architecture and the GPU path guide before adding a new backend path.
Review checklist¶
Before proposing an extension:
identify the layer that owns the new behavior;
reuse an existing extension point when one matches;
avoid copying complete option or configuration references into examples;
add a focused test and a runnable example when the behavior is user-facing;
update the canonical guide or reference page for any new public contract;
record release-visible changes under
[Unreleased]in the changelog.