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

Register species from MICM #102

Merged
merged 18 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: build
on: [pull_request,workflow_dispatch]

jobs:
test_micm_api:
test_musica_api:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down
47 changes: 47 additions & 0 deletions doc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,52 @@
===============================================================

Tag name:
Originator(s): mattldawson
Date: 29 May 2024
One-line Summary: Add dynamic species from MICM
Github PR URL: https://github.com/ESCOMP/atmospheric_physics/pull/93

This PR fixes the following NCAR/atmospheric_physics Github issues: 74

Code reviewed by: cacraigucar, k20shores, boulderdaze, peverwhee, mwaxmonsky, nusbaume

List all existing files that have been added (A), modified (M), or deleted (D),
and describe the changes:

M .github/workflows/test.yaml
M doc/ChangeLog
M musica/micm/micm.F90
A musica/musica.F90
M musica/micm/micm.meta -> musica/musica.meta
M musica/micm/micm_namelist.xml -> musica/musica_namelist.xml
A musica/util.F90
M suite_musica.xml
M test/CMakeLists.txt
M test/cmake/SetDefaults.cmake
A test/cmake/TestUtils.cmake
M test/docker/Dockerfile.musica
M test/musica/micm/CMakeLists.txt -> test/musica/CMakeLists.txt
M test/musica/micm/configs/chapman/reactions.json
M test/musica/micm/configs/chapman/species.json
D test/musica/micm/test_micm_api.F90
A test/musica/musica_namelist.F90
A test/musica/test_musica_api.F90

Registers constituents and sets needed constituent properties from MICM configuration.

Additionally:

- returns error codes and messages from MUSICA functions using new error handling in MICM
- creates a musica_ccpp module to act as a the CCPP interface and moves existing functionality to a musica_ccpp_micm module in preparation for adding TUV-x (we will use musica_ccpp_ as a prefix for all the MUSICA modules in this repo to prevent naming conflicts with MUSICA Fortran library modules)
- updates build scripts for changes to MUSICA and CCPP framework
- adds memory checking to MUSICA tests

List and Describe any test failures: none

Summarize any changes to answers: none

===============================================================

Tag name: atmos_phys0_04_000
Originator(s): jet
Date: May 3, 2024
Expand Down
110 changes: 75 additions & 35 deletions musica/micm/micm.F90 → musica/micm/musica_ccpp_micm.F90
Original file line number Diff line number Diff line change
@@ -1,58 +1,100 @@
module micm
module musica_ccpp_micm
use iso_c_binding

! Note: "micm_core" is included in an external pre-built MICM library that the host
! model is responsible for linking to during compilation
use micm_core, only: micm_t
use musica_micm, only: micm_t
use musica_ccpp_util, only: has_error_occurred
use ccpp_kinds, only: kind_phys
use musica_ccpp_namelist, only: filename_of_micm_configuration

implicit none
private

public :: micm_init, micm_run, micm_final
private :: convert_to_mol_per_cubic_meter, convert_to_mass_mixing_ratio
public :: micm_register, micm_init, micm_run, micm_final

type(micm_t), pointer :: micm_obj
type(micm_t), pointer :: micm => null( )

contains

!> \section arg_table_micm_init Argument Table
!! \htmlinclude micm_init.html
subroutine micm_init(config_path, iulog, errcode, errmsg)
character(len=*), intent(in) :: config_path
integer, intent(in) :: iulog
integer, intent(out) :: errcode
!> Register MICM constituents with the CCPP
subroutine micm_register(constituents, errmsg, errcode)
use ccpp_constituent_prop_mod, only: ccpp_constituent_properties_t
use musica_util, only: error_t, mapping_t
type(ccpp_constituent_properties_t), allocatable, intent(out) :: constituents(:)
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errcode

type(error_t) :: error
type(mapping_t) :: mapping
real(kind=kind_phys) :: molar_mass
logical :: is_advected
integer :: i

errcode = 0
errmsg = ''

micm_obj => micm_t(config_path, errcode)
micm => micm_t(filename_of_micm_configuration, error)
if (has_error_occurred(error, errmsg, errcode)) return

allocate(constituents(size(micm%species_ordering)), stat=errcode)
if (errcode /= 0) then
errmsg = "[fatal] [micm] Failed to create MICM solver. Parsing configuration failed. &
Please look over at MICM log file for further information."
errmsg = "[MUSICA Error] Failed to allocate memory for constituents."
return
endif
end if

do i = 1, size(micm%species_ordering)
associate( map => micm%species_ordering(i) )
molar_mass = micm%get_species_property_double(map%name(), &
"molecular weight [kg mol-1]", &
error)
if (has_error_occurred(error, errmsg, errcode)) return
is_advected = micm%get_species_property_bool(map%name(), &
"__is advected", &
error)
if (has_error_occurred(error, errmsg, errcode)) return

call constituents(map%index())%instantiate( &
std_name = map%name(), &
long_name = map%name(), &
units = 'kg kg-1', &
vertical_dim = 'vertical_layer_dimension', &
default_value = 0.0_kind_phys, &
min_value = 0.0_kind_phys, &
molar_mass = molar_mass, &
advected = is_advected, &
errcode = errcode, &
errmsg = errmsg)
if (errcode /= 0) return
end associate ! map
end do

end subroutine micm_register

write(iulog,*) "[info] [micm] Created MICM solver."
!> Intitialize MICM
subroutine micm_init(errmsg, errcode)
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errcode

errcode = 0
errmsg = ''

end subroutine micm_init

