From 0f40dab3bf75d31f882b98b35b0c0731c43c6038 Mon Sep 17 00:00:00 2001 From: Michael Levy Date: Sun, 12 Oct 2025 11:46:20 -0600 Subject: [PATCH 01/13] Fix from Alper to run regional with DROF --- config_src/drivers/nuopc_cap/mom_cap.F90 | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index ad49e9d833..9354744a03 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -1799,15 +1799,14 @@ subroutine ModelAdvance(gcomp, rc) endif endif - if (do_advance) then - - call ESMF_GridCompGetInternalState(gcomp, ocean_internalstate, rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_GridCompGetInternalState(gcomp, ocean_internalstate, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return - Ice_ocean_boundary => ocean_internalstate%ptr%ice_ocean_boundary_type_ptr - ocean_public => ocean_internalstate%ptr%ocean_public_type_ptr - ocean_state => ocean_internalstate%ptr%ocean_state_type_ptr + Ice_ocean_boundary => ocean_internalstate%ptr%ice_ocean_boundary_type_ptr + ocean_public => ocean_internalstate%ptr%ocean_public_type_ptr + ocean_state => ocean_internalstate%ptr%ocean_state_type_ptr + if (do_advance) then !--------------- ! Write diagnostics for import !--------------- From 610b74f1a4a58288090a9fef4091d74a1536d9ee Mon Sep 17 00:00:00 2001 From: manishvenu Date: Tue, 2 Dec 2025 12:08:45 -0700 Subject: [PATCH 02/13] Add framework --- src/tracer/MARBL_tracers.F90 | 26 ++++++++++++++++++++++++-- src/tracer/MOM_tracer_flow_control.F90 | 4 +++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/tracer/MARBL_tracers.F90 b/src/tracer/MARBL_tracers.F90 index db7edbfa39..1ec3e21b1b 100644 --- a/src/tracer/MARBL_tracers.F90 +++ b/src/tracer/MARBL_tracers.F90 @@ -47,7 +47,7 @@ module MARBL_tracers #include -public register_MARBL_tracers, initialize_MARBL_tracers +public register_MARBL_tracers, initialize_MARBL_tracers, register_MARBL_tracer_segments public MARBL_tracers_column_physics, MARBL_tracers_surface_state public MARBL_tracers_set_forcing public MARBL_tracers_stock, MARBL_tracers_get, MARBL_tracers_end @@ -846,6 +846,24 @@ function register_MARBL_tracers(HI, GV, US, param_file, CS, tr_Reg, restart_CS, end function register_MARBL_tracers +!> Register OBC segments for MARBL tracers +subroutine register_MARBL_tracer_segments(CS,GV, tr_Reg, param_file, OBC) + type(MARBL_tracers_CS), pointer :: CS !< Pointer to the control structure for this module. + type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure + !! where, and what open boundary conditions are used. + type(tracer_registry_type), pointer :: tr_Reg !< Pointer to the control structure for the tracer + !! advection and diffusion module. + type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters + type(OBC_segment_type), pointer :: segment => NULL() ! pointer to segment type list + type(ocean_OBC_type), pointer :: OBC !< This open boundary condition + + ! This include declares and sets the variable "version". +# include "version_variable.h" + character(len=128), parameter :: sub_name = 'register_MARBL_tracer_segments' + + +end subroutine register_MARBL_tracer_segments + !> This subroutine initializes the CS%ntr tracer fields in tr(:,:,:,:) !! and it sets up the tracer output. subroutine initialize_MARBL_tracers(restart, day, G, GV, US, h, param_file, diag, OBC, CS, sponge_CSp) @@ -865,7 +883,7 @@ subroutine initialize_MARBL_tracers(restart, day, G, GV, US, h, param_file, diag !! call to register_MARBL_tracers. type(sponge_CS), pointer :: sponge_CSp !< A pointer to the control structure !! for the sponges, if they are in use. - + ! Local variables character(len=200) :: log_message character(len=48) :: name ! A variable's name in a NetCDF file. @@ -1162,6 +1180,10 @@ subroutine initialize_MARBL_tracers(restart, day, G, GV, US, h, param_file, diag end select endif + do m=1,CS%ntr + call fill_obgc_segments(G, GV, OBC, CS%tracer_data(m)%tr, CS%tracer_data(m)%var_name) + enddo + end subroutine initialize_MARBL_tracers !> This subroutine is used to register tracer fields and subroutines diff --git a/src/tracer/MOM_tracer_flow_control.F90 b/src/tracer/MOM_tracer_flow_control.F90 index 2298cb466f..f39f62c2f7 100644 --- a/src/tracer/MOM_tracer_flow_control.F90 +++ b/src/tracer/MOM_tracer_flow_control.F90 @@ -39,7 +39,7 @@ module MOM_tracer_flow_control use ideal_age_example, only : register_ideal_age_tracer, initialize_ideal_age_tracer use ideal_age_example, only : ideal_age_tracer_column_physics, ideal_age_tracer_surface_state use ideal_age_example, only : ideal_age_stock, ideal_age_example_end, ideal_age_tracer_CS -use MARBL_tracers, only : register_MARBL_tracers, initialize_MARBL_tracers +use MARBL_tracers, only : register_MARBL_tracers, initialize_MARBL_tracers, register_MARBL_tracer_segments use MARBL_tracers, only : MARBL_tracers_column_physics, MARBL_tracers_set_forcing use MARBL_tracers, only : MARBL_tracers_surface_state, MARBL_tracers_get use MARBL_tracers, only : MARBL_tracers_stock, MARBL_tracers_end, MARBL_tracers_CS @@ -390,6 +390,8 @@ subroutine call_tracer_register_obc_segments(GV, param_file, CS, tr_Reg, OBC) if (CS%use_MOM_generic_tracer) & call register_MOM_generic_tracer_segments(CS%MOM_generic_tracer_CSp, GV, OBC, tr_Reg, param_file) + if (CS%use_MARBL_tracers) & + call register_MARBL_tracer_segments(CS%MARBL_tracers_CSp, GV,tr_Reg, param_file, OBC) end subroutine call_tracer_register_obc_segments From 884782643de974c8570fe0a811e033d7ea9eaead Mon Sep 17 00:00:00 2001 From: manishvenu Date: Wed, 3 Dec 2025 09:45:47 -0700 Subject: [PATCH 03/13] Add the parameter stuff --- src/tracer/MARBL_tracers.F90 | 57 +++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/src/tracer/MARBL_tracers.F90 b/src/tracer/MARBL_tracers.F90 index 1ec3e21b1b..7559ddfdb1 100644 --- a/src/tracer/MARBL_tracers.F90 +++ b/src/tracer/MARBL_tracers.F90 @@ -21,7 +21,7 @@ module MARBL_tracers use MOM_interpolate, only : forcing_timeseries_set_time_type_vars use MOM_interpolate, only : map_model_time_to_forcing_time use MOM_io, only : file_exists, MOM_read_data, slasher, vardesc, var_desc, query_vardesc -use MOM_open_boundary, only : ocean_OBC_type +use MOM_open_boundary, only : ocean_OBC_type, fill_obgc_segments, register_obgc_segments, set_obgc_segments_props use MOM_remapping, only : reintegrate_column use MOM_remapping, only : remapping_CS, initialize_remapping, remapping_core_h use MOM_restart, only : query_initialized, MOM_restart_CS, register_restart_field @@ -47,7 +47,7 @@ module MARBL_tracers #include -public register_MARBL_tracers, initialize_MARBL_tracers, register_MARBL_tracer_segments +public register_MARBL_tracers, initialize_MARBL_tracers, register_MARBL_tracer_segments, get_marbl_tracer_props public MARBL_tracers_column_physics, MARBL_tracers_surface_state public MARBL_tracers_set_forcing public MARBL_tracers_stock, MARBL_tracers_get, MARBL_tracers_end @@ -100,6 +100,7 @@ module MARBL_tracers !> Pointer to tracer concentration and to tracer_type in tracer registry type, private :: MARBL_tracer_data + character(len=32) :: var_name !< The name of the tracer in the tracer registry real, pointer :: tr(:,:,:) => NULL() !< Array of tracers used in this subroutine [CU ~> conc] !! (ALK tracers use meq m-3 instead of mmol m-3) type(tracer_type), pointer :: tr_ptr => NULL() !< pointer to tracer inside Tr_reg @@ -790,15 +791,15 @@ function register_MARBL_tracers(HI, GV, US, param_file, CS, tr_Reg, restart_CS, do m=1,CS%ntr allocate(CS%tracer_data(m)%tr(isd:ied,jsd:jed,nz), source=0.0) - write(var_name(:),'(A)') trim(MARBL_instances%tracer_metadata(m)%short_name) + write(CS%tracer_data(m)%var_name(:),'(A)') trim(MARBL_instances%tracer_metadata(m)%short_name) write(desc_name(:),'(A)') trim(MARBL_instances%tracer_metadata(m)%long_name) write(units(:),'(A)') trim(MARBL_instances%tracer_metadata(m)%units) - CS%tr_desc(m) = var_desc(trim(var_name), trim(units), trim(desc_name), caller=mdl) + CS%tr_desc(m) = var_desc(trim(CS%tracer_data(m)%var_name), trim(units), trim(desc_name), caller=mdl) ! This is needed to force the compiler not to do a copy in the registration ! calls. Curses on the designers and implementers of Fortran90. tr_ptr => CS%tracer_data(m)%tr(:,:,:) - call query_vardesc(CS%tr_desc(m), name=var_name, & + call query_vardesc(CS%tr_desc(m), name=CS%tracer_data(m)%var_name, & caller="register_MARBL_tracers") ! Register the tracer for horizontal advection, diffusion, and restarts. call register_tracer(tr_ptr, tr_Reg, param_file, HI, GV, units = units, & @@ -810,7 +811,7 @@ function register_MARBL_tracers(HI, GV, US, param_file, CS, tr_Reg, restart_CS, ! values to the coupler (if any). This is meta-code and its arguments will ! currently (deliberately) give fatal errors if it is used. if (CS%coupled_tracers) & - CS%ind_tr(m) = aof_set_coupler_flux(trim(var_name)//'_flux', & + CS%ind_tr(m) = aof_set_coupler_flux(trim(CS%tracer_data(m)%var_name)//'_flux', & flux_type=' ', implementation=' ', caller="register_MARBL_tracers") enddo @@ -846,6 +847,34 @@ function register_MARBL_tracers(HI, GV, US, param_file, CS, tr_Reg, restart_CS, end function register_MARBL_tracers +!> Register MARBL tracer file and field names. Each segment must be in one file per tracer +subroutine get_marbl_tracer_props(varname, ntr, param_file, obc_src_file_name, obc_src_field_name) + character(len=32), intent(in) :: varname !< Control structure pointer + integer, intent(in) :: ntr !< Index of the tracer + type(param_file_type), intent(in) :: param_file !< Run-time parameter file + character(len=256), intent(out) :: obc_src_file_name + character(len=256), intent(out) :: obc_src_field_name + character(len=512) :: varstr + integer :: i1, i2 + +! Get the param with OBC_DATA first + call get_param(param_file, 'MARBL_tracers', 'OBC_DATA_' // varname, varstr) + + ! varstr should of form filename.nc(varname), we need to get the filename.nc part to obc_src_file_name and varname part to the obc_src_field_name + ! Find parentheses manually (more reliable than extract_word) + i1 = index(varstr, '(') + i2 = index(varstr, ')') + ! obc_src_file_name = trim(extract_word(varstr, '(', 1)) + ! obc_src_field_name = trim(extract_word(varstr, '(', 2)) + ! obc_src_field_name = trim(extract_word(obc_src_field_name, ')', 1)) + obc_src_file_name = trim(varstr(1:i1-1)) + obc_src_field_name = trim(varstr(i1+1:i2-1)) + + + + +end subroutine get_marbl_tracer_props + !> Register OBC segments for MARBL tracers subroutine register_MARBL_tracer_segments(CS,GV, tr_Reg, param_file, OBC) type(MARBL_tracers_CS), pointer :: CS !< Pointer to the control structure for this module. @@ -854,14 +883,26 @@ subroutine register_MARBL_tracer_segments(CS,GV, tr_Reg, param_file, OBC) type(tracer_registry_type), pointer :: tr_Reg !< Pointer to the control structure for the tracer !! advection and diffusion module. type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters - type(OBC_segment_type), pointer :: segment => NULL() ! pointer to segment type list type(ocean_OBC_type), pointer :: OBC !< This open boundary condition + character(len=256) :: obc_src_file_name, obc_src_field_name + integer :: n,m, ntr_id + real :: lfac_in ! Multiplicative factor used in setting the tracer-specific inverse length + ! scales associated with inflowing tracer reservoirs at OBCs [nondim] + real :: lfac_out ! Multiplicative factor used in setting the tracer-specific inverse length + ! scales associated with outflowing tracer reservoirs at OBCs [nondim] ! This include declares and sets the variable "version". # include "version_variable.h" character(len=128), parameter :: sub_name = 'register_MARBL_tracer_segments' + if (.NOT. associated(OBC)) return + do m=1,CS%ntr + call get_marbl_tracer_props(CS%tracer_data(m)%var_name, m, param_file,obc_src_file_name,obc_src_field_name ) + ! I don't like this, you have to have all boundaries of each tracer on one file. >:( Who thought hardcoding this was the right way to do it? so like O2_obc_segment.nc has 02_segment_001 O2_segment_002 + ! I can't even override these functions because get_obgc_tracers isn't flexible enough for this?? So the file reading can only be done from the file? + call set_obgc_segments_props(OBC,CS%tracer_data(m)%var_name,obc_src_file_name,obc_src_field_name,1.0,1.0) ! The last two vars are lfac_in and lfac_out + call register_obgc_segments(GV, OBC, tr_Reg, param_file, CS%tracer_data(m)%var_name) + enddo - end subroutine register_MARBL_tracer_segments !> This subroutine initializes the CS%ntr tracer fields in tr(:,:,:,:) From f6ac0dcbdb73c3314a0cd4bf1be3a3b19a9aaab6 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Wed, 3 Dec 2025 11:32:53 -0700 Subject: [PATCH 04/13] Cleaned up --- src/tracer/MARBL_tracers.F90 | 117 ++++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 42 deletions(-) diff --git a/src/tracer/MARBL_tracers.F90 b/src/tracer/MARBL_tracers.F90 index 7559ddfdb1..e77d29df6e 100644 --- a/src/tracer/MARBL_tracers.F90 +++ b/src/tracer/MARBL_tracers.F90 @@ -847,64 +847,97 @@ function register_MARBL_tracers(HI, GV, US, param_file, CS, tr_Reg, restart_CS, end function register_MARBL_tracers -!> Register MARBL tracer file and field names. Each segment must be in one file per tracer -subroutine get_marbl_tracer_props(varname, ntr, param_file, obc_src_file_name, obc_src_field_name) - character(len=32), intent(in) :: varname !< Control structure pointer - integer, intent(in) :: ntr !< Index of the tracer - type(param_file_type), intent(in) :: param_file !< Run-time parameter file - character(len=256), intent(out) :: obc_src_file_name - character(len=256), intent(out) :: obc_src_field_name - character(len=512) :: varstr - integer :: i1, i2 - -! Get the param with OBC_DATA first +!> Register MARBL tracer file and field names. +!! Each tracer segment must be contained in one file per tracer. +subroutine get_marbl_tracer_props(varname, param_file, obc_src_file_name, obc_src_field_name) + character(len=32), intent(in) :: varname !< Tracer variable name used in MARBL parameter file + type(param_file_type), intent(in) :: param_file !< Run-time parameter file object + character(len=256), intent(out) :: obc_src_file_name !< Parsed file name containing tracer OBC data + character(len=256), intent(out) :: obc_src_field_name !< Parsed field name inside that file + +# include "version_variable.h" + + character(len=128), parameter :: sub_name = 'get_marbl_tracer_props' + character(len=512) :: varstr !< Full string from parameter file (e.g., "file.nc(tracer)") + integer :: i1, i2 !< Indices for locating parentheses + + !----------------------------------------------------------------------- + ! Retrieve the OBC_DATA entry for this MARBL tracer. + ! Example entry format: + ! OBC_DATA_ = file.nc(tracer_name) + !----------------------------------------------------------------------- call get_param(param_file, 'MARBL_tracers', 'OBC_DATA_' // varname, varstr) - ! varstr should of form filename.nc(varname), we need to get the filename.nc part to obc_src_file_name and varname part to the obc_src_field_name - ! Find parentheses manually (more reliable than extract_word) + !----------------------------------------------------------------------- + ! Parse the returned string: + ! varstr = "filename.nc(fieldname)" + ! Extract: + ! - filename.nc → obc_src_file_name + ! - fieldname → obc_src_field_name + ! + ! Use INDEX for reliability instead of extract_word(). + !----------------------------------------------------------------------- i1 = index(varstr, '(') i2 = index(varstr, ')') - ! obc_src_file_name = trim(extract_word(varstr, '(', 1)) - ! obc_src_field_name = trim(extract_word(varstr, '(', 2)) - ! obc_src_field_name = trim(extract_word(obc_src_field_name, ')', 1)) + obc_src_file_name = trim(varstr(1:i1-1)) obc_src_field_name = trim(varstr(i1+1:i2-1)) +end subroutine get_marbl_tracer_props +!> Register OBC segments for MARBL tracers. +!! Each MARBL tracer can have OBC data specified in a parameter file, and this +!! routine reads that mapping and registers the segments with the OBC system (using generic tracers). +subroutine register_MARBL_tracer_segments(CS, GV, tr_Reg, param_file, OBC) + type(MARBL_tracers_CS), pointer :: CS !< Control structure for MARBL tracer configuration + type(verticalGrid_type), intent(in) :: GV !< Ocean vertical grid structure + type(tracer_registry_type), pointer :: tr_Reg !< Tracer advection/diffusion registry + type(param_file_type), intent(in) :: param_file !< Runtime parameter file accessor + type(ocean_OBC_type), pointer :: OBC !< Open boundary condition structure + character(len=256) :: obc_src_file_name !< Extracted filename for this tracer's OBC data + character(len=256) :: obc_src_field_name !< Extracted field name within the file + integer :: m !< Loop index over MARBL tracers -end subroutine get_marbl_tracer_props +# include "version_variable.h" -!> Register OBC segments for MARBL tracers -subroutine register_MARBL_tracer_segments(CS,GV, tr_Reg, param_file, OBC) - type(MARBL_tracers_CS), pointer :: CS !< Pointer to the control structure for this module. - type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure - !! where, and what open boundary conditions are used. - type(tracer_registry_type), pointer :: tr_Reg !< Pointer to the control structure for the tracer - !! advection and diffusion module. - type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters - type(ocean_OBC_type), pointer :: OBC !< This open boundary condition - character(len=256) :: obc_src_file_name, obc_src_field_name - integer :: n,m, ntr_id - real :: lfac_in ! Multiplicative factor used in setting the tracer-specific inverse length - ! scales associated with inflowing tracer reservoirs at OBCs [nondim] - real :: lfac_out ! Multiplicative factor used in setting the tracer-specific inverse length - ! scales associated with outflowing tracer reservoirs at OBCs [nondim] - - ! This include declares and sets the variable "version". -# include "version_variable.h" character(len=128), parameter :: sub_name = 'register_MARBL_tracer_segments' + if (.NOT. associated(OBC)) return - do m=1,CS%ntr - call get_marbl_tracer_props(CS%tracer_data(m)%var_name, m, param_file,obc_src_file_name,obc_src_field_name ) - ! I don't like this, you have to have all boundaries of each tracer on one file. >:( Who thought hardcoding this was the right way to do it? so like O2_obc_segment.nc has 02_segment_001 O2_segment_002 - ! I can't even override these functions because get_obgc_tracers isn't flexible enough for this?? So the file reading can only be done from the file? - call set_obgc_segments_props(OBC,CS%tracer_data(m)%var_name,obc_src_file_name,obc_src_field_name,1.0,1.0) ! The last two vars are lfac_in and lfac_out - call register_obgc_segments(GV, OBC, tr_Reg, param_file, CS%tracer_data(m)%var_name) - enddo + + ! Loop over all MARBL tracers and register the corresponding OBC segments. + do m = 1, CS%ntr + + ! Extract file and field names for this tracer from the MARBL parameter file. + call get_marbl_tracer_props( CS%tracer_data(m)%var_name, & + param_file, & + obc_src_file_name, & + obc_src_field_name ) + + ! NOTE: + ! MARBL currently requires all OBC segments for a tracer to live in one file. + ! This is limiting, since files like "O2_obc_segment.nc" must contain + ! O2_segment_001, O2_segment_002, etc. There is no flexible override path for per-segment files + ! because get_obgc_props assumes this fixed structure. + ! Improving this would require extending the OBC file-reading layer. + + + ! Set properties that describe the OBC segments for this tracer. + ! lfac_in and lfac_out are scaling factors (set to default 1.0). + call set_obgc_segments_props( OBC, & + CS%tracer_data(m)%var_name, & + obc_src_file_name, & + obc_src_field_name, & + 1.0, 1.0 ) + + ! Register the segments with the generic tracers system. + call register_obgc_segments( GV, OBC, tr_Reg, param_file, & + CS%tracer_data(m)%var_name ) + end do end subroutine register_MARBL_tracer_segments + !> This subroutine initializes the CS%ntr tracer fields in tr(:,:,:,:) !! and it sets up the tracer output. subroutine initialize_MARBL_tracers(restart, day, G, GV, US, h, param_file, diag, OBC, CS, sponge_CSp) From d0d14d58ce488ef152d33b629abdcedd500d3774 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Wed, 3 Dec 2025 11:49:24 -0700 Subject: [PATCH 05/13] Rename --- src/tracer/MARBL_tracers.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tracer/MARBL_tracers.F90 b/src/tracer/MARBL_tracers.F90 index e77d29df6e..4830d29c12 100644 --- a/src/tracer/MARBL_tracers.F90 +++ b/src/tracer/MARBL_tracers.F90 @@ -47,7 +47,7 @@ module MARBL_tracers #include -public register_MARBL_tracers, initialize_MARBL_tracers, register_MARBL_tracer_segments, get_marbl_tracer_props +public register_MARBL_tracers, initialize_MARBL_tracers, register_MARBL_tracer_segments, get_marbl_obc_params public MARBL_tracers_column_physics, MARBL_tracers_surface_state public MARBL_tracers_set_forcing public MARBL_tracers_stock, MARBL_tracers_get, MARBL_tracers_end @@ -849,7 +849,7 @@ end function register_MARBL_tracers !> Register MARBL tracer file and field names. !! Each tracer segment must be contained in one file per tracer. -subroutine get_marbl_tracer_props(varname, param_file, obc_src_file_name, obc_src_field_name) +subroutine get_marbl_obc_params(varname, param_file, obc_src_file_name, obc_src_field_name) character(len=32), intent(in) :: varname !< Tracer variable name used in MARBL parameter file type(param_file_type), intent(in) :: param_file !< Run-time parameter file object character(len=256), intent(out) :: obc_src_file_name !< Parsed file name containing tracer OBC data @@ -857,7 +857,7 @@ subroutine get_marbl_tracer_props(varname, param_file, obc_src_file_name, obc_sr # include "version_variable.h" - character(len=128), parameter :: sub_name = 'get_marbl_tracer_props' + character(len=128), parameter :: sub_name = 'get_marbl_obc_params' character(len=512) :: varstr !< Full string from parameter file (e.g., "file.nc(tracer)") integer :: i1, i2 !< Indices for locating parentheses @@ -883,7 +883,7 @@ subroutine get_marbl_tracer_props(varname, param_file, obc_src_file_name, obc_sr obc_src_file_name = trim(varstr(1:i1-1)) obc_src_field_name = trim(varstr(i1+1:i2-1)) -end subroutine get_marbl_tracer_props +end subroutine get_marbl_obc_params !> Register OBC segments for MARBL tracers. !! Each MARBL tracer can have OBC data specified in a parameter file, and this @@ -909,7 +909,7 @@ subroutine register_MARBL_tracer_segments(CS, GV, tr_Reg, param_file, OBC) do m = 1, CS%ntr ! Extract file and field names for this tracer from the MARBL parameter file. - call get_marbl_tracer_props( CS%tracer_data(m)%var_name, & + call get_marbl_obc_params( CS%tracer_data(m)%var_name, & param_file, & obc_src_file_name, & obc_src_field_name ) From 9bfb91e4a93a70661d3326de482fde11d287cb05 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Wed, 3 Dec 2025 11:56:22 -0700 Subject: [PATCH 06/13] Spaces --- src/tracer/MARBL_tracers.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracer/MARBL_tracers.F90 b/src/tracer/MARBL_tracers.F90 index 4830d29c12..8879751365 100644 --- a/src/tracer/MARBL_tracers.F90 +++ b/src/tracer/MARBL_tracers.F90 @@ -957,7 +957,7 @@ subroutine initialize_MARBL_tracers(restart, day, G, GV, US, h, param_file, diag !! call to register_MARBL_tracers. type(sponge_CS), pointer :: sponge_CSp !< A pointer to the control structure !! for the sponges, if they are in use. - + ! Local variables character(len=200) :: log_message character(len=48) :: name ! A variable's name in a NetCDF file. From a34510cae02960c0c9c14000f7b0110f3a7f7171 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Wed, 3 Dec 2025 11:57:26 -0700 Subject: [PATCH 07/13] Fix comment --- src/tracer/MARBL_tracers.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tracer/MARBL_tracers.F90 b/src/tracer/MARBL_tracers.F90 index 8879751365..c46876115d 100644 --- a/src/tracer/MARBL_tracers.F90 +++ b/src/tracer/MARBL_tracers.F90 @@ -915,11 +915,11 @@ subroutine register_MARBL_tracer_segments(CS, GV, tr_Reg, param_file, OBC) obc_src_field_name ) ! NOTE: - ! MARBL currently requires all OBC segments for a tracer to live in one file. + ! Generic tracers currently requires all OBC segments for a tracer to live in one file. ! This is limiting, since files like "O2_obc_segment.nc" must contain ! O2_segment_001, O2_segment_002, etc. There is no flexible override path for per-segment files ! because get_obgc_props assumes this fixed structure. - ! Improving this would require extending the OBC file-reading layer. + ! Improving this would require extending the three functions below in MOM_open_boundary ! Set properties that describe the OBC segments for this tracer. From 52d158bf0eb5c1cbc527fbfb2db9bde6f9b7c469 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Tue, 9 Dec 2025 11:03:41 -0700 Subject: [PATCH 08/13] Comment --- src/tracer/MARBL_tracers.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracer/MARBL_tracers.F90 b/src/tracer/MARBL_tracers.F90 index c46876115d..1a44d62b8d 100644 --- a/src/tracer/MARBL_tracers.F90 +++ b/src/tracer/MARBL_tracers.F90 @@ -875,7 +875,7 @@ subroutine get_marbl_obc_params(varname, param_file, obc_src_file_name, obc_src_ ! - filename.nc → obc_src_file_name ! - fieldname → obc_src_field_name ! - ! Use INDEX for reliability instead of extract_word(). + ! Using index instead of extract_word(). !----------------------------------------------------------------------- i1 = index(varstr, '(') i2 = index(varstr, ')') From fe9c68dd2d1c82021762e6ffa0bbb49427706c24 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Wed, 31 Dec 2025 14:06:55 -0700 Subject: [PATCH 09/13] This --- src/core/MOM.F90 | 12 ++++++------ src/tracer/MARBL_tracers.F90 | 16 +++++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index 5533f4b282..2172f4ca87 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -2929,12 +2929,6 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & endif CS%HFrz = (US%Z_to_m * GV%m_to_H) * HFrz_z - if (associated(OBC_in)) then - ! This call allocates the arrays on the segments for open boundary data and initializes the - ! relevant vertical remapping structures. It can only occur after the vertical grid has been - ! initialized. - call initialize_segment_data(G_in, GV, US, OBC_in, param_file) - endif ! Shift from using the temporary dynamic grid type to using the final (potentially static) ! and properly rotated ocean-specific grid type and horizontal index type. @@ -3152,6 +3146,12 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & if (CS%debug_OBCs) call write_OBC_info(CS%OBC, G, GV, US) endif + if (associated(OBC_in)) then + ! This call allocates the arrays on the segments for open boundary data and initializes the + ! relevant vertical remapping structures. It can only occur after the vertical grid has been + ! initialized. + call initialize_segment_data(G_in, GV, US, OBC_in, param_file) + endif if (present(waves_CSp)) then diff --git a/src/tracer/MARBL_tracers.F90 b/src/tracer/MARBL_tracers.F90 index 1a44d62b8d..c07a95e73a 100644 --- a/src/tracer/MARBL_tracers.F90 +++ b/src/tracer/MARBL_tracers.F90 @@ -47,7 +47,7 @@ module MARBL_tracers #include -public register_MARBL_tracers, initialize_MARBL_tracers, register_MARBL_tracer_segments, get_marbl_obc_params +public register_MARBL_tracers, initialize_MARBL_tracers, register_MARBL_tracer_segments public MARBL_tracers_column_physics, MARBL_tracers_surface_state public MARBL_tracers_set_forcing public MARBL_tracers_stock, MARBL_tracers_get, MARBL_tracers_end @@ -897,7 +897,7 @@ subroutine register_MARBL_tracer_segments(CS, GV, tr_Reg, param_file, OBC) character(len=256) :: obc_src_file_name !< Extracted filename for this tracer's OBC data character(len=256) :: obc_src_field_name !< Extracted field name within the file - integer :: m !< Loop index over MARBL tracers + integer :: m !< Loop index over MARBL tracers # include "version_variable.h" @@ -919,7 +919,7 @@ subroutine register_MARBL_tracer_segments(CS, GV, tr_Reg, param_file, OBC) ! This is limiting, since files like "O2_obc_segment.nc" must contain ! O2_segment_001, O2_segment_002, etc. There is no flexible override path for per-segment files ! because get_obgc_props assumes this fixed structure. - ! Improving this would require extending the three functions below in MOM_open_boundary + ! Improving this would require extending the obgc functions in MOM_open_boundary ! Set properties that describe the OBC segments for this tracer. @@ -932,7 +932,7 @@ subroutine register_MARBL_tracer_segments(CS, GV, tr_Reg, param_file, OBC) ! Register the segments with the generic tracers system. call register_obgc_segments( GV, OBC, tr_Reg, param_file, & - CS%tracer_data(m)%var_name ) + CS%tracer_data(m)%var_name ) end do end subroutine register_MARBL_tracer_segments @@ -1254,9 +1254,11 @@ subroutine initialize_MARBL_tracers(restart, day, G, GV, US, h, param_file, diag end select endif - do m=1,CS%ntr - call fill_obgc_segments(G, GV, OBC, CS%tracer_data(m)%tr, CS%tracer_data(m)%var_name) - enddo + if (associated(OBC) .and. .NOT. restart) then + do m=1,CS%ntr + call fill_obgc_segments(G, GV, OBC, CS%tracer_data(m)%tr, CS%tracer_data(m)%var_name) + enddo + endif end subroutine initialize_MARBL_tracers From 5c39f0d4189a99b44a33a470ca8bab59ba5263ee Mon Sep 17 00:00:00 2001 From: manishvenu Date: Thu, 15 Jan 2026 10:31:20 -0700 Subject: [PATCH 10/13] Revert MOM.F90 change --- src/core/MOM.F90 | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index 2172f4ca87..ce051163c2 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -2929,7 +2929,13 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & endif CS%HFrz = (US%Z_to_m * GV%m_to_H) * HFrz_z - + if (associated(OBC_in)) then + ! This call allocates the arrays on the segments for open boundary data and initializes the + ! relevant vertical remapping structures. It can only occur after the vertical grid has been + ! initialized. + call initialize_segment_data(G_in, GV, US, OBC_in, param_file) + endif + ! Shift from using the temporary dynamic grid type to using the final (potentially static) ! and properly rotated ocean-specific grid type and horizontal index type. if (CS%rotate_index) then @@ -3146,12 +3152,7 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & if (CS%debug_OBCs) call write_OBC_info(CS%OBC, G, GV, US) endif - if (associated(OBC_in)) then - ! This call allocates the arrays on the segments for open boundary data and initializes the - ! relevant vertical remapping structures. It can only occur after the vertical grid has been - ! initialized. - call initialize_segment_data(G_in, GV, US, OBC_in, param_file) - endif + if (present(waves_CSp)) then From b2f4ea84b8811448b31e093e790e83ca7e9d7de2 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Thu, 15 Jan 2026 10:31:51 -0700 Subject: [PATCH 11/13] 2 --- src/core/MOM.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index ce051163c2..5533f4b282 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -2935,7 +2935,7 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & ! initialized. call initialize_segment_data(G_in, GV, US, OBC_in, param_file) endif - + ! Shift from using the temporary dynamic grid type to using the final (potentially static) ! and properly rotated ocean-specific grid type and horizontal index type. if (CS%rotate_index) then @@ -3154,7 +3154,6 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & endif - if (present(waves_CSp)) then call waves_register_restarts(waves_CSp, HI, GV, US, param_file, restart_CSp) endif From 19ac8361018ff198c7f9afeb666130448fd26d80 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Mon, 30 Mar 2026 11:26:50 -0600 Subject: [PATCH 12/13] Style --- src/tracer/MARBL_tracers.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracer/MARBL_tracers.F90 b/src/tracer/MARBL_tracers.F90 index aa97d20bb6..cf763689e5 100644 --- a/src/tracer/MARBL_tracers.F90 +++ b/src/tracer/MARBL_tracers.F90 @@ -951,7 +951,7 @@ subroutine register_MARBL_tracer_segments(CS, GV, tr_Reg, param_file, OBC) ! Register the segments with the generic tracers system. call register_obgc_segments( GV, OBC, tr_Reg, param_file, & - CS%tracer_data(m)%var_name ) + CS%tracer_data(m)%var_name ) end do end subroutine register_MARBL_tracer_segments From dbce6577ee2537049174b024a1ace3669ba637ff Mon Sep 17 00:00:00 2001 From: manishvenu Date: Thu, 30 Apr 2026 18:42:02 -0600 Subject: [PATCH 13/13] Mike Comment --- src/tracer/MARBL_tracers.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracer/MARBL_tracers.F90 b/src/tracer/MARBL_tracers.F90 index cf763689e5..fbfbc6ca7f 100644 --- a/src/tracer/MARBL_tracers.F90 +++ b/src/tracer/MARBL_tracers.F90 @@ -876,7 +876,7 @@ subroutine get_marbl_obc_params(varname, param_file, obc_src_file_name, obc_src_ # include "version_variable.h" - character(len=128), parameter :: sub_name = 'get_marbl_obc_params' + character(len=*), parameter :: sub_name = 'get_marbl_obc_params' character(len=512) :: varstr !< Full string from parameter file (e.g., "file.nc(tracer)") integer :: i1, i2 !< Indices for locating parentheses