diff --git a/musica/micm/micm_util.F90 b/musica/micm/micm_util.F90 new file mode 100644 index 0000000..3272ee9 --- /dev/null +++ b/musica/micm/micm_util.F90 @@ -0,0 +1,159 @@ +module micm_util + implicit none + + private + public :: reshape_into_micm_arr, reshape_into_ccpp_arr, convert_to_mol_per_cubic_meter, & + convert_to_mass_mixing_ratio + +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) + 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 + + 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) + 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 + + 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) + + 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 + + end subroutine reshape_into_ccpp_arr + + ! Convert CAM-SIMA unit to MICM unit (kg kg-1 -> mol m-3) + subroutine convert_to_mol_per_cubic_meter(dry_air_density, molar_mass_arr, constituents) + use ccpp_kinds, only: kind_phys + + real(kind_phys), intent(in) :: dry_air_density(:,:) ! kg m-3 + real(kind_phys), intent(in) :: molar_mass_arr(:) ! kg mol-1 + real(kind_phys), intent(inout) :: constituents(:,:,:) ! in: kg kg-1 | out: mol m-3 + + integer :: num_columns, num_layers, num_constituents + integer :: i_column, i_layer, i_elem + real(kind_phys) :: val + + num_columns = size(constituents, dim=1) + num_layers = size(constituents, dim=2) + num_constituents = size(constituents, dim=3) + + do i_elem = 1, num_constituents + do i_layer = 1, num_layers + do i_column = 1, num_columns + val = constituents(i_column, i_layer, i_elem) * dry_air_density(i_column, i_layer) & + / molar_mass_arr(i_elem) + constituents(i_column, i_layer, i_elem) = val + end do + end do + end do + + end subroutine convert_to_mol_per_cubic_meter + + ! Convert MICM unit to CAM-SIMA unit (mol m-3 -> kg kg-1) + subroutine convert_to_mass_mixing_ratio(dry_air_density, molar_mass_arr, constituents) + use ccpp_kinds, only: kind_phys + + real(kind_phys), intent(in) :: dry_air_density(:,:) ! kg m-3 + real(kind_phys), intent(in) :: molar_mass_arr(:) ! kg mol-1 + real(kind_phys), intent(inout) :: constituents(:,:,:) ! in: mol m-3 | out: kg kg-1 + + integer :: num_columns, num_layers, num_constituents + integer :: i_column, i_layer, i_elem + real(kind_phys) :: val + + num_columns = size(constituents, dim=1) + num_layers = size(constituents, dim=2) + num_constituents = size(constituents, dim=3) + + do i_elem = 1, num_constituents + do i_layer = 1, num_layers + do i_column = 1, num_columns + val = constituents(i_column, i_layer, i_elem) / dry_air_density(i_column, i_layer) & + * molar_mass_arr(i_elem) + constituents(i_column, i_layer, i_elem) = val + end do + end do + end do + + end subroutine convert_to_mass_mixing_ratio + +end module micm_util \ No newline at end of file diff --git a/musica/micm/musica_ccpp_micm.F90 b/musica/micm/musica_ccpp_micm.F90 index 88aa7f3..d11e86d 100644 --- a/musica/micm/musica_ccpp_micm.F90 +++ b/musica/micm/musica_ccpp_micm.F90 @@ -1,12 +1,12 @@ module musica_ccpp_micm use iso_c_binding - ! Note: "micm_core" is included in an external pre-built MICM library that the host + ! Note: "micm_t" is included in an external pre-built MICM library that the host ! model is responsible for linking to during compilation - use musica_micm, only: micm_t - use musica_ccpp_util, only: has_error_occurred - use ccpp_kinds, only: kind_phys + use musica_micm, only: micm_t + use musica_ccpp_util, only: has_error_occurred use musica_ccpp_namelist, only: filename_of_micm_configuration + use ccpp_kinds, only: kind_phys implicit none private @@ -18,23 +18,27 @@ module musica_ccpp_micm contains !> Register MICM constituents with the CCPP - subroutine micm_register(constituents, errmsg, errcode) + subroutine micm_register(constituents, solver_type, num_grid_cells, 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 + use musica_micm, only: Rosenbrock, RosenbrockStandardOrder + use musica_util, only: error_t + + type(ccpp_constituent_properties_t), allocatable, intent(out) :: constituents(:) + integer(c_int), intent(in) :: solver_type + integer(c_int), intent(in) :: num_grid_cells + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errcode - type(error_t) :: error - type(mapping_t) :: mapping + ! local variables + type(error_t) :: error real(kind=kind_phys) :: molar_mass - logical :: is_advected - integer :: i + logical :: is_advected + integer :: i errcode = 0 errmsg = '' - micm => micm_t(filename_of_micm_configuration, error) + 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) @@ -82,87 +86,41 @@ subroutine micm_init(errmsg, errcode) end subroutine micm_init !> Solve chemistry at the current time step - subroutine micm_run(time_step, temperature, pressure, dry_air_density, constituent_props, & - 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 - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errcode + subroutine micm_run(time_step, temperature, pressure, dry_air_density, constituents, & + rate_params, errmsg, errcode) + use musica_micm, only: solver_stats_t + use musica_util, only: string_t, error_t + + real(kind_phys), intent(in) :: time_step ! s + real(c_double), target, intent(in) :: temperature(:) ! K + 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(:) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errcode ! local variables - real(c_double) :: c_time_step - real(c_double), dimension(size(temperature, dim=1), & - size(temperature, dim=2)) :: c_temperature - real(c_double), dimension(size(pressure, dim=1), & - size(pressure, dim=2)) :: c_pressure - 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 - - num_columns = size(constituents, dim=1) - num_layers = size(constituents, dim=2) - num_constituents = size(constituents, dim=3) + type(string_t) :: solver_state + type(solver_stats_t) :: solver_stats + type(error_t) :: error + real(c_double) :: c_time_step + integer :: i_elem errcode = 0 errmsg = '' - - ! Get the molar_mass that is set in the call to instantiate() - do i_elem = 1, num_constituents - call constituent_props(i_elem)%molar_mass(molar_mass_arr(i_elem), errcode, errmsg) - - if (errcode /= 0) then - errmsg = "[error] [micm] Unable to get molar mass." - return - end if - end do - - ! TODO(jiwon) Check molar mass is non zero as it becomes a denominator for unit converison - ! this code needs to go when ccpp framework does the check - do i_elem = 1, num_constituents - if (molar_mass_arr(i_elem) == 0) then - errcode = 1 - errmsg = "[error] [micm] Molar mass must be a non zero value." - return - end if - end do - - ! Convert CAM-SIMA unit to MICM unit (kg kg-1 -> mol m-3) - call convert_to_mol_per_cubic_meter(dry_air_density, molar_mass_arr, constituents) - - c_time_step = real(time_step, c_double) - c_temperature = real(temperature, c_double) - c_pressure = real(pressure, c_double) - c_constituents = real(constituents, c_double) - - do i_column = 1, num_columns - do i_layer = 1, num_layers - 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 - - 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) + 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, & + error) + if (has_error_occurred(error, errmsg, errcode)) return end subroutine micm_run @@ -176,58 +134,4 @@ subroutine micm_final(errmsg, errcode) end subroutine micm_final - ! Convert CAM-SIMA unit to MICM unit (kg kg-1 -> mol m-3) - subroutine convert_to_mol_per_cubic_meter(dry_air_density, molar_mass_arr, constituents) - real(kind_phys), intent(in) :: dry_air_density(:,:) ! kg m-3 - real(kind_phys), intent(in) :: molar_mass_arr(:) ! kg mol-1 - real(kind_phys), intent(inout) :: constituents(:,:,:) ! in: kg kg-1 | out: mol m-3 - - integer :: num_columns, num_layers, num_constituents - integer :: i_column, i_layer, i_elem - - real(kind_phys) :: val - - num_columns = size(constituents, dim=1) - num_layers = size(constituents, dim=2) - num_constituents = size(constituents, dim=3) - - do i_column = 1, num_columns - do i_layer = 1, num_layers - do i_elem = 1, num_constituents - val = constituents(i_column, i_layer, i_elem) * dry_air_density(i_column, i_layer) & - / molar_mass_arr(i_elem) - constituents(i_column, i_layer, i_elem) = val - end do - end do - end do - - end subroutine convert_to_mol_per_cubic_meter - - ! Convert MICM unit to CAM-SIMA unit (mol m-3 -> kg kg-1) - subroutine convert_to_mass_mixing_ratio(dry_air_density, molar_mass_arr, constituents) - real(kind_phys), intent(in) :: dry_air_density(:,:) ! kg m-3 - real(kind_phys), intent(in) :: molar_mass_arr(:) ! kg mol-1 - real(kind_phys), intent(inout) :: constituents(:,:,:) ! in: mol m-3 | out: kg kg-1 - - integer :: num_columns, num_layers, num_constituents - integer :: i_column, i_layer, i_elem - - real(kind_phys) :: val - - num_columns = size(constituents, dim=1) - num_layers = size(constituents, dim=2) - num_constituents = size(constituents, dim=3) - - do i_column = 1, num_columns - do i_layer = 1, num_layers - do i_elem = 1, num_constituents - val = constituents(i_column, i_layer, i_elem) / dry_air_density(i_column, i_layer) & - * molar_mass_arr(i_elem) - constituents(i_column, i_layer, i_elem) = val - end do - end do - end do - - end subroutine convert_to_mass_mixing_ratio - end module musica_ccpp_micm diff --git a/musica/musica_ccpp.F90 b/musica/musica_ccpp.F90 index 9b5ae53..bf4fae3 100644 --- a/musica/musica_ccpp.F90 +++ b/musica/musica_ccpp.F90 @@ -1,6 +1,7 @@ !> Top-level wrapper for MUSICA chemistry components module musica_ccpp use musica_ccpp_micm, only : micm_register, micm_init, micm_run, micm_final + use musica_ccpp_tuvx, only : tuvx_init, tuvx_run, tuvx_final implicit none private @@ -9,52 +10,115 @@ module musica_ccpp contains - subroutine musica_ccpp_register(constituents, errmsg, errcode) - use ccpp_constituent_prop_mod, only : ccpp_constituent_properties_t + subroutine musica_ccpp_register(constituents, solver_type, num_grid_cells, 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 + integer, intent(in) :: solver_type + integer, intent(in) :: num_grid_cells + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errcode + + call micm_register(constituents, solver_type, num_grid_cells, errmsg, 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 + integer, intent(out) :: errcode + call tuvx_init(errmsg, 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 + 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 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 + 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 type(ccpp_constituent_prop_ptr_t), intent(in) :: constituent_props(:) - real(kind_phys), intent(inout) :: constituents(:,:,:) ! kg kg-1 + 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 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) + ! local variables + real(c_double), target, dimension(size(temperature, dim=1) & + * size(temperature, dim=2)) :: m_temperature + real(c_double), target, dimension(size(pressure, dim=1) & + * size(pressure, dim=2)) :: m_pressure + real(c_double), target, dimension(size(dry_air_density, dim=1) & + * size(dry_air_density, dim=2)) :: m_dry_air_density + 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 + integer :: i_elem + + call tuvx_run(height, temperature, dry_air_density, errmsg, errcode) + + ! Get the molar_mass that is set in the call to instantiate() + do i_elem = 1, size(molar_mass_arr) + call constituent_props(i_elem)%molar_mass(molar_mass_arr(i_elem), errcode, errmsg) + if (errcode /= 0) then + errmsg = "[MUSICA Error] Unable to get molar mass." + return + end if + end do + + ! TODO(jiwon) Check molar mass is non zero as it becomes a denominator for unit converison + ! this code needs to go when ccpp framework does the check + do i_elem = 1, size(molar_mass_arr) + if (molar_mass_arr(i_elem) <= 0) then + errcode = 1 + errmsg = "[MUSICA Error] Molar mass must be greater than zero." + return + end if + end do + + ! Convert CAM-SIMA unit to MICM unit (kg kg-1 -> mol m-3) + 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 micm_run(time_step, m_temperature, m_pressure, m_dry_air_density, m_constituents, & + m_rate_params, 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) + + ! 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 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 + integer, intent(out) :: errcode character(len=512), intent(out) :: errmsg + call tuvx_final(errmsg, errcode) call micm_final(errmsg, errcode) + end subroutine musica_ccpp_final end module musica_ccpp diff --git a/musica/musica_ccpp.meta b/musica/musica_ccpp.meta index 5b2fa0e..30b7c7c 100644 --- a/musica/musica_ccpp.meta +++ b/musica/musica_ccpp.meta @@ -1,7 +1,7 @@ [ccpp-table-properties] name = musica_ccpp type = scheme - dependencies = micm/musica_ccpp_micm.F90,musica_ccpp_util.F90 + dependencies = micm/musica_ccpp_micm.F90,micm/musica_ccpp_tuvx.F90,musica_ccpp_util.F90 dynamic_constituent_routine = musica_ccpp_register [ccpp-arg-table] diff --git a/musica/musica_ccpp_namelist.xml b/musica/musica_ccpp_namelist.xml index 398efb4..9ab6b13 100644 --- a/musica/musica_ccpp_namelist.xml +++ b/musica/musica_ccpp_namelist.xml @@ -90,5 +90,18 @@ UNSET_PATH + + char*512 + musica_ccpp + musica_ccpp + filename_of_tuvx_configuration + none + + A configuration file for the TUVX photolysis rate calculator + + + UNSET_PATH + + diff --git a/musica/tuvx/musica_ccpp_tuvx.F90 b/musica/tuvx/musica_ccpp_tuvx.F90 new file mode 100644 index 0000000..2413a47 --- /dev/null +++ b/musica/tuvx/musica_ccpp_tuvx.F90 @@ -0,0 +1,84 @@ +module musica_ccpp_tuvx + use iso_c_binding + + ! Note: "tuvx_t" is included in an external pre-built tuvx library that the host + ! model is responsible for linking to during compilation + use musica_tuvx, only: tuvx_t + use musica_ccpp_util, only: has_error_occurred + use ccpp_kinds, only: kind_phys + use musica_ccpp_namelist, only: filename_of_tuvx_configuration + + implicit none + private + + public :: tuvx_init, tuvx_run, tuvx_final + + type(tuvx_t), pointer :: tuvx => null( ) + +contains + + !> Intitialize TUVX + subroutine tuvx_init(errmsg, errcode) + use musica_tuvx, only: grid_map_t, profile_map_t, radiator_map_t + use musica_util, only: error_t, mapping_t + + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errcode + + ! local variables + type(grid_map_t), pointer :: grids + type(profile_map_t), pointer :: profiles + type(radiator_map_t), pointer :: radiators + type(error_t) :: error + + errcode = 0 + errmsg = '' + + grids => grid_map_t( error ) + if (has_error_occurred(error, errmsg, errcode)) return + + profiles => profile_map_t( error ) + if (has_error_occurred(error, errmsg, errcode)) return + + radiators =>radiator_map_t( error ) + if (has_error_occurred(error, errmsg, errcode)) return + + tuvx => tuvx_t( filename_of_tuvx_configuration, error ) + if (has_error_occurred(error, errmsg, errcode)) return + + deallocate( grids ) + deallocate( profiles ) + deallocate( radiators ) + deallocate( tuvx ) + + end subroutine tuvx_init + + !> Calculates photolysis rate constants for the current model conditions + subroutine tuvx_run( height, temperature, dry_air_density, errmsg, errcode ) + use musica_util, only: error_t + + real(kind_phys), intent(in) :: height(:,:) ! km (layer, column) + real(kind_phys), intent(in) :: temperature(:,:) ! K (layer, column) + real(kind_phys), intent(in) :: dry_air_density(:,:) ! molecule cm-3 (layer, column) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errcode + + ! local variables + type(error_t) :: error + + errcode = 0 + errmsg = '' + + end subroutine tuvx_run + + !> Finalize tuvx + subroutine tuvx_final(errmsg, errcode) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errcode + + errcode = 0 + errmsg = '' + + end subroutine tuvx_final + +end module musica_ccpp_tuvx \ No newline at end of file diff --git a/test/docker/Dockerfile.musica b/test/docker/Dockerfile.musica index 7b6f49f..2ad24b7 100644 --- a/test/docker/Dockerfile.musica +++ b/test/docker/Dockerfile.musica @@ -1,5 +1,7 @@ FROM ubuntu:22.04 +ARG MUSICA_GIT_TAG=aa0854ecee54bd7a5aeb7ea1ba0eebb2cf656146 + RUN apt update \ && apt install -y sudo \ && adduser test_user \ @@ -43,9 +45,10 @@ ENV FFLAGS="-I/usr/include/" # Install MUSICA (MUSICA-C) RUN git clone https://github.com/NCAR/musica.git + RUN cd musica \ && git fetch \ - && git checkout 2a5eeaac982a3eb80b96d1e2087b91b301d1e748 \ + && git checkout ${MUSICA_GIT_TAG} \ && cmake \ -S . \ -B build \ @@ -73,7 +76,10 @@ RUN cd atmospheric_physics/test \ -D CCPP_ENABLE_MEMCHECK=ON \ && cmake --build ./build -RUN cd atmospheric_physics \ - && cp -r test/musica/micm/configs/chapman ./test/build/chapman +RUN cd atmospheric_physics/test \ + && mkdir third_party \ + && cd third_party \ + && git clone --depth 1 https://github.com/NCAR/tuv-x.git \ + && cp -r tuv-x/data ../build/data -WORKDIR /home/test_user/atmospheric_physics/test/build +WORKDIR /home/test_user/atmospheric_physics/test/build \ No newline at end of file diff --git a/test/musica/CMakeLists.txt b/test/musica/CMakeLists.txt index fea776b..3fcdd84 100644 --- a/test/musica/CMakeLists.txt +++ b/test/musica/CMakeLists.txt @@ -3,8 +3,7 @@ include(TestUtils) FetchContent_Declare(musica GIT_REPOSITORY https://github.com/NCAR/musica.git -# GIT_TAG v0.6.1 - GIT_TAG 2a5eeaac982a3eb80b96d1e2087b91b301d1e748 + GIT_TAG $ENV{MUSICA_GIT_TAG} # Set by docker ) set(MUSICA_BUILD_C_CXX_INTERFACE OFF) @@ -23,6 +22,8 @@ add_executable(test_musica_api test_musica_api.F90 musica_ccpp_namelist.F90) target_sources(test_musica_api PUBLIC ${MUSICA_SRC_PATH}/micm/musica_ccpp_micm.F90 + ${MUSICA_SRC_PATH}/micm/micm_util.F90 + ${MUSICA_SRC_PATH}/tuvx/musica_ccpp_tuvx.F90 ${MUSICA_SRC_PATH}/musica_ccpp.F90 ${MUSICA_SRC_PATH}/musica_ccpp_util.F90 ${CCPP_SRC_PATH}/ccpp_constituent_prop_mod.F90 @@ -51,3 +52,15 @@ add_test( ) add_memory_check_test(test_musica_api $ "" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + +add_custom_target( + copy_micm_configs ALL ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/micm/configs/chapman ${CMAKE_BINARY_DIR}/chapman +) + +add_custom_target( + copy_tuvx_configs ALL ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/tuvx/configs ${CMAKE_BINARY_DIR}/configs +) + +add_subdirectory(micm) \ No newline at end of file diff --git a/test/musica/micm/CMakeLists.txt b/test/musica/micm/CMakeLists.txt new file mode 100644 index 0000000..d239da2 --- /dev/null +++ b/test/musica/micm/CMakeLists.txt @@ -0,0 +1,26 @@ + +add_executable(test_micm_util test_micm_util.F90) + +target_sources(test_micm_util + PUBLIC + ${MUSICA_SRC_PATH}/micm/micm_util.F90 + ${CCPP_TEST_SRC_PATH}/ccpp_kinds.F90 +) + +target_link_libraries(test_micm_util + PRIVATE + musica::musica-fortran +) + +set_target_properties(test_micm_util + PROPERTIES + LINKER_LANGUAGE Fortran +) + +add_test( + NAME test_micm_util + COMMAND $ + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} +) + +add_memory_check_test(test_micm_util $ "" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) \ No newline at end of file diff --git a/test/musica/micm/configs/chapman/reactions.json b/test/musica/micm/configs/chapman/reactions.json index f37fd20..32af898 100644 --- a/test/musica/micm/configs/chapman/reactions.json +++ b/test/musica/micm/configs/chapman/reactions.json @@ -14,7 +14,7 @@ "yield": 2.0 } }, - "MUSICA name": "R1" + "MUSICA name": "jO2" }, { "type": "ARRHENIUS", @@ -37,7 +37,7 @@ "O": {}, "O2": {} }, - "MUSICA name": "R3" + "MUSICA name": "jO3->O" }, { "type": "ARRHENIUS", @@ -62,7 +62,7 @@ "O1D": {}, "O2": {} }, - "MUSICA name": "R5" + "MUSICA name": "jO3->O1D" }, { "type": "ARRHENIUS", @@ -94,4 +94,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/test/musica/micm/configs/chapman/species.json b/test/musica/micm/configs/chapman/species.json index 07d77d2..aa2c2dc 100644 --- a/test/musica/micm/configs/chapman/species.json +++ b/test/musica/micm/configs/chapman/species.json @@ -3,7 +3,7 @@ { "name": "M", "type": "CHEM_SPEC", - "tracer type": "CONSTANT", + "tracer type": "THIRD_BODY", "molecular weight [kg mol-1]": 0.029, "__is advected": false }, diff --git a/test/musica/micm/test_micm_util.F90 b/test/musica/micm/test_micm_util.F90 new file mode 100644 index 0000000..76f2c13 --- /dev/null +++ b/test/musica/micm/test_micm_util.F90 @@ -0,0 +1,168 @@ +program test_micm_util + + use iso_c_binding + use micm_util + use ccpp_kinds, only: kind_phys + + implicit none + +#define ASSERT(x) if (.not.(x)) then; write(*,*) "Assertion failed[", __FILE__, ":", __LINE__, "]: x"; stop 1; endif +#define ASSERT_NEAR( a, b, abs_error ) if( (abs(a - b) >= abs_error) .and. (abs(a - b) /= 0.0) ) then; write(*,*) "Assertion failed[", __FILE__, ":", __LINE__, "]: a, b"; stop 1; endif + + call test_reshape() + call test_unit_conversion() + + +contains + + subroutine test_reshape() + use iso_c_binding, only: c_double + use ccpp_kinds, only: kind_phys + + integer, parameter :: NUM_SPECIES = 4 + integer, parameter :: NUM_RATES = 3 + integer, parameter :: NUM_COLUMNS = 2 + integer, parameter :: NUM_LAYERS = 2 + integer, parameter :: NUM_GRID_CELLS = 4 + real(kind_phys), target :: temperature(NUM_COLUMNS,NUM_LAYERS) + real(kind_phys), target :: pressure(NUM_COLUMNS,NUM_LAYERS) + real(kind_phys), target :: dry_air_density(NUM_COLUMNS,NUM_LAYERS) + real(kind_phys), target :: constituents(NUM_COLUMNS,NUM_LAYERS,NUM_SPECIES) + real(kind_phys), target :: rate_params(NUM_COLUMNS,NUM_LAYERS,NUM_RATES) + real(c_double), target :: m_temperature(NUM_GRID_CELLS) + real(c_double), target :: m_pressure(NUM_GRID_CELLS) + real(c_double), target :: m_dry_air_density(NUM_GRID_CELLS) + real(c_double), target :: m_constituents(NUM_GRID_CELLS*NUM_SPECIES) + real(c_double), target :: m_rate_params(NUM_GRID_CELLS*NUM_RATES) + + ! local variables + real(c_double), dimension(NUM_GRID_CELLS) :: arr_conditions + real(c_double), dimension(NUM_GRID_CELLS*NUM_SPECIES) :: arr_constituents + real(c_double), dimension(NUM_GRID_CELLS*NUM_RATES) :: arr_rates + integer :: i_column, i_layer, i_elem, i_arr + real :: abs_error = 1e-7 + + temperature(:,1) = (/ 100._kind_phys, 200._kind_phys /) + temperature(:,2) = (/ 300._kind_phys, 400._kind_phys /) + pressure(:,1) = (/ 100._kind_phys, 200._kind_phys /) + pressure(:,2) = (/ 300._kind_phys, 400._kind_phys /) + dry_air_density(:,1) = (/ 100._kind_phys, 200._kind_phys /) + dry_air_density(:,2) = (/ 300._kind_phys, 400._kind_phys /) + constituents(1,1,:) = (/ 0.1_kind_phys, 0.2_kind_phys, 0.3_kind_phys, 0.4_kind_phys /) + constituents(1,2,:) = (/ 0.41_kind_phys, 0.42_kind_phys, 0.43_kind_phys, 0.44_kind_phys /) + constituents(2,1,:) = (/ 0.21_kind_phys, 0.22_kind_phys, 0.23_kind_phys, 0.24_kind_phys /) + constituents(2,2,:) = (/ 0.31_kind_phys, 0.32_kind_phys, 0.33_kind_phys, 0.34_kind_phys /) + rate_params(1,1,:) = (/ 100._kind_phys, 200._kind_phys, 300._kind_phys /) + rate_params(1,2,:) = (/ 400._kind_phys, 500._kind_phys, 600._kind_phys /) + rate_params(2,1,:) = (/ 700._kind_phys, 800._kind_phys, 900._kind_phys /) + rate_params(2,2,:) = (/ 1000._kind_phys, 1100._kind_phys, 1200._kind_phys /) + + arr_conditions = (/ 100.0, 200.0, 300.0, 400.0 /) + arr_constituents = (/ 0.1, 0.2, 0.3, 0.4, 0.21, 0.22, 0.23, 0.24, 0.41, 0.42, 0.43, 0.44, 0.31, 0.32, 0.33, 0.34 /) + arr_rates = (/ 100., 200., 300., 700., 800., 900., 400., 500., 600., 1000., 1100., 1200. /) + + 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) + + do i_elem = 1, NUM_GRID_CELLS + ASSERT(m_temperature(i_elem) == arr_conditions(i_elem)) + ASSERT(m_pressure(i_elem) == arr_conditions(i_elem)) + ASSERT(m_dry_air_density(i_elem) == arr_conditions(i_elem)) + end do + + do i_elem = 1, size(m_constituents) + ASSERT_NEAR(m_constituents(i_elem), arr_constituents(i_elem), abs_error) + end do + + do i_elem = 1, size(m_rate_params) + ASSERT_NEAR(m_rate_params(i_elem), arr_rates(i_elem), abs_error) + end do + + 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) + + i_elem = 1 + do i_layer = 1, NUM_LAYERS + do i_column = 1, NUM_COLUMNS + ASSERT(temperature(i_column, i_layer) == arr_conditions(i_elem)) + ASSERT(pressure(i_column, i_layer) == arr_conditions(i_elem)) + ASSERT(dry_air_density(i_column, i_layer) == arr_conditions(i_elem)) + i_elem = i_elem + 1 + end do + end do + + i_arr = 1 + do i_layer = 1, NUM_LAYERS + do i_column = 1, NUM_COLUMNS + do i_elem = 1, NUM_SPECIES + ASSERT_NEAR(constituents(i_column, i_layer, i_elem), arr_constituents(i_arr), abs_error) + i_arr = i_arr + 1 + end do + end do + end do + + i_arr = 1 + do i_layer = 1, NUM_LAYERS + do i_column = 1, NUM_COLUMNS + do i_elem = 1, NUM_RATES + ASSERT_NEAR(rate_params(i_column, i_layer, i_elem), arr_rates(i_arr), abs_error) + i_arr = i_arr + 1 + end do + end do + end do + + end subroutine test_reshape + + subroutine test_unit_conversion() + use ccpp_kinds, only: kind_phys + + integer, parameter :: NUM_COLUMNS = 2 + integer, parameter :: NUM_LAYERS = 2 + integer, parameter :: NUM_SPECIES = 4 + real(kind_phys), target, dimension(NUM_COLUMNS,NUM_LAYERS) :: dry_air_density ! kg m-3 + real(kind_phys), target, dimension(NUM_SPECIES) :: molar_mass_arr + real(kind_phys), target, dimension(NUM_COLUMNS,NUM_LAYERS,NUM_SPECIES) :: constituents ! kg kg-1 + real(kind_phys), target, dimension(NUM_COLUMNS,NUM_LAYERS,NUM_SPECIES) :: ccpp_constituents ! mol m-3 + real(kind_phys), target, dimension(NUM_COLUMNS,NUM_LAYERS,NUM_SPECIES) :: micm_constituents ! mol m-3 + integer :: i_column, i_layer, i_elem + real :: abs_error = 1e-3 + dry_air_density(:,1) = (/ 3.5_kind_phys, 4.5_kind_phys /) + dry_air_density(:,2) = (/ 5.5_kind_phys, 6.5_kind_phys /) + molar_mass_arr(:) = (/ 200._kind_phys, 200._kind_phys, 200._kind_phys, 200._kind_phys /) + constituents(1,1,:) = (/ 0.1_kind_phys, 0.2_kind_phys, 0.3_kind_phys, 0.4_kind_phys /) + constituents(1,2,:) = (/ 0.41_kind_phys, 0.42_kind_phys, 0.43_kind_phys, 0.44_kind_phys /) + constituents(2,1,:) = (/ 0.21_kind_phys, 0.22_kind_phys, 0.23_kind_phys, 0.24_kind_phys /) + constituents(2,2,:) = (/ 0.31_kind_phys, 0.32_kind_phys, 0.33_kind_phys, 0.34_kind_phys /) + + ccpp_constituents(1,1,:) = (/ 0.1_kind_phys, 0.2_kind_phys, 0.3_kind_phys, 0.4_kind_phys /) + ccpp_constituents(1,2,:) = (/ 0.41_kind_phys, 0.42_kind_phys, 0.43_kind_phys, 0.44_kind_phys /) + ccpp_constituents(2,1,:) = (/ 0.21_kind_phys, 0.22_kind_phys, 0.23_kind_phys, 0.24_kind_phys /) + ccpp_constituents(2,2,:) = (/ 0.31_kind_phys, 0.32_kind_phys, 0.33_kind_phys, 0.34_kind_phys /) + + micm_constituents(1,1,:) = (/ 1.750E-003_kind_phys, 3.500E-003_kind_phys, 5.250E-003_kind_phys, 7.000E-003_kind_phys /) + micm_constituents(1,2,:) = (/ 1.127E-002_kind_phys, 1.155E-002_kind_phys, 1.182E-002_kind_phys, 1.210E-002_kind_phys /) + micm_constituents(2,1,:) = (/ 4.725E-003_kind_phys, 4.949E-003_kind_phys, 5.175E-003_kind_phys, 5.400E-003_kind_phys /) + micm_constituents(2,2,:) = (/ 1.007E-002_kind_phys, 1.040E-002_kind_phys, 1.072E-002_kind_phys, 1.104E-002_kind_phys /) + + call convert_to_mol_per_cubic_meter(dry_air_density, molar_mass_arr, constituents) + + do i_column = 1, NUM_COLUMNS + do i_layer = 1, NUM_LAYERS + do i_elem = 1, NUM_SPECIES + ASSERT_NEAR(constituents(i_column, i_layer, i_elem), micm_constituents(i_column, i_layer, i_elem), abs_error) + end do + end do + end do + + call convert_to_mass_mixing_ratio(dry_air_density, molar_mass_arr, constituents) + + do i_column = 1, NUM_COLUMNS + do i_layer = 1, NUM_LAYERS + do i_elem = 1, NUM_SPECIES + ASSERT_NEAR(constituents(i_column, i_layer, i_elem), ccpp_constituents(i_column, i_layer, i_elem), abs_error) + end do + end do + end do + end subroutine test_unit_conversion + +end program test_micm_util \ No newline at end of file diff --git a/test/musica/musica_ccpp_namelist.F90 b/test/musica/musica_ccpp_namelist.F90 index d0b8fad..a3e507c 100644 --- a/test/musica/musica_ccpp_namelist.F90 +++ b/test/musica/musica_ccpp_namelist.F90 @@ -3,9 +3,10 @@ module musica_ccpp_namelist implicit none + public :: filename_of_micm_configuration, filename_of_tuvx_configuration private - public :: filename_of_micm_configuration - + character(len=*), parameter :: filename_of_micm_configuration = 'chapman' + character(len=*), parameter :: filename_of_tuvx_configuration = 'configs/ts1_tsmlt.json' end module musica_ccpp_namelist diff --git a/test/musica/test_musica_api.F90 b/test/musica/test_musica_api.F90 index 79a6b90..e69f514 100644 --- a/test/musica/test_musica_api.F90 +++ b/test/musica/test_musica_api.F90 @@ -4,51 +4,59 @@ subroutine test_musica_ccpp_api() use iso_c_binding use musica_ccpp + use musica_micm, only: Rosenbrock, RosenbrockStandardOrder use ccpp_kinds, only: kind_phys use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use ccpp_constituent_prop_mod, only: ccpp_constituent_properties_t implicit none - real(kind_phys) :: time_step ! s - real(kind_phys), dimension(2,1) :: temperature ! K - real(kind_phys), dimension(2,1) :: pressure ! Pa - real(kind_phys), dimension(2,1) :: dry_air_density ! kg m-3 - type(ccpp_constituent_prop_ptr_t), allocatable :: constituent_props_ptr(:) - real(kind_phys), dimension(5) :: molar_mass_arr ! kg mol-1 - real(kind_phys), dimension(2,1,5) :: constituents ! kg kg-1 - integer :: errcode - character(len=512) :: errmsg + integer, parameter :: NUM_SPECIES = 4 + integer, parameter :: NUM_RATES = 3 + integer, parameter :: NUM_COLUMNS = 2 + integer, parameter :: NUM_LAYERS = 2 + integer :: solver_type + integer :: errcode + character(len=512) :: errmsg + real(kind_phys) :: time_step ! s + real(kind_phys), dimension(NUM_COLUMNS,NUM_LAYERS) :: height ! km + real(kind_phys), target, dimension(NUM_COLUMNS,NUM_LAYERS) :: temperature ! K + real(kind_phys), target, dimension(NUM_COLUMNS,NUM_LAYERS) :: pressure ! Pa + real(kind_phys), target, dimension(NUM_COLUMNS,NUM_LAYERS) :: dry_air_density ! kg m-3 + real(kind_phys), target, dimension(NUM_COLUMNS,NUM_LAYERS,NUM_SPECIES) :: constituents ! kg kg-1 + real(kind_phys), target, dimension(NUM_COLUMNS,NUM_LAYERS,NUM_RATES) :: user_defined_reaction_rates + type(ccpp_constituent_prop_ptr_t), allocatable :: constituent_props_ptr(:) ! local variables type(ccpp_constituent_properties_t), allocatable, target :: constituent_props(:) type(ccpp_constituent_properties_t), pointer :: const_prop - integer :: i + real(kind_phys) :: molar_mass character(len=512) :: species_name, units logical :: tmp_bool, is_advected - real(kind_phys) :: molar_mass + integer :: num_grid_cells + integer :: i + solver_type = Rosenbrock + num_grid_cells = NUM_COLUMNS * NUM_LAYERS time_step = 60._kind_phys - - temperature(1,1) = 206.6374207_kind_phys - temperature(2,1) = 206.6374207_kind_phys - - pressure(1,1) = 6152.049805_kind_phys - pressure(2,1) = 6152.049805_kind_phys - - dry_air_density(1,1) = 3.580_kind_phys - dry_air_density(2,1) = 3.580_kind_phys - - molar_mass_arr = (/ 200._kind_phys, 200._kind_phys, 200._kind_phys, 200._kind_phys, 200._kind_phys /) - - constituents(1,1,1:5) = (/ 0.75_kind_phys, 8.1e-6_kind_phys, 2.42e-17_kind_phys, & - 1.15e-5_kind_phys, 6.61e-9_kind_phys /) - constituents(2,1,1:5) = (/ 0.75_kind_phys, 8.1e-6_kind_phys, 2.42e-17_kind_phys, & - 1.15e-5_kind_phys, 6.61e-9_kind_phys /) - - call musica_ccpp_register(constituent_props, errmsg, errcode) + temperature(:,1) = (/ 100._kind_phys, 200._kind_phys /) + temperature(:,2) = (/ 300._kind_phys, 400._kind_phys /) + pressure(:,1) = (/ 6000.04_kind_phys, 7000.04_kind_phys /) + pressure(:,2) = (/ 8000.04_kind_phys, 9000.04_kind_phys /) + dry_air_density(:,1) = (/ 3.5_kind_phys, 4.5_kind_phys /) + dry_air_density(:,2) = (/ 5.5_kind_phys, 6.5_kind_phys /) + constituents(1,1,:) = (/ 0.1_kind_phys, 0.2_kind_phys, 0.3_kind_phys, 0.4_kind_phys /) + constituents(1,2,:) = (/ 0.41_kind_phys, 0.42_kind_phys, 0.43_kind_phys, 0.44_kind_phys /) + constituents(2,1,:) = (/ 0.21_kind_phys, 0.22_kind_phys, 0.23_kind_phys, 0.24_kind_phys /) + constituents(2,2,:) = (/ 0.31_kind_phys, 0.32_kind_phys, 0.33_kind_phys, 0.34_kind_phys /) + user_defined_reaction_rates(1,1,:) = (/2.7e-19_kind_phys, 1.13e-9_kind_phys, 5.8e-8_kind_phys/) + user_defined_reaction_rates(1,2,:) = (/2.7e-19_kind_phys, 1.13e-9_kind_phys, 5.8e-8_kind_phys/) + user_defined_reaction_rates(2,1,:) = (/2.7e-19_kind_phys, 1.13e-9_kind_phys, 5.8e-8_kind_phys/) + user_defined_reaction_rates(2,2,:) = (/2.7e-19_kind_phys, 1.13e-9_kind_phys, 5.8e-8_kind_phys/) + + call musica_ccpp_register(constituent_props, solver_type, num_grid_cells, errmsg, errcode) ASSERT(allocated(constituent_props)) - ASSERT(size(constituent_props) == 5) + ASSERT(size(constituent_props) == NUM_SPECIES) do i = 1, size(constituent_props) ASSERT(constituent_props(i)%is_instantiated(errcode, errmsg)) ASSERT(errcode == 0) @@ -58,9 +66,8 @@ subroutine test_musica_ccpp_api() ASSERT(errcode == 0) call constituent_props(i)%is_advected(is_advected, errcode, errmsg) ASSERT(errcode == 0) - tmp_bool = (trim(species_name) == "M" .and. molar_mass == 0.029_kind_phys .and. .not. is_advected) .or. & - (trim(species_name) == "O2" .and. molar_mass == 0.032_kind_phys .and. .not. is_advected) .or. & - (trim(species_name) == "O" .and. molar_mass == 0.016_kind_phys .and. .not. is_advected) .or. & + tmp_booL = (trim(species_name) == "O2" .and. molar_mass == 0.032_kind_phys .and. .not. is_advected) .or. & + (trim(species_name) == "O" .and. molar_mass == 0.016_kind_phys .and. .not. is_advected) .or. & (trim(species_name) == "O1D" .and. molar_mass == 0.016_kind_phys .and. .not. is_advected) .or. & (trim(species_name) == "O3" .and. molar_mass == 0.048_kind_phys .and. is_advected) ASSERT(tmp_bool) @@ -80,26 +87,33 @@ subroutine test_musica_ccpp_api() end do call musica_ccpp_init(errmsg, errcode) - if (errcode /= 0) then write(*,*) trim(errmsg) stop 3 endif - write(*,*) " -- Initial time_step", time_step - write(*,*) " -- Initial temp", temperature - write(*,*) " -- Initial pressure", pressure - write(*,*) " -- Initial concentrations", constituents + write(*,*) "[MUSICA INFO] Initial Time Step" + write(*,fmt="(1x,f10.2)") time_step + write(*,*) "[MUSICA INFO] Initial Temperature" + write(*,fmt="(4(1x,f10.4))") temperature + write(*,*) "[MUSICA INFO] Initial Pressure" + write(*,fmt="(4(1x,f10.4))") pressure + write(*,*) "[MUSICA INFO] Initial Concentrations" + write(*,fmt="(4(3x,e13.6))") constituents + write(*,*) "[MUSICA INFO] Initial User-defined Reaction Rates" + write(*,fmt="(3(3x,e13.6))") user_defined_reaction_rates call musica_ccpp_run(time_step, temperature, pressure, dry_air_density, constituent_props_ptr, & - constituents, errmsg, errcode) - + constituents, user_defined_reaction_rates, height, errmsg, errcode) if (errcode /= 0) then write(*,*) trim(errmsg) stop 3 endif - write(*,*) " -- After solving, concentrations", constituents + write(*,*) "[MUSICA INFO] Solved Concentrations" + write(*,fmt="(4(3x,e13.6))") constituents + write(*,*) "[MUSICA INFO] Solved User-defined Reaction Rates" + write(*,fmt="(3(3x,e13.6))") user_defined_reaction_rates call musica_ccpp_final(errmsg, errcode) @@ -113,4 +127,4 @@ end subroutine test_musica_ccpp_api program run_test_musica_ccpp implicit none call test_musica_ccpp_api() -end program +end program \ No newline at end of file diff --git a/test/musica/tuvx/configs/ts1_tsmlt.json b/test/musica/tuvx/configs/ts1_tsmlt.json new file mode 100644 index 0000000..7ea1806 --- /dev/null +++ b/test/musica/tuvx/configs/ts1_tsmlt.json @@ -0,0 +1,2095 @@ +{ + "__description": "TUV-x configuration for the MOZART-TS1 and MOZART-TSMLT chemical mechanisms", + "O2 absorption" : { + "cross section parameters file": "data/cross_sections/O2_parameters.txt" + }, + "grids": [ + { + "name": "height", + "type": "equal interval", + "units": "km", + "begins at" : 0.0, + "ends at" : 120.0, + "cell delta" : 1.0 + }, + { + "name": "wavelength", + "type": "from csv file", + "units": "nm", + "file path": "data/grids/wavelength/cam.csv" + }, + { + "name": "time", + "type": "from config file", + "units": "hours", + "values": [ 12.0, 14.0 ] + } + ], + "profiles": [ + { + "name": "O3", + "type": "O3", + "units": "molecule cm-3", + "file path": "data/profiles/atmosphere/ussa.ozone" + }, + { + "name": "air", + "type": "air", + "units": "molecule cm-3", + "file path": "data/profiles/atmosphere/ussa.dens" + }, + { + "name": "O2", + "type": "O2", + "units": "molecule cm-3", + "file path": "data/profiles/atmosphere/ussa.dens" + }, + { + "name": "temperature", + "type": "from csv file", + "units": "K", + "file path": "data/profiles/atmosphere/ussa.temp", + "grid": { + "name": "height", + "units": "km" + } + }, + { + "name": "solar zenith angle", + "type": "solar zenith angle", + "units": "degrees", + "year" : 2002, + "month": 3, + "day": 21, + "longitude": 0.0, + "latitude": 0.0 + }, + { + "name": "Earth-Sun distance", + "type": "Earth-Sun distance", + "units": "AU", + "year" : 2002, + "month": 3, + "day": 21 + }, + { + "name": "surface albedo", + "type": "from config file", + "units": "none", + "uniform value": 0.10, + "grid": { + "name": "wavelength", + "units": "nm" + } + }, + { + "name": "extraterrestrial flux", + "enable diagnostics" : true, + "type": "extraterrestrial flux", + "units": "photon cm-2 s-1", + "file path": ["data/profiles/solar/susim_hi.flx", + "data/profiles/solar/atlas3_1994_317_a.dat", + "data/profiles/solar/sao2010.solref.converted", + "data/profiles/solar/neckel.flx"], + "interpolator": ["","","","fractional target"] + } + ], + "radiative transfer": { + "__output": true, + "solver" : { + "type" : "delta eddington" + }, + "cross sections": [ + { + "name": "air", + "type": "air" + }, + { + "name": "O3", + "netcdf files": [ + { "file path": "data/cross_sections/O3_1.nc" }, + { "file path": "data/cross_sections/O3_2.nc" }, + { "file path": "data/cross_sections/O3_3.nc" }, + { "file path": "data/cross_sections/O3_4.nc" } + ], + "type": "O3" + }, + { + "name": "O2", + "netcdf files": [ + { + "file path": "data/cross_sections/O2_1.nc", + "lower extrapolation": { "type": "boundary" } + } + ], + "type": "base" + } + ], + "radiators": [ + { + "enable diagnostics" : true, + "name": "air", + "type": "base", + "treat as air": true, + "cross section": "air", + "vertical profile": "air", + "vertical profile units": "molecule cm-3" + }, + { + "enable diagnostics" : true, + "name": "O2", + "type": "base", + "cross section": "O2", + "vertical profile": "O2", + "vertical profile units": "molecule cm-3" + }, + { + "enable diagnostics" : true, + "name": "O3", + "type": "base", + "cross section": "O3", + "vertical profile": "O3", + "vertical profile units": "molecule cm-3" + }, + { + "enable diagnostics" : true, + "name": "aerosols", + "type": "aerosol", + "optical depths": [2.40e-01, 1.06e-01, 4.56e-02, 1.91e-02, 1.01e-02, 7.63e-03, + 5.38e-03, 5.00e-03, 5.15e-03, 4.94e-03, 4.82e-03, 4.51e-03, + 4.74e-03, 4.37e-03, 4.28e-03, 4.03e-03, 3.83e-03, 3.78e-03, + 3.88e-03, 3.08e-03, 2.26e-03, 1.64e-03, 1.23e-03, 9.45e-04, + 7.49e-04, 6.30e-04, 5.50e-04, 4.21e-04, 3.22e-04, 2.48e-04, + 1.90e-04, 1.45e-04, 1.11e-04, 8.51e-05, 6.52e-05, 5.00e-05, + 3.83e-05, 2.93e-05, 2.25e-05, 1.72e-05, 1.32e-05, 1.01e-05, + 7.72e-06, 5.91e-06, 4.53e-06, 3.46e-06, 2.66e-06, 2.04e-06, + 1.56e-06, 1.19e-06, 9.14e-07], + "single scattering albedo": 0.99, + "asymmetry factor": 0.61, + "550 nm optical depth": 0.235 + } + ] + }, + "photolysis": { + "reactions": [ + { + "name": "jo2_a", + "__reaction": "O2 + hv -> O + O1D", + "cross section": { + "apply O2 bands": true, + "netcdf files": [ + { + "file path": "data/cross_sections/O2_1.nc", + "lower extrapolation": { "type": "boundary" }, + "interpolator": { "type": "fractional target" } + } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 0, + "override bands": [ + { + "band": "lyman-alpha", + "value": 0.53 + }, + { + "band": "schumann-runge continuum", + "value": 1.0 + } + ] + }, + "heating" : { + "energy term": 175.05 + } + }, + { + "name": "jo2_b", + "__reaction": "O2 + hv -> O + O", + "cross section": { + "apply O2 bands": true, + "netcdf files": [ + { + "file path": "data/cross_sections/O2_1.nc", + "lower extrapolation": { "type": "boundary" }, + "interpolator": { "type": "fractional target" } + } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0, + "override bands": [ + { + "band": "lyman-alpha", + "value": 0.47 + }, + { + "band": "schumann-runge continuum", + "value": 0.0 + } + ] + }, + "heating" : { + "energy term": 242.37 + } + }, + { + "name": "jo3_a", + "__reaction": "O3 + hv -> O2 + O(1D)", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/O3_1.nc" }, + { "file path": "data/cross_sections/O3_2.nc" }, + { "file path": "data/cross_sections/O3_3.nc" }, + { "file path": "data/cross_sections/O3_4.nc" } + ], + "type": "O3" + }, + "quantum yield": { + "type": "O3+hv->O2+O(1D)" + }, + "heating" : { + "energy term": 310.32 + } + }, + { + "name": "jo3_b", + "__reaction": "O3 + hv -> O2 + O(3P)", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/O3_1.nc" }, + { "file path": "data/cross_sections/O3_2.nc" }, + { "file path": "data/cross_sections/O3_3.nc" }, + { "file path": "data/cross_sections/O3_4.nc" } + ], + "type": "O3" + }, + "quantum yield": { + "type": "O3+hv->O2+O(3P)" + }, + "heating" : { + "energy term": 1179.87 + } + }, + { + "name": "jn2o", + "__reaction": "N2O + hv -> N2 + O(1D)", + "cross section": { + "type": "N2O+hv->N2+O(1D)" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jno2", + "__reaction": "NO2 + hv -> NO + O(3P)", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/NO2_1.nc" } + ], + "type": "NO2 tint" + }, + "quantum yield": { + "netcdf files": ["data/quantum_yields/NO2_1.nc"], + "type": "NO2 tint", + "lower extrapolation": { "type": "boundary" } + } + }, + { + "name": "jn2o5_a", + "__reaction": "N2O5 + hv -> NO2 + NO3", + "cross section": { + "type":"temperature based", + "netcdf file": "data/cross_sections/N2O5_JPL06.nc", + "parameterization": { + "type": "HARWOOD", + "aa": [ -18.27, -18.42, -18.59, -18.72, -18.84, + -18.90, -18.93, -18.87, -18.77, -18.71, + -18.31, -18.14, -18.01, -18.42, -18.59, + -18.13 ], + "bb": [ -91.0, -104.0, -112.0, -135.0, -170.0, + -226.0, -294.0, -388.0, -492.0, -583.0, + -770.0, -885.0, -992.0, -949.0, -966.0, + -1160.0 ], + "base temperature": 0.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "minimum wavelength": 260.0, + "maximum wavelength": 410.0, + "temperature ranges": [ + { + "maximum": 199.999999999999, + "fixed value": 200 + }, + { + "minimum": 200, + "maximum": 295 + }, + { + "minimum": 295.00000000001, + "fixed value": 295.0 + } + ] + }, + "parameterization wavelength grid": { + "name": "custom wavelengths", + "type": "from config file", + "units": "nm", + "values": [ + 255.0, 265.0, 275.0, 285.0, 295.0, 305.0, + 315.0, 325.0, 335.0, 345.0, 355.0, 365.0, + 375.0, 385.0, 395.0, 405.0, 415.0 + ] + } + }, + "quantum yield": { + "type": "Taylor series", + "constant value": 0.0, + "coefficients": [ -2.832441, 0.012809638 ], + "override bands": [ + { + "band": "range", + "minimum wavelength": 300.0, + "value": 1.0 + } + ] + } + }, + { + "name": "jn2o5_b", + "__reaction": "N2O5 + hv -> NO + O + NO3", + "cross section": { + "type":"temperature based", + "netcdf file": "data/cross_sections/N2O5_JPL06.nc", + "parameterization": { + "type": "HARWOOD", + "aa": [ -18.27, -18.42, -18.59, -18.72, -18.84, + -18.90, -18.93, -18.87, -18.77, -18.71, + -18.31, -18.14, -18.01, -18.42, -18.59, + -18.13 ], + "bb": [ -91.0, -104.0, -112.0, -135.0, -170.0, + -226.0, -294.0, -388.0, -492.0, -583.0, + -770.0, -885.0, -992.0, -949.0, -966.0, + -1160.0 ], + "base temperature": 0.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "minimum wavelength": 260.0, + "maximum wavelength": 410.0, + "temperature ranges": [ + { + "maximum": 199.999999999999, + "fixed value": 200 + }, + { + "minimum": 200, + "maximum": 295 + }, + { + "minimum": 295.00000000001, + "fixed value": 295.0 + } + ] + }, + "parameterization wavelength grid": { + "name": "custom wavelengths", + "type": "from config file", + "units": "nm", + "values": [ + 255.0, 265.0, 275.0, 285.0, 295.0, 305.0, + 315.0, 325.0, 335.0, 345.0, 355.0, 365.0, + 375.0, 385.0, 395.0, 405.0, 415.0 + ] + } + }, + "quantum yield": { + "type": "Taylor series", + "constant value": 0.0, + "coefficients": [ 3.832441, -0.012809638 ], + "override bands": [ + { + "band": "range", + "minimum wavelength": 300.0, + "value": 0.0 + } + ] + } + }, + { + "name": "jhno3", + "__reaction": "HNO3 + hv -> OH + NO2", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/HNO3_JPL06.nc" } + ], + "type": "HNO3+hv->OH+NO2" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jno3_a", + "__reaction": "NO3 + hv -> NO2 + O(3P)", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/NO3_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "netcdf files": [ + "data/quantum_yields/NO3-NO2+O(3P)_1.nc" + ], + "type": "tint", + "lower extrapolation": { + "type": "constant", + "value": 1.0 + } + } + }, + { + "name": "jno3_b", + "__reaction": "NO3 + hv -> NO + O2", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/NO3_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "netcdf files": [ + "data/quantum_yields/NO3-NO+O2_1.nc" + ], + "type": "tint" + } + }, + { + "name": "jch3ooh", + "__reaction": "CH3OOH + hv -> CH3O + OH", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CH3OOH_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jch2o_a", + "__reaction": "CH2O + hv -> H + HCO", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CH2O_1.nc" } + ], + "type": "CH2O" + }, + "quantum yield": { + "netcdf files": [ + "data/quantum_yields/CH2O_1.nc" + ], + "type": "base", + "lower extrapolation": { + "type": "boundary" + } + } + }, + { + "name": "jch2o_b", + "__reaction": "CH2O + hv -> H2 + CO", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CH2O_1.nc" } + ], + "type": "CH2O" + }, + "quantum yield": { + "netcdf files": [ + "data/quantum_yields/CH2O_1.nc" + ], + "type": "CH2O", + "lower extrapolation": { + "type": "boundary" + } + } + }, + { + "name": "jh2o2", + "__reaction": "H2O2 + hv -> OH + OH", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/H2O2_1.nc" } + ], + "type": "H2O2+hv->OH+OH" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jch3cho", + "__reaction": "CH3CHO + hv -> CH3 + HCO", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CH3CHO_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "netcdf files": [ + "data/quantum_yields/CH3CHO_1.nc" + ], + "type": "CH3CHO+hv->CH3+HCO" + } + }, + { + "name": "jpan", + "__reaction": "PAN + hv -> 0.6*CH3CO3 + 0.6*NO2 + 0.4*CH3O2 + 0.4*NO3 + 0.4*CO2", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/PAN_1.nc" } + ], + "type": "CH3ONO2+hv->CH3O+NO2" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jmvk", + "__reaction": "MVK + hv -> 0.7*C3H6 + 0.7*CO + 0.3*CH3O2 + 0.3*CH3CO3", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/MVK_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "MVK+hv->Products" + } + }, + { + "name": "jacet", + "__reaction": "CH3COCH3 + hv -> CH3CO + CH3", + "cross section": { + "type": "temperature based", + "parameterization": { + "type": "TAYLOR_SERIES", + "netcdf file": { + "file path": "data/cross_sections/ACETONE_JPL06.nc" + }, + "base temperature": 0.0, + "temperature ranges": [ + { + "maximum": 234.999999999999, + "fixed value": 235.0 + }, + { + "minimum": 235.0, + "maximum": 298.0 + }, + { + "minimum": 298.00000000001, + "fixed value": 298.0 + } + ] + } + }, + "quantum yield": { + "type": "CH3COCH3+hv->CH3CO+CH3", + "branch": "CO+CH3CO", + "low wavelength value": 1, + "minimum temperature": 218, + "maximum temperature": 295 + } + }, + { + "name": "jmgly", + "__reaction": "CH3COCHO + hv -> CH3CO3 + CO + HO2", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CH3COCHO_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "CH3COCHO+hv->CH3CO+HCO" + } + }, + { + "name": "jglyald", + "__reaction": "GLYALD + hv -> 2*HO2 + CO + CH2O", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/HOCH2CHO_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 0.5 + } + }, + { + "name": "jbrcl", + "__reaction": "BrCl + hv -> Br + Cl", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/BrCl_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jbro", + "__reaction": "BrO + hv -> Br + O", + "cross section": { + "netcdf files": [ + { + "file path": "data/cross_sections/BRO_JPL06.nc" + } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jbrono2_a", + "__reaction": "BrONO2 + hv -> Br + NO3", + "cross section": { + "type": "temperature based", + "parameterization": { + "type": "TAYLOR_SERIES", + "netcdf file": { + "file path": "data/cross_sections/BRONO2_JPL06.nc" + }, + "base temperature": 296.0, + "temperature ranges": [ + { + "maximum": 199.999999999999, + "fixed value": 200.0 + }, + { + "minimum": 200.0, + "maximum": 296.0 + }, + { + "minimum": 296.00000000001, + "fixed value": 296.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 0.85 + } + }, + { + "name": "jbrono2_b", + "__reaction": "BrONO2 + hv -> BrO + NO2", + "cross section": { + "type": "temperature based", + "parameterization": { + "type": "TAYLOR_SERIES", + "netcdf file": { + "file path": "data/cross_sections/BRONO2_JPL06.nc" + }, + "base temperature": 296.0, + "temperature ranges": [ + { + "maximum": 199.999999999999, + "fixed value": 200.0 + }, + { + "minimum": 200.0, + "maximum": 296.0 + }, + { + "minimum": 296.00000000001, + "fixed value": 296.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 0.15 + } + }, + { + "name": "jccl4", + "__reaction": "CCl4 + hv -> Products", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CCl4_1.nc" } + ], + "type": "CCl4+hv->Products" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jcf2clbr", + "__reaction": "CF2BrCl + hv -> Products", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CF2BrCl_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jcf3br", + "__reaction": "CF3Br + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/H1301_JPL06.nc", + "parameterization": { + "AA": [ 62.563, -2.0068, 1.6592e-2, -5.6465e-5, 6.7459e-8 ], + "BB": [ -9.1755e-1, 1.8575e-2, -1.3857e-4, 4.5066e-7, -5.3803e-10 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 178.0, + "maximum wavelength": 280.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210.0, + "maximum": 300.0 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jcfcl3", + "__reaction": "CCl3F + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/CFCL3_JPL06.nc", + "parameterization": { + "AA": [ -84.611, 7.9551e-1, -2.0550e-3, -4.4812e-6, 1.5838e-8 ], + "BB": [ -5.7912, 1.1689e-1, -8.8069e-4, 2.9335e-6, -3.6421e-9 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 174.1, + "maximum wavelength": 230.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210, + "maximum": 300 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jcfc113", + "__reaction": "CFC-113 + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/CFC113_JPL06.nc", + "parameterization": { + "AA": [ -1087.9, 20.004, -1.3920e-1, 4.2828e-4, -4.9384e-7 ], + "BB": [ 12.493, -2.3937e-1, 1.7142e-3, -5.4393e-6, 6.4548e-9 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 182.0, + "maximum wavelength": 230.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210, + "maximum": 300 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jcfc114", + "__reaction": "CFC-114 + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/CFC114_JPL10.nc", + "parameterization": { + "AA": [ -160.50, 2.4807, -1.5202e-2, 3.8412e-5, -3.4373e-8 ], + "BB": [ -1.5296, 3.5248e-2, -2.9951e-4, 1.1129e-6, -1.5259e-9 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 172.0, + "maximum wavelength": 220.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210, + "maximum": 300 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jcfc115", + "__reaction": "CFC-115 + hv -> Products", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/CFC115_JPL10.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jcf2cl2", + "__reaction": "CCl2F2 + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/CF2CL2_JPL06.nc", + "parameterization": { + "AA": [ -43.8954569, -2.403597e-1, -4.2619e-4, 9.8743e-6, 0.0 ], + "BB": [ 4.8438e-3, 4.96145e-4, -5.6953e-6, 0.0, 0.0 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 200.0, + "maximum wavelength": 231.0, + "base temperature": 296.0, + "base wavelength": 200.0, + "logarithm": "natural", + "temperature ranges": [ + { + "maximum": 219.999999999999, + "fixed value": 220.0 + }, + { + "minimum": 220, + "maximum": 296 + }, + { + "minimum": 296.00000000001, + "fixed value": 296.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jch2br2", + "__reaction": "CH2BR2 + hv -> 2*BR", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/CH2BR2_1.nc", + "parameterization": { + "AA": [ -70.211776, 1.940326e-1, 2.726152e-3, -1.695472e-5, 2.500066e-8 ], + "BB": [ 2.899280, -4.327724e-2, 2.391599e-4, -5.807506e-7, 5.244883e-10 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 210.0, + "maximum wavelength": 290.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210, + "maximum": 300 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jch3br", + "__reaction": "CH3Br + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/CH3BR_JPL06.nc", + "parameterization": { + "AA": [ 46.520, -1.4580, 1.1469e-2, -3.7627e-5, 4.3264e-8 ], + "BB": [ 9.3408e-1, -1.6887e-2, 1.1487e-4, -3.4881e-7, 3.9945e-10 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 200.0, + "maximum wavelength": 280.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210, + "maximum": 300 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jch3ccl3", + "__reaction": "CH3CCl3+hv->Products", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CH3CCl3_1.nc" } + ], + "type": "tint" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jch3cl", + "__reaction": "CH3Cl + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/CH3CL_JPL06.nc", + "parameterization": { + "AA": [ -299.80, 5.1047, -3.3630e-2, 9.5805e-5, -1.0135e-7 ], + "BB": [ -7.1727, 1.4837e-1, -1.1463e-3, 3.9188e-6, -4.9994e-9 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 174.1, + "maximum wavelength": 216.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210, + "maximum": 300 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jchbr3", + "__reaction": "CHBr3 + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/CHBR3_JPL10.nc", + "parameterization": { + "AA": [ -32.6067, 0.10308, 6.39e-5, -7.7392e-7, -2.2513e-9, 6.1376e-12 ], + "BB": [ 0.1582, -0.0014758, 3.8058e-6, 9.187e-10, -1.0772e-11, 0.0 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 ], + "minimum wavelength": 260.0, + "maximum wavelength": 362.0, + "base temperature": 296.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "invert temperature offset": true, + "temperature ranges": [ + { + "maximum": 259.999999999999, + "fixed value": 260.0 + }, + { + "minimum": 260.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jcl2", + "__reaction": "Cl2 + hv -> Cl + Cl", + "cross section": { + "type": "Cl2+hv->Cl+Cl" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jcl2o2", + "__reaction": "ClOOCl + hv -> Cl + ClOO", + "__comments": "TODO - this doesn't exactly match the products in TS1", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CL2O2_JPL10.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jclo", + "__reaction": "ClO + hv -> Cl + O", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CLO_JPL06.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jclono2_a", + "__reaction": "ClONO2 + hv -> Cl + NO3", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/ClONO2_1.nc" } + ], + "type": "ClONO2" + }, + "quantum yield": { + "type": "ClONO2+hv->Cl+NO3" + } + }, + { + "name": "jclono2_b", + "__reaction": "ClONO2 + hv -> ClO + NO2", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/ClONO2_1.nc" } + ], + "type": "ClONO2" + }, + "quantum yield": { + "type": "ClONO2+hv->ClO+NO2" + } + }, + { + "name": "jcof2", + "__reaction": "CF2O + hv -> Products", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CF2O_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jcofcl", + "__reaction": "CClFO + hv -> Products", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/CClFO_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jh2402", + "__reaction": "H2402 + hv -> 2*BR + 2*COF2", + "__comments": "TUV data set name CF2BrCF2Br", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/H2402_JPL06.nc", + "parameterization": { + "AA": [ 34.026, -1.152616, 8.959798e-3, -2.9089e-5, 3.307212e-8 ], + "BB": [ 4.010664e-1, -8.358968e-3, 6.415741e-5, -2.157554e-7, 2.691871e-10 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 190.0, + "maximum wavelength": 290.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210.0, + "maximum": 300.0 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jhcfc141b", + "__reaction": "HCFC-141b + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/HCFC141b_JPL10.nc", + "parameterization": { + "AA": [ -682.913042, 12.122290, -8.187699e-2, 2.437244e-4, -2.719103e-7 ], + "BB": [ 4.074747, -8.053899e-2, 5.946552e-4, -1.945048e-6, 2.380143e-9 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 172.0, + "maximum wavelength": 240.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210.0, + "maximum": 300.0 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jhcfc142b", + "__reaction": "HCFC-142b + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/HCFC142b_JPL10.nc", + "parameterization": { + "AA": [ -328.092008, 6.342799, -4.810362e-2, 1.611991e-4, -2.042613e-7 ], + "BB": [ 4.289533e-1, -9.042817e-3, 7.018009e-5, -2.389064e-7, 3.039799e-10 ], + "lp": [ 0.0, 1.0, 2.0, 3.0, 4.0 ], + "minimum wavelength": 172.0, + "maximum wavelength": 230.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210.0, + "maximum": 300.0 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jhcfc22", + "__reaction": "HCFC-22 + hv -> Products", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/HCFC22_JPL06.nc", + "parameterization wavelength grid": { + "name": "custom wavelengths", + "type": "from config file", + "units": "nm", + "values": [ + 169.0, 171.0, 173.0, 175.0, 177.0, 179.0, 181.0, 183.0, 185.0, + 187.0, 189.0, 191.0, 193.0, 195.0, 197.0, 199.0, 201.0, 203.0, + 205.0, 207.0, 209.0, 211.0, 213.0, 215.0, 217.0, 219.0, 221.0 + ] + }, + "parameterization": { + "AA": [ -106.029, 1.5038, -8.2476e-3, 1.4206e-5 ], + "BB": [ -1.3399e-1, 2.7405e-3, -1.8028e-5, 3.8504e-8 ], + "lp": [ 0.0, 1.0, 2.0, 3.0 ], + "minimum wavelength": 174.0, + "maximum wavelength": 204.0, + "base temperature": 273.0, + "base wavelength": 0.0, + "logarithm": "base 10", + "temperature ranges": [ + { + "maximum": 209.999999999999, + "fixed value": 210.0 + }, + { + "minimum": 210.0, + "maximum": 300.0 + }, + { + "minimum": 300.00000000001, + "fixed value": 300.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jhcl", + "__reaction": "HCl + hv -> H + Cl", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/HCl_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jhobr", + "__reaction": "HOBr + hv -> OH + Br", + "cross section": { + "type": "HOBr+hv->OH+Br" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jhocl", + "__reaction": "HOCl + hv -> HO + Cl", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/HOCl_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "joclo", + "__reaction": "OClO + hv -> Products", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/OClO_1.nc" }, + { "file path": "data/cross_sections/OClO_2.nc" }, + { "file path": "data/cross_sections/OClO_3.nc" } + ], + "type": "OClO+hv->Products" + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jho2no2_a", + "__reaction": "HNO4 + hv -> OH + NO3", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/HO2NO2_JPL06.nc", + "parameterization": { + "type": "BURKHOLDER", + "netcdf file": { + "file path": "data/cross_sections/HO2NO2_temp_JPL06.nc" + }, + "A": -988.0, + "B": 0.69, + "temperature ranges": [ + { + "maximum": 279.999999999999, + "fixed value": 280.0 + }, + { + "minimum": 280.0, + "maximum": 350.0 + }, + { + "minimum": 350.00000000001, + "fixed value": 350.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 0.30, + "override bands": [ + { + "band": "range", + "minimum wavelength": 200.0, + "value": 0.20 + } + ] + } + }, + { + "name": "jho2no2_b", + "__reaction": "HNO4 + hv -> HO2 + NO2", + "cross section": { + "type": "temperature based", + "netcdf file": "data/cross_sections/HO2NO2_JPL06.nc", + "parameterization": { + "type": "BURKHOLDER", + "netcdf file": { + "file path": "data/cross_sections/HO2NO2_temp_JPL06.nc" + }, + "A": -988.0, + "B": 0.69, + "temperature ranges": [ + { + "maximum": 279.999999999999, + "fixed value": 280.0 + }, + { + "minimum": 280.0, + "maximum": 350.0 + }, + { + "minimum": 350.00000000001, + "fixed value": 350.0 + } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 0.70, + "override bands": [ + { + "band": "range", + "minimum wavelength": 200.0, + "value": 0.80 + } + ] + } + }, + { + "name": "jmacr_a", + "__reaction": "CH2=C(CH3)CHO->1.34HO2+0.66MCO3+1.34CH2O+CH3CO3", + "__comments": "Methacrolein photolysis channel 1", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/Methacrolein_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 0.005 + } + }, + { + "name": "jmacr_b", + "__reaction": "CH2=C(CH3)CHO->0.66OH+1.34CO", + "__comments": "Methacrolein photolysis channel 2", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/Methacrolein_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 0.005 + } + }, + { + "name": "jhyac", + "__reaction": "CH2(OH)COCH3->CH3CO3+HO2+CH2O", + "__comments": "hydroxy acetone TODO: the products of this reaction differ from standalone TUV-x", + "cross section": { + "netcdf files": [ + { "file path": "data/cross_sections/Hydroxyacetone_1.nc" } + ], + "type": "base" + }, + "quantum yield": { + "type": "base", + "constant value": 0.65 + } + }, + { + "name": "jh2o_a", + "__reaction": "H2O + hv -> OH + H", + "cross section": { + "type": "base", + "merge data": true, + "netcdf files": [ + { + "file path": "data/cross_sections/H2O_1.nc", + "zero above": 183.0 + }, + { + "file path": "data/cross_sections/H2O_2.nc", + "zero below": 183.00000000001, + "zero above": 190.0 + }, + { + "file path": "data/cross_sections/H2O_3.nc", + "zero below": 190.00000000001 + } + ] + }, + "quantum yield" : { + "type": "base", + "netcdf files": [ "data/quantum_yields/H2O_H_OH.nc" ] + } + }, + { + "name": "jh2o_b", + "__reaction": "H2O + hv -> H2 + O1D", + "cross section": { + "type": "base", + "merge data": true, + "netcdf files": [ + { + "file path": "data/cross_sections/H2O_1.nc", + "zero above": 183.0 + }, + { + "file path": "data/cross_sections/H2O_2.nc", + "zero below": 183.00000000001, + "zero above": 190.0 + }, + { + "file path": "data/cross_sections/H2O_3.nc", + "zero below": 190.00000000001 + } + ] + }, + "quantum yield" : { + "type": "base", + "netcdf files": [ "data/quantum_yields/H2O_H2_O1D.nc" ] + } + }, + { + "name": "jh2o_c", + "__reaction": "H2O + hv -> 2*H + O", + "cross section": { + "type": "base", + "merge data": true, + "netcdf files": [ + { + "file path": "data/cross_sections/H2O_1.nc", + "zero above": 183.0 + }, + { + "file path": "data/cross_sections/H2O_2.nc", + "zero below": 183.00000000001, + "zero above": 190.0 + }, + { + "file path": "data/cross_sections/H2O_3.nc", + "zero below": 190.00000000001 + } + ] + }, + "quantum yield" : { + "type": "base", + "netcdf files": [ "data/quantum_yields/H2O_2H_O3P.nc" ] + } + }, + { + "name": "jch4_a", + "__reaction": "CH4 + hv -> H + CH3O2", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/CH4_1.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 0.45 + } + }, + { + "name": "jch4_b", + "__reaction": "CH4 + hv -> 1.44*H2 + 0.18*CH2O + 0.18*O + 0.33*OH + 0.33*H + 0.44*CO2 + 0.38*CO + 0.05*H2O", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/CH4_1.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 0.55 + } + }, + { + "name": "jco2", + "__reaction": "CO2 + hv -> CO + O", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/CO2_1.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jhbr", + "__reaction": "HBR + hv -> BR + H", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/HBr_1.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jhf", + "__reaction": "HF + hv -> H + F", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/HF_1.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jsf6", + "__reaction": "SF6 + hv -> sink", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/SF6_1.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jh2so4", + "__reaction": "H2SO4 + hv -> SO3 + H2O", + "cross section": { + "type": "base", + "data": { + "default value": 0.0, + "point values": [ + { "wavelength": 121.65, "value": 6.3e-17 }, + { "wavelength": 525.0, "value": 1.43e-26 }, + { "wavelength": 625.0, "value": 1.8564e-25 }, + { "wavelength": 725.0, "value": 3.086999e-24 } + ] + } + }, + "quantum yield": { + "type": "H2SO4 Mills", + "netcdf files": [ + "data/quantum_yields/H2SO4_mills.nc" + ], + "parameterized wavelengths": [ + 525, + 625, + 725 + ], + "collision interval s": [ + 1.1e-9, + 8.9e-9, + 1.7e-7 + ], + "molecular diameter m": 4.18e-10, + "molecular weight kg mol-1": 98.078479e-3 + } + }, + { + "name": "jocs", + "__reaction": "OCS + hv -> S + CO", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/OCS_1.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jso", + "__reaction": "SO + hv -> S + O", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/SO_1.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jso2", + "__reaction": "SO2 + hv -> SO + O", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/SO2_Mills.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jso3", + "__reaction": "SO3 + hv -> SO2 + O", + "cross section": { + "type": "base", + "netcdf files": [ + { "file path": "data/cross_sections/SO3_1.nc" } + ] + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + }, + { + "name": "jno_i", + "__reaction": "NO + hv -> NOp + e", + "cross section": { + "type": "base", + "data": { + "default value": 0.0, + "point values": [ + { "wavelength": 121.65, "value": 2.0e-18 } + ] + } + }, + "quantum yield": { + "type": "base", + "constant value": 1.0 + } + } + ] + }, + "__CAM options": { + "aliasing": { + "default matching": "backup", + "pairs": [ + { + "to": "jalknit", + "__reaction": "ALKNIT + hv -> NO2 + 0.4*CH3CHO + 0.1*CH2O + 0.25*CH3COCH3 + HO2 + 0.8*MEK", + "from": "jch3ooh" + }, + { + "to": "jpooh", + "__reaction": "POOH (C3H6OHOOH) + hv -> CH3CHO + CH2O + HO2 + OH", + "from": "jch3ooh" + }, + { + "to": "jch3co3h", + "__reaction": "CH3COOOH + hv -> CH3O2 + OH + CO2", + "from": "jh2o2", + "scale by": 0.28 + }, + { + "to": "jmpan", + "__reaction": "MPAN + hv -> MCO3 + NO2", + "from": "jpan" + }, + { + "to": "jc2h5ooh", + "__reaction": "C2H5OOH + hv -> CH3CHO + HO2 + OH", + "from": "jch3ooh" + }, + { + "to": "jc3h7ooh", + "__reaction": "C3H7OOH + hv -> 0.82*CH3COCH3 + OH + HO2", + "from": "jch3ooh" + }, + { + "to": "jc6h5ooh", + "__reaction": "C6H5OOH + hv -> PHENO + OH", + "from": "jch3ooh" + }, + { + "to": "jeooh", + "__reaction": "EOOH + hv -> EO + OH", + "from": "jch3ooh" + }, + { + "to": "jrooh", + "__reaction": "ROOH + hv -> CH3CO3 + CH2O + OH", + "from": "jch3ooh" + }, + { + "to": "jxooh", + "__reaction": "XOOH + hv -> OH", + "from": "jch3ooh" + }, + { + "to": "jonitr", + "__reaction": "ONITR + hv -> NO2", + "from": "jch3cho" + }, + { + "to": "jisopooh", + "__reaction": "ISOPOOH + hv -> 0.402*MVK + 0.288*MACR + 0.69*CH2O + HO2", + "from": "jch3ooh" + }, + { + "to": "jmek", + "__reaction": "MEK + hv -> CH3CO3 + C2H5O2", + "from": "jacet" + }, + { + "to": "jalkooh", + "__reaction": "ALKOOH + hv -> .4*CH3CHO + .1*CH2O + .25*CH3COCH3 + .9*HO2 + .8*MEK + OH", + "from": "jch3ooh" + }, + { + "to": "jbenzooh", + "__reaction": "BENZOOH + hv -> OH + GLYOXAL + 0.5*BIGALD1 + HO2", + "from": "jch3ooh" + }, + { + "to": "jbepomuc", + "__reaction": "BEPOMUC + hv -> BIGALD1 + 1.5*HO2 + 1.5*CO", + "from": "jno2", + "scale by": 0.1 + }, + { + "to": "jbigald", + "__reaction": "BIGALD + hv -> 0.45*CO + 0.13*GLYOXAL + 0.56*HO2 + 0.13*CH3CO3 + 0.18*CH3COCHO", + "from": "jno2", + "scale by": 0.2 + }, + { + "to": "jbigald1", + "__reaction": "BIGALD1 + hv -> 0.6*MALO2 + HO2", + "from": "jno2", + "scale by": 0.14 + }, + { + "to": "jbigald2", + "__reaction": "BIGALD2 + hv -> 0.6*HO2 + 0.6*DICARBO2", + "from": "jno2", + "scale by": 0.2 + }, + { + "to": "jbigald3", + "__reaction": "BIGALD3 + hv -> 0.6*HO2 + 0.6*CO + 0.6*MDIALO2", + "from": "jno2", + "scale by": 0.2 + }, + { + "to": "jbigald4", + "__reaction": "BIGALD4 + hv -> HO2 + CO + CH3COCHO + CH3CO3", + "from": "jno2", + "scale by": 0.006 + }, + { + "to": "jbzooh", + "__reaction": "BZOOH + hv -> BZALD + OH + HO2", + "from": "jch3ooh" + }, + { + "to": "jmekooh", + "__reaction": "MEKOOH + hv -> OH + CH3CO3 + CH3CHO", + "from": "jch3ooh" + }, + { + "to": "jtolooh", + "__reaction": "TOLOOH + hv -> OH + .45*GLYOXAL + .45*CH3COCHO + .9*BIGALD", + "from": "jch3ooh" + }, + { + "to": "jterpooh", + "__reaction": "TERPOOH + hv -> OH + .1*CH3COCH3 + HO2 + MVK + MACR", + "from": "jch3ooh" + }, + { + "to": "jhonitr", + "__reaction": "HONITR + hv -> NO2 + 0.67*HO2 + 0.33*CH3CHO + 0.33*CH2O + 0.33*CO + 0.33*GLYALD + 0.33*CH3CO3 + 0.17*HYAC + 0.17*CH3COCH3", + "from": "jch2o_a" + }, + { + "to": "jhpald", + "__reaction": "HPALD + hv -> BIGALD3 + OH + HO2", + "from": "jno2", + "scale by": 0.006 + }, + { + "to": "jisopnooh", + "__reaction": "ISOPNOOH + hv -> NO2 + HO2 + ISOPOOH", + "from": "jch3ooh" + }, + { + "to": "jnc4cho", + "__reaction": "NC4CHO + hv -> BIGALD3 + NO2 + HO2", + "from": "jch2o_a" + }, + { + "to": "jnoa", + "__reaction": "NOA + hv -> NO2 + CH2O + CH3CO3", + "from": "jch2o_a" + }, + { + "to": "jnterpooh", + "__reaction": "NTERPOOH + hv -> TERPROD1 + NO2 + OH", + "from": "jch3ooh" + }, + { + "to": "jphenooh", + "__reaction": "PHENOOH + hv -> OH + HO2 + 0.7*GLYOXAL", + "from": "jch3ooh" + }, + { + "to": "jtepomuc", + "__reaction": "TEPOMUC + hv -> 0.5*CH3CO3 + HO2 + 1.5*CO", + "from": "jno2", + "scale by": 0.1 + }, + { + "to": "jterp2ooh", + "__reaction": "TERP2OOH + hv -> OH + 0.375*CH2O + 0.3*CH3COCH3 + 0.25*CO + CO2 + TERPROD2 + HO2 + 0.25*GLYALD", + "from": "jch3ooh" + }, + { + "to": "jterpnit", + "__reaction": "TERPNIT + hv -> TERPROD1 + NO2 + HO2", + "from": "jch3ooh" + }, + { + "to": "jterprd1", + "__reaction": "TERPROD1 + hv -> HO2 + CO + TERPROD2", + "from": "jch3cho" + }, + { + "to": "jterprd2", + "__reaction": "TERPROD2 + hv -> 0.15*RO2 + 0.68*CH2O + 0.8*CO2 + 0.5*CH3COCH3 + 0.65*CH3CO3 + 1.2*HO2 + 1.7*CO", + "from": "jch3cho" + }, + { + "to": "jxylenooh", + "__reaction": "XYLENOOH + hv -> OH + HO2 + 0.34*GLYOXAL + 0.54*CH3COCHO + 0.06*BIGALD1 + 0.2*BIGALD2 + 0.15*BIGALD3 + 0.21*BIGALD4", + "from": "jch3ooh" + }, + { + "to": "jxylolooh", + "__reaction": "XYLOLOOH + hv -> OH + 0.17*GLYOXAL + 0.51*CH3COCHO + HO2", + "from": "jch3ooh" + }, + { + "to": "jsoa1_a1", + "__reaction": "soa1_a1 + hv -> Products", + "from": "jno2", + "scale by": 0.0004 + }, + { + "to": "jsoa1_a2", + "__reaction": "soa1_a2 + hv -> Products", + "from": "jno2", + "scale by": 0.0004 + }, + { + "to": "jsoa2_a1", + "__reaction": "soa2_a1 + hv -> Products", + "from": "jno2", + "scale by": 0.0004 + }, + { + "to": "jsoa2_a2", + "__reaction": "soa2_a2 + hv -> Products", + "from": "jno2", + "scale by": 0.0004 + }, + { + "to": "jsoa3_a1", + "__reaction": "soa3_a1 + hv -> Products", + "from": "jno2", + "scale by": 0.0004 + }, + { + "to": "jsoa3_a2", + "__reaction": "soa3_a2 + hv -> Products", + "from": "jno2", + "scale by": 0.0004 + }, + { + "to": "jsoa4_a1", + "__reaction": "soa4_a1 + hv -> Products", + "from": "jno2", + "scale by": 0.0004 + }, + { + "to": "jsoa4_a2", + "__reaction": "soa4_a2 + hv -> Products", + "from": "jno2", + "scale by": 0.0004 + }, + { + "to": "jsoa5_a1", + "__reaction": "soa5_a1 + hv -> Products", + "from": "jno2", + "scale by": 0.0004 + }, + { + "to": "jsoa5_a2", + "__reaction": "soa5_a2 + hv -> Products", + "from": "jno2", + "scale by": 0.0004 + }, + { + "to": "jglyoxal", + "__reaction": "GLYOXAL + hv -> 2*CO + 2*HO2", + "from": "jmgly" + } + ] + } + } +}