Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement namelist reading and early initialization of MPAS dynamical core #248

Merged
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d985991
Add XML namelist definition file for MPAS dynamical core
gdicker1 Jan 22, 2024
3b42c4f
Wire up XML namelist definition file in CAM config
kuanchihwang Jan 22, 2024
ef48506
Manually backport necessary subroutines to time manager for MPAS
kuanchihwang Feb 13, 2024
a217fdf
Start implementing MPAS subdriver
kuanchihwang Feb 13, 2024
3b27365
Implement `dyn_readnl`
kuanchihwang Feb 13, 2024
f9c6a1b
Build MPAS subdriver with upstream
kuanchihwang Feb 14, 2024
c348ea5
Build MPAS subdriver with upstream
kuanchihwang Feb 14, 2024
9494b82
Fix wrong prefix in XML namelist definition file
kuanchihwang Feb 15, 2024
363d782
Adjust indentation level
kuanchihwang Feb 15, 2024
5b90e51
Reword a comment
kuanchihwang Feb 21, 2024
7b4633b
Whitespace around construct
kuanchihwang Feb 21, 2024
5ef859f
Adjust indentation level
kuanchihwang Feb 21, 2024
ce9bc5f
Disable debug prints in release builds
kuanchihwang Feb 21, 2024
3eaeeb8
Default to MPI master rank for debug prints
kuanchihwang Feb 21, 2024
c4fda96
Move instantiation of MPAS dynamical core to `dyn_comp` module
kuanchihwang Feb 22, 2024
361d187
Use `DEBUG` macro instead
kuanchihwang Feb 27, 2024
8669b0e
Prefix `mpas_` to MPAS namelist groups to avoid naming collisions
kuanchihwang Feb 27, 2024
c58059b
Prefix `mpas_` to MPAS namelist groups to avoid naming collisions
kuanchihwang Feb 27, 2024
0e62d59
Change wording
kuanchihwang Feb 27, 2024
4a34799
Add more comments for `stringify` pure function
kuanchihwang Feb 27, 2024
c8e09ca
Add `stringify` pure function to `string_utils` module
kuanchihwang Feb 27, 2024
176e00b
Make debug output run-time configurable
kuanchihwang Feb 27, 2024
6e5d6ab
Add more comments for `dyn_readnl` subroutine
kuanchihwang Feb 28, 2024
4c0f612
Add more comments for XML namelist definition file
kuanchihwang Mar 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/dynamics/mpas/Makefile.in.CESM
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ all:
@echo ' `make libmpas-clean ESM="CESM" LIBROOT="..."`'

.PHONY: libmpas-prepare
libmpas-prepare: libmpas-archiver-script.txt libmpas-no-physics libmpas-preview
libmpas-prepare: libmpas-archiver-script.txt libmpas-no-physics libmpas-prefix-namelist-groups libmpas-preview

# Combine multiple static libraries into `libmpas.a` via archiver/MRI script. This requires GNU or GNU-like archiver (`ar`) program.
libmpas-archiver-script.txt:
Expand All @@ -79,6 +79,12 @@ libmpas-archiver-script.txt:
libmpas-no-physics:
@sed -E -i -e "s/^ *PHYSICS=.+$$/PHYSICS=/g" core_atmosphere/Makefile

# Prefix `mpas_` to MPAS namelist groups to avoid naming collisions.
.PHONY: libmpas-prefix-namelist-groups
libmpas-prefix-namelist-groups:
@sed -E -i -e "s/(^ *< *nml_record.+name=)\"(mpas_)?(\w+)\"/\1\"mpas_\3\"/g" core_atmosphere/Registry.xml
@sed -E -i -e "s/(^ *< *nml_record.+name=)\"(mpas_)?(\w+)\"/\1\"mpas_\3\"/g" core_atmosphere/diagnostics/Registry_*.xml

.PHONY: libmpas-preview
libmpas-preview:
@echo "Previewing build options for $(LIBROOT)/libmpas.a:"
Expand Down
18 changes: 12 additions & 6 deletions src/dynamics/mpas/driver/dyn_mpas_subdriver.F90
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ end subroutine model_error_if
type :: mpas_dynamical_core_type
private

logical, public :: debug_output = .false.

integer :: log_unit = output_unit
integer :: mpi_comm = mpi_comm_null
integer :: mpi_rank = 0
logical :: mpi_rank_master = .false.
logical :: mpi_rank_root = .false.

