diff --git a/components/eam/bld/configure b/components/eam/bld/configure
index 30ad7e6fced1..a14eda84d646 100755
--- a/components/eam/bld/configure
+++ b/components/eam/bld/configure
@@ -2617,6 +2617,7 @@ sub write_filepath
} elsif ($rad eq 'rrtmgp') {
print $fh "$camsrcdir/eam/src/physics/rrtmgp\n";
if (not defined $opts{'rrtmgpxx'} ) {
+ print $fh "$camsrcdir/eam/src/physics/rrtmgp/f90\n";
print $fh "$camsrcdir/eam/src/physics/rrtmgp/external/rte\n";
print $fh "$camsrcdir/eam/src/physics/rrtmgp/external/rte/kernels\n";
print $fh "$camsrcdir/eam/src/physics/rrtmgp/external/rrtmgp\n";
@@ -2624,7 +2625,6 @@ sub write_filepath
print $fh "$camsrcdir/eam/src/physics/rrtmgp/external/extensions\n";
print $fh "$camsrcdir/eam/src/physics/rrtmgp/external/extensions/rng\n";
print $fh "$camsrcdir/eam/src/physics/rrtmgp/external/examples\n";
- print $fh "$camsrcdir/eam/src/physics/rrtmgp/f90\n";
}
}
diff --git a/components/eam/bld/namelist_files/namelist_defaults_eam.xml b/components/eam/bld/namelist_files/namelist_defaults_eam.xml
index 371a9d7857b5..787e8f3a7bec 100755
--- a/components/eam/bld/namelist_files/namelist_defaults_eam.xml
+++ b/components/eam/bld/namelist_files/namelist_defaults_eam.xml
@@ -359,8 +359,8 @@
atm/cam/physprops/F_nwvl200_mu20_lam50_res64_t298_c080428.nc
-atm/cam/rad/rrtmgp_coefficients_lw_20181204.nc
-atm/cam/rad/rrtmgp_coefficients_sw_20181204.nc
+atm/cam/rad/rrtmgp-data-lw-g128-210809.nc
+atm/cam/rad/rrtmgp-data-sw-g112-210809.nc
.true.
.false.
diff --git a/components/eam/src/physics/rrtmgp/cpp/CMakeLists.txt b/components/eam/src/physics/rrtmgp/cpp/CMakeLists.txt
index 5415e410c64f..91ec61acf625 100644
--- a/components/eam/src/physics/rrtmgp/cpp/CMakeLists.txt
+++ b/components/eam/src/physics/rrtmgp/cpp/CMakeLists.txt
@@ -1,8 +1,8 @@
set (F90_SRC rrtmgp_interface.F90)
set (CXX_SRC
rrtmgp_interface.cpp
+ mo_load_coefficients.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../external/cpp/extensions/fluxes_byband/mo_fluxes_byband_kernels.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/../external/cpp/examples/mo_load_coefficients.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../external/cpp/examples/all-sky/mo_load_cloud_coefficients.cpp
)
diff --git a/components/eam/src/physics/rrtmgp/cpp/mo_load_coefficients.cpp b/components/eam/src/physics/rrtmgp/cpp/mo_load_coefficients.cpp
new file mode 100644
index 000000000000..e1d9c0a526c0
--- /dev/null
+++ b/components/eam/src/physics/rrtmgp/cpp/mo_load_coefficients.cpp
@@ -0,0 +1,123 @@
+
+#include "mo_load_coefficients.h"
+#include "YAKL_netcdf.h"
+
+// This code is part of RRTM for GCM Applications - Parallel (RRTMGP)
+//
+// Contacts: Robert Pincus and Eli Mlawer
+// email: rrtmgp@aer.com
+//
+// Copyright 2015-2018, Atmospheric and Environmental Research and
+// Regents of the University of Colorado. All right reserved.
+//
+// Use and duplication is permitted under the terms of the
+// BSD 3-clause license, see http://opensource.org/licenses/BSD-3-Clause
+// -------------------------------------------------------------------------------------------------
+
+void load_and_init(GasOpticsRRTMGP &kdist, std::string filename, GasConcs const &available_gases) {
+ yakl::SimpleNetCDF io;
+ io.open(filename , yakl::NETCDF_MODE_READ);
+
+ // Read the many arrays
+ string1d gas_names;
+ string1d gas_minor;
+ string1d identifier_minor;
+ string1d minor_gases_lower;
+ string1d minor_gases_upper;
+ string1d scaling_gas_lower;
+ string1d scaling_gas_upper;
+ intHost3d key_species;
+ realHost2d band_lims;
+ intHost2d band2gpt;
+ real press_ref_trop;
+ real temp_ref_p;
+ real temp_ref_t;
+ realHost1d press_ref;
+ realHost1d temp_ref;
+ realHost3d vmr_ref;
+ realHost4d kmajor;
+ intHost2d minor_limits_gpt_lower;
+ intHost2d minor_limits_gpt_upper;
+ boolHost1d minor_scales_with_density_lower;
+ boolHost1d minor_scales_with_density_upper;
+ boolHost1d scale_by_complement_lower;
+ boolHost1d scale_by_complement_upper;
+ intHost1d kminor_start_lower;
+ intHost1d kminor_start_upper;
+ realHost3d kminor_lower;
+ realHost3d kminor_upper;
+ realHost3d rayl_lower;
+ realHost3d rayl_upper;
+
+ // Read in strings
+ charHost2d tmp;
+ tmp = charHost2d(); io.read( tmp , "gas_names" ); gas_names = char2d_to_string1d(tmp);
+ tmp = charHost2d(); io.read( tmp , "gas_minor" ); gas_minor = char2d_to_string1d(tmp);
+ tmp = charHost2d(); io.read( tmp , "identifier_minor" ); identifier_minor = char2d_to_string1d(tmp);
+ tmp = charHost2d(); io.read( tmp , "minor_gases_lower" ); minor_gases_lower = char2d_to_string1d(tmp);
+ tmp = charHost2d(); io.read( tmp , "minor_gases_upper" ); minor_gases_upper = char2d_to_string1d(tmp);
+ tmp = charHost2d(); io.read( tmp , "scaling_gas_lower" ); scaling_gas_lower = char2d_to_string1d(tmp);
+ tmp = charHost2d(); io.read( tmp , "scaling_gas_upper" ); scaling_gas_upper = char2d_to_string1d(tmp);
+
+ io.read( key_species , "key_species" );
+ io.read( band_lims , "bnd_limits_wavenumber" );
+ io.read( band2gpt , "bnd_limits_gpt" );
+ io.read( press_ref , "press_ref" );
+ io.read( temp_ref , "temp_ref" );
+ io.read( temp_ref_p , "absorption_coefficient_ref_P" );
+ io.read( temp_ref_t , "absorption_coefficient_ref_T" );
+ io.read( press_ref_trop , "press_ref_trop" );
+ io.read( kminor_lower , "kminor_lower" );
+ io.read( kminor_upper , "kminor_upper" );
+ io.read( minor_limits_gpt_lower , "minor_limits_gpt_lower" );
+ io.read( minor_limits_gpt_upper , "minor_limits_gpt_upper" );
+ io.read( minor_scales_with_density_lower , "minor_scales_with_density_lower" );
+ io.read( minor_scales_with_density_upper , "minor_scales_with_density_upper" );
+ io.read( scale_by_complement_lower , "scale_by_complement_lower" );
+ io.read( scale_by_complement_upper , "scale_by_complement_upper" );
+ io.read( kminor_start_lower , "kminor_start_lower" );
+ io.read( kminor_start_upper , "kminor_start_upper" );
+ io.read( vmr_ref , "vmr_ref" );
+ io.read( kmajor , "kmajor" );
+
+ if (io.varExists("rayl_lower")) {
+ io.read( rayl_lower , "rayl_lower" );
+ io.read( rayl_upper , "rayl_upper" );
+ }
+
+ // Initialize the gas optics class with data. The calls look slightly different depending
+ // on whether the radiation sources are internal to the atmosphere (longwave) or external (shortwave)
+ // gas_optics%load() returns a string; a non-empty string indicates an error.
+ if (io.varExists("totplnk")) {
+ // If there's a totplnk variable in the file, then it's a longwave (internal sources) type
+ realHost2d totplnk;
+ realHost4d planck_frac;
+ io.read( totplnk , "totplnk" );
+ io.read( planck_frac , "plank_fraction" );
+ kdist.load(available_gases, gas_names, key_species, band2gpt, band_lims, press_ref, press_ref_trop,
+ temp_ref, temp_ref_p, temp_ref_t, vmr_ref, kmajor, kminor_lower, kminor_upper,
+ gas_minor, identifier_minor, minor_gases_lower, minor_gases_upper,
+ minor_limits_gpt_lower, minor_limits_gpt_upper, minor_scales_with_density_lower,
+ minor_scales_with_density_upper, scaling_gas_lower, scaling_gas_upper,
+ scale_by_complement_lower, scale_by_complement_upper, kminor_start_lower,
+ kminor_start_upper, totplnk, planck_frac, rayl_lower, rayl_upper);
+ } else {
+ // Otherwise, it's a shortwave type
+ realHost1d solar_src;
+ if (io.varExists("solar_source")) {
+ io.read( solar_src , "solar_source" );
+ } else {
+ io.read( solar_src , "solar_source_quiet" );
+ }
+ kdist.load(available_gases, gas_names, key_species, band2gpt, band_lims, press_ref, press_ref_trop,
+ temp_ref, temp_ref_p, temp_ref_t, vmr_ref, kmajor, kminor_lower, kminor_upper,
+ gas_minor, identifier_minor, minor_gases_lower, minor_gases_upper,
+ minor_limits_gpt_lower, minor_limits_gpt_upper, minor_scales_with_density_lower,
+ minor_scales_with_density_upper, scaling_gas_lower, scaling_gas_upper,
+ scale_by_complement_lower, scale_by_complement_upper, kminor_start_lower,
+ kminor_start_upper, solar_src, rayl_lower, rayl_upper);
+ }
+ io.close();
+}
+
+
diff --git a/components/eam/src/physics/rrtmgp/f90/mo_load_coefficients.F90 b/components/eam/src/physics/rrtmgp/f90/mo_load_coefficients.F90
new file mode 100644
index 000000000000..2858c9931864
--- /dev/null
+++ b/components/eam/src/physics/rrtmgp/f90/mo_load_coefficients.F90
@@ -0,0 +1,241 @@
+! This code is part of RRTM for GCM Applications - Parallel (RRTMGP)
+!
+! Contacts: Robert Pincus and Eli Mlawer
+! email: rrtmgp@aer.com
+!
+! Copyright 2015-2018, Atmospheric and Environmental Research and
+! Regents of the University of Colorado. All right reserved.
+!
+! Use and duplication is permitted under the terms of the
+! BSD 3-clause license, see http://opensource.org/licenses/BSD-3-Clause
+! -------------------------------------------------------------------------------------------------
+!
+! The gas optics class used by RRMTGP needs to be initialized with data stored in a netCDF file.
+! RRTMGP itself doesn't include methods for reading the data so we don't conflict with users'
+! local environment. This module provides a straight-forward implementation of reading the data
+! and calling gas_optics%load().
+!
+! -------------------------------------------------------------------------------------------------
+module mo_load_coefficients
+ !
+ ! Modules for working with rte and rrtmgp
+ !
+ use mo_rte_kind, only: wp, wl
+ use mo_gas_concentrations, only: ty_gas_concs
+ use mo_gas_optics_rrtmgp, only: ty_gas_optics_rrtmgp
+ ! --------------------------------------------------
+ use mo_simple_netcdf, only: read_field, read_char_vec, read_logical_vec, var_exists, get_dim_size
+ use netcdf
+ implicit none
+ private
+ public :: load_and_init
+
+contains
+ subroutine stop_on_err(msg)
+ use iso_fortran_env, only : error_unit
+ character(len=*), intent(in) :: msg
+
+ if(msg /= "") then
+ write(error_unit, *) msg
+ stop
+ end if
+ end subroutine
+ !--------------------------------------------------------------------------------------------------------------------
+ ! read optical coefficients from NetCDF file
+ subroutine load_and_init(kdist, filename, available_gases)
+ class(ty_gas_optics_rrtmgp), intent(inout) :: kdist
+ character(len=*), intent(in ) :: filename
+ class(ty_gas_concs), intent(in ) :: available_gases ! Which gases does the host model have available?
+ ! --------------------------------------------------
+ !
+ ! Variables that will be passed to gas_optics%load()
+ !
+ character(len=32), dimension(:), allocatable :: gas_names
+ integer, dimension(:,:,:), allocatable :: key_species
+ integer, dimension(:,: ), allocatable :: band2gpt
+ real(wp), dimension(:,: ), allocatable :: band_lims
+ real(wp) :: press_ref_trop, temp_ref_p, temp_ref_t
+ real(wp), dimension(: ), allocatable :: press_ref
+ real(wp), dimension(: ), allocatable :: temp_ref
+ real(wp), dimension(:,:,: ), allocatable :: vmr_ref
+ real(wp), dimension(:,:,:,:), allocatable :: kmajor
+
+ character(len=32), dimension(:), allocatable :: gas_minor, identifier_minor
+ character(len=32), dimension(:), allocatable :: minor_gases_lower, minor_gases_upper
+ integer, dimension(:,:), allocatable :: minor_limits_gpt_lower, minor_limits_gpt_upper
+ logical(wl), dimension(:), allocatable :: minor_scales_with_density_lower, minor_scales_with_density_upper
+ character(len=32), dimension(:), allocatable :: scaling_gas_lower, scaling_gas_upper
+ logical(wl), dimension(:), allocatable :: scale_by_complement_lower, scale_by_complement_upper
+ integer, dimension(:), allocatable :: kminor_start_lower, kminor_start_upper
+ real(wp), dimension(:,:,:), allocatable :: kminor_lower, kminor_upper
+
+ real(wp), dimension(:,:,: ), allocatable :: rayl_lower, rayl_upper
+ real(wp), dimension(: ), allocatable :: solar_src
+ real(wp), dimension(:,: ), allocatable :: totplnk
+ real(wp), dimension(:,:,:,:), allocatable :: planck_frac
+ ! -----------------
+ !
+ ! Book-keeping variables
+ !
+ integer :: ncid
+ integer :: ntemps, &
+ npress, &
+ nabsorbers, &
+ nextabsorbers, &
+ nminorabsorbers, &
+ nmixingfracs, &
+ nlayers, &
+ nbnds, &
+ ngpts, &
+ npairs, &
+ nminor_absorber_intervals_lower, &
+ nminor_absorber_intervals_upper, &
+ ncontributors_lower, &
+ ncontributors_upper, &
+ ninternalSourcetemps
+ ! --------------------------------------------------
+ !
+ ! How big are the various arrays?
+ !
+ if(nf90_open(trim(fileName), NF90_NOWRITE, ncid) /= NF90_NOERR) &
+ call stop_on_err("load_and_init(): can't open file " // trim(fileName))
+ ntemps = get_dim_size(ncid,'temperature')
+ npress = get_dim_size(ncid,'pressure')
+ nabsorbers = get_dim_size(ncid,'absorber')
+ nminorabsorbers = get_dim_size(ncid,'minor_absorber')
+ nextabsorbers = get_dim_size(ncid,'absorber_ext')
+ nmixingfracs = get_dim_size(ncid,'mixing_fraction')
+ nlayers = get_dim_size(ncid,'atmos_layer')
+ nbnds = get_dim_size(ncid,'bnd')
+ ngpts = get_dim_size(ncid,'gpt')
+ npairs = get_dim_size(ncid,'pair')
+ nminor_absorber_intervals_lower &
+ = get_dim_size(ncid,'minor_absorber_intervals_lower')
+ nminor_absorber_intervals_upper &
+ = get_dim_size(ncid,'minor_absorber_intervals_upper')
+ ninternalSourcetemps &
+ = get_dim_size(ncid,'temperature_Planck')
+ ncontributors_lower = get_dim_size(ncid,'contributors_lower')
+ ncontributors_upper = get_dim_size(ncid,'contributors_upper')
+ ! -----------------
+ !
+ ! Read the many arrays
+ !
+ gas_names = read_char_vec(ncid, 'gas_names', nabsorbers)
+ key_species = read_field(ncid, 'key_species', 2, nlayers, nbnds)
+ band_lims = read_field(ncid, 'bnd_limits_wavenumber', 2, nbnds)
+ band2gpt = int(read_field(ncid, 'bnd_limits_gpt', 2, nbnds))
+ press_ref = read_field(ncid, 'press_ref', npress)
+ temp_ref = read_field(ncid, 'temp_ref', ntemps)
+ temp_ref_p = read_field(ncid, 'absorption_coefficient_ref_P')
+ temp_ref_t = read_field(ncid, 'absorption_coefficient_ref_T')
+ press_ref_trop = read_field(ncid, 'press_ref_trop')
+ kminor_lower = read_field(ncid, 'kminor_lower', &
+ ncontributors_lower, nmixingfracs, ntemps)
+ kminor_upper = read_field(ncid, 'kminor_upper', &
+ ncontributors_upper, nmixingfracs, ntemps)
+ gas_minor = read_char_vec(ncid, 'gas_minor', nminorabsorbers)
+ identifier_minor = read_char_vec(ncid, 'identifier_minor', nminorabsorbers)
+ minor_gases_lower = read_char_vec(ncid, 'minor_gases_lower', nminor_absorber_intervals_lower)
+ minor_gases_upper = read_char_vec(ncid, 'minor_gases_upper', nminor_absorber_intervals_upper)
+ minor_limits_gpt_lower &
+ = int(read_field(ncid, 'minor_limits_gpt_lower', npairs,nminor_absorber_intervals_lower))
+ minor_limits_gpt_upper &
+ = int(read_field(ncid, 'minor_limits_gpt_upper', npairs,nminor_absorber_intervals_upper))
+ minor_scales_with_density_lower &
+ = read_logical_vec(ncid, 'minor_scales_with_density_lower', nminor_absorber_intervals_lower)
+ minor_scales_with_density_upper &
+ = read_logical_vec(ncid, 'minor_scales_with_density_upper', nminor_absorber_intervals_upper)
+ scale_by_complement_lower &
+ = read_logical_vec(ncid, 'scale_by_complement_lower', nminor_absorber_intervals_lower)
+ scale_by_complement_upper &
+ = read_logical_vec(ncid, 'scale_by_complement_upper', nminor_absorber_intervals_upper)
+ scaling_gas_lower &
+ = read_char_vec(ncid, 'scaling_gas_lower', nminor_absorber_intervals_lower)
+ scaling_gas_upper &
+ = read_char_vec(ncid, 'scaling_gas_upper', nminor_absorber_intervals_upper)
+ kminor_start_lower &
+ = read_field(ncid, 'kminor_start_lower', nminor_absorber_intervals_lower)
+ kminor_start_upper &
+ = read_field(ncid, 'kminor_start_upper', nminor_absorber_intervals_upper)
+ vmr_ref = read_field(ncid, 'vmr_ref', nlayers, nextabsorbers, ntemps)
+
+ kmajor = read_field(ncid, 'kmajor', ngpts, nmixingfracs, npress+1, ntemps)
+ if(var_exists(ncid, 'rayl_lower')) then
+ rayl_lower = read_field(ncid, 'rayl_lower', ngpts, nmixingfracs, ntemps)
+ rayl_upper = read_field(ncid, 'rayl_upper', ngpts, nmixingfracs, ntemps)
+ end if
+ ! --------------------------------------------------
+ !
+ ! Initialize the gas optics class with data. The calls look slightly different depending
+ ! on whether the radiation sources are internal to the atmosphere (longwave) or external (shortwave)
+ ! gas_optics%load() returns a string; a non-empty string indicates an error.
+ !
+ if(var_exists(ncid, 'totplnk')) then
+ !
+ ! If there's a totplnk variable in the file it's a longwave (internal sources) type
+ !
+ totplnk = read_field(ncid, 'totplnk', ninternalSourcetemps, nbnds)
+ planck_frac = read_field(ncid, 'plank_fraction', ngpts, nmixingfracs, npress+1, ntemps)
+ call stop_on_err(kdist%load(available_gases, &
+ gas_names, &
+ key_species, &
+ band2gpt, &
+ band_lims, &
+ press_ref, &
+ press_ref_trop, &
+ temp_ref, &
+ temp_ref_p, temp_ref_t, &
+ vmr_ref, kmajor, &
+ kminor_lower, kminor_upper, &
+ gas_minor,identifier_minor, &
+ minor_gases_lower, minor_gases_upper, &
+ minor_limits_gpt_lower, &
+ minor_limits_gpt_upper, &
+ minor_scales_with_density_lower, &
+ minor_scales_with_density_upper, &
+ scaling_gas_lower, scaling_gas_upper, &
+ scale_by_complement_lower, &
+ scale_by_complement_upper, &
+ kminor_start_lower, &
+ kminor_start_upper, &
+ totplnk, planck_frac, &
+ rayl_lower, rayl_upper))
+ else
+ !
+ ! Solar source doesn't have an dependencies yet
+ !
+ if (var_exists(ncid, 'solar_source')) then
+ solar_src = read_field(ncid, 'solar_source', ngpts)
+ else
+ solar_src = read_field(ncid, 'solar_source_quiet', ngpts)
+ end if
+ call stop_on_err(kdist%load(available_gases, &
+ gas_names, &
+ key_species, &
+ band2gpt, &
+ band_lims, &
+ press_ref, &
+ press_ref_trop, &
+ temp_ref, &
+ temp_ref_p, temp_ref_t, &
+ vmr_ref, kmajor, &
+ kminor_lower, kminor_upper, &
+ gas_minor,identifier_minor,&
+ minor_gases_lower, minor_gases_upper, &
+ minor_limits_gpt_lower, &
+ minor_limits_gpt_upper, &
+ minor_scales_with_density_lower, &
+ minor_scales_with_density_upper, &
+ scaling_gas_lower, scaling_gas_upper, &
+ scale_by_complement_lower, &
+ scale_by_complement_upper, &
+ kminor_start_lower, &
+ kminor_start_upper, &
+ solar_src, &
+ rayl_lower, rayl_upper))
+ end if
+ ! --------------------------------------------------
+ ncid = nf90_close(ncid)
+ end subroutine load_and_init
+end module