dyn_mpas_final Subroutine

private subroutine dyn_mpas_final(self)

Uses

    • mpas_atm_halos
    • mpas_log
    • mpas_atm_threading
    • mpas_timekeeping
    • mpas_pool_routines
    • mpas_framework
    • mpas_timer
    • mpas_decomp
    • mpas_field_routines
    • atm_time_integration
    • mpas_derived_types
  • proc~~dyn_mpas_final~~UsesGraph proc~dyn_mpas_final mpas_dynamical_core_type%dyn_mpas_final atm_time_integration atm_time_integration proc~dyn_mpas_final->atm_time_integration mpas_atm_halos mpas_atm_halos proc~dyn_mpas_final->mpas_atm_halos mpas_atm_threading mpas_atm_threading proc~dyn_mpas_final->mpas_atm_threading mpas_decomp mpas_decomp proc~dyn_mpas_final->mpas_decomp mpas_derived_types mpas_derived_types proc~dyn_mpas_final->mpas_derived_types mpas_field_routines mpas_field_routines proc~dyn_mpas_final->mpas_field_routines mpas_framework mpas_framework proc~dyn_mpas_final->mpas_framework mpas_log mpas_log proc~dyn_mpas_final->mpas_log mpas_pool_routines mpas_pool_routines proc~dyn_mpas_final->mpas_pool_routines mpas_timekeeping mpas_timekeeping proc~dyn_mpas_final->mpas_timekeeping mpas_timer mpas_timer proc~dyn_mpas_final->mpas_timer

This subroutine finalizes and cleans up MPAS dynamical core as well as its framework that was set up during initialization. Finalization happens in reverse chronological order. Essentially, it closely follows what is done in atm_core_finalize and mpas_finalize, except that here, there is no need to call MPAS diagnostics manager or MPAS stream manager. Ported and refactored for CAM-SIMA. (KCW, 2024-10-10)

Type Bound

mpas_dynamical_core_type

Arguments

Type IntentOptional Attributes Name
class(mpas_dynamical_core_type), intent(inout) :: self

Calls

proc~~dyn_mpas_final~~CallsGraph proc~dyn_mpas_final mpas_dynamical_core_type%dyn_mpas_final atm_destroy_halo_groups atm_destroy_halo_groups proc~dyn_mpas_final->atm_destroy_halo_groups mpas_atm_dynamics_finalize mpas_atm_dynamics_finalize proc~dyn_mpas_final->mpas_atm_dynamics_finalize mpas_atm_threading_finalize mpas_atm_threading_finalize proc~dyn_mpas_final->mpas_atm_threading_finalize mpas_deallocate_scratch_field mpas_deallocate_scratch_field proc~dyn_mpas_final->mpas_deallocate_scratch_field mpas_decomp_destroy_decomp_list mpas_decomp_destroy_decomp_list proc~dyn_mpas_final->mpas_decomp_destroy_decomp_list mpas_destroy_clock mpas_destroy_clock proc~dyn_mpas_final->mpas_destroy_clock mpas_framework_finalize mpas_framework_finalize proc~dyn_mpas_final->mpas_framework_finalize mpas_log_finalize mpas_log_finalize proc~dyn_mpas_final->mpas_log_finalize mpas_pool_get_field mpas_pool_get_field proc~dyn_mpas_final->mpas_pool_get_field mpas_timer_finalize mpas_timer_finalize proc~dyn_mpas_final->mpas_timer_finalize mpas_timer_write mpas_timer_write proc~dyn_mpas_final->mpas_timer_write mpas_timer_write_header mpas_timer_write_header proc~dyn_mpas_final->mpas_timer_write_header proc~dyn_mpas_debug_print mpas_dynamical_core_type%dyn_mpas_debug_print proc~dyn_mpas_final->proc~dyn_mpas_debug_print proc~stringify stringify proc~dyn_mpas_debug_print->proc~stringify

Variables

Type Visibility Attributes Name Initial
type(field2dreal), private, pointer :: field_2d_real
integer, private :: ierr
character(len=*), private, parameter :: subname = 'dyn_mpas_subdriver::dyn_mpas_final'

Source Code

    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