Skip to content

Commit

Permalink
resolve the merge conflict with main
Browse files Browse the repository at this point in the history
  • Loading branch information
boulderdaze committed Jan 9, 2025
2 parents f034bae + d4bd202 commit f771a70
Show file tree
Hide file tree
Showing 9 changed files with 263 additions and 7 deletions.
40 changes: 38 additions & 2 deletions schemes/musica/tuvx/musica_ccpp_tuvx.F90
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module musica_ccpp_tuvx
type(profile_t), pointer :: O2_profile => null()
type(profile_t), pointer :: O3_profile => null()
type(radiator_t), pointer :: cloud_optics => null()
type(radiator_t), pointer :: aerosol_optics => null()
type(index_mappings_t), pointer :: photolysis_rate_constants_mapping => null( )
integer, parameter :: DEFAULT_NUM_PHOTOLYSIS_RATE_CONSTANTS = 0
integer :: number_of_photolysis_rate_constants = DEFAULT_NUM_PHOTOLYSIS_RATE_CONSTANTS
Expand Down Expand Up @@ -94,6 +95,11 @@ subroutine cleanup_tuvx_resources()
cloud_optics => null()
end if

if (associated( aerosol_optics )) then
deallocate( aerosol_optics )
aerosol_optics => null()
end if