!> \section arg_table_micm_run Argument Table
!! \htmlinclude micm_run.html
!> Solve chemistry at the current time step
subroutine micm_run(time_step, temperature, pressure, dry_air_density, constituent_props, &
constituents, iulog, errcode, errmsg)
constituents, errmsg, errcode)
use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t
use musica_util, only: error_t

real(kind_phys), intent(in) :: time_step ! s
real(kind_phys), intent(in) :: temperature(:,:) ! K
real(kind_phys), intent(in) :: pressure(:,:) ! Pa
real(kind_phys), intent(in) :: dry_air_density(:,:) ! kg m-3
type(ccpp_constituent_prop_ptr_t), intent(in) :: constituent_props(:)
real(kind_phys), intent(inout) :: constituents(:,:,:) ! kg kg-1
integer, intent(in) :: iulog
integer, intent(out) :: errcode
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errcode

! local variables
real(c_double) :: c_time_step
Expand All @@ -63,8 +105,12 @@ subroutine micm_run(time_step, temperature, pressure, dry_air_density, constitue
real(c_double), dimension(size(constituents, dim=1), &
size(constituents, dim=2), &
size(constituents, dim=3)) :: c_constituents
real(c_double), dimension(size(constituents, dim=1), &
size(constituents, dim=2), &
0) :: c_rate_params

real(kind_phys), dimension(size(constituents, dim=3)) :: molar_mass_arr ! kg mol-1
type(error_t) :: error

integer :: num_columns, num_layers, num_constituents
integer :: i_column, i_layer, i_elem
Expand Down Expand Up @@ -104,36 +150,30 @@ subroutine micm_run(time_step, temperature, pressure, dry_air_density, constitue
c_pressure = real(pressure, c_double)
c_constituents = real(constituents, c_double)

write(iulog,*) "[info] [micm] Running MICM solver..."

do i_column = 1, num_columns
do i_layer = 1, num_layers
call micm_obj%solve(c_temperature(i_column, i_layer), c_pressure(i_column, i_layer), &
c_time_step, num_constituents, c_constituents(i_column, i_layer, :))
call micm%solve(c_temperature(i_column, i_layer), c_pressure(i_column, i_layer), &
c_time_step, num_constituents, c_constituents(i_column, i_layer, :), &
0, c_rate_params(i_column, i_layer, :), error)
if (has_error_occurred(error, errmsg, errcode)) return
end do
end do

write(iulog,*) "[info] [micm] MICM solver has finished."

constituents = real(c_constituents, kind_phys)

! Convert MICM unit back to CAM-SIMA unit (mol m-3 -> kg kg-1)
call convert_to_mass_mixing_ratio(dry_air_density, molar_mass_arr, constituents)

end subroutine micm_run

!> \section arg_table_micm_final Argument Table
!! \htmlinclude micm_final.html
subroutine micm_final(iulog, errcode, errmsg)
integer, intent(in) :: iulog
integer, intent(out) :: errcode
!> Finalize MICM
subroutine micm_final(errmsg, errcode)
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errcode

errcode = 0
errmsg = ''

write(iulog,*) "[debug] [micm] Deallocating MICM object..."

end subroutine micm_final

! Convert CAM-SIMA unit to MICM unit (kg kg-1 -> mol m-3)
Expand Down Expand Up @@ -190,4 +230,4 @@ subroutine convert_to_mass_mixing_ratio(dry_air_density, molar_mass_arr, constit

end subroutine convert_to_mass_mixing_ratio

end module micm
end module musica_ccpp_micm
60 changes: 60 additions & 0 deletions musica/musica_ccpp.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
!> Top-level wrapper for MUSICA chemistry components
module musica_ccpp
use musica_ccpp_micm, only : micm_register, micm_init, micm_run, micm_final

implicit none
private

public :: musica_ccpp_register, musica_ccpp_init, musica_ccpp_run, musica_ccpp_final

contains

subroutine musica_ccpp_register(constituents, errmsg, errcode)
use ccpp_constituent_prop_mod, only : ccpp_constituent_properties_t
type(ccpp_constituent_properties_t), allocatable, intent(out) :: constituents(:)
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errcode

call micm_register(constituents, errmsg, errcode)
end subroutine musica_ccpp_register

!> \section arg_table_musica_ccpp_init Argument Table
!! \htmlinclude musica_ccpp_init.html
subroutine musica_ccpp_init(errmsg, errcode)
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errcode

call micm_init(errmsg, errcode)
end subroutine musica_ccpp_init

!> \section arg_table_musica_ccpp_run Argument Table
!! \htmlinclude musica_ccpp_run.html
subroutine musica_ccpp_run(time_step, temperature, pressure, dry_air_density, constituent_props, &
constituents, errmsg, errcode)
use ccpp_kinds, only: kind_phys
use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t

real(kind_phys), intent(in) :: time_step ! s
real(kind_phys), intent(in) :: temperature(:,:) ! K
real(kind_phys), intent(in) :: pressure(:,:) ! Pa
real(kind_phys), intent(in) :: dry_air_density(:,:) ! kg m-3
type(ccpp_constituent_prop_ptr_t), intent(in) :: constituent_props(:)
real(kind_phys), intent(inout) :: constituents(:,:,:) ! kg kg-1
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errcode

call micm_run(time_step, temperature, pressure, dry_air_density, constituent_props, &
constituents, errmsg, errcode)

end subroutine musica_ccpp_run

!> \section arg_table_musica_ccpp_final Argument Table
!! \htmlinclude musica_ccpp_final.html
subroutine musica_ccpp_final(errmsg, errcode)
integer, intent(out) :: errcode
character(len=512), intent(out) :: errmsg

call micm_final(errmsg, errcode)
end subroutine musica_ccpp_final

end module musica_ccpp
Loading