-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
draft burkholder parameterization and tests
- Loading branch information
1 parent
643c95a
commit 676861a
Showing
10 changed files
with
387 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
244 changes: 244 additions & 0 deletions
244
src/cross_sections/util/temperature_parameterization_burkholder.F90
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
! Copyright (C) 2024 National Center for Atmospheric Research | ||
! SPDX-License-Identifier: Apache-2.0 | ||
|
||
module tuvx_temperature_parameterization_burkholder | ||
! Calculates cross-section elements using a temperature-based | ||
! parameterization from Burkholder et al. Phys. Chem. Chem. Phys. 4, 1432-1437 (2002). | ||
|
||
! Including musica_config at the module level to avoid an ICE | ||
! with Intel 2022.1 compiler | ||
use musica_config, only : config_t | ||
use musica_constants, only : dk => musica_dk | ||
use tuvx_temperature_parameterization, & | ||
only : temperature_parameterization_t | ||
use tuvx_temperature_range, only : temperature_range_t | ||
|
||
implicit none | ||
|
||
private | ||
public :: temperature_parameterization_burkholder_t | ||
|
||
!> Parameters for calculating cross section values based on | ||
!! temperature using the algoritm in Burkholder et al. | ||
!! Phys. Chem. Chem. Phys. 4, 1432-1437 (2002). | ||
!! | ||
!! Cross section elements are calculated as: | ||
!! | ||
!! \f[ | ||
!! Q(T) = 1 + e^{\frac{A}{B*T}} | ||
!! \sigma(T,\lambda) = \frac{aa(\lambda)}{Q(T)} + bb(\lambda)*\[1-\frac{1}{Q(T)}\] | ||
!! \f] | ||
!! | ||
!! where A, B, aa, and bb are constants, T is temperature [K] and \f$\lambda\f$ is | ||
!! wavelength [nm]. | ||
type, extends(temperature_parameterization_t) :: temperature_parameterization_burkholder_t | ||
real(kind=dk) :: A_ | ||
real(kind=dk) :: B_ | ||
contains | ||
!> Calculate the cross section value for a specific temperature and wavelength | ||
procedure :: calculate | ||
!> Returns the number of bytes required to pack the parameterization | ||
!! onto a character buffer | ||
procedure :: pack_size => pack_size | ||
!> Packs the parameterization onto a character buffer | ||
procedure :: mpi_pack => mpi_pack | ||
!> Unpacks the parameterization from a character buffer | ||
procedure :: mpi_unpack => mpi_unpack | ||
end type temperature_parameterization_burkholder_t | ||
|
||
!> Constructor for temperature_parameterization_burkholder_t | ||
interface temperature_parameterization_burkholder_t | ||
module procedure :: constructor | ||
end interface temperature_parameterization_burkholder_t | ||
|
||
contains | ||
|
||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
||
!> Constructs a Burkholder (2002) temperature-based parameterization | ||
function constructor( config ) result ( this ) | ||
|
||
use musica_assert, only : assert_msg | ||
use musica_config, only : config_t | ||
use musica_iterator, only : iterator_t | ||
use musica_string, only : string_t | ||
use tuvx_grid, only : grid_t | ||
use tuvx_netcdf, only : netcdf_t | ||
|
||
type(temperature_parameterization_burkholder_t) :: this | ||
type(config_t), intent(inout) :: config | ||
|
||
character(len=*), parameter :: my_name = & | ||
"Burkholder (2002) temperature parameterization constructor" | ||
type(string_t) :: required_keys(3), optional_keys(2), file_path | ||
type(config_t) :: temp_ranges, temp_range, netcdf_file | ||
class(iterator_t), pointer :: iter | ||
type(netcdf_t) :: netcdf | ||
integer :: i_range, i_param, n_param | ||
logical :: found | ||
|
||
required_keys(1) = "netcdf file" | ||
required_keys(2) = "A" | ||
required_keys(3) = "B" | ||
optional_keys(1) = "type" | ||
optional_keys(2) = "temperature ranges" | ||
call assert_msg( 235183546, & | ||
config%validate( required_keys, optional_keys ), & | ||
"Bad configuration for Burkholder (2002) temperature "// & | ||
"parameterization." ) | ||
|
||
! Load NetCDF file | ||
call config%get( "netcdf file", netcdf_file, my_name ) | ||
call netcdf_file%get( "file path", file_path, my_name ) | ||
call netcdf%read_netcdf_file( file_path = file_path%to_char( ), & | ||
variable_name = "temperature_" ) | ||
n_param = size( netcdf%parameters, dim = 2 ) | ||
call assert_msg( 164185428, n_param >= 2, "Burkholder (2002) "// & | ||
"parameterization must have at two sets of "// & | ||
"coefficients" ) | ||
|
||
! Load parameters | ||
call config%get( "A", this%A_, my_name ) | ||
call config%get( "B", this%B_, my_name ) | ||
this%wavelengths_ = netcdf%wavelength(:) | ||
this%AA_ = netcdf%parameters(:,1) | ||
this%BB_ = netcdf%parameters(:,2) | ||
call config%get( "temperature ranges", temp_ranges, my_name, & | ||
found = found ) | ||
if( .not. found ) then | ||
allocate( this%ranges_( 1 ) ) | ||
return | ||
end if | ||
allocate( this%ranges_( temp_ranges%number_of_children( ) ) ) | ||
iter => temp_ranges%get_iterator( ) | ||
i_range = 0 | ||
do while( iter%next( ) ) | ||
i_range = i_range + 1 | ||
call temp_ranges%get( iter, temp_range, my_name ) | ||
this%ranges_( i_range ) = temperature_range_t( temp_range ) | ||
end do | ||
deallocate( iter ) | ||
|
||
! initialize unused data members | ||
allocate( this%lp_(0) ) | ||
|
||
end function constructor | ||
|
||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
||
subroutine calculate( this, temperature, wavelengths, cross_section ) | ||
|
||
use tuvx_profile, only : profile_t | ||
|
||
class(temperature_parameterization_burkholder_t), intent(in) :: this | ||
real(kind=dk), intent(in) :: temperature | ||
real(kind=dk), intent(in) :: wavelengths(:) | ||
real(kind=dk), intent(inout) :: cross_section(:) | ||
|
||
real(kind=dk) :: temp, Q | ||
integer :: i_range, w_min, w_max | ||
|
||
w_min = this%min_wavelength_index_ | ||
w_max = this%max_wavelength_index_ | ||
do i_range = 1, size( this%ranges_ ) | ||
associate( temp_range => this%ranges_( i_range ) ) | ||
if( temperature < temp_range%min_temperature_ .or. & | ||
temperature > temp_range%max_temperature_ ) cycle | ||
if( temp_range%is_fixed_ ) then | ||
temp = temp_range%fixed_temperature_ - this%base_temperature_ | ||
else | ||
temp = temperature - this%base_temperature_ | ||
end if | ||
Q = 1.0 + exp( this%A_ / ( this%B_ * temp ) ) | ||
cross_section( w_min:w_max ) = ( this%AA_(:) / Q + & | ||
this%BB_(:) * ( 1.0 - 1.0 / Q ) & | ||
) * 1.0e-20 | ||
end associate | ||
end do | ||
|
||
end subroutine calculate | ||
|
||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
||
!> Returns the size of a character buffer required to pack the | ||
!! parameterization | ||
integer function pack_size( this, comm ) | ||
|
||
use musica_mpi, only : musica_mpi_pack_size | ||
|
||
!> Parameterization to be packed | ||
class(temperature_parameterization_burkholder_t), intent(in) :: this | ||
!> MPI communicator | ||
integer, intent(in) :: comm | ||
|
||
#ifdef MUSICA_USE_MPI | ||
pack_size = this%temperature_parameterization_t%pack_size( comm ) + & | ||
musica_mpi_pack_size( this%A_, comm ) + & | ||
musica_mpi_pack_size( this%B_, comm ) | ||
#else | ||
pack_size = 0 | ||
#endif | ||
|
||
end function pack_size | ||
|
||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
||
!> Packs the parameterization onto a character buffer | ||
subroutine mpi_pack( this, buffer, position, comm ) | ||
|
||
use musica_assert, only : assert | ||
use musica_mpi, only : musica_mpi_pack | ||
|
||
!> Parameterization to be packed | ||
class(temperature_parameterization_burkholder_t), intent(in) :: this | ||
!> Memory buffer | ||
character, intent(inout) :: buffer(:) | ||
!> Current buffer position | ||
integer, intent(inout) :: position | ||
!> MPI communicator | ||
integer, intent(in) :: comm | ||
|
||
#ifdef MUSICA_USE_MPI | ||
integer :: prev_pos | ||
|
||
prev_pos = position | ||
call this%temperature_parameterization_t%mpi_pack( buffer, position, comm ) | ||
call musica_mpi_pack( buffer, position, this%A_, comm ) | ||
call musica_mpi_pack( buffer, position, this%B_, comm ) | ||
call assert( 190816083, position - prev_pos <= this%pack_size( comm ) ) | ||
#endif | ||
|
||
end subroutine mpi_pack | ||
|
||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
||
!> Unpacks a parameterization from a character buffer | ||
subroutine mpi_unpack( this, buffer, position, comm ) | ||
|
||
use musica_assert, only : assert | ||
use musica_mpi, only : musica_mpi_unpack | ||
|
||
!> The parameterization to be unpacked | ||
class(temperature_parameterization_burkholder_t), intent(out) :: this | ||
!> Memory buffer | ||
character, intent(inout) :: buffer(:) | ||
!> Current buffer position | ||
integer, intent(inout) :: position | ||
!> MPI communicator | ||
integer, intent(in) :: comm | ||
|
||
#ifdef MUSICA_USE_MPI | ||
integer :: prev_pos | ||
|
||
prev_pos = position | ||
call this%temperature_parameterization_t%mpi_unpack( buffer, position, comm ) | ||
call musica_mpi_unpack( buffer, position, this%A_, comm ) | ||
call musica_mpi_unpack( buffer, position, this%B_, comm ) | ||
call assert( 634825156, position - prev_pos <= this%pack_size( comm ) ) | ||
#endif | ||
|
||
end subroutine mpi_unpack | ||
|
||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
||
end module tuvx_temperature_parameterization_burkholder |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"type": "BURKHOLDER", | ||
"netcdf file": { | ||
"file path": "test/data/cross_sections/util/burkholder.nc" | ||
}, | ||
"A": 12.5, | ||
"B": 202.3, | ||
"temperature ranges": [ | ||
{ | ||
"maximum": 209.999999999999, | ||
"fixed value": 210.0 | ||
}, | ||
{ | ||
"minimum": 210.0, | ||
"maximum": 300.0 | ||
}, | ||
{ | ||
"minimum": 300.00000000001, | ||
"fixed value": 300.0 | ||
} | ||
] | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.