! Actual implementation is supplied at runtime.
procedure(model_error_if), nopass, pointer :: model_error => null()
Expand All @@ -61,21 +63,25 @@ end subroutine model_error_if
end type mpas_dynamical_core_type
contains
!> Print a debug message with optionally the value(s) of a variable.
!> If `printer` is not supplied, the MPI master rank will print. Otherwise, the designated MPI rank will print instead.
!> If `printer` is not supplied, the MPI root rank will print. Otherwise, the designated MPI rank will print instead.
!> (KCW, 2024-02-03)
subroutine dyn_mpas_debug_print(self, message, variable, printer)
class(mpas_dynamical_core_type), intent(in) :: self
character(*), intent(in) :: message
class(*), optional, intent(in) :: variable(:)
integer, optional, intent(in) :: printer

#ifdef DEBUG
! Bail out early if debug output is not requested.
if (.not. self % debug_output) then
return
end if

if (present(printer)) then
if (self % mpi_rank /= printer) then
return
end if
else
if (.not. self % mpi_rank_master) then
if (.not. self % mpi_rank_root) then
return
end if
end if
Expand All @@ -87,13 +93,13 @@ subroutine dyn_mpas_debug_print(self, message, variable, printer)
write(self % log_unit, '(a)') 'dyn_mpas_debug_print (' // stringify([self % mpi_rank]) // '): ' // &
message
end if
#endif
end subroutine dyn_mpas_debug_print

!> Convert one or more values of any intrinsic data types to a character string for pretty printing.
!> If `value` contains more than one element, the elements will be stringified, delimited by `separator`, then concatenated.
!> If `value` contains exactly one element, the element will be stringified without using `separator`.
!> If `value` contains zero element or is of unsupported data types, an empty character string is produced.
!> If `separator` is not supplied, it defaults to `, ` (i.e., a comma and a space).
!> (KCW, 2024-02-04)
pure function stringify(value, separator)
kuanchihwang marked this conversation as resolved.
Show resolved Hide resolved
use, intrinsic :: iso_fortran_env, only: int32, int64, real32, real64
Expand Down Expand Up @@ -226,7 +232,7 @@ subroutine dyn_mpas_init_phase1(self, mpi_comm, model_error_impl, log_unit, mpas
call self % model_error('Invalid MPI communicator group', subname, __LINE__)
end if

self % mpi_rank_master = (self % mpi_rank == 0)
self % mpi_rank_root = (self % mpi_rank == 0)
self % log_unit = log_unit

call self % debug_print(subname // ' entered')
Expand Down
11 changes: 10 additions & 1 deletion src/dynamics/mpas/dyn_comp.F90
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module dyn_comp
use cam_abortutils, only: endrun
use cam_control_mod, only: initial_run
use cam_instance, only: atm_id
use cam_logfile, only: iulog
use cam_logfile, only: debug_output, debugout_none, iulog
use runtime_obj, only: runtime_options
use spmd_utils, only: mpicom
use time_manager, only: get_start_date, get_stop_date, get_run_duration, timemgr_get_calendar_cf
Expand Down Expand Up @@ -55,10 +55,15 @@ subroutine dyn_readnl(namelist_path)
sec_since_midnight ! Second(s) since midnight.
type(iosystem_desc_t), pointer :: pio_iosystem => null()

! Enable/disable the debug output of MPAS dynamical core according to the debug verbosity level of CAM-SIMA.
mpas_dynamical_core % debug_output = (debug_output > debugout_none)

! Get free units for MPAS so it can write its own log files, e.g., `log.atmosphere.0000.{out,err}`.
log_unit(1) = shr_file_getunit()
log_unit(2) = shr_file_getunit()

! Initialize MPAS framework with supplied MPI communicator group and log units.
! See comment blocks in `src/dynamics/mpas/driver/dyn_mpas_subdriver.F90` for details.
call mpas_dynamical_core % init_phase1(mpicom, endrun, iulog, log_unit)
kuanchihwang marked this conversation as resolved.
Show resolved Hide resolved

cam_calendar = timemgr_get_calendar_cf()
Expand All @@ -72,11 +77,15 @@ subroutine dyn_readnl(namelist_path)
call get_run_duration(run_duration(1), sec_since_midnight)
run_duration(2:4) = sec_to_hour_min_sec(sec_since_midnight)

! Read MPAS-related namelist variables from `namelist_path`, e.g., `atm_in`.
! See comment blocks in `src/dynamics/mpas/driver/dyn_mpas_subdriver.F90` for details.
call mpas_dynamical_core % read_namelist(namelist_path, &
cam_calendar, start_date_time, stop_date_time, run_duration, initial_run)

pio_iosystem => shr_pio_getiosys(atm_id)

! Initialize MPAS framework with supplied PIO system descriptor.
! See comment blocks in `src/dynamics/mpas/driver/dyn_mpas_subdriver.F90` for details.
call mpas_dynamical_core % init_phase2(pio_iosystem)
kuanchihwang marked this conversation as resolved.
Show resolved Hide resolved

nullify(pio_iosystem)
kuanchihwang marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Loading
Loading