if (associated( photolysis_rate_constants_mapping )) then
deallocate( photolysis_rate_constants_mapping )
photolysis_rate_constants_mapping => null()
Expand Down Expand Up @@ -145,6 +151,8 @@ subroutine tuvx_init(vertical_layer_dimension, vertical_interface_dimension, &
only: create_dry_air_profile, create_O2_profile, create_O3_profile
use musica_ccpp_tuvx_cloud_optics, &
only: create_cloud_optics_radiator, cloud_optics_label
use musica_ccpp_tuvx_aerosol_optics, &
only: create_aerosol_optics_radiator, aerosol_optics_label
use musica_ccpp_tuvx_load_species, &
only: DRY_AIR_LABEL, O2_LABEL, O3_LABEL, TUVX_GAS_SPECIES_UNITS

Expand Down Expand Up @@ -310,6 +318,21 @@ subroutine tuvx_init(vertical_layer_dimension, vertical_interface_dimension, &
return
end if

aerosol_optics => create_aerosol_optics_radiator( height_grid, wavelength_grid, &
errmsg, errcode )
if (errcode /= 0) then
call reset_tuvx_map_state( grids, profiles, radiators )
call cleanup_tuvx_resources()
return
endif

call radiators%add( aerosol_optics, error )
if (has_error_occurred( error, errmsg, errcode )) then
call reset_tuvx_map_state( grids, profiles, radiators )
call cleanup_tuvx_resources()
return
end if

tuvx => tuvx_t( trim(filename_of_tuvx_configuration), grids, profiles, &
radiators, error )
if (has_error_occurred( error, errmsg, errcode )) then
Expand Down Expand Up @@ -431,6 +454,15 @@ subroutine tuvx_init(vertical_layer_dimension, vertical_interface_dimension, &
return
end if

aerosol_optics => radiators%get( aerosol_optics_label, error )
if (has_error_occurred( error, errmsg, errcode )) then
deallocate( tuvx )
tuvx => null()
call reset_tuvx_map_state( grids, profiles, radiators )
call cleanup_tuvx_resources()
return
end if

call reset_tuvx_map_state( grids, profiles, radiators )

! 'photolysis_rate_constants_ordering' is a local variable
Expand Down Expand Up @@ -491,6 +523,7 @@ subroutine tuvx_run(temperature, dry_air_density, &
use musica_ccpp_tuvx_surface_albedo, only: set_surface_albedo_values
use musica_ccpp_tuvx_extraterrestrial_flux, only: set_extraterrestrial_flux_values
use musica_ccpp_tuvx_cloud_optics, only: set_cloud_optics_values
use musica_ccpp_tuvx_aerosol_optics, only: set_aerosol_optics_values
use musica_ccpp_tuvx_load_species, only: index_cloud_liquid_water_content, &
index_dry_air, index_O2, index_O3
use musica_ccpp_tuvx_gas_species, only: set_gas_species_values
Expand Down Expand Up @@ -579,6 +612,9 @@ subroutine tuvx_run(temperature, dry_air_density, &
errmsg, errcode )
if (errcode /= 0) return

call set_aerosol_optics_values( aerosol_optics, errmsg, errcode )
if (errcode /= 0) return

! calculate photolysis rate constants and heating rates
call tuvx%run( solar_zenith_angle(i_col), earth_sun_distance, &
photolysis_rate_constants(:,:), heating_rates(:,:), &
Expand All @@ -587,7 +623,7 @@ subroutine tuvx_run(temperature, dry_air_density, &

! filter out negative photolysis rate constants
photolysis_rate_constants(:,:) = &
max( photolysis_rate_constants(:,:), 0.0_kind_phys )
max( photolysis_rate_constants(:,:), 0.0_kind_phys )
end if ! solar zenith angle check

! map photolysis rate constants to the host model's rate parameters and vertical grid
Expand Down Expand Up @@ -617,4 +653,4 @@ subroutine tuvx_final(errmsg, errcode)

end subroutine tuvx_final

end module musica_ccpp_tuvx
end module musica_ccpp_tuvx
103 changes: 103 additions & 0 deletions schemes/musica/tuvx/musica_ccpp_tuvx_aerosol_optics.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
! Copyright (C) 2024 National Science Foundation-National Center for Atmospheric Research
! SPDX-License-Identifier: Apache-2.0
module musica_ccpp_tuvx_aerosol_optics
implicit none

private
public :: create_aerosol_optics_radiator, set_aerosol_optics_values

!> Label for aerosol optical properties in TUV-x
character(len=*), parameter, public :: aerosol_optics_label = "aerosols"
!> Label
character(len=*), parameter, public :: \
aerosol_optical_depth_label = "optical depths"
character(len=*), parameter, public :: \
aerosol_single_scattering_albedo_label = "single scattering albedos"
character(len=*), parameter, public :: \
aerosol_asymmetry_factor_label = "asymmetry factor"
!> Unit
character(len=*), parameter, public :: aerosol_optical_depth_unit = "none"
character(len=*), parameter, public :: aerosol_single_scattering_albedo_unit = "none"
character(len=*), parameter, public :: aerosol_asymmetry_factor_unit = "none"
!> Default value of number of vertical levels
integer, parameter :: DEFAULT_NUM_VERTICAL_LEVELS = 0
!> Number of vertical levels
integer, protected :: num_vertical_levels = DEFAULT_NUM_VERTICAL_LEVELS
!> Default value of number of wavelength bins
integer, parameter :: DEFAULT_NUM_WAVELENGTH_BINS = 0
!> Number of wavelength bins
integer, protected :: num_wavelength_bins = DEFAULT_NUM_WAVELENGTH_BINS
!> Default value of number of streams
integer, parameter :: DEFAULT_NUM_STREAMS = 1
!> Number of streams
integer, protected :: num_streams = DEFAULT_NUM_STREAMS

contains

!> Creates a TUV-x aerosol optics radiator
function create_aerosol_optics_radiator( height_grid, wavelength_grid, &
errmsg, errcode ) result( radiator )
use musica_ccpp_util, only: has_error_occurred
use musica_tuvx_grid, only: grid_t
use musica_tuvx_radiator, only: radiator_t
use musica_util, only: error_t

type(grid_t), intent(inout) :: height_grid
type(grid_t), intent(inout) :: wavelength_grid
character(len=*), intent(out) :: errmsg
integer, intent(out) :: errcode
type(radiator_t), pointer :: radiator

! local variables
type(error_t) :: error

num_vertical_levels = height_grid%number_of_sections( error )
if ( has_error_occurred( error, errmsg, errcode ) ) return

num_wavelength_bins = wavelength_grid%number_of_sections( error )
if ( has_error_occurred( error, errmsg, errcode ) ) return

radiator => radiator_t( aerosol_optics_label, height_grid, wavelength_grid, &
error )
if ( has_error_occurred( error, errmsg, errcode ) ) return

end function create_aerosol_optics_radiator

!> Sets TUV-x aerosol optics values
! Temporarily setting optical properties to zero until aerosol optical
! property calculations are ported to CAM-SIMA.
subroutine set_aerosol_optics_values( radiator, errmsg, errcode )
use ccpp_kinds, only: kind_phys
use musica_ccpp_util, only: has_error_occurred
use musica_tuvx_radiator, only: radiator_t
use musica_util, only: error_t

type(radiator_t), intent(inout) :: radiator
character(len=*), intent(out) :: errmsg
integer, intent(out) :: errcode

! local variables
type(error_t) :: error
real(kind_phys) :: \
aerosol_optical_depth(num_vertical_levels, num_wavelength_bins)
real(kind_phys) :: \
aerosol_single_scattering_albedo(num_vertical_levels, num_wavelength_bins)
real(kind_phys) :: \
aerosol_asymmetry_factor(num_vertical_levels, num_wavelength_bins, num_streams)

aerosol_optical_depth(:,:) = 0.0_kind_phys
aerosol_single_scattering_albedo(:,:) = 0.0_kind_phys
aerosol_asymmetry_factor(:,:,:) = 0.0_kind_phys

call radiator%set_optical_depths( aerosol_optical_depth, error )
if ( has_error_occurred( error, errmsg, errcode ) ) return

call radiator%set_single_scattering_albedos( aerosol_single_scattering_albedo, error )
if ( has_error_occurred( error, errmsg, errcode ) ) return

call radiator%set_asymmetry_factors( aerosol_asymmetry_factor, error )
if ( has_error_occurred( error, errmsg, errcode ) ) return

end subroutine set_aerosol_optics_values

end module musica_ccpp_tuvx_aerosol_optics
2 changes: 1 addition & 1 deletion schemes/musica/tuvx/musica_ccpp_tuvx_surface_albedo.F90
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@ subroutine set_surface_albedo_values( profile, host_surface_albedo, &

end subroutine set_surface_albedo_values

end module musica_ccpp_tuvx_surface_albedo
end module musica_ccpp_tuvx_surface_albedo
2 changes: 1 addition & 1 deletion suites/suite_cam7.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

<!-- Dry Adiabatic Adjustment -->
<scheme>dadadj</scheme>
<scheme>dadadj_apply_qv_tendency</scheme>
<scheme>apply_constituent_tendencies</scheme>
<scheme>apply_heating_rate</scheme>
<scheme>qneg</scheme>
<scheme>geopotential_temp</scheme>
Expand Down
2 changes: 1 addition & 1 deletion test/docker/Dockerfile.musica
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,4 @@ RUN cd atmospheric_physics/test \
-D CCPP_ENABLE_MEMCHECK=ON \
&& cmake --build ./build

WORKDIR /home/test_user/atmospheric_physics/test/build
WORKDIR /home/test_user/atmospheric_physics/test/build
2 changes: 1 addition & 1 deletion test/docker/Dockerfile.musica.no_install
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ RUN cd atmospheric_physics/test \
-D CCPP_ENABLE_MEMCHECK=ON \
&& cmake --build ./build

WORKDIR /home/test_user/atmospheric_physics/test/build
WORKDIR /home/test_user/atmospheric_physics/test/build
30 changes: 30 additions & 0 deletions test/musica/tuvx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,36 @@ add_test(

add_memory_check_test(test_tuvx_cloud_optics $<TARGET_FILE:test_tuvx_cloud_optics> "" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})

# Aerosol optics
add_executable(test_tuvx_aerosol_optics test_tuvx_aerosol_optics.F90)

target_sources(test_tuvx_aerosol_optics
PUBLIC
${MUSICA_SRC_PATH}/tuvx/musica_ccpp_tuvx_height_grid.F90
${MUSICA_SRC_PATH}/tuvx/musica_ccpp_tuvx_wavelength_grid.F90
${MUSICA_SRC_PATH}/tuvx/musica_ccpp_tuvx_aerosol_optics.F90
${MUSICA_SRC_PATH}/musica_ccpp_util.F90
${CCPP_TEST_SRC_PATH}/ccpp_kinds.F90
)

target_link_libraries(test_tuvx_aerosol_optics
PRIVATE
musica::musica-fortran
)

set_target_properties(test_tuvx_aerosol_optics
PROPERTIES
LINKER_LANGUAGE Fortran
)

add_test(
NAME test_tuvx_aerosol_optics
COMMAND $<TARGET_FILE:test_tuvx_aerosol_optics>
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
)

add_memory_check_test(test_tuvx_aerosol_optics $<TARGET_FILE:test_tuvx_aerosol_optics> "" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})

# TUV-x gas species profiles
add_executable(test_tuvx_gas_species test_tuvx_gas_species.F90)

Expand Down
85 changes: 85 additions & 0 deletions test/musica/tuvx/test_tuvx_aerosol_optics.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
! Copyright (C) 2024 National Science Foundation-National Center for Atmospheric Research
! SPDX-License-Identifier: Apache-2.0
program test_tuvx_aerosol_optics

use musica_ccpp_tuvx_aerosol_optics

#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_create_aerosol_optics_radiator()

contains

subroutine test_create_aerosol_optics_radiator()

use musica_util, only: error_t
use musica_ccpp_tuvx_height_grid, only: create_height_grid
use musica_ccpp_tuvx_wavelength_grid, only: create_wavelength_grid
use musica_tuvx_grid, only: grid_t
use musica_tuvx_radiator, only: radiator_t
use ccpp_kinds, only: kind_phys

integer, parameter :: NUM_HOST_HEIGHT_MIDPOINTS = 2
integer, parameter :: NUM_HOST_HEIGHT_INTERFACES = 3
integer, parameter :: NUM_WAVELENGTH_MIDPOINTS = 3
integer, parameter :: NUM_WAVELENGTH_INTERFACES = 4
real(kind_phys) :: host_wavelength_interfaces(NUM_WAVELENGTH_INTERFACES) = [180.0e-9_kind_phys, 200.0e-9_kind_phys, 240.0e-9_kind_phys, 300.0e-9_kind_phys]
real(kind_phys) :: aerosol_optical_depth(NUM_HOST_HEIGHT_MIDPOINTS+1, NUM_WAVELENGTH_MIDPOINTS)
real(kind_phys) :: single_scattering_albedo(NUM_HOST_HEIGHT_MIDPOINTS+1, NUM_WAVELENGTH_MIDPOINTS)
real(kind_phys) :: asymmetry_parameter(NUM_HOST_HEIGHT_MIDPOINTS+1, NUM_WAVELENGTH_MIDPOINTS,1)
type(grid_t), pointer :: height_grid => null()
type(grid_t), pointer :: wavelength_grid => null()
type(radiator_t), pointer :: aerosols => null()
type(error_t) :: error
character(len=512) :: errmsg
integer :: errcode
integer :: i

height_grid => create_height_grid(NUM_HOST_HEIGHT_MIDPOINTS, NUM_HOST_HEIGHT_INTERFACES, &
errmsg, errcode)
ASSERT(errcode == 0)
ASSERT(associated(height_grid))

wavelength_grid => create_wavelength_grid(host_wavelength_interfaces, errmsg, errcode)
ASSERT(errcode == 0)
ASSERT(associated(wavelength_grid))

aerosols => create_aerosol_optics_radiator(height_grid, wavelength_grid, errmsg, errcode)
ASSERT(errcode == 0)
ASSERT(associated(aerosols))

call set_aerosol_optics_values(aerosols, errmsg, errcode)
ASSERT(errcode == 0)

call aerosols%get_optical_depths(aerosol_optical_depth, error)
ASSERT(error%is_success())
do i = 1, size(aerosol_optical_depth, dim=1)
do j = 1, size(aerosol_optical_depth, dim=2)
ASSERT_NEAR(aerosol_optical_depth(i,j), 0.0_kind_phys, ABS_ERROR)
end do
end do

call aerosols%get_single_scattering_albedos(single_scattering_albedo, error)
ASSERT(error%is_success())
do i = 1, size(single_scattering_albedo, dim=1)
do j = 1, size(single_scattering_albedo, dim=2)
ASSERT_NEAR(single_scattering_albedo(i,j), 0.0_kind_phys, ABS_ERROR)
end do
end do

call aerosols%get_asymmetry_factors(asymmetry_parameter, error)
ASSERT(error%is_success())
do i = 1, size(asymmetry_parameter, dim=1)
do j = 1, size(asymmetry_parameter, dim=2)
ASSERT_NEAR(asymmetry_parameter(i,j,1), 0.0_kind_phys, ABS_ERROR)
end do
end do

deallocate( height_grid )
deallocate( wavelength_grid )
deallocate( aerosols )

end subroutine test_create_aerosol_optics_radiator

end program test_tuvx_aerosol_optics
4 changes: 3 additions & 1 deletion test/test_schemes/initialize_constituents.F90
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,16 @@ subroutine initialize_constituents_register(constituents, errmsg, errcode)
errcode = errcode, &
errmsg = errmsg)
else if (any(water_species_std_names == trim(constituent_names(var_index)))) then
! Do not set water_species = .true. for water species mixing ratios
! Avoiding mismatch in properties vs. metadata-specified constituents
! Water species properties are set in air_composition.F90 in CAM-SIMA
call constituents(var_index)%instantiate( &
std_name = constituent_names(var_index), &
long_name = constituent_names(var_index), &
units = 'kg kg-1', &
vertical_dim = 'vertical_layer_dimension', &
min_value = 0.0_kind_phys, &
advected = .true., &
water_species = .true., &
mixing_ratio_type = 'wet', &
errcode = errcode, &
errmsg = errmsg)
Expand Down

0 comments on commit f771a70

Please sign in to comment.