Skip to content

Commit

Permalink
Merge pull request #7 from NCAR/develop-3-initial-optics
Browse files Browse the repository at this point in the history
  • Loading branch information
mattldawson authored Oct 19, 2023
2 parents 956c682 + 6e120a6 commit 7b7b7fb
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 19 deletions.
2 changes: 1 addition & 1 deletion cmake/dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ else()

FetchContent_Declare(musicacore
GIT_REPOSITORY https://github.com/NCAR/musica-core.git
GIT_TAG v0.4.0
GIT_TAG v0.4.1
FIND_PACKAGE_ARGS NAMES musicacore
)

Expand Down
48 changes: 47 additions & 1 deletion docs/source/user_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,52 @@ the provided units that is present in the list of
These profiles should describe the concentration of
the constituent on the ``height`` grid.


From NetCDF file
~~~~~~~~~~~~~~~~
This radiator type allows loading the optical properties of
a radiator from a NetCDF file. The optical properties will
remain constant throughout the calculations.

.. code-block:: JSON
{
"name": "foo",
"type": "from netcdf file",
"file path": "path/to/file.nc"
}
============================ ==============
keys Required/Optional
============================ ==============
``name`` required
``type`` required
``file path`` required
============================ ==============

The ``file path`` should be a string containing the absolute
or relative path to the NetCDF file containing the optical
properties.

The NetCDF file should be structured as follows::

dimensions:
heights = NUMBER_OF_VERTICAL_LAYERS ;
wavelengths = NUMBER_OF_WAVELENGTH_BINS ;
variables:
double optical_depth(wavelengths, heights) ;
double single_scattering_albedo(wavelengths, heights) ;
double asymmetry_factor(wavelengths, heights) ;


The ``NUMBER_OF_VERTICAL_LAYERS`` and ``NUMBER_OF_WAVELENGTH_BINS``
must correspond to the number of bins in the ``height`` and
``wavelength`` grids specified in the TUV-x configuration file.
(Note that these optical properties are per grid section and not at
grid edges.) No interpolation is performed on this data set.


Aerosols
~~~~~~~~
A special radiator type exists for aerosols, which
Expand Down Expand Up @@ -762,7 +808,7 @@ keys Required/Optional
``enable diagnostics`` optional
============================ ==============

The regressoin tests compare the new version of TUV-x to the old version. One
The regression tests compare the new version of TUV-x to the old version. One
way is by directly comparing output. The `enable diagnostics` allows for this
ouptut to be disabled. If this is enabled, a folder named `output` will be
created in the same directory TUV-x is run from.
Expand Down
19 changes: 2 additions & 17 deletions etc/modeling2/build_tuvx_modeling2_gnu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export LD_LIBRARY_PATH="/opt/local/lib64:/opt/local/lib:/usr/bin:/usr/lib:usr/li
cd ${TUVX_HOME}
curl -LO https://github.com/jacobwilliams/json-fortran/archive/8.2.1.tar.gz
git clone https://github.com/NCAR/tuv-x.git
git clone https://github.com/NCAR/musica-core.git

