Compile a user-defined Fortran source file to a shared library at runtime
and call its ic_udf subroutine to fill the initial state.
The source file must contain exactly one subroutine with the interface:
subroutine ic_udf(n, x, rho, rho_u, E) bind(C, name="ic_udf") use iso_c_binding, only: c_int, c_double integer(c_int), value, intent(in) :: n real(c_double), intent(in) :: x(n) ! grid-point coordinates [m] real(c_double), intent(out) :: rho(n) ! density [kg/m^3] real(c_double), intent(out) :: rho_u(n) ! momentum [kg/m^2/s] real(c_double), intent(out) :: E(n) ! total energy [J/m^3] end subroutine
bind(C) requires C-interoperable argument types: use c_int / c_double
from iso_c_binding regardless of the solver's wp kind parameter.
(The default wp=real64 happens to match c_double, but this is not
guaranteed if wp is changed to real32 or real128; the UDF ABI is
fixed to c_int/c_double and must not rely on wp.) This also
suppresses gfortran -Wc-binding-type warnings.
See example/udf_sod.f90 for a complete working example.
The source is compiled via execute_command_line and the resulting shared
library is written to /tmp/ on POSIX hosts or %TEMP% / %TMP% on
Windows. Linux uses -shared -fPIC with a .so suffix; macOS uses
-dynamiclib with .dylib; Windows uses -shared with .dll. The
library is loaded through a small C portability shim that calls
dlopen/dlsym on POSIX hosts and LoadLibrary/GetProcAddress on
Windows. Requires gfortran on PATH.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(solver_state_t), | intent(inout) | :: | state |
Solver state (must have ub allocated, schemes bound) |
||
| type(config_t), | intent(in) | :: | cfg |
Runtime configuration (uses cfg%ic_udf_src) |