How Many Saved State Fields Need to be Stored?

MARBL does not yet have a stand-alone test to provide a list of requested saved state fields, but marbl_saved_state_init() shows that there are four saved state fields - two for the surface and two for the interior. The two surface fields are surface pH and surface pH (alternate CO2):

call surface_state%construct(num_elements_surface_flux, num_levels)

lname = 'surface pH'
sname = 'PH_SURF'
units = 'pH'
vgrid = 'none'
rank  = 2
call surface_state%add_state(lname, sname, units, vgrid, rank,            &
     surf_ind%ph_surf, marbl_status_log)
if (marbl_status_log%labort_marbl) then
  call marbl_status_log%log_error_trace("add_state(PH_SURF)", subname)
  return
end if

lname = 'surface pH (alternate CO2)'
sname = 'PH_SURF_ALT_CO2'
units = 'pH'
vgrid = 'none'
rank  = 2
call surface_state%add_state(lname, sname, units, vgrid, rank,            &
     surf_ind%ph_alt_co2_surf, marbl_status_log)
if (marbl_status_log%labort_marbl) then
  call marbl_status_log%log_error_trace("add_state(PH_SURF_ALT_CO2)", subname)
  return
end if

The two interior state fields are 3D pH and 3D pH (alternate CO2)

call interior_state%construct(num_elements_interior_tendency, num_levels)

lname = '3D pH'
sname = 'PH_3D'
units = 'pH'
vgrid = 'layer_avg'
rank  = 3
call interior_state%add_state(lname, sname, units, vgrid, rank,           &
     interior_ind%ph_col, marbl_status_log)
if (marbl_status_log%labort_marbl) then
  call marbl_status_log%log_error_trace("add_state(PH_3D)", subname)
  return
end if

lname = '3D pH (alternate CO2)'
sname = 'PH_3D_ALT_CO2'
units = 'pH'
vgrid = 'layer_avg'
rank  = 3
call interior_state%add_state(lname, sname, units, vgrid, rank,           &
     interior_ind%ph_alt_co2_col, marbl_status_log)
if (marbl_status_log%labort_marbl) then
  call marbl_status_log%log_error_trace("add_state(PH_3D_ALT_CO2)", subname)
  return
end if

The pH computation is an iterative solver, and it has proven useful to use the pH at timestep t as an initial value when solving for time t+1.

Saved State in the Interface

MARBL splits the saved state fields between those needed for computing surface fluxes and those needed for computing interior tendencies, so on the interface we have

type, public :: marbl_interface_class

  .
  .
  .
  type(marbl_saved_state_type)              , public               :: surface_flux_saved_state             ! input/output
  type(marbl_saved_state_type)              , public               :: interior_tendency_saved_state        ! input/output
  .
  .
  .
end type marbl_interface_class

The marbl_saved_state_type is a wrapper for marbl_single_saved_state_type:

type, public :: marbl_single_saved_state_type
  integer                 :: rank
  character(len=char_len) :: long_name
  character(len=char_len) :: short_name
  character(len=char_len) :: units
  character(len=char_len) :: vertical_grid ! 'none', 'layer_avg', 'layer_iface'
  real(r8), allocatable, dimension(:)   :: field_2d  ! num_elements
  real(r8), allocatable, dimension(:,:) :: field_3d  ! num_levels, num_elements
contains
  procedure :: construct => marbl_single_saved_state_construct
end type marbl_single_saved_state_type

!*****************************************************************************

type, public :: marbl_saved_state_type
  integer :: saved_state_cnt
  integer :: num_elements
  integer :: num_levels
  type(marbl_single_saved_state_type), dimension(:), pointer :: state => NULL()
 contains
   procedure, public :: construct => marbl_saved_state_constructor
   procedure, public :: add_state => marbl_saved_state_add
end type marbl_saved_state_type

What Should the GCM Do?

After marbl_instance%surface_flux_compute() returns, the GCM needs to process marbl_instance%surface_flux_saved_state. That means looping through each element in the marbl_instance%surface_flux_saved_state%state(:) array, checking state(n)%rank, and then storing either state(n)%field_2d or state(n)%field_3d in a global array. Before calling surface_flux_compute() in the next time step, these saved values should be copied back into marbl_intance%surface_flux_saved_state.

Similar actions must be taken with marbl_instance%interior_tendency_saved_state before / after calls to marbl_instance%interior_tendency_compute().