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"
+ }
+ ]
+ }
+ }
+}