# extract
cd ${TUVX_HOME}
Expand All @@ -39,35 +38,21 @@ cd $JSON_FORTRAN_ROOT
sed -i 's/\-C $<CONFIG>//' CMakeLists.txt
mkdir -p build
cd build
cmake3 -D CMAKE_Fortran_COMPILER=/opt/local/bin/gfortran \
cmake -D CMAKE_Fortran_COMPILER=/opt/local/bin/gfortran \
-D SKIP_DOC_GEN:BOOL=TRUE \
-D CMAKE_INSTALL_PREFIX=$INSTALL_ROOT \
..
make -j4 install
mkdir -p $JSON_FORTRAN_HOME/lib/shared
mv $JSON_FORTRAN_HOME/lib/*.so* $JSON_FORTRAN_HOME/lib/shared

# musica-core
MUSICA_CORE_ROOT=${TUVX_HOME}/musica-core
export MUSICA_CORE_HOME=${INSTALL_ROOT}/musica-core-0.1.0
export MUSICA_CORE_PACKAGE=${INSTALL_ROOT}/musicacore-0.1.0/cmake/musicacore-0.1.0
cd ${MUSICA_CORE_ROOT}
mkdir -p build
cd build
cmake3 -D CMAKE_Fortran_COMPILER=gfortran \
-D CMAKE_BUILD_TYPE=release \
-D CMAKE_INSTALL_PREFIX=${INSTALL_ROOT} \
..
make -j4 install

# TUV-x
TUVX_ROOT=$TUVX_HOME/tuv-x
cd $TUVX_ROOT
mkdir -p build
cd build
cmake3 -D CMAKE_Fortran_COMPILER=/opt/local/bin/gfortran \
cmake -D CMAKE_Fortran_COMPILER=/opt/local/bin/gfortran \
-D CMAKE_BUILD_TYPE=release \
-D musicacore_DIR=${MUSICA_CORE_PACKAGE} \
-D ENABLE_COVERAGE=OFF \
-D ENABLE_MEMCHECK=OFF \
-D CMAKE_INSTALL_PREFIX=${TUVX_HOME} \
Expand Down
8 changes: 8 additions & 0 deletions src/radiative_transfer/radiator_factory.F90
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module tuvx_radiator_factory
use tuvx_radiator, only : radiator_t
use tuvx_radiator_aerosol, only : radiator_aerosol_t
use tuvx_radiator_from_host, only : radiator_from_host_t
use tuvx_radiator_from_netcdf_file, only : radiator_from_netcdf_file_t

implicit none

Expand Down Expand Up @@ -49,6 +50,9 @@ function radiator_builder( config, grid_warehouse, profile_warehouse, &
case( 'aerosol' )
new_radiator => radiator_aerosol_t( config, grid_warehouse, &
profile_warehouse )
case( 'from netcdf file' )
new_radiator => radiator_from_netcdf_file_t( config, grid_warehouse, &
profile_warehouse )
case default
call die_msg( 460768245, "Invalid radiator type: '"// &
radiator_type%to_char()//"'" )
Expand All @@ -73,6 +77,8 @@ type(string_t) function radiator_type_name( radiator ) result( name )
name = "radiator_aerosol_t"
type is( radiator_from_host_t )
name = "radiator_from_host_t"
type is( radiator_from_netcdf_file_t )
name = "radiator_from_netcdf_file_t"
class default
call die( 365718517 )
end select
Expand All @@ -99,6 +105,8 @@ function radiator_allocate( type_name ) result( radiator )
allocate( radiator_aerosol_t :: radiator )
case( 'radiator_from_host_t' )
allocate( radiator_from_host_t :: radiator )
case( 'radiator_from_netcdf_file_t' )
allocate( radiator_from_netcdf_file_t :: radiator )
case default
call die_msg( 670539061, "Invalid radiator type: '"// &
type_name//"'" )
Expand Down
1 change: 1 addition & 0 deletions src/radiative_transfer/radiators/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ target_sources(tuvx_object
PRIVATE
aerosol.F90
from_host.F90
from_netcdf_file.F90
)

################################################################################
116 changes: 116 additions & 0 deletions src/radiative_transfer/radiators/from_netcdf_file.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
! Copyright (C) 2023 National Center for Atmospheric Research
! SPDX-License-Identifier: Apache-2.0
module tuvx_radiator_from_netcdf_file

use musica_constants, only : dk => musica_dk
use musica_string, only : string_t
use tuvx_radiator, only : radiator_t

implicit none

private
public :: radiator_from_netcdf_file_t

!> User-specified radiator
!!
!! User-specified radiators have fixed optical properties that are read
!! in from a NetCDF file.
type, extends(radiator_t) :: radiator_from_netcdf_file_t
contains
!> Update the radiator for new environmental conditions
procedure :: update_state
end type radiator_from_netcdf_file_t

!> User-specified radiator constructor
interface radiator_from_netcdf_file_t
module procedure constructor
end interface radiator_from_netcdf_file_t

contains

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!> Initialize a user-specified radiator
function constructor( config, grid_warehouse, profile_warehouse ) &
result ( this )

use musica_assert, only : assert_msg
use musica_config, only : config_t
use musica_string, only : string_t
use tuvx_grid, only : grid_t
use tuvx_grid_warehouse, only : grid_warehouse_t
use musica_io_netcdf, only : io_netcdf_t
use tuvx_profile_warehouse, only : profile_warehouse_t

class(radiator_from_netcdf_file_t), pointer :: this ! The constructor radiator
type(config_t), intent(inout) :: config ! configuration for the radiator
type(grid_warehouse_t), intent(inout) :: grid_warehouse ! Configured grids
type(profile_warehouse_t), intent(inout) :: profile_warehouse ! Configured profiles

character(len=*), parameter :: Iam = &
"radiator from NetCDF file constructor"
class(grid_t), pointer :: heights, wavelengths
type(string_t) :: file_path, variable
type(io_netcdf_t), pointer :: netcdf_file
real(kind=dk), allocatable :: temp_G(:,:)
integer :: i_wl, i_height
type(string_t) :: required_keys(3), optional_keys(0)

required_keys(1) = "type"
required_keys(2) = "name"
required_keys(3) = "file path"
call assert_msg( 723245326, &
config%validate( required_keys, optional_keys ), &
"Bad configuration data format for radiator from NetCDF" )

allocate(this)

call config%get( "name", this%handle_, Iam )
call config%get( "type", this%type_, Iam )

heights => grid_warehouse%get_grid( "height", "km" )
wavelengths => grid_warehouse%get_grid( "wavelength", "nm" )

allocate( this%state_%layer_OD_( heights%ncells_, wavelengths%ncells_ ) )
allocate( this%state_%layer_SSA_( heights%ncells_, wavelengths%ncells_ ) )
allocate( this%state_%layer_G_( heights%ncells_, wavelengths%ncells_, 1 ) )
allocate( temp_G( heights%ncells_, wavelengths%ncells_ ) )

call config%get( "file path", file_path, Iam )
netcdf_file => io_netcdf_t( file_path, read_only = .true. )
variable = "optical_depth"
call netcdf_file%read_2D_double( variable, this%state_%layer_OD_, Iam )
variable = "single_scattering_albedo"
call netcdf_file%read_2D_double( variable, this%state_%layer_SSA_, Iam )
variable = "asymmetry_factor"
call netcdf_file%read_2D_double( variable, temp_G, Iam )
this%state_%layer_G_(:,:,1) = temp_G(:,:)

deallocate( netcdf_file )
deallocate( heights )
deallocate( wavelengths )

end function constructor

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!> Update the radiator state for current conditions
subroutine update_state( this, grid_warehouse, profile_warehouse, &
cross_section_warehouse )

use tuvx_cross_section_warehouse, only : cross_section_warehouse_t
use tuvx_grid_warehouse, only : grid_warehouse_t
use tuvx_profile_warehouse, only : profile_warehouse_t

class(radiator_from_netcdf_file_t), intent(inout) :: this ! Radiator to update
type(grid_warehouse_t), intent(inout) :: grid_warehouse ! Current grids
type(profile_warehouse_t), intent(inout) :: profile_warehouse ! Current profiles
type(cross_section_warehouse_t), intent(inout) :: cross_section_warehouse ! Current cross-sections

! nothing to update - radiator properties for this type are fixed

end subroutine update_state

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

end module tuvx_radiator_from_netcdf_file
Binary file added test/data/radiator.nc
Binary file not shown.
23 changes: 23 additions & 0 deletions test/data/radiators.from_netcdf_file.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"grids": [
{
"name" : "height",
"type" : "from config file",
"units" : "km",
"values" : [ 0.0, 10.0, 20.0, 30.0 ]
},
{
"name" : "wavelength",
"type" : "from config file",
"units" : "nm",
"values" : [ 550.0, 600.0, 650.0, 700.0, 720.0 ]
}
],
"radiators": [
{
"name" : "foo",
"type" : "from netcdf file",
"file path" : "test/data/radiator.nc"
}
]
}
1 change: 1 addition & 0 deletions test/unit/radiator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ include(test_util)
create_standard_test(NAME radiator SOURCES radiator_core.F90
radiator_test.F90)
create_standard_test(NAME radiator_from_host SOURCES from_host.F90)
create_standard_test(NAME radiator_from_netcdf_file SOURCES from_netcdf_file.F90)

################################################################################
Loading

0 comments on commit 7b7b7fb

Please sign in to comment.