subroutine dyn_mpas_run(self)
! Module(s) from MPAS.
use atm_core, only: atm_compute_output_diagnostics, atm_do_timestep
use mpas_derived_types, only: mpas_pool_type, mpas_time_type, mpas_timeinterval_type, &
mpas_now
use mpas_pool_routines, only: mpas_pool_shift_time_levels
use mpas_timekeeping, only: mpas_advance_clock, mpas_get_clock_time, mpas_get_time, &
mpas_set_timeinterval, &
operator(+), operator(<)
class(mpas_dynamical_core_type), intent(inout) :: self
character(*), parameter :: subname = 'dyn_mpas_subdriver::dyn_mpas_run'
character(strkind) :: date_time
integer :: ierr
real(rkind), pointer :: config_dt
type(mpas_pool_type), pointer :: mpas_pool_diag, mpas_pool_mesh, mpas_pool_state
type(mpas_time_type) :: mpas_time_end, mpas_time_now ! This derived type is analogous to `ESMF_Time`.
type(mpas_timeinterval_type) :: mpas_time_interval ! This derived type is analogous to `ESMF_TimeInterval`.
call self % debug_print(log_level_debug, subname // ' entered')
nullify(config_dt)
nullify(mpas_pool_diag, mpas_pool_mesh, mpas_pool_state)
call self % get_variable_pointer(config_dt, 'cfg', 'config_dt')
call self % get_pool_pointer(mpas_pool_diag, 'diag')
call self % get_pool_pointer(mpas_pool_mesh, 'mesh')
call self % get_pool_pointer(mpas_pool_state, 'state')
mpas_time_now = mpas_get_clock_time(self % domain_ptr % clock, mpas_now, ierr=ierr)
if (ierr /= 0) then
call self % model_error('Failed to get time for "mpas_now"', subname, __LINE__)
end if
call mpas_get_time(mpas_time_now, datetimestring=date_time, ierr=ierr)
if (ierr /= 0) then
call self % model_error('Failed to get time for "mpas_now"', subname, __LINE__)
end if
call self % debug_print(log_level_info, 'Time integration of MPAS dynamical core begins at ' // trim(adjustl(date_time)))
call mpas_set_timeinterval(mpas_time_interval, s=self % coupling_time_interval, ierr=ierr)
if (ierr /= 0) then
call self % model_error('Failed to set coupling time interval', subname, __LINE__)
end if
! The `+` operator is overloaded here.
mpas_time_end = mpas_time_now + mpas_time_interval
! Integrate until the coupling time interval is reached.
! The `<` operator is overloaded here.
do while (mpas_time_now < mpas_time_end)
! Number of time steps that has been completed in this MPAS dynamical core instance.
self % number_of_time_steps = self % number_of_time_steps + 1
! Advance the dynamical states forward in time by `config_dt` seconds.
! Current states are in time level 1. Upon exit, time level 2 will contain updated states.
call atm_do_timestep(self % domain_ptr, config_dt, self % number_of_time_steps)
! MPAS "state" pool has two time levels.
! Swap them after advancing a time step.
call mpas_pool_shift_time_levels(mpas_pool_state)
call mpas_advance_clock(self % domain_ptr % clock, ierr=ierr)
if (ierr /= 0) then
call self % model_error('Failed to advance clock', subname, __LINE__)
end if
mpas_time_now = mpas_get_clock_time(self % domain_ptr % clock, mpas_now, ierr=ierr)
if (ierr /= 0) then
call self % model_error('Failed to get time for "mpas_now"', subname, __LINE__)
end if
call self % debug_print(log_level_info, 'Time step ' // stringify([self % number_of_time_steps]) // ' completed')
end do
call mpas_get_time(mpas_time_now, datetimestring=date_time, ierr=ierr)
if (ierr /= 0) then
call self % model_error('Failed to get time for "mpas_now"', subname, __LINE__)
end if
call self % debug_print(log_level_info, 'Time integration of MPAS dynamical core ends at ' // trim(adjustl(date_time)))
! Compute diagnostic variables like "pressure", "rho", and "theta" from time level 1 of MPAS "state" pool
! by calling upstream MPAS functionality.
call atm_compute_output_diagnostics(mpas_pool_state, 1, mpas_pool_diag, mpas_pool_mesh)
nullify(config_dt)
nullify(mpas_pool_diag, mpas_pool_mesh, mpas_pool_state)
call self % debug_print(log_level_debug, subname // ' completed')
end subroutine dyn_mpas_run