Build a minimal config-driven application¶
This tutorial creates an OpenPFC executable in a separate CMake project using
pfc::ui::make_simulation_session and pfc::sim::run. Shipped 0.2 apps
(tungsten, aluminumNew) drive JSON/TOML through ETD sessions instead. The JSON
keys (domain, time, plan_options, modifiers, writers) are the same.
Use this path when the simulation belongs in its own repository. Do not fork
OpenPFC merely to add an application main. Porting 0.1 App<Model> code:
MIGRATION_0.1_to_0.2.md.
Prerequisites¶
You need:
an installed OpenPFC package;
the same compatible compiler, MPI, and HeFFTe stack used to build OpenPFC;
CMAKE_PREFIX_PATHorOpenPFC_DIRpointing to the installation;nlohmann-json available to the downstream project when frontend JSON headers are used.
Complete installation guidance is in INSTALL.md.
Project layout¶
Create a new directory with this layout:
my-openpfc-app/
├── CMakeLists.txt
├── main.cpp
└── settings.json
Configure the CMake project¶
The target and enabled languages below match the installed-package consumer exercised by OpenPFC CI:
cmake_minimum_required(VERSION 3.21)
project(my_openpfc_app LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(OpenPFC REQUIRED)
find_package(nlohmann_json REQUIRED)
add_executable(my_app main.cpp)
target_link_libraries(
my_app
PRIVATE
OpenPFC::openpfc
nlohmann_json::nlohmann_json
)
The C language is enabled because the installed package resolves MPI components
that include an MPI C target. OpenPFC::openpfc is the supported installed
target; un-namespaced in-tree aliases are not a downstream contract.
Drive a spectral session¶
Physics is a callable step(t), not a pfc::Model subclass. Keep the driver
thin and place reusable mechanics in ordinary functions.
// main.cpp
#include <exception>
#include <iostream>
#include <mpi.h>
#include <nlohmann/json.hpp>
#include <openpfc/frontend/ui/from_json.hpp>
#include <openpfc/frontend/ui/from_json_simulation_session.hpp>
#include <openpfc/frontend/ui/settings_loader.hpp>
#include <openpfc/kernel/simulation/stacks/spectral_cpu_stack.hpp>
int main(int argc, char **argv) {
try {
MPI_Init(&argc, &argv);
int rank = 0;
int nproc = 1;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
if (argc < 2) {
if (rank == 0) {
std::cerr << "usage: my_app settings.json\n";
}
MPI_Finalize();
return 1;
}
const auto settings = pfc::ui::load_settings_file(argv[1]);
auto session =
pfc::ui::make_simulation_session<pfc::sim::stacks::SpectralCPUStack>(
settings, rank, nproc);
auto &psi = session.stack().u();
for (auto &v : psi.vec()) {
v = 0.0;
}
session.run([&](double /*t*/) {
// Advance psi by one step (FFT / stepper / ETD).
});
MPI_Finalize();
return 0;
} catch (const std::exception &error) {
std::cerr << error.what() << '\n';
MPI_Abort(MPI_COMM_WORLD, 1);
}
}
make_simulation_session reads domain, time, method/backend, and
plan_options from the document. session.run is pfc::sim::run over
Time. For a full spectral implicit-Euler example see
examples/04_diffusion_model.cpp. Production tungsten/aluminum sessions add
ICs, BCs, writers, and CheckpointService around the same loop.
Add a configuration¶
Start from a shipped input, then reduce it to the fields required by your physics. The exact supported keys belong in the Spectral App configuration reference. The conversion from configuration to runtime objects is described in Application pipeline.
A document that consumes model.params should parse that subtree in the
driver (tungsten uses apply_tungsten_json). Optional
ParameterValidator can run on the
same subtree before construction.
Next steps¶
Register JSON ICs with a catalog:
examples/10_ui_register_ic.cpp.Attach writers on the
on_savehook:examples/11_write_results.cpp.Extension checklist:
extending_openpfc/README.md.