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

Add TUV-x height grid updates #134

Open
wants to merge 23 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4c269e4
update TUV-x height grid from host data
mattldawson Sep 4, 2024
e1fd505
Merge branch 'development' into develop-94-tuvx-height-grid
mattldawson Sep 4, 2024
beb5126
add missing newlines
mattldawson Sep 4, 2024
afbe013
add tuvx temperature function
boulderdaze Sep 11, 2024
778a65a
Merge remote-tracking branch 'remotes/matt/develop-94-tuvx-height-gri…
boulderdaze Sep 11, 2024
fc1e9c5
set temperature edges
boulderdaze Sep 11, 2024
6ea9c50
fix module name
boulderdaze Sep 12, 2024
9642bfa
fix temperature test
boulderdaze Sep 12, 2024
e0d6f83
rewrote comments
boulderdaze Sep 12, 2024
7851097
add test
boulderdaze Sep 23, 2024
3a71dc3
add metadata cmake test
boulderdaze Sep 26, 2024
99d6dea
correct metadata
boulderdaze Sep 26, 2024
e4119ea
add height grid from host and run TUV-x for photo rate calcs
mattldawson Oct 9, 2024
0ec84f1
update musica commit in tests
mattldawson Oct 9, 2024
2261760
Merge branch 'development' into develop-94-tuvx-height-grid
mattldawson Oct 9, 2024
45ef3b6
fix typo
mattldawson Oct 9, 2024
aafd074
Merge metadata check from branch '120-test-metadata' into develop-94-…
mattldawson Oct 10, 2024
4660749
update metadata and test build script
mattldawson Oct 10, 2024
fe44583
add conversion from geopotential height to regular height
mattldawson Oct 11, 2024
e8c6b61
code review
boulderdaze Oct 15, 2024
a29d7c0
fix valgrind errors
boulderdaze Oct 16, 2024
452f068
fix minor syntax errors
boulderdaze Oct 16, 2024
e3ec7b2
Merge branch 'development' into 94-tuvx-height-grid
boulderdaze Oct 17, 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
12 changes: 11 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,14 @@ jobs:
- name: build Docker image
run: docker build -t musica -f test/docker/Dockerfile.musica .
- name: run tests in container
run: docker run --name test-container -t musica bash -c 'make test ARGS="--rerun-failed --output-on-failure -j8"'
run: docker run --name test-container -t musica bash -c 'make test ARGS="--rerun-failed --output-on-failure -j8"'
test_musica_api_no_install:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: build Docker image
run: docker build -t musica-no-install -f test/docker/Dockerfile.musica.no_install .
- name: run tests in container
run: docker run --name test-container -t musica-no-install bash -c 'make test ARGS="--rerun-failed --output-on-failure -j8"'
52 changes: 28 additions & 24 deletions schemes/musica/micm/musica_ccpp_micm.F90
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,41 @@ subroutine micm_register(constituents, solver_type, num_grid_cells, errmsg, errc
integer, intent(out) :: errcode

! local variables
type(error_t) :: error
real(kind=kind_phys) :: molar_mass
logical :: is_advected
integer :: i
type(error_t) :: error
real(kind=kind_phys) :: molar_mass
character(len=:), allocatable :: species_name
logical :: is_advected
integer :: i, species_index

errcode = 0
errmsg = ''

micm => micm_t(filename_of_micm_configuration, solver_type, num_grid_cells, error)
if (has_error_occurred(error, errmsg, errcode)) return

allocate(constituents(size(micm%species_ordering)), stat=errcode)
allocate(constituents(micm%species_ordering%size()), stat=errcode)
if (errcode /= 0) then
errmsg = "[MUSICA Error] Failed to allocate memory for constituents."
return
end if

do i = 1, size(micm%species_ordering)
associate( map => micm%species_ordering(i) )
molar_mass = micm%get_species_property_double(map%name(), &
do i = 1, micm%species_ordering%size()
associate( map => micm%species_ordering )
species_name = map%name(i)
species_index = map%index(i)

molar_mass = micm%get_species_property_double(species_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)
is_advected = micm%get_species_property_bool(species_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(), &
call constituents(species_index)%instantiate( &
std_name = species_name, &
long_name = species_name, &
units = 'kg kg-1', &
vertical_dim = 'vertical_layer_dimension', &
default_value = 0.0_kind_phys, &
Expand All @@ -87,7 +91,7 @@ end subroutine micm_init

!> Solve chemistry at the current time step
subroutine micm_run(time_step, temperature, pressure, dry_air_density, constituents, &
rate_params, errmsg, errcode)
user_defined_rate_parameters, errmsg, errcode)
use musica_micm, only: solver_stats_t
use musica_util, only: string_t, error_t

Expand All @@ -96,7 +100,7 @@ subroutine micm_run(time_step, temperature, pressure, dry_air_density, constitue
real(c_double), target, intent(in) :: pressure(:) ! Pa
real(c_double), target, intent(in) :: dry_air_density(:) ! kg m-3
real(c_double), target, intent(inout) :: constituents(:) ! mol m-3
real(c_double), target, intent(inout) :: rate_params(:)
real(c_double), target, intent(in) :: user_defined_rate_parameters(:) ! various units
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errcode

Expand All @@ -111,14 +115,14 @@ subroutine micm_run(time_step, temperature, pressure, dry_air_density, constitue
errmsg = ''
c_time_step = real(time_step, c_double)

call micm%solve(c_time_step, &
temperature, &
pressure, &
dry_air_density, &
constituents, &
rate_params, &
solver_state, &
solver_stats, &
call micm%solve(c_time_step, &
temperature, &
pressure, &
dry_air_density, &
constituents, &
user_defined_rate_parameters, &
solver_state, &
solver_stats, &
error)
if (has_error_occurred(error, errmsg, errcode)) return

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module micm_util
module musica_ccpp_micm_util
implicit none

private
Expand All @@ -8,93 +8,67 @@ module micm_util
contains

subroutine reshape_into_micm_arr(temperature, pressure, dry_air_density, constituents, &
rate_params, m_temperature, m_pressure, m_dry_air_density, m_constituents, m_rate_params)
m_temperature, m_pressure, m_dry_air_density, m_constituents)
use iso_c_binding, only: c_double
use ccpp_kinds, only: kind_phys

real(kind_phys), target, intent(in) :: temperature(:,:) ! K
real(kind_phys), target, intent(in) :: pressure(:,:) ! Pa
real(kind_phys), target, intent(in) :: dry_air_density(:,:) ! kg m-3
real(kind_phys), target, intent(in) :: constituents(:,:,:) ! kg kg-1
real(kind_phys), target, intent(in) :: rate_params(:,:,:)
real(c_double), target, intent(out) :: m_temperature(:) ! K
real(c_double), target, intent(out) :: m_pressure(:) ! Pa
real(c_double), target, intent(out) :: m_dry_air_density(:) ! kg m-3
real(c_double), target, intent(out) :: m_constituents(:) ! kg kg-1
real(c_double), target, intent(out) :: m_rate_params(:)

! local variables
integer :: num_columns, num_layers
integer :: num_constituents, num_rate_params
integer :: i_column, i_layer, i_elem, i_constituents, i_rate_params
integer :: num_constituents
integer :: i_column, i_layer, i_elem, i_constituents

num_columns = size(constituents, dim=1)
num_layers = size(constituents, dim=2)
num_constituents = size(constituents, dim=3)
num_rate_params = size(rate_params, dim=3)

! Reshape into 1-D arry in species-column first order
! refers to: state.variables_[i_cell][i_species] = concentrations[i_species_elem++]
i_elem = 1
i_constituents = 1
i_rate_params = 1
do i_layer = 1, num_layers
do i_column = 1, num_columns
m_temperature(i_elem) = real(temperature(i_column, i_layer), c_double)
m_pressure(i_elem) = real(pressure(i_column, i_layer), c_double)
m_dry_air_density(i_elem) = real(dry_air_density(i_column, i_layer), c_double)
m_constituents(i_constituents : i_constituents + num_constituents - 1) &
= real(constituents(i_column, i_layer, :), c_double)
m_rate_params(i_rate_params : i_rate_params + num_rate_params - 1) &
= real(rate_params(i_column, i_layer, :), c_double)
i_elem = i_elem + 1
i_constituents = i_constituents + num_constituents
i_rate_params = i_rate_params + num_rate_params
end do
end do

end subroutine reshape_into_micm_arr

subroutine reshape_into_ccpp_arr(temperature, pressure, dry_air_density, constituents, &
rate_params, m_temperature, m_pressure, m_dry_air_density, m_constituents, m_rate_params)
subroutine reshape_into_ccpp_arr(constituents, m_constituents)
use iso_c_binding, only: c_double
use ccpp_kinds, only: kind_phys
real(kind_phys), intent(out) :: temperature(:,:) ! K
real(kind_phys), intent(out) :: pressure(:,:) ! Pa
real(kind_phys), intent(out) :: dry_air_density(:,:) ! kg m-3
real(kind_phys), intent(out) :: constituents(:,:,:) ! kg kg-1
real(kind_phys), intent(out) :: rate_params(:,:,:)
real(c_double), intent(in) :: m_temperature(:) ! K
real(c_double), intent(in) :: m_pressure(:) ! Pa
real(c_double), intent(in) :: m_dry_air_density(:) ! kg m-3
real(c_double), intent(in) :: m_constituents(:) ! kg kg-1
real(c_double), intent(in) :: m_rate_params(:)

! local variables
integer :: num_columns, num_layers
integer :: num_constituents, num_rate_params
integer :: i_column, i_layer, i_elem, i_constituents, i_rate_params
integer :: num_constituents
integer :: i_column, i_layer, i_constituents

num_columns = size(constituents, dim=1)
num_layers = size(constituents, dim=2)
num_constituents = size(constituents, dim=3)
Comment on lines 63 to 65
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we still do this when the intent of constituents is out?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe the intent can be inout to get the dimension?

real(kind_phys), intent(inout) :: constituents(:,:,:)  ! kg kg-1

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using intent(inout) should definitely work here, and is probably the safest bet.

Comment on lines 63 to 65
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
num_columns = size(constituents, dim=1)
num_layers = size(constituents, dim=2)
num_constituents = size(constituents, dim=3)
num_columns = size(micm_constituents, dim=1)
num_layers = size(micm_constituents, dim=2)
num_constituents = size(micm_constituents, dim=3)

Should it be this instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I found this possibly confusing. The function reshape_into_ccpp_arr() takes 1-D micm array and reshape it into 3-D CCPP array. It doesn't seem straightforward to get the dimension of CCPP array from micm array because this function does not want to know the number of columns and layers that are set when MCIM species are registered. (unless we want to do this way) I made CCPP array with intent(inout) instead of intent(out) solely to get the dimensions for the array. Any thoughts on this? I was also questioning about this.

!> Reshape array (1D -> 3D) and convert type (c_double -> kind_phys)
subroutine reshape_into_ccpp_arr(micm_constituents, constituents)

num_rate_params = size(rate_params, dim=3)

i_elem = 1
i_constituents = 1
i_rate_params = 1
do i_layer = 1, num_layers
do i_column = 1, num_columns
temperature(i_column, i_layer) = real(m_temperature(i_elem), kind_phys)
pressure(i_column, i_layer) = real(m_pressure(i_elem), kind_phys)
dry_air_density(i_column, i_layer) = real(m_dry_air_density(i_elem), kind_phys)
constituents(i_column, i_layer, :) &
= real(m_constituents(i_constituents : i_constituents + num_constituents - 1), kind_phys)
rate_params(i_column, i_layer, :) &
= real(m_rate_params(i_rate_params : i_rate_params + num_rate_params - 1), kind_phys)
i_elem = i_elem + 1
i_constituents = i_constituents + num_constituents
i_rate_params = i_rate_params + num_rate_params
end do
end do

Expand Down Expand Up @@ -156,4 +130,4 @@ subroutine convert_to_mass_mixing_ratio(dry_air_density, molar_mass_arr, constit

end subroutine convert_to_mass_mixing_ratio

end module micm_util
end module musica_ccpp_micm_util
58 changes: 37 additions & 21 deletions schemes/musica/musica_ccpp.F90
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,43 @@ end subroutine musica_ccpp_register

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

call tuvx_init(errmsg, errcode)
call tuvx_init(vertical_layer_dimension, vertical_interface_dimension, &
errmsg, errcode)
if (errcode /= 0) return
call micm_init(errmsg, errcode)
if (errcode /= 0) return

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, rate_params, height, errmsg, errcode)
use micm_util, only: reshape_into_micm_arr, reshape_into_ccpp_arr
use micm_util, only: convert_to_mol_per_cubic_meter, convert_to_mass_mixing_ratio
constituents, geopotential_height_wrt_surface_at_midpoint, &
geopotential_height_wrt_surface_at_interface, &
surface_geopotential, reciprocal_of_gravitational_acceleration, &
errmsg, errcode)
use musica_ccpp_micm_util, only: reshape_into_micm_arr, reshape_into_ccpp_arr
use musica_ccpp_micm_util, only: convert_to_mol_per_cubic_meter, convert_to_mass_mixing_ratio
use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t
use ccpp_kinds, only: kind_phys
use iso_c_binding, only: c_double
real(kind_phys), intent(inout) :: time_step ! s
real(kind_phys), target, intent(inout) :: temperature(:,:) ! K
real(kind_phys), target, intent(inout) :: pressure(:,:) ! Pa
real(kind_phys), target, intent(inout) :: dry_air_density(:,:) ! kg m-3
real(kind_phys), intent(in) :: time_step ! s
real(kind_phys), target, intent(in) :: temperature(:,:) ! K
real(kind_phys), target, intent(in) :: pressure(:,:) ! Pa
real(kind_phys), target, intent(in) :: dry_air_density(:,:) ! kg m-3
type(ccpp_constituent_prop_ptr_t), intent(in) :: constituent_props(:)
real(kind_phys), target, intent(inout) :: constituents(:,:,:) ! kg kg-1
real(kind_phys), target, intent(inout) :: rate_params(:,:,:)
real(kind_phys), target, intent(in) :: height(:,:) ! km
real(kind_phys), target, intent(inout) :: constituents(:,:,:) ! kg kg-1
real(kind_phys), target, intent(in) :: geopotential_height_wrt_surface_at_midpoint(:,:) ! m
real(kind_phys), target, intent(in) :: geopotential_height_wrt_surface_at_interface(:,:) ! m
real(kind_phys), target, intent(in) :: surface_geopotential(:) ! m2 s-2
real(kind_phys), target, intent(in) :: reciprocal_of_gravitational_acceleration ! s2 m-1
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errcode

Expand All @@ -64,13 +75,18 @@ subroutine musica_ccpp_run(time_step, temperature, pressure, dry_air_density, co
real(c_double), target, dimension(size(constituents, dim=1) &
* size(constituents, dim=2) &
* size(constituents, dim=3)) :: m_constituents ! mol m-3
real(c_double), target, dimension(size(rate_params, dim=1) &
* size(rate_params, dim=2) &
* size(rate_params, dim=3)) :: m_rate_params
real(kind_phys), target, dimension(size(constituents, dim=3)) :: molar_mass_arr ! kg mol-1

! temporarily dimensioned to Chapman mechanism until mapping between MICM and TUV-x is implemented
real(c_double), target, dimension(size(constituents, dim=1) &
* size(constituents, dim=2) &
* 3) :: photolysis_rate_constants ! s-1
integer :: i_elem

call tuvx_run(height, temperature, dry_air_density, errmsg, errcode)
call tuvx_run(temperature, dry_air_density, geopotential_height_wrt_surface_at_midpoint, &
geopotential_height_wrt_surface_at_interface, &
surface_geopotential, reciprocal_of_gravitational_acceleration, &
photolysis_rate_constants, errmsg, errcode)

! Get the molar_mass that is set in the call to instantiate()
do i_elem = 1, size(molar_mass_arr)
Expand All @@ -95,15 +111,15 @@ subroutine musica_ccpp_run(time_step, temperature, pressure, dry_air_density, co
call convert_to_mol_per_cubic_meter(dry_air_density, molar_mass_arr, constituents)

! Reshape array (3D -> 1D) and convert type (kind_phys -> c_double)
call reshape_into_micm_arr(temperature, pressure, dry_air_density, constituents, rate_params, &
m_temperature, m_pressure, m_dry_air_density, m_constituents, m_rate_params)
call reshape_into_micm_arr(temperature, pressure, dry_air_density, constituents, &
m_temperature, m_pressure, m_dry_air_density, m_constituents)

! temporarily pass in unmapped photolysis rate constants until mapping between MICM and TUV-x is implemented
call micm_run(time_step, m_temperature, m_pressure, m_dry_air_density, m_constituents, &
m_rate_params, errmsg, errcode)
photolysis_rate_constants, errmsg, errcode)

! Reshape array (1D -> 3D) and convert type (c_double -> kind_phys)
call reshape_into_ccpp_arr(temperature, pressure, dry_air_density, constituents, rate_params, &
m_temperature, m_pressure, m_dry_air_density, m_constituents, m_rate_params)
call reshape_into_ccpp_arr(constituents, m_constituents)

! 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)
Expand Down
38 changes: 37 additions & 1 deletion schemes/musica/musica_ccpp.meta
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
[ccpp-table-properties]
name = musica_ccpp
type = scheme
dependencies = micm/musica_ccpp_micm.F90,micm/musica_ccpp_tuvx.F90,musica_ccpp_util.F90
dependencies = micm/musica_ccpp_micm.F90,micm/musica_ccpp_micm_util.F90,tuvx/musica_ccpp_tuvx.F90,tuvx/musica_ccpp_tuvx_height_grid.F90,musica_ccpp_util.F90
dynamic_constituent_routine = musica_ccpp_register

[ccpp-arg-table]
name = musica_ccpp_init
type = scheme
[ vertical_layer_dimension ]
standard_name = vertical_layer_dimension
units = none
type = integer
dimensions = ()
intent = in
[ vertical_interface_dimension ]
standard_name = vertical_interface_dimension
units = none
type = integer
dimensions = ()
intent = in
[ errmsg ]
standard_name = ccpp_error_message
units = none
Expand Down Expand Up @@ -59,6 +71,30 @@
type = real | kind = kind_phys
dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_ccpp_constituents)
intent = inout
[ geopotential_height_wrt_surface_at_midpoint ]
standard_name = geopotential_height_wrt_surface
units = km
type = real | kind = kind_phys
dimensions = (horizontal_loop_extent,vertical_layer_dimension)
intent = in
[ geopotential_height_wrt_surface_at_interface ]
standard_name = geopotential_height_wrt_surface_at_interface
units = km
type = real | kind = kind_phys
dimensions = (horizontal_loop_extent,vertical_layer_dimension)
intent = in
[ surface_geopotential ]
standard_name = surface_geopotential
type = real | kind = kind_phys
units = m2 s-2
dimensions = (horizontal_loop_extent)
intent = in
[ reciprocal_of_gravitational_acceleration ]
standard_name = reciprocal_of_gravitational_acceleration
units = s2 m-1
type = real | kind = kind_phys
dimensions = ()
intent = in
[ errmsg ]
standard_name = ccpp_error_message
units = none
Expand Down
Loading