#include <misc.h>
#include <preproc.h>
module SNICARMod 8,4
!-----------------------------------------------------------------------
!BOP
!
! !MODULE: SNICARMod
!
! !DESCRIPTION:
! Calculate albedo of snow containing impurities
! and the evolution of snow effective radius
!
! !USES:
use shr_kind_mod
, only : r8 => shr_kind_r8
use shr_sys_mod
, only : shr_sys_flush
use clm_varctl
, only : iulog
use shr_const_mod
, only : SHR_CONST_RHOICE
implicit none
save
!
! !PUBLIC MEMBER FUNCTIONS:
public :: SNICAR_RT ! Snow albedo and vertically-resolved solar absorption
public :: SnowAge_grain ! Snow effective grain size evolution
public :: SnowAge_init ! Initial read in of snow-aging file
public :: SnowOptics_init ! Initial read in of snow-optics file
!
! !PUBLIC DATA MEMBERS:
real(r8), public, parameter :: snw_rds_min = 54.526_r8 ! minimum allowed snow effective radius (also "fresh snow" value) [microns]
integer, public, parameter :: sno_nbr_aer = 8 ! number of aerosol species in snowpack (indices described above) [nbr]
logical, public, parameter :: DO_SNO_OC = .false. ! parameter to include organic carbon (OC) in snowpack radiative calculations
logical, public, parameter :: DO_SNO_AER = .true. ! parameter to include aerosols in snowpack radiative calculations
real(r8), public, parameter :: scvng_fct_mlt_bcphi = 0.20_r8 ! scavenging factor for hydrophillic BC inclusion in meltwater [frc]
real(r8), public, parameter :: scvng_fct_mlt_bcpho = 0.03_r8 ! scavenging factor for hydrophobic BC inclusion in meltwater [frc]
real(r8), public, parameter :: scvng_fct_mlt_ocphi = 0.20_r8 ! scavenging factor for hydrophillic OC inclusion in meltwater [frc]
real(r8), public, parameter :: scvng_fct_mlt_ocpho = 0.03_r8 ! scavenging factor for hydrophobic OC inclusion in meltwater [frc]
real(r8), public, parameter :: scvng_fct_mlt_dst1 = 0.02_r8 ! scavenging factor for dust species 1 inclusion in meltwater [frc]
real(r8), public, parameter :: scvng_fct_mlt_dst2 = 0.02_r8 ! scavenging factor for dust species 2 inclusion in meltwater [frc]
real(r8), public, parameter :: scvng_fct_mlt_dst3 = 0.01_r8 ! scavenging factor for dust species 3 inclusion in meltwater [frc]
real(r8), public, parameter :: scvng_fct_mlt_dst4 = 0.01_r8 ! scavenging factor for dust species 4 inclusion in meltwater [frc]
! !PRIVATE MEMBER FUNCTIONS:
!
! !PRIVATE DATA MEMBERS:
! Aerosol species indices:
! 1= hydrophillic black carbon
! 2= hydrophobic black carbon
! 3= hydrophilic organic carbon
! 4= hydrophobic organic carbon
! 5= dust species 1
! 6= dust species 2
! 7= dust species 3
! 8= dust species 4
integer, parameter :: numrad_snw = 5 ! number of spectral bands used in snow model [nbr]
integer, parameter :: nir_bnd_bgn = 2 ! first band index in near-IR spectrum [idx]
integer, parameter :: nir_bnd_end = 5 ! ending near-IR band index [idx]
integer, parameter :: idx_Mie_snw_mx = 1471 ! number of effective radius indices used in Mie lookup table [idx]
integer, parameter :: idx_T_max = 11 ! maxiumum temperature index used in aging lookup table [idx]
integer, parameter :: idx_T_min = 1 ! minimum temperature index used in aging lookup table [idx]
integer, parameter :: idx_Tgrd_max = 31 ! maxiumum temperature gradient index used in aging lookup table [idx]
integer, parameter :: idx_Tgrd_min = 1 ! minimum temperature gradient index used in aging lookup table [idx]
integer, parameter :: idx_rhos_max = 8 ! maxiumum snow density index used in aging lookup table [idx]
integer, parameter :: idx_rhos_min = 1 ! minimum snow density index used in aging lookup table [idx]
integer, parameter :: snw_rds_max_tbl = 1500 ! maximum effective radius defined in Mie lookup table [microns]
integer, parameter :: snw_rds_min_tbl = 30 ! minimium effective radius defined in Mie lookup table [microns]
real(r8), parameter :: snw_rds_max = 1500._r8 ! maximum allowed snow effective radius [microns]
real(r8), parameter :: snw_rds_refrz = 1000._r8 ! effective radius of re-frozen snow [microns]
real(r8), parameter :: min_snw = 1.0E-30_r8 ! minimum snow mass required for SNICAR RT calculation [kg m-2]
!real(r8), parameter :: C1_liq_Brun89 = 1.28E-17_r8 ! constant for liquid water grain growth [m3 s-1], from Brun89
real(r8), parameter :: C1_liq_Brun89 = 0._r8 ! constant for liquid water grain growth [m3 s-1], from Brun89: zeroed to accomodate dry snow aging
real(r8), parameter :: C2_liq_Brun89 = 4.22E-13_r8 ! constant for liquid water grain growth [m3 s-1], from Brun89: corrected for LWC in units of percent
real(r8), parameter :: tim_cns_bc_rmv = 2.2E-8_r8 ! time constant for removal of BC in snow on sea-ice [s-1] (50% mass removal/year)
real(r8), parameter :: tim_cns_oc_rmv = 2.2E-8_r8 ! time constant for removal of OC in snow on sea-ice [s-1] (50% mass removal/year)
real(r8), parameter :: tim_cns_dst_rmv = 2.2E-8_r8 ! time constant for removal of dust in snow on sea-ice [s-1] (50% mass removal/year)
! scaling of the snow aging rate (tuning option):
logical :: flg_snoage_scl = .false. ! flag for scaling the snow aging rate by some arbitrary factor
real(r8), parameter :: xdrdt = 1.0_r8 ! arbitrary factor applied to snow aging rate
! snow and aerosol Mie parameters:
! (arrays declared here, but are set in iniTimeConst)
! (idx_Mie_snw_mx is number of snow radii with defined parameters (i.e. from 30um to 1500um))
! direct-beam weighted ice optical properties
real(r8) :: ss_alb_snw_drc(idx_Mie_snw_mx,numrad_snw)
real(r8) :: asm_prm_snw_drc(idx_Mie_snw_mx,numrad_snw)
real(r8) :: ext_cff_mss_snw_drc(idx_Mie_snw_mx,numrad_snw)
! diffuse radiation weighted ice optical properties
real(r8) :: ss_alb_snw_dfs(idx_Mie_snw_mx,numrad_snw)
real(r8) :: asm_prm_snw_dfs(idx_Mie_snw_mx,numrad_snw)
real(r8) :: ext_cff_mss_snw_dfs(idx_Mie_snw_mx,numrad_snw)
! hydrophiliic BC
real(r8) :: ss_alb_bc1(1,numrad_snw)
real(r8) :: asm_prm_bc1(1,numrad_snw)
real(r8) :: ext_cff_mss_bc1(1,numrad_snw)
! hydrophobic BC
real(r8) :: ss_alb_bc2(1,numrad_snw)
real(r8) :: asm_prm_bc2(1,numrad_snw)
real(r8) :: ext_cff_mss_bc2(1,numrad_snw)
! hydrophobic OC
real(r8) :: ss_alb_oc1(1,numrad_snw)
real(r8) :: asm_prm_oc1(1,numrad_snw)
real(r8) :: ext_cff_mss_oc1(1,numrad_snw)
! hydrophilic OC
real(r8) :: ss_alb_oc2(1,numrad_snw)
real(r8) :: asm_prm_oc2(1,numrad_snw)
real(r8) :: ext_cff_mss_oc2(1,numrad_snw)
! dust species 1:
real(r8) :: ss_alb_dst1(1,numrad_snw)
real(r8) :: asm_prm_dst1(1,numrad_snw)
real(r8) :: ext_cff_mss_dst1(1,numrad_snw)
! dust species 2:
real(r8) :: ss_alb_dst2(1,numrad_snw)
real(r8) :: asm_prm_dst2(1,numrad_snw)
real(r8) :: ext_cff_mss_dst2(1,numrad_snw)
! dust species 3:
real(r8) :: ss_alb_dst3(1,numrad_snw)
real(r8) :: asm_prm_dst3(1,numrad_snw)
real(r8) :: ext_cff_mss_dst3(1,numrad_snw)
! dust species 4:
real(r8) :: ss_alb_dst4(1,numrad_snw)
real(r8) :: asm_prm_dst4(1,numrad_snw)
real(r8) :: ext_cff_mss_dst4(1,numrad_snw)
! best-fit parameters for snow aging defined over:
! 11 temperatures from 225 to 273 K
! 31 temperature gradients from 0 to 300 K/m
! 8 snow densities from 0 to 350 kg/m3
! (arrays declared here, but are set in iniTimeConst)
real(r8) :: snowage_tau(idx_rhos_max,idx_Tgrd_max,idx_T_max)
real(r8) :: snowage_kappa(idx_rhos_max,idx_Tgrd_max,idx_T_max)
real(r8) :: snowage_drdt0(idx_rhos_max,idx_Tgrd_max,idx_T_max)
!
! !REVISION HISTORY:
! Created by Mark Flanner
!
!EOP
!-----------------------------------------------------------------------
contains
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: SNICAR_RT
!
!
! !CALLED FROM:
! subroutine SurfaceAlbedo in module SurfaceAlbedoMod (CLM)
! subroutine albice (CSIM)
!
! !REVISION HISTORY:
! Author: Mark Flanner
!
! !INTERFACE:
subroutine SNICAR_RT (flg_snw_ice, lbc, ubc, num_nourbanc, filter_nourbanc, & 10,18
coszen, flg_slr_in, h2osno_liq, h2osno_ice, snw_rds, &
mss_cnc_aer_in, albsfc, albout, flx_abs)
!
! !DESCRIPTION:
! Determine reflectance of, and vertically-resolved solar absorption in,
! snow with impurities.
!
! Original references on physical models of snow reflectance include:
! Wiscombe and Warren [1980] and Warren and Wiscombe [1980],
! Journal of Atmospheric Sciences, 37,
!
! The multi-layer solution for multiple-scattering used here is from:
! Toon et al. [1989], Rapid calculation of radiative heating rates
! and photodissociation rates in inhomogeneous multiple scattering atmospheres,
! J. Geophys. Res., 94, D13, 16287-16301
!
! The implementation of the SNICAR model in CLM/CSIM is described in:
! Flanner, M., C. Zender, J. Randerson, and P. Rasch [2007],
! Present-day climate forcing and response from black carbon in snow,
! J. Geophys. Res., 112, D11202, doi: 10.1029/2006JD008003
! !USES:
use clmtype
use clm_varpar
, only : nlevsno, numrad
use clm_time_manager
, only : get_nstep
use abortutils
, only : endrun
use shr_const_mod
, only : SHR_CONST_PI
!
! !ARGUMENTS:
implicit none
integer , intent(in) :: flg_snw_ice ! flag: =1 when called from CLM, =2 when called from CSIM
integer , intent(in) :: lbc, ubc ! column index bounds [unitless]
integer , intent(in) :: num_nourbanc ! number of columns in non-urban filter
integer , intent(in) :: filter_nourbanc(ubc-lbc+1) ! column filter for non-urban points
real(r8), intent(in) :: coszen(lbc:ubc) ! cosine of solar zenith angle for next time step (col) [unitless]
integer , intent(in) :: flg_slr_in ! flag: =1 for direct-beam incident flux, =2 for diffuse incident flux
real(r8), intent(in) :: h2osno_liq(lbc:ubc,-nlevsno+1:0) ! liquid water content (col,lyr) [kg/m2]
real(r8), intent(in) :: h2osno_ice(lbc:ubc,-nlevsno+1:0) ! ice content (col,lyr) [kg/m2]
integer, intent(in) :: snw_rds(lbc:ubc,-nlevsno+1:0) ! snow effective radius (col,lyr) [microns, m^-6]
real(r8), intent(in) :: mss_cnc_aer_in(lbc:ubc,-nlevsno+1:0,sno_nbr_aer) ! mass concentration of all aerosol species (col,lyr,aer) [kg/kg]
real(r8), intent(in) :: albsfc(lbc:ubc,numrad) ! albedo of surface underlying snow (col,bnd) [frc]
real(r8), intent(out) :: albout(lbc:ubc,numrad) ! snow albedo, averaged into 2 bands (=0 if no sun or no snow) (col,bnd) [frc]
real(r8), intent(out) :: flx_abs(lbc:ubc,-nlevsno+1:1,numrad) ! absorbed flux in each layer per unit flux incident on top of snowpack (col,lyr,bnd) [frc]
!
! !LOCAL VARIABLES:
!
! local pointers to implicit in arguments
!
integer, pointer :: snl(:) ! negative number of snow layers (col) [nbr]
real(r8), pointer :: h2osno(:) ! snow liquid water equivalent (col) [kg/m2]
integer, pointer :: clandunit(:) ! corresponding landunit of column (col) [idx] (debugging only)
integer, pointer :: cgridcell(:) ! columns's gridcell index (col) [idx] (debugging only)
integer, pointer :: ltype(:) ! landunit type (lnd) (debugging only)
real(r8), pointer :: londeg(:) ! longitude (degrees) (debugging only)
real(r8), pointer :: latdeg(:) ! latitude (degrees) (debugging only)
!
! !OTHER LOCAL VARIABLES:
!EOP
!-----------------------------------------------------------------------
!
! variables for snow radiative transfer calculations
! Local variables representing single-column values of arrays:
integer :: snl_lcl ! negative number of snow layers [nbr]
integer :: snw_rds_lcl(-nlevsno+1:0) ! snow effective radius [m^-6]
real(r8):: flx_slrd_lcl(1:numrad_snw) ! direct beam incident irradiance [W/m2] (set to 1)
real(r8):: flx_slri_lcl(1:numrad_snw) ! diffuse incident irradiance [W/m2] (set to 1)
real(r8):: mss_cnc_aer_lcl(-nlevsno+1:0,1:sno_nbr_aer) ! aerosol mass concentration (lyr,aer_nbr) [kg/kg]
real(r8):: h2osno_lcl ! total column snow mass [kg/m2]
real(r8):: h2osno_liq_lcl(-nlevsno+1:0) ! liquid water mass [kg/m2]
real(r8):: h2osno_ice_lcl(-nlevsno+1:0) ! ice mass [kg/m2]
real(r8):: albsfc_lcl(1:numrad_snw) ! albedo of underlying surface [frc]
real(r8):: ss_alb_snw_lcl(-nlevsno+1:0) ! single-scatter albedo of ice grains (lyr) [frc]
real(r8):: asm_prm_snw_lcl(-nlevsno+1:0) ! asymmetry parameter of ice grains (lyr) [frc]
real(r8):: ext_cff_mss_snw_lcl(-nlevsno+1:0) ! mass extinction coefficient of ice grains (lyr) [m2/kg]
real(r8):: ss_alb_aer_lcl(sno_nbr_aer) ! single-scatter albedo of aerosol species (aer_nbr) [frc]
real(r8):: asm_prm_aer_lcl(sno_nbr_aer) ! asymmetry parameter of aerosol species (aer_nbr) [frc]
real(r8):: ext_cff_mss_aer_lcl(sno_nbr_aer) ! mass extinction coefficient of aerosol species (aer_nbr) [m2/kg]
! Other local variables
integer :: APRX_TYP ! two-stream approximation type (1=Eddington, 2=Quadrature, 3=Hemispheric Mean) [nbr]
integer :: DELTA ! flag to use Delta approximation (Joseph, 1976) (1= use, 0= don't use)
real(r8):: flx_wgt(1:numrad_snw) ! weights applied to spectral bands, specific to direct and diffuse cases (bnd) [frc]
integer :: flg_nosnl ! flag: =1 if there is snow, but zero snow layers, =0 if at least 1 snow layer [flg]
integer :: trip ! flag: =1 to redo RT calculation if result is unrealistic
integer :: flg_dover ! defines conditions for RT redo (explained below)
real(r8):: albedo ! temporary snow albedo [frc]
real(r8):: flx_sum ! temporary summation variable for NIR weighting
real(r8):: albout_lcl(numrad_snw) ! snow albedo by band [frc]
real(r8):: flx_abs_lcl(-nlevsno+1:1,numrad_snw)! absorbed flux per unit incident flux at top of snowpack (lyr,bnd) [frc]
real(r8):: L_snw(-nlevsno+1:0) ! h2o mass (liquid+solid) in snow layer (lyr) [kg/m2]
real(r8):: tau_snw(-nlevsno+1:0) ! snow optical depth (lyr) [unitless]
real(r8):: L_aer(-nlevsno+1:0,sno_nbr_aer) ! aerosol mass in snow layer (lyr,nbr_aer) [kg/m2]
real(r8):: tau_aer(-nlevsno+1:0,sno_nbr_aer) ! aerosol optical depth (lyr,nbr_aer) [unitless]
real(r8):: tau_sum ! cumulative (snow+aerosol) optical depth [unitless]
real(r8):: tau_clm(-nlevsno+1:0) ! column optical depth from layer bottom to snowpack top (lyr) [unitless]
real(r8):: omega_sum ! temporary summation of single-scatter albedo of all aerosols [frc]
real(r8):: g_sum ! temporary summation of asymmetry parameter of all aerosols [frc]
real(r8):: tau(-nlevsno+1:0) ! weighted optical depth of snow+aerosol layer (lyr) [unitless]
real(r8):: omega(-nlevsno+1:0) ! weighted single-scatter albedo of snow+aerosol layer (lyr) [frc]
real(r8):: g(-nlevsno+1:0) ! weighted asymmetry parameter of snow+aerosol layer (lyr) [frc]
real(r8):: tau_star(-nlevsno+1:0) ! transformed (i.e. Delta-Eddington) optical depth of snow+aerosol layer (lyr) [unitless]
real(r8):: omega_star(-nlevsno+1:0) ! transformed (i.e. Delta-Eddington) SSA of snow+aerosol layer (lyr) [frc]
real(r8):: g_star(-nlevsno+1:0) ! transformed (i.e. Delta-Eddington) asymmetry paramater of snow+aerosol layer (lyr) [frc]
integer :: nstep ! current timestep [nbr] (debugging only)
integer :: g_idx, c_idx, l_idx ! gridcell, column, and landunit indices [idx]
integer :: bnd_idx ! spectral band index (1 <= bnd_idx <= numrad_snw) [idx]
integer :: rds_idx ! snow effective radius index for retrieving Mie parameters from lookup table [idx]
integer :: snl_btm ! index of bottom snow layer (0) [idx]
integer :: snl_top ! index of top snow layer (-4 to 0) [idx]
integer :: fc ! column filter index
integer :: i ! layer index [idx]
integer :: j ! aerosol number index [idx]
integer :: n ! tridiagonal matrix index [idx]
integer :: m ! secondary layer index [idx]
real(r8):: F_direct(-nlevsno+1:0) ! direct-beam radiation at bottom of layer interface (lyr) [W/m^2]
real(r8):: F_net(-nlevsno+1:0) ! net radiative flux at bottom of layer interface (lyr) [W/m^2]
real(r8):: F_abs(-nlevsno+1:0) ! net absorbed radiative energy (lyr) [W/m^2]
real(r8):: F_abs_sum ! total absorbed energy in column [W/m^2]
real(r8):: F_sfc_pls ! upward radiative flux at snowpack top [W/m^2]
real(r8):: F_btm_net ! net flux at bottom of snowpack [W/m^2]
real(r8):: F_sfc_net ! net flux at top of snowpack [W/m^2]
real(r8):: energy_sum ! sum of all energy terms; should be 0.0 [W/m^2]
real(r8):: F_direct_btm ! direct-beam radiation at bottom of snowpack [W/m^2]
real(r8):: mu_not ! cosine of solar zenith angle (used locally) [frc]
integer :: err_idx ! counter for number of times through error loop [nbr]
real(r8):: lat_coord ! gridcell latitude (debugging only)
real(r8):: lon_coord ! gridcell longitude (debugging only)
integer :: sfctype ! underlying surface type (debugging only)
real(r8):: pi ! 3.1415...
! intermediate variables for radiative transfer approximation:
real(r8):: gamma1(-nlevsno+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
real(r8):: gamma2(-nlevsno+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
real(r8):: gamma3(-nlevsno+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
real(r8):: gamma4(-nlevsno+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
real(r8):: lambda(-nlevsno+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
real(r8):: GAMMA
(-nlevsno+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
real(r8):: mu_one ! two-stream coefficient from Toon et al. (lyr) [unitless]
real(r8):: e1(-nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
real(r8):: e2(-nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
real(r8):: e3(-nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
real(r8):: e4(-nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
real(r8):: C_pls_btm(-nlevsno+1:0) ! intermediate variable: upward flux at bottom interface (lyr) [W/m2]
real(r8):: C_mns_btm(-nlevsno+1:0) ! intermediate variable: downward flux at bottom interface (lyr) [W/m2]
real(r8):: C_pls_top(-nlevsno+1:0) ! intermediate variable: upward flux at top interface (lyr) [W/m2]
real(r8):: C_mns_top(-nlevsno+1:0) ! intermediate variable: downward flux at top interface (lyr) [W/m2]
real(r8):: A(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
real(r8):: B(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
real(r8):: D(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
real(r8):: E(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
real(r8):: AS(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
real(r8):: DS(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
real(r8):: X(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
real(r8):: Y(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
! Assign local pointers to derived subtypes components (column-level)
! (CLM-specific)
if (flg_snw_ice == 1) then
snl => clm3%g%l%c%cps%snl
h2osno => clm3%g%l%c%cws%h2osno
clandunit => clm3%g%l%c%landunit ! (debug only)
cgridcell => clm3%g%l%c%gridcell ! (debug only)
ltype => clm3%g%l%itype ! (debug only)
londeg => clm3%g%londeg ! (debug only)
latdeg => clm3%g%latdeg ! (debug only)
endif
! Define constants
pi = SHR_CONST_PI
! always use Delta approximation for snow
DELTA = 1
! Get current timestep
nstep = get_nstep
()
! Loop over all non-urban columns
! (when called from CSIM, there is only one column)
do fc = 1,num_nourbanc
c_idx = filter_nourbanc(fc)
! Zero absorbed radiative fluxes:
do i=-nlevsno+1,1,1
flx_abs_lcl(:,:) = 0._r8
flx_abs(c_idx,i,:) = 0._r8
enddo
! set snow/ice mass to be used for RT:
if (flg_snw_ice == 1) then
h2osno_lcl = h2osno(c_idx)
else
h2osno_lcl = h2osno_ice(c_idx,0)
endif
! Qualifier for computing snow RT:
! 1) sunlight from atmosphere model
! 2) minimum amount of snow on ground.
! Otherwise, set snow albedo to zero
if ((coszen(c_idx) > 0._r8) .and. (h2osno_lcl > min_snw)) then
! Set variables specific to CLM
if (flg_snw_ice == 1) then
! Assign local (single-column) variables to global values
! If there is snow, but zero snow layers, we must create a layer locally.
! This layer is presumed to have the fresh snow effective radius.
if (snl(c_idx) > -1) then
flg_nosnl = 1
snl_lcl = -1
h2osno_ice_lcl(0) = h2osno_lcl
h2osno_liq_lcl(0) = 0._r8
snw_rds_lcl(0) = nint(snw_rds_min)
else
flg_nosnl = 0
snl_lcl = snl(c_idx)
h2osno_liq_lcl(:) = h2osno_liq(c_idx,:)
h2osno_ice_lcl(:) = h2osno_ice(c_idx,:)
snw_rds_lcl(:) = snw_rds(c_idx,:)
endif
snl_btm = 0
snl_top = snl_lcl+1
! for debugging only
l_idx = clandunit(c_idx)
g_idx = cgridcell(c_idx)
sfctype = ltype(l_idx)
lat_coord = latdeg(g_idx)
lon_coord = londeg(g_idx)
! Set variables specific to CSIM
else
flg_nosnl = 0
snl_lcl = -1
h2osno_liq_lcl(:) = h2osno_liq(c_idx,:)
h2osno_ice_lcl(:) = h2osno_ice(c_idx,:)
snw_rds_lcl(:) = snw_rds(c_idx,:)
snl_btm = 0
snl_top = 0
sfctype = -1
lat_coord = -90
lon_coord = 0
endif
! Set local aerosol array
do j=1,sno_nbr_aer
mss_cnc_aer_lcl(:,j) = mss_cnc_aer_in(c_idx,:,j)
enddo
! Set spectral underlying surface albedos to their corresponding VIS or NIR albedos
albsfc_lcl(1) = albsfc(c_idx,1)
albsfc_lcl(nir_bnd_bgn:nir_bnd_end) = albsfc(c_idx,2)
! Error check for snow grain size:
do i=snl_top,snl_btm,1
if ((snw_rds_lcl(i) < snw_rds_min_tbl) .or. (snw_rds_lcl(i) > snw_rds_max_tbl)) then
write (iulog,*) "SNICAR ERROR: snow grain radius of ", snw_rds_lcl(i), " out of bounds."
write (iulog,*) "NSTEP= ", nstep
write (iulog,*) "flg_snw_ice= ", flg_snw_ice
write (iulog,*) "column: ", c_idx, " level: ", i, " snl(c)= ", snl_lcl
write (iulog,*) "lat= ", lat_coord, " lon= ", lon_coord
write (iulog,*) "h2osno(c)= ", h2osno_lcl
call endrun
()
endif
enddo
! Incident flux weighting parameters
! - sum of all VIS bands must equal 1
! - sum of all NIR bands must equal 1
!
! Spectral bands (5-band case)
! Band 1: 0.3-0.7um (VIS)
! Band 2: 0.7-1.0um (NIR)
! Band 3: 1.0-1.2um (NIR)
! Band 4: 1.2-1.5um (NIR)
! Band 5: 1.5-5.0um (NIR)
!
! The following weights are appropriate for surface-incident flux in a mid-latitude winter atmosphere
!
! 3-band weights
if (numrad_snw==3) then
! Direct:
if (flg_slr_in == 1) then
flx_wgt(1) = 1._r8
flx_wgt(2) = 0.66628670195247_r8
flx_wgt(3) = 0.33371329804753_r8
! Diffuse:
elseif (flg_slr_in == 2) then
flx_wgt(1) = 1._r8
flx_wgt(2) = 0.77887652162877_r8
flx_wgt(3) = 0.22112347837123_r8
endif
! 5-band weights
elseif(numrad_snw==5) then
! Direct:
if (flg_slr_in == 1) then
flx_wgt(1) = 1._r8
flx_wgt(2) = 0.49352158521175_r8
flx_wgt(3) = 0.18099494230665_r8
flx_wgt(4) = 0.12094898498813_r8
flx_wgt(5) = 0.20453448749347_r8
! Diffuse:
elseif (flg_slr_in == 2) then
flx_wgt(1) = 1._r8
flx_wgt(2) = 0.58581507618433_r8
flx_wgt(3) = 0.20156903770812_r8
flx_wgt(4) = 0.10917889346386_r8
flx_wgt(5) = 0.10343699264369_r8
endif
endif
! Loop over snow spectral bands
do bnd_idx = 1,numrad_snw
mu_not = coszen(c_idx) ! must set here, because of error handling
flg_dover = 1 ! default is to redo
err_idx = 0 ! number of times through loop
do while (flg_dover > 0)
! DEFAULT APPROXIMATIONS:
! VIS: Delta-Eddington
! NIR (all): Delta-Hemispheric Mean
! WARNING: DO NOT USE DELTA-EDDINGTON FOR NIR DIFFUSE - this sometimes results in negative albedo
!
! ERROR CONDITIONS:
! Conditions which cause "trip", resulting in redo of RT approximation:
! 1. negative absorbed flux
! 2. total absorbed flux greater than incident flux
! 3. negative albedo
! NOTE: These errors have only been encountered in spectral bands 4 and 5
!
! ERROR HANDLING
! 1st error (flg_dover=2): switch approximation (Edd->HM or HM->Edd)
! 2nd error (flg_dover=3): change zenith angle by 0.02 (this happens about 1 in 10^6 cases)
! 3rd error (flg_dover=4): switch approximation with new zenith
! Subsequent errors: repeatedly change zenith and approximations...
if (bnd_idx == 1) then
if (flg_dover == 2) then
APRX_TYP = 3
elseif (flg_dover == 3) then
APRX_TYP = 1
if (coszen(c_idx) > 0.5_r8) then
mu_not = mu_not - 0.02_r8
else
mu_not = mu_not + 0.02_r8
endif
elseif (flg_dover == 4) then
APRX_TYP = 3
else
APRX_TYP = 1
endif
else
if (flg_dover == 2) then
APRX_TYP = 1
elseif (flg_dover == 3) then
APRX_TYP = 3
if (coszen(c_idx) > 0.5_r8) then
mu_not = mu_not - 0.02_r8
else
mu_not = mu_not + 0.02_r8
endif
elseif (flg_dover == 4) then
APRX_TYP = 1
else
APRX_TYP = 3
endif
endif
! Set direct or diffuse incident irradiance to 1
! (This has to be within the bnd loop because mu_not is adjusted in rare cases)
if (flg_slr_in == 1) then
flx_slrd_lcl(bnd_idx) = 1._r8/(mu_not*pi) ! this corresponds to incident irradiance of 1.0
flx_slri_lcl(bnd_idx) = 0._r8
else
flx_slrd_lcl(bnd_idx) = 0._r8
flx_slri_lcl(bnd_idx) = 1._r8
endif
! Pre-emptive error handling: aerosols can reap havoc on these absorptive bands.
! Since extremely high soot concentrations have a negligible effect on these bands, zero them.
if ( (numrad_snw == 5).and.((bnd_idx == 5).or.(bnd_idx == 4)) ) then
mss_cnc_aer_lcl(:,:) = 0._r8
endif
if ( (numrad_snw == 3).and.(bnd_idx == 3) ) then
mss_cnc_aer_lcl(:,:) = 0._r8
endif
! Define local Mie parameters based on snow grain size and aerosol species,
! retrieved from a lookup table.
if (flg_slr_in == 1) then
do i=snl_top,snl_btm,1
rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1
! snow optical properties (direct radiation)
ss_alb_snw_lcl(i) = ss_alb_snw_drc(rds_idx,bnd_idx)
asm_prm_snw_lcl(i) = asm_prm_snw_drc(rds_idx,bnd_idx)
ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_drc(rds_idx,bnd_idx)
enddo
elseif (flg_slr_in == 2) then
do i=snl_top,snl_btm,1
rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1
! snow optical properties (diffuse radiation)
ss_alb_snw_lcl(i) = ss_alb_snw_dfs(rds_idx,bnd_idx)
asm_prm_snw_lcl(i) = asm_prm_snw_dfs(rds_idx,bnd_idx)
ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_dfs(rds_idx,bnd_idx)
enddo
endif
! aerosol species 1 optical properties
ss_alb_aer_lcl(1) = ss_alb_bc1(1,bnd_idx)
asm_prm_aer_lcl(1) = asm_prm_bc1(1,bnd_idx)
ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(1,bnd_idx)
! aerosol species 2 optical properties
ss_alb_aer_lcl(2) = ss_alb_bc2(1,bnd_idx)
asm_prm_aer_lcl(2) = asm_prm_bc2(1,bnd_idx)
ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(1,bnd_idx)
! aerosol species 3 optical properties
ss_alb_aer_lcl(3) = ss_alb_oc1(1,bnd_idx)
asm_prm_aer_lcl(3) = asm_prm_oc1(1,bnd_idx)
ext_cff_mss_aer_lcl(3) = ext_cff_mss_oc1(1,bnd_idx)
! aerosol species 4 optical properties
ss_alb_aer_lcl(4) = ss_alb_oc2(1,bnd_idx)
asm_prm_aer_lcl(4) = asm_prm_oc2(1,bnd_idx)
ext_cff_mss_aer_lcl(4) = ext_cff_mss_oc2(1,bnd_idx)
! aerosol species 5 optical properties
ss_alb_aer_lcl(5) = ss_alb_dst1(1,bnd_idx)
asm_prm_aer_lcl(5) = asm_prm_dst1(1,bnd_idx)
ext_cff_mss_aer_lcl(5) = ext_cff_mss_dst1(1,bnd_idx)
! aerosol species 6 optical properties
ss_alb_aer_lcl(6) = ss_alb_dst2(1,bnd_idx)
asm_prm_aer_lcl(6) = asm_prm_dst2(1,bnd_idx)
ext_cff_mss_aer_lcl(6) = ext_cff_mss_dst2(1,bnd_idx)
! aerosol species 7 optical properties
ss_alb_aer_lcl(7) = ss_alb_dst3(1,bnd_idx)
asm_prm_aer_lcl(7) = asm_prm_dst3(1,bnd_idx)
ext_cff_mss_aer_lcl(7) = ext_cff_mss_dst3(1,bnd_idx)
! aerosol species 8 optical properties
ss_alb_aer_lcl(8) = ss_alb_dst4(1,bnd_idx)
asm_prm_aer_lcl(8) = asm_prm_dst4(1,bnd_idx)
ext_cff_mss_aer_lcl(8) = ext_cff_mss_dst4(1,bnd_idx)
! 1. snow and aerosol layer column mass (L_snw, L_aer [kg/m^2])
! 2. optical Depths (tau_snw, tau_aer)
! 3. weighted Mie properties (tau, omega, g)
! Weighted Mie parameters of each layer
do i=snl_top,snl_btm,1
L_snw(i) = h2osno_ice_lcl(i)+h2osno_liq_lcl(i)
tau_snw(i) = L_snw(i)*ext_cff_mss_snw_lcl(i)
do j=1,sno_nbr_aer
L_aer(i,j) = L_snw(i)*mss_cnc_aer_lcl(i,j)
tau_aer(i,j) = L_aer(i,j)*ext_cff_mss_aer_lcl(j)
enddo
tau_sum = 0._r8
omega_sum = 0._r8
g_sum = 0._r8
do j=1,sno_nbr_aer
tau_sum = tau_sum + tau_aer(i,j)
omega_sum = omega_sum + (tau_aer(i,j)*ss_alb_aer_lcl(j))
g_sum = g_sum + (tau_aer(i,j)*ss_alb_aer_lcl(j)*asm_prm_aer_lcl(j))
enddo
tau(i) = tau_sum + tau_snw(i)
omega(i) = (1/tau(i))*(omega_sum+(ss_alb_snw_lcl(i)*tau_snw(i)))
g(i) = (1/(tau(i)*omega(i)))*(g_sum+ (asm_prm_snw_lcl(i)*ss_alb_snw_lcl(i)*tau_snw(i)))
enddo
! DELTA transformations, if requested
if (DELTA == 1) then
do i=snl_top,snl_btm,1
g_star(i) = g(i)/(1+g(i))
omega_star(i) = ((1-(g(i)**2))*omega(i)) / (1-(omega(i)*(g(i)**2)))
tau_star(i) = (1-(omega(i)*(g(i)**2)))*tau(i)
enddo
else
do i=snl_top,snl_btm,1
g_star(i) = g(i)
omega_star(i) = omega(i)
tau_star(i) = tau(i)
enddo
endif
! Total column optical depth:
! tau_clm(i) = total optical depth above the bottom of layer i
tau_clm(snl_top) = 0._r8
do i=snl_top+1,snl_btm,1
tau_clm(i) = tau_clm(i-1)+tau_star(i-1)
enddo
! Direct radiation at bottom of snowpack:
F_direct_btm = albsfc_lcl(bnd_idx)*mu_not*exp(-(tau_clm(snl_btm)+tau_star(snl_btm))/mu_not)*pi*flx_slrd_lcl(bnd_idx)
! Intermediates
! Gamma values are approximation-specific.
! Eddington
if (APRX_TYP==1) then
do i=snl_top,snl_btm,1
gamma1(i) = (7-(omega_star(i)*(4+(3*g_star(i)))))/4
gamma2(i) = -(1-(omega_star(i)*(4-(3*g_star(i)))))/4
gamma3(i) = (2-(3*g_star(i)*mu_not))/4
gamma4(i) = 1-gamma3(i)
mu_one = 0.5
enddo
! Quadrature
elseif (APRX_TYP==2) then
do i=snl_top,snl_btm,1
gamma1(i) = (3**0.5)*(2-(omega_star(i)*(1+g_star(i))))/2
gamma2(i) = omega_star(i)*(3**0.5)*(1-g_star(i))/2
gamma3(i) = (1-((3**0.5)*g_star(i)*mu_not))/2
gamma4(i) = 1-gamma3(i)
mu_one = 1/(3**0.5)
enddo
! Hemispheric Mean
elseif (APRX_TYP==3) then
do i=snl_top,snl_btm,1
gamma1(i) = 2 - (omega_star(i)*(1+g_star(i)))
gamma2(i) = omega_star(i)*(1-g_star(i))
gamma3(i) = (1-((3**0.5)*g_star(i)*mu_not))/2
gamma4(i) = 1-gamma3(i)
mu_one = 0.5
enddo
endif
! Intermediates for tri-diagonal solution
do i=snl_top,snl_btm,1
lambda(i) = sqrt(abs((gamma1(i)**2) - (gamma2(i)**2)))
GAMMA
(i) = gamma2(i)/(gamma1(i)+lambda(i))
e1(i) = 1+(GAMMA
(i)*exp(-lambda(i)*tau_star(i)))
e2(i) = 1-(GAMMA
(i)*exp(-lambda(i)*tau_star(i)))
e3(i) = GAMMA
(i) + exp(-lambda(i)*tau_star(i))
e4(i) = GAMMA
(i) - exp(-lambda(i)*tau_star(i))
enddo !enddo over snow layers
! Intermediates for tri-diagonal solution
do i=snl_top,snl_btm,1
if (flg_slr_in == 1) then
C_pls_btm(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
exp(-(tau_clm(i)+tau_star(i))/mu_not)* &
(((gamma1(i)-(1/mu_not))*gamma3(i))+ &
(gamma4(i)*gamma2(i))))/((lambda(i)**2)-(1/(mu_not**2)))
C_mns_btm(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
exp(-(tau_clm(i)+tau_star(i))/mu_not)* &
(((gamma1(i)+(1/mu_not))*gamma4(i))+ &
(gamma2(i)*gamma3(i))))/((lambda(i)**2)-(1/(mu_not**2)))
C_pls_top(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
exp(-tau_clm(i)/mu_not)*(((gamma1(i)-(1/mu_not))* &
gamma3(i))+(gamma4(i)*gamma2(i))))/((lambda(i)**2)-(1/(mu_not**2)))
C_mns_top(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
exp(-tau_clm(i)/mu_not)*(((gamma1(i)+(1/mu_not))* &
gamma4(i))+(gamma2(i)*gamma3(i))))/((lambda(i)**2)-(1/(mu_not**2)))
else
C_pls_btm(i) = 0._r8
C_mns_btm(i) = 0._r8
C_pls_top(i) = 0._r8
C_mns_top(i) = 0._r8
endif
enddo
! Coefficients for tridiaganol matrix solution
do i=2*snl_lcl+1,0,1
!Boundary values for i=1 and i=2*snl_lcl, specifics for i=odd and i=even
if (i==(2*snl_lcl+1)) then
A(i) = 0
B(i) = e1(snl_top)
D(i) = -e2(snl_top)
E(i) = flx_slri_lcl(bnd_idx)-C_mns_top(snl_top)
elseif(i==0) then
A(i) = e1(snl_btm)-(albsfc_lcl(bnd_idx)*e3(snl_btm))
B(i) = e2(snl_btm)-(albsfc_lcl(bnd_idx)*e4(snl_btm))
D(i) = 0
E(i) = F_direct_btm-C_pls_btm(snl_btm)+(albsfc_lcl(bnd_idx)*C_mns_btm(snl_btm))
elseif(mod(i,2)==-1) then ! If odd and i>=3 (n=1 for i=3)
n=floor(i/2.0)
A(i) = (e2(n)*e3(n))-(e4(n)*e1(n))
B(i) = (e1(n)*e1(n+1))-(e3(n)*e3(n+1))
D(i) = (e3(n)*e4(n+1))-(e1(n)*e2(n+1))
E(i) = (e3(n)*(C_pls_top(n+1)-C_pls_btm(n)))+(e1(n)*(C_mns_btm(n)-C_mns_top(n+1)))
elseif(mod(i,2)==0) then ! If even and i<=2*snl_lcl
n=(i/2)
A(i) = (e2(n+1)*e1(n))-(e3(n)*e4(n+1))
B(i) = (e2(n)*e2(n+1))-(e4(n)*e4(n+1))
D(i) = (e1(n+1)*e4(n+1))-(e2(n+1)*e3(n+1))
E(i) = (e2(n+1)*(C_pls_top(n+1)-C_pls_btm(n)))+(e4(n+1)*(C_mns_top(n+1)-C_mns_btm(n)))
endif
enddo
AS(0) = A(0)/B(0)
DS(0) = E(0)/B(0)
do i=-1,(2*snl_lcl+1),-1
X(i) = 1/(B(i)-(D(i)*AS(i+1)))
AS(i) = A(i)*X(i)
DS(i) = (E(i)-(D(i)*DS(i+1)))*X(i)
enddo
Y(2*snl_lcl+1) = DS(2*snl_lcl+1)
do i=(2*snl_lcl+2),0,1
Y(i) = DS(i)-(AS(i)*Y(i-1))
enddo
! Downward direct-beam and net flux (F_net) at the base of each layer:
do i=snl_top,snl_btm,1
F_direct(i) = mu_not*pi*flx_slrd_lcl(bnd_idx)*exp(-(tau_clm(i)+tau_star(i))/mu_not)
F_net(i) = (Y(2*i-1)*(e1(i)-e3(i))) + (Y(2*i)*(e2(i)-e4(i))) + &
C_pls_btm(i) - C_mns_btm(i) - F_direct(i)
enddo
! Upward flux at snowpack top:
F_sfc_pls = (Y(2*snl_lcl+1)*(exp(-lambda(snl_top)*tau_star(snl_top))+ &
GAMMA
(snl_top))) + (Y(2*snl_lcl+2)*(exp(-lambda(snl_top)* &
tau_star(snl_top))-GAMMA
(snl_top))) + C_pls_top(snl_top)
! Net flux at bottom = absorbed radiation by underlying surface:
F_btm_net = -F_net(snl_btm)
! Bulk column albedo and surface net flux
albedo = F_sfc_pls/((mu_not*pi*flx_slrd_lcl(bnd_idx))+flx_slri_lcl(bnd_idx))
F_sfc_net = F_sfc_pls - ((mu_not*pi*flx_slrd_lcl(bnd_idx))+flx_slri_lcl(bnd_idx))
trip = 0
! Absorbed flux in each layer
do i=snl_top,snl_btm,1
if(i==snl_top) then
F_abs(i) = F_net(i)-F_sfc_net
else
F_abs(i) = F_net(i)-F_net(i-1)
endif
flx_abs_lcl(i,bnd_idx) = F_abs(i)
! ERROR check: negative absorption
if (flx_abs_lcl(i,bnd_idx) < -0.00001) then
trip = 1
endif
enddo
flx_abs_lcl(1,bnd_idx) = F_btm_net
if (flg_nosnl == 1) then
! If there are no snow layers (but still snow), all absorbed energy must be in top soil layer
!flx_abs_lcl(:,bnd_idx) = 0._r8
!flx_abs_lcl(1,bnd_idx) = F_abs(0) + F_btm_net
! changed on 20070408:
! OK to put absorbed energy in the fictitous snow layer because routine SurfaceRadiation
! handles the case of no snow layers. Then, if a snow layer is addded between now and
! SurfaceRadiation (called in Hydrology1), absorbed energy will be properly distributed.
flx_abs_lcl(0,bnd_idx) = F_abs(0)
flx_abs_lcl(1,bnd_idx) = F_btm_net
endif
!Underflow check (we've already tripped the error condition above)
do i=snl_top,1,1
if (flx_abs_lcl(i,bnd_idx) < 0._r8) then
flx_abs_lcl(i,bnd_idx) = 0._r8
endif
enddo
F_abs_sum = 0._r8
do i=snl_top,snl_btm,1
F_abs_sum = F_abs_sum + F_abs(i)
enddo
!ERROR check: absorption greater than incident flux
! (should make condition more generic than "1._r8")
if (F_abs_sum > 1._r8) then
trip = 1
endif
!ERROR check:
if ((albedo < 0._r8).and.(trip==0)) then
trip = 1
endif
! Set conditions for redoing RT calculation
if ((trip == 1).and.(flg_dover == 1)) then
flg_dover = 2
elseif ((trip == 1).and.(flg_dover == 2)) then
flg_dover = 3
elseif ((trip == 1).and.(flg_dover == 3)) then
flg_dover = 4
elseif((trip == 1).and.(flg_dover == 4).and.(err_idx < 20)) then
flg_dover = 3
err_idx = err_idx + 1
elseif((trip == 1).and.(flg_dover == 4).and.(err_idx >= 20)) then
flg_dover = 0
write(iulog,*) "SNICAR ERROR: FOUND A WORMHOLE. STUCK IN INFINITE LOOP! Called from: ", flg_snw_ice
write(iulog,*) "SNICAR STATS: snw_rds(0)= ", snw_rds(c_idx,0)
write(iulog,*) "SNICAR STATS: L_snw(0)= ", L_snw(0)
write(iulog,*) "SNICAR STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl
write(iulog,*) "SNICAR STATS: soot1(0)= ", mss_cnc_aer_lcl(0,1)
write(iulog,*) "SNICAR STATS: soot2(0)= ", mss_cnc_aer_lcl(0,2)
write(iulog,*) "SNICAR STATS: dust1(0)= ", mss_cnc_aer_lcl(0,3)
write(iulog,*) "SNICAR STATS: dust2(0)= ", mss_cnc_aer_lcl(0,4)
write(iulog,*) "SNICAR STATS: dust3(0)= ", mss_cnc_aer_lcl(0,5)
write(iulog,*) "SNICAR STATS: dust4(0)= ", mss_cnc_aer_lcl(0,6)
call endrun
()
else
flg_dover = 0
endif
enddo !enddo while (flg_dover > 0)
! Energy conservation check:
! Incident direct+diffuse radiation equals (absorbed+bulk_transmitted+bulk_reflected)
energy_sum = (mu_not*pi*flx_slrd_lcl(bnd_idx)) + flx_slri_lcl(bnd_idx) - (F_abs_sum + F_btm_net + F_sfc_pls)
if (abs(energy_sum) > 0.00001_r8) then
write (iulog,"(a,e12.6,a,i6,a,i6)") "SNICAR ERROR: Energy conservation error of : ", energy_sum, &
" at timestep: ", nstep, " at column: ", c_idx
call endrun
()
endif
albout_lcl(bnd_idx) = albedo
! Check that albedo is less than 1
if (albout_lcl(bnd_idx) > 1.0) then
write (iulog,*) "SNICAR ERROR: Albedo > 1.0 at c: ", c_idx, " NSTEP= ",nstep
write (iulog,*) "SNICAR STATS: bnd_idx= ",bnd_idx
write (iulog,*) "SNICAR STATS: albout_lcl(bnd)= ",albout_lcl(bnd_idx), " albsfc_lcl(bnd_idx)= ",albsfc_lcl(bnd_idx)
write (iulog,*) "SNICAR STATS: landtype= ", sfctype
write (iulog,*) "SNICAR STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl
write (iulog,*) "SNICAR STATS: coszen= ", coszen(c_idx), " flg_slr= ", flg_slr_in
write (iulog,*) "SNICAR STATS: soot(-4)= ", mss_cnc_aer_lcl(-4,1)
write (iulog,*) "SNICAR STATS: soot(-3)= ", mss_cnc_aer_lcl(-3,1)
write (iulog,*) "SNICAR STATS: soot(-2)= ", mss_cnc_aer_lcl(-2,1)
write (iulog,*) "SNICAR STATS: soot(-1)= ", mss_cnc_aer_lcl(-1,1)
write (iulog,*) "SNICAR STATS: soot(0)= ", mss_cnc_aer_lcl(0,1)
write (iulog,*) "SNICAR STATS: L_snw(-4)= ", L_snw(-4)
write (iulog,*) "SNICAR STATS: L_snw(-3)= ", L_snw(-3)
write (iulog,*) "SNICAR STATS: L_snw(-2)= ", L_snw(-2)
write (iulog,*) "SNICAR STATS: L_snw(-1)= ", L_snw(-1)
write (iulog,*) "SNICAR STATS: L_snw(0)= ", L_snw(0)
write (iulog,*) "SNICAR STATS: snw_rds(-4)= ", snw_rds(c_idx,-4)
write (iulog,*) "SNICAR STATS: snw_rds(-3)= ", snw_rds(c_idx,-3)
write (iulog,*) "SNICAR STATS: snw_rds(-2)= ", snw_rds(c_idx,-2)
write (iulog,*) "SNICAR STATS: snw_rds(-1)= ", snw_rds(c_idx,-1)
write (iulog,*) "SNICAR STATS: snw_rds(0)= ", snw_rds(c_idx,0)
call endrun
()
endif
enddo ! loop over wvl bands
! Weight output NIR albedo appropriately
albout(c_idx,1) = albout_lcl(1)
flx_sum = 0._r8
do bnd_idx= nir_bnd_bgn,nir_bnd_end
flx_sum = flx_sum + flx_wgt(bnd_idx)*albout_lcl(bnd_idx)
end do
albout(c_idx,2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
! Weight output NIR absorbed layer fluxes (flx_abs) appropriately
flx_abs(c_idx,:,1) = flx_abs_lcl(:,1)
do i=snl_top,1,1
flx_sum = 0._r8
do bnd_idx= nir_bnd_bgn,nir_bnd_end
flx_sum = flx_sum + flx_wgt(bnd_idx)*flx_abs_lcl(i,bnd_idx)
enddo
flx_abs(c_idx,i,2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
end do
! Write diagnostics, if desired. (default is to not compile this)
#if 0
write(iulog,*) "SNICAR STATS: NSTEP= ", nstep
write(iulog,*) "SNICAR STATS: Col: ", c_idx
write(iulog,*) "SNICAR STATS: snl(c)= ",snl_lcl
write(iulog,*) "SNICAR STATS: cosine zenith= ", coszen(c_idx)
write(iulog,*) "SNICAR STATS: h2osno(c): ", h2osno_lcl
write(iulog,*) "SNICAR STATS: albout_lcl(1): ", albout_lcl(1)
write(iulog,*) "SNICAR STATS: albout_lcl(2): ", albout_lcl(2)
write(iulog,*) "SNICAR STATS: albout_lcl(3): ", albout_lcl(3)
write(iulog,*) "SNICAR STATS: albout_lcl(4): ", albout_lcl(4)
write(iulog,*) "SNICAR STATS: albout_lcl(5): ", albout_lcl(5)
write(iulog,*) "SNICAR STATS: albout(1): ", albout(c_idx,1)
write(iulog,*) "SNICAR STATS: albout(2): ", albout(c_idx,2)
write(iulog,*) "SNICAR STATS: NIR flx_abs(-4): ", flx_abs(c_idx,-4,2)
write(iulog,*) "SNICAR STATS: NIR flx_abs(-3): ", flx_abs(c_idx,-3,2)
write(iulog,*) "SNICAR STATS: NIR flx_abs(-2): ", flx_abs(c_idx,-2,2)
write(iulog,*) "SNICAR STATS: NIR flx_abs(-1): ", flx_abs(c_idx,-1,2)
write(iulog,*) "SNICAR STATS: NIR flx_abs(0): ", flx_abs(c_idx,0,2)
write(iulog,*) "SNICAR STATS: TOPLYR ABS, BND 1= ", flx_abs_lcl(snl_top,1)
write(iulog,*) "SNICAR STATS: TOPLYR ABS, BND 2= ", flx_abs_lcl(snl_top,2)
write(iulog,*) "SNICAR STATS: TOPLYR ABS, BND 3= ", flx_abs_lcl(snl_top,3)
write(iulog,*) "SNICAR STATS: TOPLYR ABS, BND 4= ", flx_abs_lcl(snl_top,4)
write(iulog,*) "SNICAR STATS: TOPLYR ABS, BND 5= ", flx_abs_lcl(snl_top,5)
write (iulog,*) "SNICAR STATS: L_snw(-4)= ", L_snw(-4)
write (iulog,*) "SNICAR STATS: L_snw(-3)= ", L_snw(-3)
write (iulog,*) "SNICAR STATS: L_snw(-2)= ", L_snw(-2)
write (iulog,*) "SNICAR STATS: L_snw(-1)= ", L_snw(-1)
write (iulog,*) "SNICAR STATS: L_snw(0)= ", L_snw(0)
write (iulog,*) "SNICAR STATS: snw_rds(-4)= ", snw_rds(c_idx,-4)
write (iulog,*) "SNICAR STATS: snw_rds(-3)= ", snw_rds(c_idx,-3)
write (iulog,*) "SNICAR STATS: snw_rds(-2)= ", snw_rds(c_idx,-2)
write (iulog,*) "SNICAR STATS: snw_rds(-1)= ", snw_rds(c_idx,-1)
write (iulog,*) "SNICAR STATS: snw_rds(0)= ", snw_rds(c_idx,0)
#endif
! If snow < minimum_snow, but > 0, and there is sun, set albedo to underlying surface albedo
elseif ( (coszen(c_idx) > 0._r8) .and. (h2osno_lcl < min_snw) .and. (h2osno_lcl > 0._r8) ) then
albout(c_idx,1) = albsfc(c_idx,1)
albout(c_idx,2) = albsfc(c_idx,2)
! There is either zero snow, or no sun
else
albout(c_idx,1) = 0._r8
albout(c_idx,2) = 0._r8
endif ! if column has snow and coszen > 0
enddo ! loop over all columns
end subroutine SNICAR_RT
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: SnowAge_grain
!
! !INTERFACE:
subroutine SnowAge_grain(lbc, ubc, num_snowc, filter_snowc, num_nosnowc, filter_nosnowc) 1,7
!
! !DESCRIPTION:
! Updates the snow effective grain size (radius).
! Contributions to grain size evolution are from:
! 1. vapor redistribution (dry snow)
! 2. liquid water redistribution (wet snow)
! 3. re-freezing of liquid water
!
! Vapor redistribution: Method is to retrieve 3 best-bit parameters that
! depend on snow temperature, temperature gradient, and density,
! that are derived from the microphysical model described in:
! Flanner and Zender (2006), Linking snowpack microphysics and albedo
! evolution, J. Geophys. Res., 111, D12208, doi:10.1029/2005JD006834.
! The parametric equation has the form:
! dr/dt = drdt_0*(tau/(dr_fresh+tau))^(1/kappa), where:
! r is the effective radius,
! tau and kappa are best-fit parameters,
! drdt_0 is the initial rate of change of effective radius, and
! dr_fresh is the difference between the current and fresh snow states
! (r_current - r_fresh).
!
! Liquid water redistribution: Apply the grain growth function from:
! Brun, E. (1989), Investigation of wet-snow metamorphism in respect of
! liquid-water content, Annals of Glaciology, 13, 22-26.
! There are two parameters that describe the grain growth rate as
! a function of snow liquid water content (LWC). The "LWC=0" parameter
! is zeroed here because we are accounting for dry snowing with a
! different representation
!
! Re-freezing of liquid water: Assume that re-frozen liquid water clumps
! into an arbitrarily large effective grain size (snw_rds_refrz).
! The phenomenon is observed (Grenfell), but so far unquantified, as far as
! I am aware.
!
!
! !USES:
use clmtype
use clm_time_manager
, only : get_step_size, get_nstep
use clm_varpar
, only : nlevsno
use clm_varcon
, only : spval
use abortutils
, only : endrun
use shr_const_mod
, only : SHR_CONST_RHOICE, SHR_CONST_PI
!
! !ARGUMENTS:
implicit none
integer, intent(in) :: lbc, ubc ! column bounds
integer, intent(in) :: num_snowc ! number of column snow points in column filter
integer, intent(in) :: filter_snowc(ubc-lbc+1) ! column filter for snow points
integer, intent(in) :: num_nosnowc ! number of column non-snow points in column filter
integer, intent(in) :: filter_nosnowc(ubc-lbc+1) ! column filter for non-snow points
!
!
! !CALLED FROM: clm_driver1
!
! !LOCAL VARIABLES:
!
! local pointers to implicit arguments
!
real(r8), pointer :: t_soisno(:,:) ! soil and snow temperature (col,lyr) [K]
integer, pointer :: snl(:) ! negative number of snow layers (col) [nbr]
real(r8), pointer :: t_grnd(:) ! ground temperature (col) [K]
real(r8), pointer :: dz(:,:) ! layer thickness (col,lyr) [m]
real(r8), pointer :: h2osno(:) ! snow water (col) [mm H2O]
real(r8), pointer :: snw_rds(:,:) ! effective grain radius (col,lyr) [microns, m-6]
real(r8), pointer :: snw_rds_top(:) ! effective grain radius, top layer (col) [microns, m-6]
real(r8), pointer :: sno_liq_top(:) ! liquid water fraction (mass) in top snow layer (col) [frc]
real(r8), pointer :: h2osoi_liq(:,:) ! liquid water content (col,lyr) [kg m-2]
real(r8), pointer :: h2osoi_ice(:,:) ! ice content (col,lyr) [kg m-2]
real(r8), pointer :: snot_top(:) ! snow temperature in top layer (col) [K]
real(r8), pointer :: dTdz_top(:) ! temperature gradient in top layer (col) [K m-1]
real(r8), pointer :: qflx_snow_grnd_col(:) ! snow on ground after interception (col) [kg m-2 s-1]
real(r8), pointer :: qflx_snwcp_ice(:) ! excess precipitation due to snow capping [kg m-2 s-1]
real(r8), pointer :: qflx_snofrz_lyr(:,:) ! snow freezing rate (col,lyr) [kg m-2 s-1]
logical , pointer :: do_capsnow(:) ! true => do snow capping
!
! !OTHER LOCAL VARIABLES:
!
integer :: snl_top ! top snow layer index [idx]
integer :: snl_btm ! bottom snow layer index [idx]
integer :: i ! layer index [idx]
integer :: c_idx ! column index [idx]
integer :: fc ! snow column filter index [idx]
integer :: T_idx ! snow aging lookup table temperature index [idx]
integer :: Tgrd_idx ! snow aging lookup table temperature gradient index [idx]
integer :: rhos_idx ! snow aging lookup table snow density index [idx]
real(r8) :: t_snotop ! temperature at upper layer boundary [K]
real(r8) :: t_snobtm ! temperature at lower layer boundary [K]
real(r8) :: dTdz(lbc:ubc,-nlevsno:0) ! snow temperature gradient (col,lyr) [K m-1]
real(r8) :: bst_tau ! snow aging parameter retrieved from lookup table [hour]
real(r8) :: bst_kappa ! snow aging parameter retrieved from lookup table [unitless]
real(r8) :: bst_drdt0 ! snow aging parameter retrieved from lookup table [um hr-1]
real(r8) :: dr ! incremental change in snow effective radius [um]
real(r8) :: dr_wet ! incremental change in snow effective radius from wet growth [um]
real(r8) :: dr_fresh ! difference between fresh snow r_e and current r_e [um]
real(r8) :: newsnow ! fresh snowfall [kg m-2]
real(r8) :: refrzsnow ! re-frozen snow [kg m-2]
real(r8) :: frc_newsnow ! fraction of layer mass that is new snow [frc]
real(r8) :: frc_oldsnow ! fraction of layer mass that is old snow [frc]
real(r8) :: frc_refrz ! fraction of layer mass that is re-frozen snow [frc]
real(r8) :: frc_liq ! fraction of layer mass that is liquid water[frc]
real(r8) :: dtime ! land model time step [sec]
real(r8) :: rhos ! snow density [kg m-3]
real(r8) :: h2osno_lyr ! liquid + solid H2O in snow layer [kg m-2]
! Assign local pointers to derived subtypes components (column-level)
t_soisno => clm3%g%l%c%ces%t_soisno
snl => clm3%g%l%c%cps%snl
t_grnd => clm3%g%l%c%ces%t_grnd
dz => clm3%g%l%c%cps%dz
h2osno => clm3%g%l%c%cws%h2osno
snw_rds => clm3%g%l%c%cps%snw_rds
h2osoi_liq => clm3%g%l%c%cws%h2osoi_liq
h2osoi_ice => clm3%g%l%c%cws%h2osoi_ice
snot_top => clm3%g%l%c%cps%snot_top
dTdz_top => clm3%g%l%c%cps%dTdz_top
snw_rds_top => clm3%g%l%c%cps%snw_rds_top
sno_liq_top => clm3%g%l%c%cps%sno_liq_top
qflx_snow_grnd_col => clm3%g%l%c%cwf%pwf_a%qflx_snow_grnd
qflx_snwcp_ice => clm3%g%l%c%cwf%pwf_a%qflx_snwcp_ice
qflx_snofrz_lyr => clm3%g%l%c%cwf%qflx_snofrz_lyr
do_capsnow => clm3%g%l%c%cps%do_capsnow
! set timestep and step interval
dtime = get_step_size
()
! loop over columns that have at least one snow layer
do fc = 1, num_snowc
c_idx = filter_snowc(fc)
snl_btm = 0
snl_top = snl(c_idx) + 1
! loop over snow layers
do i=snl_top,snl_btm,1
!
!********** 1. DRY SNOW AGING ***********
!
h2osno_lyr = h2osoi_liq(c_idx,i) + h2osoi_ice(c_idx,i)
! temperature gradient
if (i == snl_top) then
! top layer
t_snotop = t_grnd(c_idx)
t_snobtm = (t_soisno(c_idx,i+1)*dz(c_idx,i) + t_soisno(c_idx,i)*dz(c_idx,i+1)) / (dz(c_idx,i)+dz(c_idx,i+1))
else
t_snotop = (t_soisno(c_idx,i-1)*dz(c_idx,i) + t_soisno(c_idx,i)*dz(c_idx,i-1)) / (dz(c_idx,i)+dz(c_idx,i-1))
t_snobtm = (t_soisno(c_idx,i+1)*dz(c_idx,i) + t_soisno(c_idx,i)*dz(c_idx,i+1)) / (dz(c_idx,i)+dz(c_idx,i+1))
endif
dTdz(c_idx,i) = abs((t_snotop - t_snobtm) / dz(c_idx,i))
! snow density
rhos = (h2osoi_liq(c_idx,i)+h2osoi_ice(c_idx,i)) / dz(c_idx,i)
! best-fit table indecies
T_idx = nint((t_soisno(c_idx,i)-223) / 5) + 1
Tgrd_idx = nint(dTdz(c_idx,i) / 10) + 1
rhos_idx = nint((rhos-50) / 50) + 1
! boundary check:
if (T_idx < idx_T_min) then
T_idx = idx_T_min
endif
if (T_idx > idx_T_max) then
T_idx = idx_T_max
endif
if (Tgrd_idx < idx_Tgrd_min) then
Tgrd_idx = idx_Tgrd_min
endif
if (Tgrd_idx > idx_Tgrd_max) then
Tgrd_idx = idx_Tgrd_max
endif
if (rhos_idx < idx_rhos_min) then
rhos_idx = idx_rhos_min
endif
if (rhos_idx > idx_rhos_max) then
rhos_idx = idx_rhos_max
endif
! best-fit parameters
bst_tau = snowage_tau(rhos_idx,Tgrd_idx,T_idx)
bst_kappa = snowage_kappa(rhos_idx,Tgrd_idx,T_idx)
bst_drdt0 = snowage_drdt0(rhos_idx,Tgrd_idx,T_idx)
! change in snow effective radius, using best-fit parameters
dr_fresh = snw_rds(c_idx,i)-snw_rds_min
dr = (bst_drdt0*(bst_tau/(dr_fresh+bst_tau))**(1/bst_kappa)) * (dtime/3600)
!
!********** 2. WET SNOW AGING ***********
!
! We are assuming wet and dry evolution occur simultaneously, and
! the contributions from both can be summed.
! This is justified by setting the linear offset constant C1_liq_Brun89 to zero [Brun, 1989]
! liquid water faction
frc_liq = min(0.1_r8, (h2osoi_liq(c_idx,i) / (h2osoi_liq(c_idx,i)+h2osoi_ice(c_idx,i))))
!dr_wet = 1E6_r8*(dtime*(C1_liq_Brun89 + C2_liq_Brun89*(frc_liq**(3))) / (4*SHR_CONST_PI*(snw_rds(c_idx,i)/1E6)**(2)))
!simplified, units of microns:
dr_wet = 1E18_r8*(dtime*(C2_liq_Brun89*(frc_liq**(3))) / (4*SHR_CONST_PI*snw_rds(c_idx,i)**(2)))
dr = dr + dr_wet
!
!********** 3. SNOWAGE SCALING (TURNED OFF BY DEFAULT) *************
!
! Multiply rate of change of effective radius by some constant, xdrdt
if (flg_snoage_scl) then
dr = dr*xdrdt
endif
!
!********** 4. INCREMENT EFFECTIVE RADIUS, ACCOUNTING FOR: ***********
! DRY AGING
! WET AGING
! FRESH SNOW
! RE-FREEZING
!
! new snowfall [kg/m2]
if (do_capsnow(c_idx)) then
newsnow = max(0._r8, (qflx_snwcp_ice(c_idx)*dtime))
else
newsnow = max(0._r8, (qflx_snow_grnd_col(c_idx)*dtime))
endif
! snow that has re-frozen [kg/m2]
refrzsnow = max(0._r8, (qflx_snofrz_lyr(c_idx,i)*dtime))
! fraction of layer mass that is re-frozen
frc_refrz = refrzsnow / h2osno_lyr
! fraction of layer mass that is new snow
if (i == snl_top) then
frc_newsnow = newsnow / h2osno_lyr
else
frc_newsnow = 0._r8
endif
if ((frc_refrz + frc_newsnow) > 1._r8) then
frc_refrz = frc_refrz / (frc_refrz + frc_newsnow)
frc_newsnow = 1._r8 - frc_refrz
frc_oldsnow = 0._r8
else
frc_oldsnow = 1._r8 - frc_refrz - frc_newsnow
endif
! mass-weighted mean of fresh snow, old snow, and re-frozen snow effective radius
snw_rds(c_idx,i) = (snw_rds(c_idx,i)+dr)*frc_oldsnow + snw_rds_min*frc_newsnow + snw_rds_refrz*frc_refrz
!
!********** 5. CHECK BOUNDARIES ***********
!
! boundary check
if (snw_rds(c_idx,i) < snw_rds_min) then
snw_rds(c_idx,i) = snw_rds_min
endif
if (snw_rds(c_idx,i) > snw_rds_max) then
snw_rds(c_idx,i) = snw_rds_max
end if
! set top layer variables for history files
if (i == snl_top) then
snot_top(c_idx) = t_soisno(c_idx,i)
dTdz_top(c_idx) = dTdz(c_idx,i)
snw_rds_top(c_idx) = snw_rds(c_idx,i)
sno_liq_top(c_idx) = h2osoi_liq(c_idx,i) / (h2osoi_liq(c_idx,i)+h2osoi_ice(c_idx,i))
endif
enddo
enddo
! Special case: snow on ground, but not enough to have defined a snow layer:
! set snw_rds to fresh snow grain size:
do fc = 1, num_nosnowc
c_idx = filter_nosnowc(fc)
if (h2osno(c_idx) > 0._r8) then
snw_rds(c_idx,0) = snw_rds_min
endif
enddo
end subroutine SnowAge_grain
subroutine SnowOptics_init( ) 1,67
use fileutils
, only : getfil
use CLM_varctl
, only : fsnowoptics
use spmdMod
, only : mpicom, MPI_REAL8, masterproc
use ncdio
, only : nf_close, nf_inq_varid, nf_open, check_ret, &
nf_get_var_double
integer :: ncid ! netCDF file id
character(len=256) :: locfn ! local filename
character(len= 32) :: subname = 'SnowOptics_init' ! subroutine name
integer :: varid ! netCDF id's
integer :: ier ! error status
!
! Open optics file:
if (masterproc) then
write(iulog,*) 'Attempting to read snow optical properties .....'
call getfil
(fsnowoptics, locfn, 0)
call check_ret
(nf_open(locfn, 0, ncid), subname)
write(iulog,*) subname,trim(fsnowoptics)
! direct-beam snow Mie parameters:
call check_ret
(nf_inq_varid(ncid, 'ss_alb_ice_drc', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ss_alb_snw_drc), subname)
call check_ret
(nf_inq_varid(ncid, 'asm_prm_ice_drc', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, asm_prm_snw_drc), subname)
call check_ret
(nf_inq_varid(ncid, 'ext_cff_mss_ice_drc', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ext_cff_mss_snw_drc), subname)
! diffuse snow Mie parameters
call check_ret
(nf_inq_varid(ncid, 'ss_alb_ice_dfs', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ss_alb_snw_dfs), subname)
call check_ret
(nf_inq_varid(ncid, 'asm_prm_ice_dfs', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, asm_prm_snw_dfs), subname)
call check_ret
(nf_inq_varid(ncid, 'ext_cff_mss_ice_dfs', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ext_cff_mss_snw_dfs), subname)
! BC species 1 Mie parameters
call check_ret
(nf_inq_varid(ncid, 'ss_alb_bcphil', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ss_alb_bc1), subname)
call check_ret
(nf_inq_varid(ncid, 'asm_prm_bcphil', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, asm_prm_bc1), subname)
call check_ret
(nf_inq_varid(ncid, 'ext_cff_mss_bcphil', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ext_cff_mss_bc1), subname)
! BC species 2 Mie parameters
call check_ret
(nf_inq_varid(ncid, 'ss_alb_bcphob', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ss_alb_bc2), subname)
call check_ret
(nf_inq_varid(ncid, 'asm_prm_bcphob', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, asm_prm_bc2), subname)
call check_ret
(nf_inq_varid(ncid, 'ext_cff_mss_bcphob', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ext_cff_mss_bc2), subname)
! OC species 1 Mie parameters
call check_ret
(nf_inq_varid(ncid, 'ss_alb_ocphil', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ss_alb_oc1), subname)
call check_ret
(nf_inq_varid(ncid, 'asm_prm_ocphil', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, asm_prm_oc1), subname)
call check_ret
(nf_inq_varid(ncid, 'ext_cff_mss_ocphil', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ext_cff_mss_oc1), subname)
! OC species 2 Mie parameters
call check_ret
(nf_inq_varid(ncid, 'ss_alb_ocphob', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ss_alb_oc2), subname)
call check_ret
(nf_inq_varid(ncid, 'asm_prm_ocphob', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, asm_prm_oc2), subname)
call check_ret
(nf_inq_varid(ncid, 'ext_cff_mss_ocphob', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ext_cff_mss_oc2), subname)
! dust species 1 Mie parameters
call check_ret
(nf_inq_varid(ncid, 'ss_alb_dust01', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ss_alb_dst1), subname)
call check_ret
(nf_inq_varid(ncid, 'asm_prm_dust01', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, asm_prm_dst1), subname)
call check_ret
(nf_inq_varid(ncid, 'ext_cff_mss_dust01', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ext_cff_mss_dst1), subname)
! dust species 2 Mie parameters
call check_ret
(nf_inq_varid(ncid, 'ss_alb_dust02', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ss_alb_dst2), subname)
call check_ret
(nf_inq_varid(ncid, 'asm_prm_dust02', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, asm_prm_dst2), subname)
call check_ret
(nf_inq_varid(ncid, 'ext_cff_mss_dust02', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ext_cff_mss_dst2), subname)
! dust species 3 Mie parameters
call check_ret
(nf_inq_varid(ncid, 'ss_alb_dust03', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ss_alb_dst3), subname)
call check_ret
(nf_inq_varid(ncid, 'asm_prm_dust03', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, asm_prm_dst3), subname)
call check_ret
(nf_inq_varid(ncid, 'ext_cff_mss_dust03', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ext_cff_mss_dst3), subname)
! dust species 4 Mie parameters
call check_ret
(nf_inq_varid(ncid, 'ss_alb_dust04', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ss_alb_dst4), subname)
call check_ret
(nf_inq_varid(ncid, 'asm_prm_dust04', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, asm_prm_dst4), subname)
call check_ret
(nf_inq_varid(ncid, 'ext_cff_mss_dust04', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, ext_cff_mss_dst4), subname)
endif
call mpi_bcast (ss_alb_snw_dfs, size(ss_alb_snw_dfs), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (asm_prm_snw_dfs, size(asm_prm_snw_dfs), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ext_cff_mss_snw_dfs, size(ext_cff_mss_snw_dfs), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ss_alb_snw_drc, size(ss_alb_snw_drc), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (asm_prm_snw_drc, size(asm_prm_snw_drc), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ext_cff_mss_snw_drc, size(ext_cff_mss_snw_drc), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ss_alb_bc1, size(ss_alb_bc1), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ss_alb_bc2, size(ss_alb_bc2), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ss_alb_oc1, size(ss_alb_oc1), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ss_alb_oc2, size(ss_alb_oc2), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (asm_prm_bc1, size(asm_prm_bc1), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (asm_prm_bc2, size(asm_prm_bc2), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (asm_prm_oc1, size(asm_prm_oc1), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (asm_prm_oc2, size(asm_prm_oc2), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ss_alb_dst1, size(ss_alb_dst1), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ss_alb_dst2, size(ss_alb_dst2), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ss_alb_dst3, size(ss_alb_dst3), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ss_alb_dst4, size(ss_alb_dst4), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (asm_prm_dst1, size(asm_prm_dst1), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (asm_prm_dst2, size(asm_prm_dst2), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (asm_prm_dst3, size(asm_prm_dst3), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (asm_prm_dst4, size(asm_prm_dst4), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ext_cff_mss_bc1, size(ext_cff_mss_bc1), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ext_cff_mss_bc2, size(ext_cff_mss_bc2), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ext_cff_mss_oc1, size(ext_cff_mss_oc1), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ext_cff_mss_oc2, size(ext_cff_mss_oc2), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ext_cff_mss_dst1, size(ext_cff_mss_dst1), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ext_cff_mss_dst2, size(ext_cff_mss_dst2), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ext_cff_mss_dst3, size(ext_cff_mss_dst3), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (ext_cff_mss_dst4, size(ext_cff_mss_dst4), MPI_REAL8 , 0, mpicom, ier)
if (masterproc) then
call check_ret
(nf_close(ncid), subname)
write(iulog,*) 'Successfully read snow optical properties'
! print some diagnostics:
write (iulog,*) 'SNICAR: Mie single scatter albedos for direct-beam ice, rds=100um: ', &
ss_alb_snw_drc(71,1), ss_alb_snw_drc(71,2), ss_alb_snw_drc(71,3), &
ss_alb_snw_drc(71,4), ss_alb_snw_drc(71,5)
write (iulog,*) 'SNICAR: Mie single scatter albedos for diffuse ice, rds=100um: ', &
ss_alb_snw_dfs(71,1), ss_alb_snw_dfs(71,2), ss_alb_snw_dfs(71,3), &
ss_alb_snw_dfs(71,4), ss_alb_snw_dfs(71,5)
if (DO_SNO_OC) then
write (iulog,*) 'SNICAR: Including OC aerosols from snow radiative transfer calculations'
else
write (iulog,*) 'SNICAR: Excluding OC aerosols from snow radiative transfer calculations'
endif
write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophillic BC: ', &
ss_alb_bc1(1,1), ss_alb_bc1(1,2), ss_alb_bc1(1,3), ss_alb_bc1(1,4), ss_alb_bc1(1,5)
write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophobic BC: ', &
ss_alb_bc2(1,1), ss_alb_bc2(1,2), ss_alb_bc2(1,3), ss_alb_bc2(1,4), ss_alb_bc2(1,5)
if (DO_SNO_OC) then
write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophillic OC: ', &
ss_alb_oc1(1,1), ss_alb_oc1(1,2), ss_alb_oc1(1,3), ss_alb_oc1(1,4), ss_alb_oc1(1,5)
write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophobic OC: ', &
ss_alb_oc2(1,1), ss_alb_oc2(1,2), ss_alb_oc2(1,3), ss_alb_oc2(1,4), ss_alb_oc2(1,5)
endif
write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 1: ', &
ss_alb_dst1(1,1), ss_alb_dst1(1,2), ss_alb_dst1(1,3), ss_alb_dst1(1,4), ss_alb_dst1(1,5)
write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 2: ', &
ss_alb_dst2(1,1), ss_alb_dst2(1,2), ss_alb_dst2(1,3), ss_alb_dst2(1,4), ss_alb_dst2(1,5)
write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 3: ', &
ss_alb_dst3(1,1), ss_alb_dst3(1,2), ss_alb_dst3(1,3), ss_alb_dst3(1,4), ss_alb_dst3(1,5)
write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 4: ', &
ss_alb_dst4(1,1), ss_alb_dst4(1,2), ss_alb_dst4(1,3), ss_alb_dst4(1,4), ss_alb_dst4(1,5)
write(iulog,*)
end if
end subroutine SnowOptics_init
subroutine SnowAge_init( ) 1,13
use CLM_varctl
, only : fsnowaging
use fileutils
, only : getfil
use spmdMod
, only : mpicom, MPI_REAL8, masterproc
use ncdio
, only : nf_close, nf_inq_varid, nf_open, check_ret, &
nf_get_var_double
integer :: ncid ! netCDF file id
character(len=256) :: locfn ! local filename
character(len= 32) :: subname = 'SnowOptics_init' ! subroutine name
integer :: varid ! netCDF id's
integer :: ier ! error status
! Open snow aging (effective radius evolution) file:
if (masterproc) then
write(iulog,*) 'Attempting to read snow aging parameters .....'
call getfil
(fsnowaging, locfn, 0)
call check_ret
(nf_open(locfn, 0, ncid), subname)
write(iulog,*) subname,trim(fsnowaging)
! snow aging parameters
call check_ret
(nf_inq_varid(ncid, 'tau', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, snowage_tau), subname)
call check_ret
(nf_inq_varid(ncid, 'kappa', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, snowage_kappa), subname)
call check_ret
(nf_inq_varid(ncid, 'drdsdt0', varid), subname)
call check_ret
(nf_get_var_double(ncid, varid, snowage_drdt0), subname)
endif
call mpi_bcast (snowage_tau, size(snowage_tau), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (snowage_kappa, size(snowage_kappa), MPI_REAL8 , 0, mpicom, ier)
call mpi_bcast (snowage_drdt0, size(snowage_drdt0), MPI_REAL8 , 0, mpicom, ier)
if (masterproc) then
call check_ret
(nf_close(ncid), subname)
write(iulog,*) 'Successfully read snow aging properties'
! print some diagnostics:
write (iulog,*) 'SNICAR: snowage tau for T=263K, dTdz = 100 K/m, rhos = 150 kg/m3: ', snowage_tau(3,11,9)
write (iulog,*) 'SNICAR: snowage kappa for T=263K, dTdz = 100 K/m, rhos = 150 kg/m3: ', snowage_kappa(3,11,9)
write (iulog,*) 'SNICAR: snowage dr/dt_0 for T=263K, dTdz = 100 K/m, rhos = 150 kg/m3: ', snowage_drdt0(3,11,9)
endif
end subroutine SnowAge_init
end module SNICARMod