C API Baseline#
Last updated: 2026-05-26
This note records the first MuPRO C ABI skeleton, runtime bridge, runtime context skeleton, and optional FFT runtime capability. The goal is to establish a stable external boundary before Python, CLI/TUI, or solver-specific host integrations depend on internal Fortran modules.
Scope#
Implemented in PR-014:
Public header:
library/c_api/include/mupro.hOpaque runtime handle:
mupro_runtime_tOpaque TDGL handle:
mupro_tdgl_tStatus object:
mupro_status_tRuntime create/destroy and size setup
TDGL create/destroy and parameter setup
TDGL solve function signature with pointer, shape, and stride metadata
C unit smoke test:
unit.c_apiC example:
examples/c_api_tdgl
Implemented in PR-015:
Runtime size setup now calls a Fortran
bind(C)bridge intomod_base_size::size_setup.Runtime size query reads back the Fortran global size state and checks it against the C handle cache.
Runtime MPI setup is explicit through
mupro_runtime_initialize_mpi.Runtime MPI query returns the rank/process discovered by Fortran
mod_base_mpi::mpi_setup.Runtime destroy finalizes MPI only when MuPRO initialized MPI itself; it does not call the legacy
mpi_exitpath because that routine stops the process.
Implemented in PR-016:
Added
library/runtimewithmod_mupro_runtimeandmod_mupro_backend.Added
type_mupro_RuntimeContext, including size, MPI, FFT placeholder, backend, setup state, and legacy-global-state flag.Added
type_mupro_BackendContextwith backend kind, device ID, and device-memory ownership flag.Added
mupro_runtime_setup,mupro_runtime_finalize, size setup/query, and MPI initialize/finalize routines.Moved the C ABI Fortran bridge to call
mod_mupro_runtimeinstead of directly owningmod_base_sizeandmod_base_mpiinteractions.Added
unit.runtimefor runtime context size/MPI lifecycle coverage.
Implemented in PR-017:
FFT is now an optional runtime capability under
mod_mupro_runtime.runtime_setupstill does not initialize FFT by default.Added
mupro_runtime_setup_fft,mupro_runtime_ensure_fft, andmupro_runtime_finalize_fft.Added minimal
mupro_fft_finalizeinL0_FFTto release the current legacy FFT plans, work buffers, and k-vector allocation.unit.runtimenow verifies that FFT is not set up implicitly, can be explicitly set up, can be finalized, and can be set up again.Adjusted the
L0_FFTinclude path to avoid stale per-module.modfiles shadowing the main build module output.
Implemented in PR-021:
Added an optional TDGL C adapter compiled when
MUPRO_BUILD_TDGL=ON.mupro_tdgl_setuprequests runtime-owned FFT setup before calling the Fortran TDGL setup path.mupro_tdgl_solvecalls the existing Fortrantype_TDGLContext%solvepath when the adapter is enabled.The default build without
MUPRO_BUILD_TDGLkeeps the stable C skeleton and returnsMUPRO_STATUS_NOT_SETUPfor solve.Added
integration.c_api_tdgl_adapterfor TDGL-enabled builds.
Non-goal for PR-014:
No numerical TDGL solve through C yet.
No direct C ABI ownership of FFT plans yet.
No Python binding or GPU backend.
Non-goal for PR-015:
No multiple-runtime support. The current bridge still writes the legacy Fortran global size/MPI state, so the process should be treated as having one active MuPRO runtime.
No FFT plan lifecycle ownership yet.
Non-goal for PR-016:
No TDGL numerical backend connection through C yet.
No GPU/backend dispatch implementation beyond backend metadata.
Non-goal for PR-017:
No C ABI FFT API surface yet; FFT remains an internal runtime capability for solver adapters.
No FFT algorithm change.
No GPU FFT backend implementation.
Non-goal for PR-021:
No TDGL numerical algorithm change.
No public C FFT API. FFT remains solver-requested through the runtime bridge.
No benchmark-backed production correctness claim for TDGL yet.
Status Contract#
Every C ABI function returns mupro_status_t.
The C status codes mirror the current Fortran status foundation:
Code |
Meaning |
|---|---|
|
Call succeeded. |
|
Required pointer argument was null. |
|
Shape or stride metadata is invalid. |
|
Required runtime or solver setup is missing, or the backend is not wired yet. |
|
Reserved for license validation failures. |
|
Numerical or allocation failure. |
|
Non-shape argument is invalid. |
Array Layout#
TDGL field arrays use the solver’s Fortran column-major layout.
Logical shape order:
[component, z, y, x]
This matches the current Fortran TDGL fields:
real(kind=rdp) :: field(3, Rn3, Rn2, Rn1)
Strides are measured in double elements, not bytes. A contiguous Fortran field has:
shape = [3, Rn3, Rn2, Rn1]
stride = [1, 3, 3*Rn3, 3*Rn3*Rn2]
The C mupro_tdgl_solve implementation validates pointer, shape, and stride metadata. Without MUPRO_BUILD_TDGL, it returns MUPRO_STATUS_NOT_SETUP because the TDGL backend is not present in that build. With MUPRO_BUILD_TDGL=ON, it currently requires contiguous Fortran-column-major strides and routes the call through the Fortran TDGL adapter.
Runtime Bridge#
mupro_runtime_set_size is now the C-side owner for writing the legacy Fortran global size state. It stores the requested size in the C handle and calls a narrow Fortran bridge into mod_mupro_runtime. The runtime module then calls size_setup. mupro_runtime_get_size reads the Fortran global state back through mod_mupro_runtime and fails with MUPRO_STATUS_NUMERICAL if the Fortran state no longer matches the C handle.
mupro_runtime_initialize_mpi is the C-side owner for initializing MPI through mod_mupro_runtime, which delegates to the existing mpi_setup implementation. The runtime records whether MPI was already initialized before MuPRO entered; mupro_runtime_destroy only finalizes MPI when MuPRO owns that initialization.
The current runtime context remains a compatibility adapter over legacy globals. It is suitable for one active runtime per process, not for independent concurrent runtime handles.
Optional FFT Capability#
FFT belongs to runtime ownership, but it is not a mandatory runtime resource. mupro_runtime_setup leaves context%fft%is_setup false. Spectral solvers should call mupro_runtime_setup_fft or mupro_runtime_ensure_fft when they need FFT plans; finite-difference, finite-volume, and finite-element paths should not pay this setup cost or inherit an FFT dependency unless they request it.
The current implementation wraps the existing L0_FFT global FFT state. mupro_runtime_finalize_fft releases the legacy FFT plans and arrays before MPI finalization. This is still single-runtime compatible, not independent multi-runtime FFT ownership.
TDGL C adapter setup calls the runtime FFT setup bridge lazily. This keeps finite-difference, finite-volume, finite-element, and non-spectral users from paying FFT setup cost unless a solver asks for it.
TDGL Adapter#
The TDGL adapter is build-time optional:
Default L0/L1 development build: C TDGL setup stores validated parameters, and solve returns
MUPRO_STATUS_NOT_SETUP.MUPRO_BUILD_TDGL=ON: C TDGL setup requests runtime FFT and calls Fortran TDGL setup; C TDGL solve calls Fortran TDGL solve.
The adapter uses the current legacy global runtime/FFT state. It should be treated as one active MuPRO runtime and one active TDGL adapter context per process until solver internals stop depending on global state.
The C field arrays must use:
shape = [3, Rn3, Rn2, Rn1]
stride = [1, 3, 3*Rn3, 3*Rn3*Rn2]
G_6x6 is interpreted as a C row-major 6x6 matrix and copied into the Fortran TDGL context before setup.
Downstream Linking#
The public ABI in mupro.h is C-compatible, but the current static SDK archive contains Fortran and C++ objects. Downstream CMake consumers should enable C, CXX, and Fortran languages before find_package(mupro). The installed package now fails early if CXX is not enabled, because otherwise C-only examples can reach link time without the C++ runtime required by the expression-evaluation object code.
Next ABI Work#
The next ABI/runtime slice should add concrete MPI smoke and benchmark-linked TDGL/FFT validation before expanding broader solver coverage.