Build a config from an in-memory namelist string (no filesystem
touch), set up the ocean dyn-core exactly as bench_ocean /
driver_run_ocean do, map it onto the device, and hand back an
opaque handle. On ANY failure, handle_out is c_null_ptr and the
partially-built handle (if one was allocated) is freed — never a
half-initialised handle escaping to the caller.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(kind=c_char, len=1), | intent(in) | :: | nml_text(nml_len) | |||
| integer(kind=c_int), | intent(in), | value | :: | nml_len | ||
| type(c_ptr), | intent(out) | :: | handle_out |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| type(c_ptr), | private | :: | c_handle | ||||
| type(ocean_handle_t), | private, | pointer | :: | h | |||
| character(len=:), | private, | allocatable | :: | text |
function rdb_ocean_create_from_string(nml_text, nml_len, handle_out) & result(status) bind(c, name="rdb_ocean_create_from_string") !! Build a config from an in-memory namelist string (no filesystem !! touch), set up the ocean dyn-core exactly as `bench_ocean` / !! `driver_run_ocean` do, map it onto the device, and hand back an !! opaque handle. On ANY failure, `handle_out` is `c_null_ptr` and the !! partially-built handle (if one was allocated) is freed — never a !! half-initialised handle escaping to the caller. integer(c_int), intent(in), value :: nml_len character(kind=c_char), intent(in) :: nml_text(nml_len) type(c_ptr), intent(out) :: handle_out integer(c_int) :: status type(c_ptr) :: c_handle type(ocean_handle_t), pointer :: h character(len=:), allocatable :: text handle_out = c_null_ptr call error_ring_clear() if (g_handle_live) then call error_ring_push("rdb_ocean_create_from_string: a live ocean handle "// & "already exists in this process (multi-instance is not "// & "supported) — destroy it before creating another") status = int(OCEAN_STATUS_ERR_ALREADY_EXISTS, c_int) return end if call c_to_f_string(nml_text, nml_len, text) call build_pending_handle(text, c_handle, h, status) if (status /= int(OCEAN_STATUS_OK, c_int)) return ! already destroyed g_handle_live = .true. ! ---- Setup (P2.4) — driver_run_ocean's exact 21-stage sequence, ! via the shared engine. Single-rank: compute_rank=0, compute_size=1 ! (defaults); no restart on the C ABI yet (a future phase's concern, ! not silently dropped — `engine_setup`'s `restart_file` is simply ! not passed here). This is where the API used to run its OWN ! independent 9-stage subset (configure_ocean_metrics/_forcing/ ! _drag/_vmix/_lateral/_pgf/_bt/_bt_split/_land_mask only) — every ! other stage (bc/diag/hdiff/porous/p_surf/sponge/tides/tracers/ ! wave_drag/wetdry/dataovr/halo_init) is now reachable through here ! too. No geometry staged on this single-call path (P2.5's ! rdb_ocean_create_pending + rdb_ocean_stage_* do that) — so ! engine_setup falls through to its ordinary namelist-driven path, ! byte-identical to before P2.5. ---- call complete_ocean_create(c_handle, h, status) handle_out = c_handle ! c_null_ptr iff complete_ocean_create failed end function rdb_ocean_create_from_string