subroutine dyn_mpas_final(self)
! Module(s) from MPAS.
use atm_time_integration, only: mpas_atm_dynamics_finalize
use mpas_atm_halos, only: atm_destroy_halo_groups, exchange_halo_group
use mpas_atm_threading, only: mpas_atm_threading_finalize
use mpas_decomp, only: mpas_decomp_destroy_decomp_list
use mpas_derived_types, only: field2dreal
use mpas_field_routines, only: mpas_deallocate_scratch_field
use mpas_framework, only: mpas_framework_finalize
use mpas_log, only: mpas_log_finalize
use mpas_pool_routines, only: mpas_pool_get_field
use mpas_timekeeping, only: mpas_destroy_clock
use mpas_timer, only: mpas_timer_write_header, mpas_timer_write, mpas_timer_finalize
class(mpas_dynamical_core_type), intent(inout) :: self
character(*), parameter :: subname = 'dyn_mpas_subdriver::dyn_mpas_final'
integer :: ierr
type(field2dreal), pointer :: field_2d_real
call self % debug_print(log_level_debug, subname // ' entered')
nullify(field_2d_real)
! First, wind down MPAS dynamical core by calling its own finalization procedures.
! Some additional "scratch" fields are needed for interoperability with CAM-SIMA, but they are not finalized by
! `mpas_atm_dynamics_finalize`. Finalize them below.
call mpas_pool_get_field(self % domain_ptr % blocklist % allfields, 'tend_uzonal', field_2d_real, timelevel=1)
call mpas_deallocate_scratch_field(field_2d_real)
nullify(field_2d_real)
call mpas_pool_get_field(self % domain_ptr % blocklist % allfields, 'tend_umerid', field_2d_real, timelevel=1)
call mpas_deallocate_scratch_field(field_2d_real)
nullify(field_2d_real)
call self % debug_print(log_level_info, 'Finalizing dynamics')
! Opposite to `mpas_atm_dynamics_init`.
call mpas_atm_dynamics_finalize(self % domain_ptr)
! Opposite to `atm_build_halo_groups`.
call atm_destroy_halo_groups(self % domain_ptr, ierr=ierr)
if (ierr /= 0) then
call self % model_error('Failed to destroy halo exchange groups', subname, __LINE__)
end if
nullify(exchange_halo_group)
call self % debug_print(log_level_info, 'Cleaning up OpenMP threading')
! Opposite to `mpas_atm_threading_init`.
call mpas_atm_threading_finalize(self % domain_ptr % blocklist, ierr=ierr)
if (ierr /= 0) then
call self % model_error('Failed to clean up OpenMP threading', subname, __LINE__)
end if
call self % debug_print(log_level_info, 'Cleaning up clock')
! Opposite to `mpas_create_clock`, which was called by `atm_simulation_clock_init`, then `atm_setup_clock`.
call mpas_destroy_clock(self % domain_ptr % clock, ierr=ierr)
if (ierr /= 0) then
call self % model_error('Failed to clean up clock', subname, __LINE__)
end if
call self % debug_print(log_level_info, 'Cleaning up decompositions')
! Opposite to `mpas_decomp_create_decomp_list`, which was called by `atm_setup_decompositions`.
call mpas_decomp_destroy_decomp_list(self % domain_ptr % decompositions)
deallocate(self % domain_ptr % streaminfo)
! Write timing information to log.
call mpas_timer_write_header()
call mpas_timer_write()
! Opposite to `mpas_timer_init`, which was called by `mpas_framework_init_phase2`.
call mpas_timer_finalize(self % domain_ptr)
call self % debug_print(log_level_info, 'Cleaning up log')
! Opposite to `mpas_log_init`, which was called by `atm_setup_log`.
call mpas_log_finalize(ierr)
if (ierr /= 0) then
call self % model_error('Failed to clean up log', subname, __LINE__)
end if
call self % debug_print(log_level_info, 'Finalizing MPAS framework')
! Opposite to `mpas_framework_init_phase1` and `mpas_framework_init_phase2`.
call mpas_framework_finalize(self % domain_ptr % dminfo, self % domain_ptr)
call self % debug_print(log_level_debug, subname // ' completed')
call self % debug_print(log_level_info, 'Successful finalization of MPAS dynamical core')
! Second, clean up this MPAS dynamical core instance.
! Initialized by `dyn_mpas_init_phase4`.
self % coupling_time_interval = 0
self % number_of_time_steps = 0
! Initialized by `dyn_mpas_define_scalar`.
deallocate(self % constituent_name)
deallocate(self % index_constituent_to_mpas_scalar)
deallocate(self % index_mpas_scalar_to_constituent)
deallocate(self % is_water_species)
! Initialized by `dyn_mpas_init_phase3`.
self % number_of_constituents = 0
! Initialized by `dyn_mpas_init_phase1`.
self % log_level = log_level_quiet
self % log_unit = output_unit
self % mpi_comm = mpi_comm_null
self % mpi_rank = 0
self % mpi_rank_root = .false.
nullify(self % model_error)
deallocate(self % corelist % domainlist)
deallocate(self % corelist)
nullify(self % corelist)
nullify(self % domain_ptr)
end subroutine dyn_mpas_final