From 9985a65cd42f849692fbc7c10d260915b88ad5ff Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 27 Mar 2021 14:58:08 -0600 Subject: [PATCH 01/69] First commit of MIMICS in CTSM Added is_microbe to SoilBiogeochemDecompCascadeConType.F90 and copied SoilBiogeochemDecompCascadeBGCMod.F90 to SoilBiogeochemDecompCascadeMIMICSMod.F90 as a template for the work to be done. No modifications to this file in this commit. --- .../SoilBiogeochemDecompCascadeConType.F90 | 3 + .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 1058 +++++++++++++++++ 2 files changed, 1061 insertions(+) create mode 100644 src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 index 3d45afef75..cb6be6f4ed 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 @@ -27,6 +27,7 @@ module SoilBiogeochemDecompCascadeConType character(len=8) , pointer :: decomp_pool_name_history(:) ! name of pool for history files character(len=20) , pointer :: decomp_pool_name_long(:) ! name of pool for netcdf long names character(len=8) , pointer :: decomp_pool_name_short(:) ! name of pool for netcdf short names + logical , pointer :: is_microbe(:) ! TRUE => pool is a microbe pool logical , pointer :: is_litter(:) ! TRUE => pool is a litter pool logical , pointer :: is_soil(:) ! TRUE => pool is a soil pool logical , pointer :: is_cwd(:) ! TRUE => pool is a cwd pool @@ -72,6 +73,7 @@ subroutine init_decomp_cascade_constants( use_century_decomp ) allocate(decomp_cascade_con%decomp_pool_name_history(ibeg:ndecomp_pools)) allocate(decomp_cascade_con%decomp_pool_name_long(ibeg:ndecomp_pools)) allocate(decomp_cascade_con%decomp_pool_name_short(ibeg:ndecomp_pools)) + allocate(decomp_cascade_con%is_microbe(ibeg:ndecomp_pools)) allocate(decomp_cascade_con%is_litter(ibeg:ndecomp_pools)) allocate(decomp_cascade_con%is_soil(ibeg:ndecomp_pools)) allocate(decomp_cascade_con%is_cwd(ibeg:ndecomp_pools)) @@ -93,6 +95,7 @@ subroutine init_decomp_cascade_constants( use_century_decomp ) decomp_cascade_con%decomp_pool_name_restart(ibeg:ndecomp_pools) = '' decomp_cascade_con%decomp_pool_name_long(ibeg:ndecomp_pools) = '' decomp_cascade_con%decomp_pool_name_short(ibeg:ndecomp_pools) = '' + decomp_cascade_con%is_microbe(ibeg:ndecomp_pools) = .false. decomp_cascade_con%is_litter(ibeg:ndecomp_pools) = .false. decomp_cascade_con%is_soil(ibeg:ndecomp_pools) = .false. decomp_cascade_con%is_cwd(ibeg:ndecomp_pools) = .false. diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 new file mode 100644 index 0000000000..56f6748761 --- /dev/null +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -0,0 +1,1058 @@ +module SoilBiogeochemDecompCascadeBGCMod + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Sets the coeffiecients used in the decomposition cascade submodel. + ! This uses the CENTURY/BGC parameters + ! + ! !USES: + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_const_mod , only : SHR_CONST_TKFRZ + use shr_log_mod , only : errMsg => shr_log_errMsg + use clm_varpar , only : nlevsoi, nlevgrnd, nlevdecomp, ndecomp_cascade_transitions, ndecomp_pools + use clm_varpar , only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd + use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_vertsoilc, use_fates + use clm_varcon , only : zsoi + use decompMod , only : bounds_type + use spmdMod , only : masterproc + use abortutils , only : endrun + use CNSharedParamsMod , only : CNParamsShareInst, nlev_soildecomp_standard + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con + use SoilBiogeochemStateType , only : soilbiogeochem_state_type + use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type + use SoilStateType , only : soilstate_type + use TemperatureType , only : temperature_type + use ch4Mod , only : ch4_type + use ColumnType , only : col + use GridcellType , only : grc + use SoilBiogeochemStateType , only : get_spinup_latitude_term + + ! + implicit none + private + ! + ! !PUBLIC MEMBER FUNCTIONS: + public :: DecompCascadeBGCreadNML ! Read in namelist + public :: readParams ! Read in parameters from params file + public :: init_decompcascade_bgc ! Initialization + public :: decomp_rate_constants_bgc ! Figure out decomposition rates + ! + ! !PUBLIC DATA MEMBERS + logical , public :: normalize_q10_to_century_tfunc = .true.! do we normalize the century decomp. rates so that they match the CLM Q10 at a given tep? + logical , public :: use_century_tfunc = .false. + real(r8), public :: normalization_tref = 15._r8 ! reference temperature for normalizaion (degrees C) + ! + ! !PRIVATE DATA MEMBERS + + integer, private :: i_soil1 = -9 ! Soil Organic Matter (SOM) first pool + integer, private :: i_soil2 = -9 ! SOM second pool + integer, private :: i_soil3 = -9 ! SOM third pool + integer, private, parameter :: nsompools = 3 ! Number of SOM pools + integer, private, parameter :: i_litr1 = i_met_lit ! First litter pool, metobolic + integer, private, parameter :: i_litr2 = i_cel_lit ! Second litter pool, cellulose + integer, private, parameter :: i_litr3 = i_lig_lit ! Third litter pool, lignin + + type, private :: params_type + real(r8):: cn_s1_bgc !C:N for SOM 1 + real(r8):: cn_s2_bgc !C:N for SOM 2 + real(r8):: cn_s3_bgc !C:N for SOM 3 + + real(r8):: rf_l1s1_bgc !respiration fraction litter 1 -> SOM 1 + real(r8):: rf_l2s1_bgc + real(r8):: rf_l3s2_bgc + + real(r8):: rf_s2s1_bgc + real(r8):: rf_s2s3_bgc + real(r8):: rf_s3s1_bgc + + real(r8):: rf_cwdl2_bgc + real(r8):: rf_cwdl3_bgc + + real(r8):: tau_l1_bgc ! 1/turnover time of litter 1 from Century (l/18.5) (1/yr) + real(r8):: tau_l2_l3_bgc ! 1/turnover time of litter 2 and litter 3 from Century (1/4.9) (1/yr) + real(r8):: tau_s1_bgc ! 1/turnover time of SOM 1 from Century (1/7.3) (1/yr) + real(r8):: tau_s2_bgc ! 1/turnover time of SOM 2 from Century (1/0.2) (1/yr) + real(r8):: tau_s3_bgc ! 1/turnover time of SOM 3 from Century (1/0.0045) (1/yr) + real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) + + real(r8) :: cwd_fcel_bgc !cellulose fraction for CWD + real(r8) :: cwd_flig_bgc ! + + real(r8) :: k_frag_bgc !fragmentation rate for CWD + real(r8) :: minpsi_bgc !minimum soil water potential for heterotrophic resp + real(r8) :: maxpsi_bgc !maximum soil water potential for heterotrophic resp + + real(r8) :: initial_Cstocks(nsompools) ! Initial Carbon stocks for a cold-start + real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start + + end type params_type + ! + type(params_type), private :: params_inst + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + + !----------------------------------------------------------------------- + +contains + + !----------------------------------------------------------------------- + subroutine DecompCascadeBGCreadNML( NLFilename ) + ! + ! !DESCRIPTION: + ! Read the namelist for soil BGC Decomposition Cascade + ! + ! !USES: + use fileutils , only : getavu, relavu, opnfil + use shr_nl_mod , only : shr_nl_find_group_name + use spmdMod , only : masterproc, mpicom + use shr_mpi_mod , only : shr_mpi_bcast + use clm_varctl , only : iulog + use shr_log_mod , only : errMsg => shr_log_errMsg + use abortutils , only : endrun + ! + ! !ARGUMENTS: + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! !LOCAL VARIABLES: + integer :: ierr ! error code + integer :: unitn ! unit for namelist file + + character(len=*), parameter :: subname = 'DecompCascadeBGCreadNML' + character(len=*), parameter :: nmlname = 'CENTURY_soilBGCDecompCascade' + !----------------------------------------------------------------------- + real(r8) :: initial_Cstocks(nsompools), initial_Cstocks_depth + namelist /CENTURY_soilBGCDecompCascade/ initial_Cstocks, initial_Cstocks_depth + + ! Initialize options to default values, in case they are not specified in + ! the namelist + + initial_Cstocks(:) = 200._r8 + initial_Cstocks_depth = 0.3 + + if (masterproc) then + unitn = getavu() + write(iulog,*) 'Read in '//nmlname//' namelist' + call opnfil (NLFilename, unitn, 'F') + call shr_nl_find_group_name(unitn, nmlname, status=ierr) + if (ierr == 0) then + read(unitn, nml=CENTURY_soilBGCDecompCascade, iostat=ierr) + if (ierr /= 0) then + call endrun(msg="ERROR reading "//nmlname//"namelist"//errmsg(__FILE__, __LINE__)) + end if + else + call endrun(msg="ERROR could NOT find "//nmlname//"namelist"//errmsg(__FILE__, __LINE__)) + end if + call relavu( unitn ) + end if + + call shr_mpi_bcast (initial_Cstocks , mpicom) + call shr_mpi_bcast (initial_Cstocks_depth, mpicom) + + if (masterproc) then + write(iulog,*) ' ' + write(iulog,*) nmlname//' settings:' + write(iulog,nml=CENTURY_soilBGCDecompCascade) + write(iulog,*) ' ' + end if + + params_inst%initial_Cstocks(:) = initial_Cstocks(:) + params_inst%initial_Cstocks_depth = initial_Cstocks_depth + + end subroutine DecompCascadeBGCreadNML + + !----------------------------------------------------------------------- + subroutine readParams ( ncid ) + ! + ! !DESCRIPTION: + ! + ! !USES: + use ncdio_pio , only: file_desc_t,ncd_io + ! + ! !ARGUMENTS: + type(file_desc_t),intent(inout) :: ncid ! pio netCDF file id + ! + ! !LOCAL VARIABLES: + character(len=32) :: subname = 'CNDecompBgcParamsType' + character(len=100) :: errCode = 'Error reading in CN const file ' + logical :: readv ! has variable been read in or not + real(r8) :: tempr ! temporary to read in constant + character(len=100) :: tString ! temp. var for reading + !----------------------------------------------------------------------- + + ! Read off of netcdf file + tString='tau_l1' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%tau_l1_bgc=tempr + + tString='tau_l2_l3' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%tau_l2_l3_bgc=tempr + + tString='tau_s1' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%tau_s1_bgc=tempr + + tString='tau_s2' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%tau_s2_bgc=tempr + + tString='tau_s3' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%tau_s3_bgc=tempr + + tString='tau_cwd' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%tau_cwd_bgc=tempr + + tString='cn_s1_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%cn_s1_bgc=tempr + + tString='cn_s2_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%cn_s2_bgc=tempr + + tString='cn_s3_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%cn_s3_bgc=tempr + + tString='rf_l1s1_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_l1s1_bgc=tempr + + tString='rf_l2s1_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_l2s1_bgc=tempr + + tString='rf_l3s2_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_l3s2_bgc=tempr + + tString='rf_s2s1_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_s2s1_bgc=tempr + + tString='rf_s2s3_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_s2s3_bgc=tempr + + tString='rf_s3s1_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_s3s1_bgc=tempr + + tString='rf_cwdl2_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_cwdl2_bgc=tempr + + tString='rf_cwdl3_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_cwdl3_bgc=tempr + + tString='cwd_fcel' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%cwd_fcel_bgc=tempr + + tString='k_frag' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%k_frag_bgc=tempr + + tString='minpsi_hr' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%minpsi_bgc=tempr + + tString='maxpsi_hr' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%maxpsi_bgc=tempr + + tString='cwd_flig' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%cwd_flig_bgc=tempr + + end subroutine readParams + + !----------------------------------------------------------------------- + subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_inst ) + ! + ! !DESCRIPTION: + ! initialize rate constants and decomposition pathways following the decomposition cascade of the BGC model. + ! written by C. Koven + ! + ! !USES: + ! + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds + type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst + type(soilstate_type) , intent(in) :: soilstate_inst + ! + ! !LOCAL VARIABLES + !-- properties of each decomposing pool + real(r8) :: rf_l1s1 + real(r8) :: rf_l2s1 + real(r8) :: rf_l3s2 + !real(r8) :: rf_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) + !real(r8) :: rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) + real(r8), allocatable :: rf_s1s2(:,:) + real(r8), allocatable :: rf_s1s3(:,:) + real(r8) :: rf_s2s1 + real(r8) :: rf_s2s3 + real(r8) :: rf_s3s1 + real(r8) :: rf_cwdl2 + real(r8) :: rf_cwdl3 + real(r8) :: cwd_fcel + real(r8) :: cwd_flig + real(r8) :: cn_s1 + real(r8) :: cn_s2 + real(r8) :: cn_s3 + !real(r8) :: f_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) + !real(r8) :: f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) + real(r8), allocatable :: f_s1s2(:,:) + real(r8), allocatable :: f_s1s3(:,:) + real(r8) :: f_s2s1 + real(r8) :: f_s2s3 + + integer :: i_l1s1 + integer :: i_l2s1 + integer :: i_l3s2 + integer :: i_s1s2 + integer :: i_s1s3 + integer :: i_s2s1 + integer :: i_s2s3 + integer :: i_s3s1 + integer :: i_cwdl2 + integer :: i_cwdl3 + real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. + + integer :: c, j ! indices + real(r8) :: t ! temporary variable + !----------------------------------------------------------------------- + + associate( & + rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) + pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) + + cellsand => soilstate_inst%cellsand_col , & ! Input: [real(r8) (:,:) ] column 3D sand + + cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Output: [integer (:) ] which pool is C taken from for a given decomposition step + cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & ! Output: [integer (:) ] which pool is C added to for a given decomposition step + floating_cn_ratio_decomp_pools => decomp_cascade_con%floating_cn_ratio_decomp_pools , & ! Output: [logical (:) ] TRUE => pool has fixed C:N ratio + is_litter => decomp_cascade_con%is_litter , & ! Output: [logical (:) ] TRUE => pool is a litter pool + is_soil => decomp_cascade_con%is_soil , & ! Output: [logical (:) ] TRUE => pool is a soil pool + is_cwd => decomp_cascade_con%is_cwd , & ! Output: [logical (:) ] TRUE => pool is a cwd pool + initial_cn_ratio => decomp_cascade_con%initial_cn_ratio , & ! Output: [real(r8) (:) ] c:n ratio for initialization of pools + initial_stock => decomp_cascade_con%initial_stock , & ! Output: [real(r8) (:) ] initial concentration for seeding at spinup + initial_stock_soildepth => decomp_cascade_con%initial_stock_soildepth , & ! Output: [real(r8) (:) ] soil depth for initial concentration for seeding at spinup + is_metabolic => decomp_cascade_con%is_metabolic , & ! Output: [logical (:) ] TRUE => pool is metabolic material + is_cellulose => decomp_cascade_con%is_cellulose , & ! Output: [logical (:) ] TRUE => pool is cellulose + is_lignin => decomp_cascade_con%is_lignin , & ! Output: [logical (:) ] TRUE => pool is lignin + spinup_factor => decomp_cascade_con%spinup_factor & ! Output: [real(r8) (:) ] factor for AD spinup associated with each pool + + ) + + allocate(rf_s1s2(bounds%begc:bounds%endc,1:nlevdecomp)) + allocate(rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp)) + allocate(f_s1s2(bounds%begc:bounds%endc,1:nlevdecomp)) + allocate(f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp)) + + !------- time-constant coefficients ---------- ! + ! set soil organic matter compartment C:N ratios + cn_s1 = params_inst%cn_s1_bgc + cn_s2 = params_inst%cn_s2_bgc + cn_s3 = params_inst%cn_s3_bgc + + ! set respiration fractions for fluxes between compartments + rf_l1s1 = params_inst%rf_l1s1_bgc + rf_l2s1 = params_inst%rf_l2s1_bgc + rf_l3s2 = params_inst%rf_l3s2_bgc + rf_s2s1 = params_inst%rf_s2s1_bgc + rf_s2s3 = params_inst%rf_s2s3_bgc + rf_s3s1 = params_inst%rf_s3s1_bgc + + rf_cwdl2 = params_inst%rf_cwdl2_bgc + rf_cwdl3 = params_inst%rf_cwdl3_bgc + + ! set the cellulose and lignin fractions for coarse woody debris + cwd_fcel = params_inst%cwd_fcel_bgc + cwd_flig = params_inst%cwd_flig_bgc + + ! set path fractions + f_s2s1 = 0.42_r8/(0.45_r8) + f_s2s3 = 0.03_r8/(0.45_r8) + + ! some of these are dependent on the soil texture properties + do c = bounds%begc, bounds%endc + do j = 1, nlevdecomp + t = 0.85_r8 - 0.68_r8 * 0.01_r8 * (100._r8 - cellsand(c,j)) + f_s1s2(c,j) = 1._r8 - .004_r8 / (1._r8 - t) + f_s1s3(c,j) = .004_r8 / (1._r8 - t) + rf_s1s2(c,j) = t + rf_s1s3(c,j) = t + end do + end do + initial_stock_soildepth = params_inst%initial_Cstocks_depth + + !------------------- list of pools and their attributes ------------ + floating_cn_ratio_decomp_pools(i_litr1) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_litr1) = 'litr1' + decomp_cascade_con%decomp_pool_name_history(i_litr1) = 'LITR1' + decomp_cascade_con%decomp_pool_name_long(i_litr1) = 'litter 1' + decomp_cascade_con%decomp_pool_name_short(i_litr1) = 'L1' + is_litter(i_litr1) = .true. + is_soil(i_litr1) = .false. + is_cwd(i_litr1) = .false. + initial_cn_ratio(i_litr1) = 90._r8 + initial_stock(i_litr1) = 0._r8 + is_metabolic(i_litr1) = .true. + is_cellulose(i_litr1) = .false. + is_lignin(i_litr1) = .false. + + floating_cn_ratio_decomp_pools(i_litr2) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_litr2) = 'litr2' + decomp_cascade_con%decomp_pool_name_history(i_litr2) = 'LITR2' + decomp_cascade_con%decomp_pool_name_long(i_litr2) = 'litter 2' + decomp_cascade_con%decomp_pool_name_short(i_litr2) = 'L2' + is_litter(i_litr2) = .true. + is_soil(i_litr2) = .false. + is_cwd(i_litr2) = .false. + initial_cn_ratio(i_litr2) = 90._r8 + initial_stock(i_litr2) = 0._r8 + is_metabolic(i_litr2) = .false. + is_cellulose(i_litr2) = .true. + is_lignin(i_litr2) = .false. + + floating_cn_ratio_decomp_pools(i_litr3) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_litr3) = 'litr3' + decomp_cascade_con%decomp_pool_name_history(i_litr3) = 'LITR3' + decomp_cascade_con%decomp_pool_name_long(i_litr3) = 'litter 3' + decomp_cascade_con%decomp_pool_name_short(i_litr3) = 'L3' + is_litter(i_litr3) = .true. + is_soil(i_litr3) = .false. + is_cwd(i_litr3) = .false. + initial_cn_ratio(i_litr3) = 90._r8 + initial_stock(i_litr3) = 0._r8 + is_metabolic(i_litr3) = .false. + is_cellulose(i_litr3) = .false. + is_lignin(i_litr3) = .true. + + if (.not. use_fates) then + ! CWD + floating_cn_ratio_decomp_pools(i_cwd) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_cwd) = 'cwd' + decomp_cascade_con%decomp_pool_name_history(i_cwd) = 'CWD' + decomp_cascade_con%decomp_pool_name_long(i_cwd) = 'coarse woody debris' + decomp_cascade_con%decomp_pool_name_short(i_cwd) = 'CWD' + is_litter(i_cwd) = .false. + is_soil(i_cwd) = .false. + is_cwd(i_cwd) = .true. + initial_cn_ratio(i_cwd) = 90._r8 + initial_stock(i_cwd) = 0._r8 + is_metabolic(i_cwd) = .false. + is_cellulose(i_cwd) = .false. + is_lignin(i_cwd) = .false. + endif + + if (.not. use_fates) then + i_soil1 = 5 + else + i_soil1 = 4 + endif + floating_cn_ratio_decomp_pools(i_soil1) = .false. + decomp_cascade_con%decomp_pool_name_restart(i_soil1) = 'soil1' + decomp_cascade_con%decomp_pool_name_history(i_soil1) = 'SOIL1' + decomp_cascade_con%decomp_pool_name_long(i_soil1) = 'soil 1' + decomp_cascade_con%decomp_pool_name_short(i_soil1) = 'S1' + is_litter(i_soil1) = .false. + is_soil(i_soil1) = .true. + is_cwd(i_soil1) = .false. + initial_cn_ratio(i_soil1) = cn_s1 + initial_stock(i_soil1) = params_inst%initial_Cstocks(1) + is_metabolic(i_soil1) = .false. + is_cellulose(i_soil1) = .false. + is_lignin(i_soil1) = .false. + + if (.not. use_fates) then + i_soil2 = 6 + else + i_soil2 = 5 + endif + floating_cn_ratio_decomp_pools(i_soil2) = .false. + decomp_cascade_con%decomp_pool_name_restart(i_soil2) = 'soil2' + decomp_cascade_con%decomp_pool_name_history(i_soil2) = 'SOIL2' + decomp_cascade_con%decomp_pool_name_long(i_soil2) = 'soil 2' + decomp_cascade_con%decomp_pool_name_short(i_soil2) = 'S2' + is_litter(i_soil2) = .false. + is_soil(i_soil2) = .true. + is_cwd(i_soil2) = .false. + initial_cn_ratio(i_soil2) = cn_s2 + initial_stock(i_soil2) = params_inst%initial_Cstocks(2) + is_metabolic(i_soil2) = .false. + is_cellulose(i_soil2) = .false. + is_lignin(i_soil2) = .false. + + if (.not. use_fates) then + i_soil3 = 7 + else + i_soil3 = 6 + endif + floating_cn_ratio_decomp_pools(i_soil3) = .false. + decomp_cascade_con%decomp_pool_name_restart(i_soil3) = 'soil3' + decomp_cascade_con%decomp_pool_name_history(i_soil3) = 'SOIL3' + decomp_cascade_con%decomp_pool_name_long(i_soil3) = 'soil 3' + decomp_cascade_con%decomp_pool_name_short(i_soil3) = 'S3' + is_litter(i_soil3) = .false. + is_soil(i_soil3) = .true. + is_cwd(i_soil3) = .false. + initial_cn_ratio(i_soil3) = cn_s3 + initial_stock(i_soil3) = params_inst%initial_Cstocks(3) + is_metabolic(i_soil3) = .false. + is_cellulose(i_soil3) = .false. + is_lignin(i_soil3) = .false. + + + speedup_fac = 1._r8 + + !lit1 + spinup_factor(i_litr1) = 1._r8 + !lit2,3 + spinup_factor(i_litr2) = 1._r8 + spinup_factor(i_litr3) = 1._r8 + !CWD + if (.not. use_fates) then + spinup_factor(i_cwd) = max(1._r8, (speedup_fac * params_inst%tau_cwd_bgc / 2._r8 )) + end if + !som1 + spinup_factor(i_soil1) = 1._r8 + !som2,3 + spinup_factor(i_soil2) = max(1._r8, (speedup_fac * params_inst%tau_s2_bgc)) + spinup_factor(i_soil3) = max(1._r8, (speedup_fac * params_inst%tau_s3_bgc)) + + if ( masterproc ) then + write(iulog,*) 'Spinup_state ',spinup_state + write(iulog,*) 'Spinup factors ',spinup_factor + end if + + !---------------- list of transitions and their time-independent coefficients ---------------! + i_l1s1 = 1 + decomp_cascade_con%cascade_step_name(i_l1s1) = 'L1S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = rf_l1s1 + cascade_donor_pool(i_l1s1) = i_litr1 + cascade_receiver_pool(i_l1s1) = i_soil1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = 1.0_r8 + + i_l2s1 = 2 + decomp_cascade_con%cascade_step_name(i_l2s1) = 'L2S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1) = rf_l2s1 + cascade_donor_pool(i_l2s1) = i_litr2 + cascade_receiver_pool(i_l2s1) = i_soil1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1)= 1.0_r8 + + i_l3s2 = 3 + decomp_cascade_con%cascade_step_name(i_l3s2) = 'L3S2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = rf_l3s2 + cascade_donor_pool(i_l3s2) = i_litr3 + cascade_receiver_pool(i_l3s2) = i_soil2 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = 1.0_r8 + + i_s1s2 = 4 + decomp_cascade_con%cascade_step_name(i_s1s2) = 'S1S2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = rf_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) + cascade_donor_pool(i_s1s2) = i_soil1 + cascade_receiver_pool(i_s1s2) = i_soil2 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = f_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) + + i_s1s3 = 5 + decomp_cascade_con%cascade_step_name(i_s1s3) = 'S1S3' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) + cascade_donor_pool(i_s1s3) = i_soil1 + cascade_receiver_pool(i_s1s3) = i_soil3 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) + + i_s2s1 = 6 + decomp_cascade_con%cascade_step_name(i_s2s1) = 'S2S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = rf_s2s1 + cascade_donor_pool(i_s2s1) = i_soil2 + cascade_receiver_pool(i_s2s1) = i_soil1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = f_s2s1 + + i_s2s3 = 7 + decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 + cascade_donor_pool(i_s2s3) = i_soil2 + cascade_receiver_pool(i_s2s3) = i_soil3 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = f_s2s3 + + i_s3s1 = 8 + decomp_cascade_con%cascade_step_name(i_s3s1) = 'S3S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = rf_s3s1 + cascade_donor_pool(i_s3s1) = i_soil3 + cascade_receiver_pool(i_s3s1) = i_soil1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 + + if (.not. use_fates) then + i_cwdl2 = 9 + decomp_cascade_con%cascade_step_name(i_cwdl2) = 'CWDL2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 + cascade_donor_pool(i_cwdl2) = i_cwd + cascade_receiver_pool(i_cwdl2) = i_litr2 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fcel + + i_cwdl3 = 10 + decomp_cascade_con%cascade_step_name(i_cwdl3) = 'CWDL3' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = rf_cwdl3 + cascade_donor_pool(i_cwdl3) = i_cwd + cascade_receiver_pool(i_cwdl3) = i_litr3 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = cwd_flig + end if + + deallocate(rf_s1s2) + deallocate(rf_s1s3) + deallocate(f_s1s2) + deallocate(f_s1s3) + + end associate + + end subroutine init_decompcascade_bgc + + !----------------------------------------------------------------------- + subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & + soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) + ! + ! !DESCRIPTION: + ! calculate rate constants and decomposition pathways for the CENTURY decomposition cascade model + ! written by C. Koven based on original CLM4 decomposition cascade + ! + ! !USES: + use clm_time_manager , only : get_days_per_year + use shr_const_mod , only : SHR_CONST_PI + use clm_varcon , only : secspday + ! + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! filter for soil columns + type(soilstate_type) , intent(in) :: soilstate_inst + type(temperature_type) , intent(in) :: temperature_inst + type(ch4_type) , intent(in) :: ch4_inst + type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst + ! + ! !LOCAL VARIABLES: + real(r8):: frw(bounds%begc:bounds%endc) ! rooting fraction weight + real(r8), allocatable:: fr(:,:) ! column-level rooting fraction by soil depth + real(r8):: psi ! temporary soilpsi for water scalar + real(r8):: rate_scalar ! combined rate scalar for decomp + real(r8):: k_l1 ! decomposition rate constant litter 1 (1/sec) + real(r8):: k_l2_l3 ! decomposition rate constant litter 2 and litter 3 (1/sec) + real(r8):: k_s1 ! decomposition rate constant SOM 1 (1/sec) + real(r8):: k_s2 ! decomposition rate constant SOM 2 (1/sec) + real(r8):: k_s3 ! decomposition rate constant SOM 3 (1/sec) + real(r8):: k_frag ! fragmentation rate constant CWD (1/sec) + real(r8):: cwdc_loss ! fragmentation rate for CWD carbon (gC/m2/s) + real(r8):: cwdn_loss ! fragmentation rate for CWD nitrogen (gN/m2/s) + real(r8):: Q10 ! temperature dependence + real(r8):: froz_q10 ! separate q10 for frozen soil respiration rates. default to same as above zero rates + real(r8):: decomp_depth_efolding ! (meters) e-folding depth for reduction in decomposition [ + integer :: c, fc, j, k, l + real(r8):: catanf ! hyperbolic temperature function from CENTURY + real(r8):: catanf_30 ! reference rate at 30C + real(r8):: t1 ! temperature argument + real(r8):: normalization_factor ! factor by which to offset the decomposition rates frm century to a q10 formulation + real(r8):: days_per_year ! days per year + real(r8):: depth_scalar(bounds%begc:bounds%endc,1:nlevdecomp) + real(r8):: mino2lim !minimum anaerobic decomposition rate + real(r8):: spinup_geogterm_l1(bounds%begc:bounds%endc) ! geographically-varying spinup term for l1 + real(r8):: spinup_geogterm_l23(bounds%begc:bounds%endc) ! geographically-varying spinup term for l2 and l3 + real(r8):: spinup_geogterm_cwd(bounds%begc:bounds%endc) ! geographically-varying spinup term for cwd + real(r8):: spinup_geogterm_s1(bounds%begc:bounds%endc) ! geographically-varying spinup term for s1 + real(r8):: spinup_geogterm_s2(bounds%begc:bounds%endc) ! geographically-varying spinup term for s2 + real(r8):: spinup_geogterm_s3(bounds%begc:bounds%endc) ! geographically-varying spinup term for s3 + + !----------------------------------------------------------------------- + + !----- CENTURY T response function + catanf(t1) = 11.75_r8 +(29.7_r8 / SHR_CONST_PI) * atan( SHR_CONST_PI * 0.031_r8 * ( t1 - 15.4_r8 )) + + associate( & + minpsi => params_inst%minpsi_bgc , & ! Input: [real(r8) ] minimum soil suction (mm) + maxpsi => params_inst%maxpsi_bgc , & ! Input: [real(r8) ] maximum soil suction (mm) + soilpsi => soilstate_inst%soilpsi_col , & ! Input: [real(r8) (:,:) ] soil water potential in each soil layer (MPa) + + t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) + + o2stress_sat => ch4_inst%o2stress_sat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) + o2stress_unsat => ch4_inst%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) + finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area + + t_scalar => soilbiogeochem_carbonflux_inst%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp + w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp + o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia + decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) + spinup_factor => decomp_cascade_con%spinup_factor & ! Input: [real(r8) (:) ] factor for AD spinup associated with each pool + ) + + mino2lim = CNParamsShareInst%mino2lim + + if ( use_century_tfunc .and. normalize_q10_to_century_tfunc ) then + call endrun(msg='ERROR: cannot have both use_century_tfunc and normalize_q10_to_century_tfunc set as true'//& + errMsg(sourcefile, __LINE__)) + endif + + days_per_year = get_days_per_year() + + ! set "Q10" parameter + Q10 = CNParamsShareInst%Q10 + + ! set "froz_q10" parameter + froz_q10 = CNParamsShareInst%froz_q10 + + ! Set "decomp_depth_efolding" parameter + decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding + + ! translate to per-second time constant + k_l1 = 1._r8 / (secspday * days_per_year * params_inst%tau_l1_bgc) + k_l2_l3 = 1._r8 / (secspday * days_per_year * params_inst%tau_l2_l3_bgc) + k_s1 = 1._r8 / (secspday * days_per_year * params_inst%tau_s1_bgc) + k_s2 = 1._r8 / (secspday * days_per_year * params_inst%tau_s2_bgc) + k_s3 = 1._r8 / (secspday * days_per_year * params_inst%tau_s3_bgc) + k_frag = 1._r8 / (secspday * days_per_year * params_inst%tau_cwd_bgc) + + ! calc ref rate + catanf_30 = catanf(30._r8) + + if ( spinup_state >= 1 ) then + do fc = 1,num_soilc + c = filter_soilc(fc) + ! + if ( abs(spinup_factor(i_litr1) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_l1(c) = spinup_factor(i_litr1) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + else + spinup_geogterm_l1(c) = 1._r8 + endif + ! + if ( abs(spinup_factor(i_litr2) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_l23(c) = spinup_factor(i_litr2) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + else + spinup_geogterm_l23(c) = 1._r8 + endif + ! + if ( .not. use_fates ) then + if ( abs(spinup_factor(i_cwd) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_cwd(c) = spinup_factor(i_cwd) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + else + spinup_geogterm_cwd(c) = 1._r8 + endif + endif + ! + if ( abs(spinup_factor(i_soil1) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s1(c) = spinup_factor(i_soil1) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + else + spinup_geogterm_s1(c) = 1._r8 + endif + ! + if ( abs(spinup_factor(i_soil2) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s2(c) = spinup_factor(i_soil2) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + else + spinup_geogterm_s2(c) = 1._r8 + endif + ! + if ( abs(spinup_factor(i_soil3) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s3(c) = spinup_factor(i_soil3) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + else + spinup_geogterm_s3(c) = 1._r8 + endif + ! + end do + else + do fc = 1,num_soilc + c = filter_soilc(fc) + spinup_geogterm_l1(c) = 1._r8 + spinup_geogterm_l23(c) = 1._r8 + spinup_geogterm_cwd(c) = 1._r8 + spinup_geogterm_s1(c) = 1._r8 + spinup_geogterm_s2(c) = 1._r8 + spinup_geogterm_s3(c) = 1._r8 + end do + endif + + !--- time dependent coefficients-----! + if ( nlevdecomp .eq. 1 ) then + + ! calculate function to weight the temperature and water potential scalars + ! for decomposition control. + + + ! the following normalizes values in fr so that they + ! sum to 1.0 across top nlevdecomp levels on a column + frw(bounds%begc:bounds%endc) = 0._r8 + nlev_soildecomp_standard=5 + allocate(fr(bounds%begc:bounds%endc,nlev_soildecomp_standard)) + do j=1,nlev_soildecomp_standard + do fc = 1,num_soilc + c = filter_soilc(fc) + frw(c) = frw(c) + col%dz(c,j) + end do + end do + do j = 1,nlev_soildecomp_standard + do fc = 1,num_soilc + c = filter_soilc(fc) + if (frw(c) /= 0._r8) then + fr(c,j) = col%dz(c,j) / frw(c) + else + fr(c,j) = 0._r8 + end if + end do + end do + + if ( .not. use_century_tfunc ) then + ! calculate rate constant scalar for soil temperature + ! assuming that the base rate constants are assigned for non-moisture + ! limiting conditions at 25 C. + + do j = 1,nlev_soildecomp_standard + do fc = 1,num_soilc + c = filter_soilc(fc) + if (j==1) t_scalar(c,:) = 0._r8 + if (t_soisno(c,j) >= SHR_CONST_TKFRZ) then + t_scalar(c,1)=t_scalar(c,1) + & + (Q10**((t_soisno(c,j)-(SHR_CONST_TKFRZ+25._r8))/10._r8))*fr(c,j) + else + t_scalar(c,1)=t_scalar(c,1) + & + (Q10**(-25._r8/10._r8))*(froz_q10**((t_soisno(c,j)-SHR_CONST_TKFRZ)/10._r8))*fr(c,j) + endif + end do + end do + + else + ! original century uses an arctangent function to calculate the temperature dependence of decomposition + do j = 1,nlev_soildecomp_standard + do fc = 1,num_soilc + c = filter_soilc(fc) + if (j==1) t_scalar(c,:) = 0._r8 + + t_scalar(c,1)=t_scalar(c,1) +max(catanf(t_soisno(c,j)-SHR_CONST_TKFRZ)/catanf_30*fr(c,j),0.01_r8) + end do + end do + + endif + + ! calculate the rate constant scalar for soil water content. + ! Uses the log relationship with water potential given in + ! Andren, O., and K. Paustian, 1987. Barley straw decomposition in the field: + ! a comparison of models. Ecology, 68(5):1190-1200. + ! and supported by data in + ! Orchard, V.A., and F.J. Cook, 1983. Relationship between soil respiration + ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. + + do j = 1,nlev_soildecomp_standard + do fc = 1,num_soilc + c = filter_soilc(fc) + if (j==1) w_scalar(c,:) = 0._r8 + psi = min(soilpsi(c,j),maxpsi) + ! decomp only if soilpsi is higher than minpsi + if (psi > minpsi) then + w_scalar(c,1) = w_scalar(c,1) + (log(minpsi/psi)/log(minpsi/maxpsi))*fr(c,j) + end if + end do + end do + + if (use_lch4) then + ! Calculate ANOXIA + if (anoxia) then + ! Check for anoxia w/o LCH4 now done in controlMod. + + do j = 1,nlev_soildecomp_standard + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (j==1) o_scalar(c,:) = 0._r8 + + o_scalar(c,1) = o_scalar(c,1) + fr(c,j) * max(o2stress_unsat(c,j), mino2lim) + end do + end do + else + o_scalar(bounds%begc:bounds%endc,1:nlevdecomp) = 1._r8 + end if + else + o_scalar(bounds%begc:bounds%endc,1:nlevdecomp) = 1._r8 + end if + + deallocate(fr) + + else + + if ( .not. use_century_tfunc ) then + ! calculate rate constant scalar for soil temperature + ! assuming that the base rate constants are assigned for non-moisture + ! limiting conditions at 25 C. + ! Peter Thornton: 3/13/09 + ! Replaced the Lloyd and Taylor function with a Q10 formula, with Q10 = 1.5 + ! as part of the modifications made to improve the seasonal cycle of + ! atmospheric CO2 concentration in global simulations. This does not impact + ! the base rates at 25 C, which are calibrated from microcosm studies. + + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + if (t_soisno(c,j) >= SHR_CONST_TKFRZ) then + t_scalar(c,j)= (Q10**((t_soisno(c,j)-(SHR_CONST_TKFRZ+25._r8))/10._r8)) + else + t_scalar(c,j)= (Q10**(-25._r8/10._r8))*(froz_q10**((t_soisno(c,j)-SHR_CONST_TKFRZ)/10._r8)) + endif + end do + end do + + else + + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + t_scalar(c,j)= max(catanf(t_soisno(c,j)-SHR_CONST_TKFRZ)/catanf_30, 0.01_r8) + end do + end do + + endif + + ! calculate the rate constant scalar for soil water content. + ! Uses the log relationship with water potential given in + ! Andren, O., and K. Paustian, 1987. Barley straw decomposition in the field: + ! a comparison of models. Ecology, 68(5):1190-1200. + ! and supported by data in + ! Orchard, V.A., and F.J. Cook, 1983. Relationship between soil respiration + ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. + + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + psi = min(soilpsi(c,j),maxpsi) + ! decomp only if soilpsi is higher than minpsi + if (psi > minpsi) then + w_scalar(c,j) = (log(minpsi/psi)/log(minpsi/maxpsi)) + else + w_scalar(c,j) = 0._r8 + end if + end do + end do + + if (use_lch4) then + ! Calculate ANOXIA + ! Check for anoxia w/o LCH4 now done in controlMod. + + if (anoxia) then + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + + o_scalar(c,j) = max(o2stress_unsat(c,j), mino2lim) + end do + end do + else + o_scalar(bounds%begc:bounds%endc,1:nlevdecomp) = 1._r8 + end if + else + o_scalar(bounds%begc:bounds%endc,1:nlevdecomp) = 1._r8 + end if + + end if + + if ( normalize_q10_to_century_tfunc ) then + ! scale all decomposition rates by a constant to compensate for offset between original CENTURY temp func and Q10 + normalization_factor = (catanf(normalization_tref)/catanf_30) / (q10**((normalization_tref-25._r8)/10._r8)) + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + t_scalar(c,j) = t_scalar(c,j) * normalization_factor + end do + end do + endif + + if (use_vertsoilc) then + ! add a term to reduce decomposition rate at depth + ! for now used a fixed e-folding depth + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + depth_scalar(c,j) = exp(-zsoi(j)/decomp_depth_efolding) + end do + end do + end if + + ! calculate rate constants for all litter and som pools + if (use_vertsoilc) then + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + decomp_k(c,j,i_litr1) = k_l1 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & + * spinup_geogterm_l1(c) + decomp_k(c,j,i_litr2) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & + * spinup_geogterm_l23(c) + decomp_k(c,j,i_litr3) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & + * spinup_geogterm_l23(c) + decomp_k(c,j,i_soil1) = k_s1 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & + * spinup_geogterm_s1(c) + decomp_k(c,j,i_soil2) = k_s2 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & + * spinup_geogterm_s2(c) + decomp_k(c,j,i_soil3) = k_s3 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & + * spinup_geogterm_s3(c) + end do + end do + else + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + decomp_k(c,j,i_litr1) = k_l1 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l1(c) + decomp_k(c,j,i_litr2) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l23(c) + decomp_k(c,j,i_litr3) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l23(c) + decomp_k(c,j,i_soil1) = k_s1 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s1(c) + decomp_k(c,j,i_soil2) = k_s2 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s2(c) + decomp_k(c,j,i_soil3) = k_s3 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s3(c) + end do + end do + end if + + ! do the same for cwd, but only if fates is not enabled, because fates handles CWD on its own structure + if (.not. use_fates) then + if (use_vertsoilc) then + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + decomp_k(c,j,i_cwd) = k_frag * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * & + o_scalar(c,j) * spinup_geogterm_cwd(c) + end do + end do + else + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + decomp_k(c,j,i_cwd) = k_frag * t_scalar(c,j) * w_scalar(c,j) * & + o_scalar(c,j) * spinup_geogterm_cwd(c) + end do + end do + end if + end if + + end associate + + end subroutine decomp_rate_constants_bgc + +end module SoilBiogeochemDecompCascadeBGCMod From 131147e62d7ff8000906aac12ec86159b882845b Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 31 Mar 2021 17:13:55 -0600 Subject: [PATCH 02/69] Introduce MIMICS using SoilBiogeochemDecompCascadeBGCMod.F90 as template Transforming SoilBiogeochemDecompCascadeBGCMod.F90 into SoilBiogeochemDecompCascadeMIMICSMod.F90. Setting up the framework that MIMICS will fit into by using hooks already present in the CTSM. I will post explanations and requests for clarification in the PR. This is NOT working code. --- src/main/clm_varpar.F90 | 11 +- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 668 ++++++++++++------ 2 files changed, 466 insertions(+), 213 deletions(-) diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index 7cadb20936..0e409ffc73 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -9,7 +9,8 @@ module clm_varpar use shr_sys_mod , only: shr_sys_abort use spmdMod , only: masterproc use clm_varctl , only: use_extralakelayers, use_vertsoilc - use clm_varctl , only: use_century_decomp, use_c13, use_c14 + use clm_varctl , only: use_century_decomp, use_mimics_decomp + use clm_varctl , only: use_c13, use_c14 use clm_varctl , only: iulog, use_crop, create_crop_landunit, irrigate use clm_varctl , only: use_vichydro, rundef use clm_varctl , only: soil_layerstruct_predefined @@ -63,6 +64,8 @@ module clm_varpar ! constants for decomposition cascade + integer, public, parameter :: i_micr_r = 1 + integer, public, parameter :: i_micr_k = i_micr_r + 1 integer, public, parameter :: i_met_lit = 1 integer, public, parameter :: i_cel_lit = i_met_lit + 1 integer, public, parameter :: i_lig_lit = i_cel_lit + 1 @@ -232,6 +235,9 @@ subroutine clm_varpar_init(actual_maxsoil_patches, actual_numcft) if (use_century_decomp) then ndecomp_pools = 6 ndecomp_cascade_transitions = 8 + else if (use_mimics_decomp) then + ndecomp_pools = ? ! TODO slevis: derive inst. of hardwiring? + ndecomp_cascade_transitions = ? else ndecomp_pools = 7 ndecomp_cascade_transitions = 7 @@ -241,6 +247,9 @@ subroutine clm_varpar_init(actual_maxsoil_patches, actual_numcft) if (use_century_decomp) then ndecomp_pools = 7 ndecomp_cascade_transitions = 10 + else if (use_mimics_decomp) then + ndecomp_pools = ? ! TODO slevis: derive inst. of hardwiring? + ndecomp_cascade_transitions = ? else ndecomp_pools = 8 ndecomp_cascade_transitions = 9 diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 56f6748761..eecd7c66dc 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -1,15 +1,15 @@ -module SoilBiogeochemDecompCascadeBGCMod +module SoilBiogeochemDecompCascadeMIMICSMod !----------------------------------------------------------------------- ! !DESCRIPTION: ! Sets the coeffiecients used in the decomposition cascade submodel. - ! This uses the CENTURY/BGC parameters + ! This uses the MIMICS parameters. ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 use shr_const_mod , only : SHR_CONST_TKFRZ use shr_log_mod , only : errMsg => shr_log_errMsg - use clm_varpar , only : nlevsoi, nlevgrnd, nlevdecomp, ndecomp_cascade_transitions, ndecomp_pools + use clm_varpar , only : nlevdecomp use clm_varpar , only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_vertsoilc, use_fates use clm_varcon , only : zsoi @@ -32,10 +32,10 @@ module SoilBiogeochemDecompCascadeBGCMod private ! ! !PUBLIC MEMBER FUNCTIONS: - public :: DecompCascadeBGCreadNML ! Read in namelist + public :: DecompCascadeMIMICSreadNML ! Read in namelist public :: readParams ! Read in parameters from params file - public :: init_decompcascade_bgc ! Initialization - public :: decomp_rate_constants_bgc ! Figure out decomposition rates + public :: init_decompcascade_mimics ! Initialization + public :: decomp_rate_constants_mimics ! Figure out decomposition rates ! ! !PUBLIC DATA MEMBERS logical , public :: normalize_q10_to_century_tfunc = .true.! do we normalize the century decomp. rates so that they match the CLM Q10 at a given tep? @@ -51,28 +51,52 @@ module SoilBiogeochemDecompCascadeBGCMod integer, private, parameter :: i_litr1 = i_met_lit ! First litter pool, metobolic integer, private, parameter :: i_litr2 = i_cel_lit ! Second litter pool, cellulose integer, private, parameter :: i_litr3 = i_lig_lit ! Third litter pool, lignin + integer, private, parameter :: i_micr1 = i_micr_r ! First microbial pool, copiotrophic, as labeled in Wieder et al. 2015 + integer, private, parameter :: i_micr2 = i_micr_k ! Second microbial pool, oligotrophic, as labeled in Wieder et al. 2015 type, private :: params_type real(r8):: cn_s1_bgc !C:N for SOM 1 real(r8):: cn_s2_bgc !C:N for SOM 2 real(r8):: cn_s3_bgc !C:N for SOM 3 - real(r8):: rf_l1s1_bgc !respiration fraction litter 1 -> SOM 1 - real(r8):: rf_l2s1_bgc - real(r8):: rf_l3s2_bgc + ! TODO slevis: New rf params in MIMICS. Update params file accordingly. + ! I haven't identified what these correspond to in testbed. + real(r8):: rf_l1m1_mimics !respiration fraction litter 1 -> microbial 1 + real(r8):: rf_l2m1_mimics + real(r8):: rf_l3m1_mimics - real(r8):: rf_s2s1_bgc - real(r8):: rf_s2s3_bgc - real(r8):: rf_s3s1_bgc + real(r8):: rf_l1m2_mimics + real(r8):: rf_l2m2_mimics + real(r8):: rf_l3m2_mimics + real(r8):: rf_s1s3_mimics ! respiration fraction soil 1 -> soil 3 + real(r8):: rf_s2s3_mimics + real(r8):: rf_s3m1_mimics + real(r8):: rf_s3m2_mimics + + real(r8):: rf_m1s1_mimics + real(r8):: rf_m1s2_mimics + real(r8):: rf_m1s3_mimics + + real(r8):: rf_m2s1_mimics + real(r8):: rf_m2s2_mimics + real(r8):: rf_m2s3_mimics + + ! TODO slevis: Keep these? real(r8):: rf_cwdl2_bgc real(r8):: rf_cwdl3_bgc - real(r8):: tau_l1_bgc ! 1/turnover time of litter 1 from Century (l/18.5) (1/yr) - real(r8):: tau_l2_l3_bgc ! 1/turnover time of litter 2 and litter 3 from Century (1/4.9) (1/yr) - real(r8):: tau_s1_bgc ! 1/turnover time of SOM 1 from Century (1/7.3) (1/yr) - real(r8):: tau_s2_bgc ! 1/turnover time of SOM 2 from Century (1/0.2) (1/yr) - real(r8):: tau_s3_bgc ! 1/turnover time of SOM 3 from Century (1/0.0045) (1/yr) + ! TODO slevis: tau params are functions (Vmax and Km) in MIMICS. Also new + ! tau params define microbial turnover to SOM. Update params + ! file if necessary. + real(r8):: tau_l1_mimics ! 1/turnover time of litter 1 (1/yr) + real(r8):: tau_l2_l3_mimics ! 1/turnover time of litter 2 and 3 (1/yr) + real(r8):: tau_s1_mimics ! 1/turnover time of SOM 1 (1/yr) + real(r8):: tau_s2_mimics ! 1/turnover time of SOM 2 (1/yr) + real(r8):: tau_s3_mimics ! 1/turnover time of SOM 3 (1/yr) + real(r8):: tau_m1_mimics ! 1/turnover time of microbial 1 (1/yr) + real(r8):: tau_m2_mimics ! 1/turnover time of microbial 2 (1/yr) + ! TODO slevis: Keep? real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) real(r8) :: cwd_fcel_bgc !cellulose fraction for CWD @@ -97,10 +121,11 @@ module SoilBiogeochemDecompCascadeBGCMod contains !----------------------------------------------------------------------- - subroutine DecompCascadeBGCreadNML( NLFilename ) + subroutine DecompCascadeMIMCSreadNML( NLFilename ) ! ! !DESCRIPTION: - ! Read the namelist for soil BGC Decomposition Cascade + ! Read the namelist for soil MIMICS Decomposition Cascade + ! TODO slevis: Modify for MIMICS if necessary ! ! !USES: use fileutils , only : getavu, relavu, opnfil @@ -118,7 +143,7 @@ subroutine DecompCascadeBGCreadNML( NLFilename ) integer :: ierr ! error code integer :: unitn ! unit for namelist file - character(len=*), parameter :: subname = 'DecompCascadeBGCreadNML' + character(len=*), parameter :: subname = 'DecompCascadeMIMICSreadNML' character(len=*), parameter :: nmlname = 'CENTURY_soilBGCDecompCascade' !----------------------------------------------------------------------- real(r8) :: initial_Cstocks(nsompools), initial_Cstocks_depth @@ -159,7 +184,7 @@ subroutine DecompCascadeBGCreadNML( NLFilename ) params_inst%initial_Cstocks(:) = initial_Cstocks(:) params_inst%initial_Cstocks_depth = initial_Cstocks_depth - end subroutine DecompCascadeBGCreadNML + end subroutine DecompCascadeMIMICSreadNML !----------------------------------------------------------------------- subroutine readParams ( ncid ) @@ -173,88 +198,116 @@ subroutine readParams ( ncid ) type(file_desc_t),intent(inout) :: ncid ! pio netCDF file id ! ! !LOCAL VARIABLES: - character(len=32) :: subname = 'CNDecompBgcParamsType' - character(len=100) :: errCode = 'Error reading in CN const file ' + character(len=32) :: subname = 'readParams' + character(len=100) :: errCode = 'Error reading MIMICS params ' logical :: readv ! has variable been read in or not real(r8) :: tempr ! temporary to read in constant character(len=100) :: tString ! temp. var for reading !----------------------------------------------------------------------- ! Read off of netcdf file - tString='tau_l1' + ! TODO slevis: new params will be added here and in the params file + ! TODO slevis: Keep tau_cwd? + tString='tau_cwd' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_l1_bgc=tempr + params_inst%tau_cwd_bgc=tempr - tString='tau_l2_l3' + tString='cn_s1_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_l2_l3_bgc=tempr + params_inst%cn_s1_bgc=tempr - tString='tau_s1' + tString='cn_s2_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_s1_bgc=tempr + params_inst%cn_s2_bgc=tempr - tString='tau_s2' + tString='cn_s3_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_s2_bgc=tempr + params_inst%cn_s3_bgc=tempr - tString='tau_s3' + ! TODO slevis: rf params changing + tString='rf_l1m1_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_s3_bgc=tempr + params_inst%rf_l1m1_mimics=tempr - tString='tau_cwd' + tString='rf_l2m1_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_cwd_bgc=tempr + params_inst%rf_l2m1_mimics=tempr - tString='cn_s1_bgc' + tString='rf_l3m1_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cn_s1_bgc=tempr + params_inst%rf_l3m1_mimics=tempr - tString='cn_s2_bgc' + tString='rf_l1m2_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cn_s2_bgc=tempr + params_inst%rf_l1m2_mimics=tempr - tString='cn_s3_bgc' + tString='rf_l2m2_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cn_s3_bgc=tempr + params_inst%rf_l2m2_mimics=tempr + + tString='rf_l3m2_mimics' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_l3m2_mimics=tempr + + tString='rf_s1s3_mimics' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_s1s3_mimics=tempr + + tString='rf_s2s3_mimics' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_s2s3_mimics=tempr + + tString='rf_s3m1_mimics' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_s3m1_mimics=tempr + + tString='rf_s3m2_mimics' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%rf_s3m2_mimics=tempr - tString='rf_l1s1_bgc' + tString='rf_m1s1_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_l1s1_bgc=tempr + params_inst%rf_m1s1_mimics=tempr - tString='rf_l2s1_bgc' + tString='rf_m1s2_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_l2s1_bgc=tempr + params_inst%rf_m1s2_mimics=tempr - tString='rf_l3s2_bgc' + tString='rf_m1s3_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_l3s2_bgc=tempr + params_inst%rf_m1s3_mimics=tempr - tString='rf_s2s1_bgc' + tString='rf_m2s1_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_s2s1_bgc=tempr + params_inst%rf_m2s1_mimics=tempr - tString='rf_s2s3_bgc' + tString='rf_m2s2_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_s2s3_bgc=tempr + params_inst%rf_m2s2_mimics=tempr - tString='rf_s3s1_bgc' + tString='rf_m2s3_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_s3s1_bgc=tempr + params_inst%rf_m2s3_mimics=tempr tString='rf_cwdl2_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) @@ -294,11 +347,11 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_inst ) + subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate_inst ) ! ! !DESCRIPTION: - ! initialize rate constants and decomposition pathways following the decomposition cascade of the BGC model. - ! written by C. Koven + ! initialize rate constants and decomposition pathways following the + ! decomposition cascade of the MIMICS model. ! ! !USES: ! @@ -309,16 +362,26 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i ! ! !LOCAL VARIABLES !-- properties of each decomposing pool - real(r8) :: rf_l1s1 - real(r8) :: rf_l2s1 - real(r8) :: rf_l3s2 - !real(r8) :: rf_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) - !real(r8) :: rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) - real(r8), allocatable :: rf_s1s2(:,:) - real(r8), allocatable :: rf_s1s3(:,:) - real(r8) :: rf_s2s1 + real(r8) :: rf_l1m1 + real(r8) :: rf_l2m1 + real(r8) :: rf_l3m1 + real(r8) :: rf_l1m2 + real(r8) :: rf_l2m2 + real(r8) :: rf_l3m2 + real(r8) :: rf_s1s3 real(r8) :: rf_s2s3 - real(r8) :: rf_s3s1 + real(r8) :: rf_s3m1 + real(r8) :: rf_s3m2 + real(r8) :: rf_m1s1 + real(r8) :: rf_m1s2 + real(r8) :: rf_m1s3 + real(r8) :: rf_m2s1 + real(r8) :: rf_m2s2 + real(r8) :: rf_m2s3 + ! TODO slevis: Already exists as scalar but keep temporarily as a template + ! for new params not coming from the params file. + ! Also keeping other params that I'm not sure about, yet. + real(r8), allocatable :: rf_s1s3(:,:) real(r8) :: rf_cwdl2 real(r8) :: rf_cwdl3 real(r8) :: cwd_fcel @@ -326,21 +389,26 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i real(r8) :: cn_s1 real(r8) :: cn_s2 real(r8) :: cn_s3 - !real(r8) :: f_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) - !real(r8) :: f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) - real(r8), allocatable :: f_s1s2(:,:) real(r8), allocatable :: f_s1s3(:,:) - real(r8) :: f_s2s1 real(r8) :: f_s2s3 - integer :: i_l1s1 - integer :: i_l2s1 - integer :: i_l3s2 - integer :: i_s1s2 + integer :: i_l1m1 + integer :: i_l2m1 + integer :: i_l3m1 + integer :: i_l1m2 + integer :: i_l2m2 + integer :: i_l3m2 integer :: i_s1s3 - integer :: i_s2s1 integer :: i_s2s3 - integer :: i_s3s1 + integer :: i_s3m1 + integer :: i_s3m2 + integer :: i_s3m3 + integer :: i_m1s1 + integer :: i_m1s2 + integer :: i_m1s3 + integer :: i_m2s1 + integer :: i_m2s2 + integer :: i_m2s3 integer :: i_cwdl2 integer :: i_cwdl3 real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. @@ -358,6 +426,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Output: [integer (:) ] which pool is C taken from for a given decomposition step cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & ! Output: [integer (:) ] which pool is C added to for a given decomposition step floating_cn_ratio_decomp_pools => decomp_cascade_con%floating_cn_ratio_decomp_pools , & ! Output: [logical (:) ] TRUE => pool has fixed C:N ratio + is_microbe => decomp_cascade_con%is_microbe , & ! Output: [logical (:) ] TRUE => pool is microbial is_litter => decomp_cascade_con%is_litter , & ! Output: [logical (:) ] TRUE => pool is a litter pool is_soil => decomp_cascade_con%is_soil , & ! Output: [logical (:) ] TRUE => pool is a soil pool is_cwd => decomp_cascade_con%is_cwd , & ! Output: [logical (:) ] TRUE => pool is a cwd pool @@ -371,9 +440,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i ) - allocate(rf_s1s2(bounds%begc:bounds%endc,1:nlevdecomp)) allocate(rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp)) - allocate(f_s1s2(bounds%begc:bounds%endc,1:nlevdecomp)) allocate(f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp)) !------- time-constant coefficients ---------- ! @@ -383,12 +450,22 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i cn_s3 = params_inst%cn_s3_bgc ! set respiration fractions for fluxes between compartments - rf_l1s1 = params_inst%rf_l1s1_bgc - rf_l2s1 = params_inst%rf_l2s1_bgc - rf_l3s2 = params_inst%rf_l3s2_bgc - rf_s2s1 = params_inst%rf_s2s1_bgc - rf_s2s3 = params_inst%rf_s2s3_bgc - rf_s3s1 = params_inst%rf_s3s1_bgc + rf_l1m1 = params_inst%rf_l1m1_mimics + rf_l2m1 = params_inst%rf_l2m1_mimics + rf_l3m1 = params_inst%rf_l3m1_mimics + rf_l1m2 = params_inst%rf_l1m2_mimics + rf_l2m2 = params_inst%rf_l2m2_mimics + rf_l3m2 = params_inst%rf_l3m2_mimics + rf_s1s3 = params_inst%rf_s1s3_mimics + rf_s2s3 = params_inst%rf_s2s3_mimics + rf_s3m1 = params_inst%rf_s3m1_mimics + rf_s3m2 = params_inst%rf_s3m2_mimics + rf_m1s1 = params_inst%rf_m1s1_mimics + rf_m1s2 = params_inst%rf_m1s2_mimics + rf_m1s3 = params_inst%rf_m1s3_mimics + rf_m2s1 = params_inst%rf_m2s1_mimics + rf_m2s2 = params_inst%rf_m2s2_mimics + rf_m2s3 = params_inst%rf_m2s3_mimics rf_cwdl2 = params_inst%rf_cwdl2_bgc rf_cwdl3 = params_inst%rf_cwdl3_bgc @@ -398,16 +475,18 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i cwd_flig = params_inst%cwd_flig_bgc ! set path fractions - f_s2s1 = 0.42_r8/(0.45_r8) f_s2s3 = 0.03_r8/(0.45_r8) ! some of these are dependent on the soil texture properties + ! TODO slevis: Template for calculated mimics params? + ! But soil texture remains const with time. + ! So one-time initializations here and time-dep params + ! in subr. decomp_rate_constants_mimics. + do c = bounds%begc, bounds%endc do j = 1, nlevdecomp t = 0.85_r8 - 0.68_r8 * 0.01_r8 * (100._r8 - cellsand(c,j)) - f_s1s2(c,j) = 1._r8 - .004_r8 / (1._r8 - t) f_s1s3(c,j) = .004_r8 / (1._r8 - t) - rf_s1s2(c,j) = t rf_s1s3(c,j) = t end do end do @@ -419,6 +498,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i decomp_cascade_con%decomp_pool_name_history(i_litr1) = 'LITR1' decomp_cascade_con%decomp_pool_name_long(i_litr1) = 'litter 1' decomp_cascade_con%decomp_pool_name_short(i_litr1) = 'L1' + is_microbe(i_litr1) = .false. is_litter(i_litr1) = .true. is_soil(i_litr1) = .false. is_cwd(i_litr1) = .false. @@ -433,6 +513,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i decomp_cascade_con%decomp_pool_name_history(i_litr2) = 'LITR2' decomp_cascade_con%decomp_pool_name_long(i_litr2) = 'litter 2' decomp_cascade_con%decomp_pool_name_short(i_litr2) = 'L2' + is_microbe(i_litr2) = .false. is_litter(i_litr2) = .true. is_soil(i_litr2) = .false. is_cwd(i_litr2) = .false. @@ -447,6 +528,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i decomp_cascade_con%decomp_pool_name_history(i_litr3) = 'LITR3' decomp_cascade_con%decomp_pool_name_long(i_litr3) = 'litter 3' decomp_cascade_con%decomp_pool_name_short(i_litr3) = 'L3' + is_microbe(i_litr3) = .false. is_litter(i_litr3) = .true. is_soil(i_litr3) = .false. is_cwd(i_litr3) = .false. @@ -463,6 +545,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i decomp_cascade_con%decomp_pool_name_history(i_cwd) = 'CWD' decomp_cascade_con%decomp_pool_name_long(i_cwd) = 'coarse woody debris' decomp_cascade_con%decomp_pool_name_short(i_cwd) = 'CWD' + is_microbe(i_cwd) = .false. is_litter(i_cwd) = .false. is_soil(i_cwd) = .false. is_cwd(i_cwd) = .true. @@ -483,6 +566,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i decomp_cascade_con%decomp_pool_name_history(i_soil1) = 'SOIL1' decomp_cascade_con%decomp_pool_name_long(i_soil1) = 'soil 1' decomp_cascade_con%decomp_pool_name_short(i_soil1) = 'S1' + is_microbe(i_soil1) = .false. is_litter(i_soil1) = .false. is_soil(i_soil1) = .true. is_cwd(i_soil1) = .false. @@ -502,6 +586,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i decomp_cascade_con%decomp_pool_name_history(i_soil2) = 'SOIL2' decomp_cascade_con%decomp_pool_name_long(i_soil2) = 'soil 2' decomp_cascade_con%decomp_pool_name_short(i_soil2) = 'S2' + is_microbe(i_soil2) = .false. is_litter(i_soil2) = .false. is_soil(i_soil2) = .true. is_cwd(i_soil2) = .false. @@ -521,6 +606,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i decomp_cascade_con%decomp_pool_name_history(i_soil3) = 'SOIL3' decomp_cascade_con%decomp_pool_name_long(i_soil3) = 'soil 3' decomp_cascade_con%decomp_pool_name_short(i_soil3) = 'S3' + is_microbe(i_soil3) = .false. is_litter(i_soil3) = .false. is_soil(i_soil3) = .true. is_cwd(i_soil3) = .false. @@ -530,6 +616,36 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i is_cellulose(i_soil3) = .false. is_lignin(i_soil3) = .false. + floating_cn_ratio_decomp_pools(i_micr1) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_micr1) = 'micr1' + decomp_cascade_con%decomp_pool_name_history(i_micr1) = 'MICR1' + decomp_cascade_con%decomp_pool_name_long(i_micr1) = 'microbial 1' + decomp_cascade_con%decomp_pool_name_short(i_micr1) = 'M1' + is_microbe(i_micr1) = .true. + is_litter(i_micr1) = .false. + is_soil(i_micr1) = .false. + is_cwd(i_micr1) = .false. + initial_cn_ratio(i_micr1) = 90._r8 + initial_stock(i_micr1) = 0._r8 + is_metabolic(i_micr1) = .false. + is_cellulose(i_micr1) = .false. + is_lignin(i_micr1) = .false. + + floating_cn_ratio_decomp_pools(i_micr2) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_micr2) = 'micr2' + decomp_cascade_con%decomp_pool_name_history(i_micr2) = 'MICR2' + decomp_cascade_con%decomp_pool_name_long(i_micr2) = 'microbial 2' + decomp_cascade_con%decomp_pool_name_short(i_micr2) = 'M2' + is_microbe(i_micr2) = .true. + is_litter(i_micr2) = .false. + is_soil(i_micr2) = .false. + is_cwd(i_micr2) = .false. + initial_cn_ratio(i_micr2) = 90._r8 + initial_stock(i_micr2) = 0._r8 + is_metabolic(i_micr2) = .false. + is_cellulose(i_micr2) = .false. + is_lignin(i_micr2) = .false. + speedup_fac = 1._r8 @@ -539,6 +655,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i spinup_factor(i_litr2) = 1._r8 spinup_factor(i_litr3) = 1._r8 !CWD + ! TODO slevis: tau params changing if (.not. use_fates) then spinup_factor(i_cwd) = max(1._r8, (speedup_fac * params_inst%tau_cwd_bgc / 2._r8 )) end if @@ -547,6 +664,9 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i !som2,3 spinup_factor(i_soil2) = max(1._r8, (speedup_fac * params_inst%tau_s2_bgc)) spinup_factor(i_soil3) = max(1._r8, (speedup_fac * params_inst%tau_s3_bgc)) + ! micr1,2 + spinup_factor(i_micr1) = 1._r8 + spinup_factor(i_micr2) = 1._r8 if ( masterproc ) then write(iulog,*) 'Spinup_state ',spinup_state @@ -554,71 +674,128 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i end if !---------------- list of transitions and their time-independent coefficients ---------------! - i_l1s1 = 1 - decomp_cascade_con%cascade_step_name(i_l1s1) = 'L1S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = rf_l1s1 - cascade_donor_pool(i_l1s1) = i_litr1 - cascade_receiver_pool(i_l1s1) = i_soil1 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = 1.0_r8 - - i_l2s1 = 2 - decomp_cascade_con%cascade_step_name(i_l2s1) = 'L2S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1) = rf_l2s1 - cascade_donor_pool(i_l2s1) = i_litr2 - cascade_receiver_pool(i_l2s1) = i_soil1 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1)= 1.0_r8 - - i_l3s2 = 3 - decomp_cascade_con%cascade_step_name(i_l3s2) = 'L3S2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = rf_l3s2 - cascade_donor_pool(i_l3s2) = i_litr3 - cascade_receiver_pool(i_l3s2) = i_soil2 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = 1.0_r8 - - i_s1s2 = 4 - decomp_cascade_con%cascade_step_name(i_s1s2) = 'S1S2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = rf_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) - cascade_donor_pool(i_s1s2) = i_soil1 - cascade_receiver_pool(i_s1s2) = i_soil2 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = f_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) - - i_s1s3 = 5 + i_l1m1 = 1 + decomp_cascade_con%cascade_step_name(i_l1m1) = 'L1M1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = rf_l1m1 + cascade_donor_pool(i_l1m1) = i_litr1 + cascade_receiver_pool(i_l1m1) = i_micr1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = 1.0_r8 + + i_l2m1 = 2 + decomp_cascade_con%cascade_step_name(i_l2m1) = 'L2M1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1) = rf_l2m1 + cascade_donor_pool(i_l2m1) = i_litr2 + cascade_receiver_pool(i_l2m1) = i_micr1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1)= 1.0_r8 + + i_l3m1 = 3 + decomp_cascade_con%cascade_step_name(i_l3m1) = 'L3M1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3m1) = rf_l3m1 + cascade_donor_pool(i_l3m1) = i_litr3 + cascade_receiver_pool(i_l3m1) = i_micr1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3m1)= 1.0_r8 + + i_l1m2 = 4 + decomp_cascade_con%cascade_step_name(i_l1m2) = 'L1M2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = rf_l1m2 + cascade_donor_pool(i_l1m2) = i_litr1 + cascade_receiver_pool(i_l1m2) = i_micr2 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = 1.0_r8 + + i_l2m2 = 5 + decomp_cascade_con%cascade_step_name(i_l2m2) = 'L2M2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2) = rf_l2m2 + cascade_donor_pool(i_l2m2) = i_litr2 + cascade_receiver_pool(i_l2m2) = i_micr2 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2)= 1.0_r8 + + i_l3m2 = 6 + decomp_cascade_con%cascade_step_name(i_l3m2) = 'L3M2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3m2) = rf_l3m2 + cascade_donor_pool(i_l3m2) = i_litr3 + cascade_receiver_pool(i_l3m2) = i_micr2 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3m2)= 1.0_r8 + + i_s1s3 = 7 decomp_cascade_con%cascade_step_name(i_s1s3) = 'S1S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) cascade_donor_pool(i_s1s3) = i_soil1 cascade_receiver_pool(i_s1s3) = i_soil3 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) - i_s2s1 = 6 - decomp_cascade_con%cascade_step_name(i_s2s1) = 'S2S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = rf_s2s1 - cascade_donor_pool(i_s2s1) = i_soil2 - cascade_receiver_pool(i_s2s1) = i_soil1 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = f_s2s1 - - i_s2s3 = 7 + i_s2s3 = 8 decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 cascade_donor_pool(i_s2s3) = i_soil2 cascade_receiver_pool(i_s2s3) = i_soil3 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = f_s2s3 - i_s3s1 = 8 - decomp_cascade_con%cascade_step_name(i_s3s1) = 'S3S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = rf_s3s1 - cascade_donor_pool(i_s3s1) = i_soil3 - cascade_receiver_pool(i_s3s1) = i_soil1 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 - + i_s3m1 = 9 + decomp_cascade_con%cascade_step_name(i_s3m1) = 'S3M1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = rf_s3m1 + cascade_donor_pool(i_s3m1) = i_soil3 + cascade_receiver_pool(i_s3m1) = i_micr1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = 1.0_r8 + + i_s3m2 = 10 + decomp_cascade_con%cascade_step_name(i_s3m2) = 'S3M2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = rf_s3m2 + cascade_donor_pool(i_s3m2) = i_soil3 + cascade_receiver_pool(i_s3m2) = i_micr2 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = 1.0_r8 + + i_m1s1 = 11 + decomp_cascade_con%cascade_step_name(i_m1s1) = 'M1S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = rf_m1s1 + cascade_donor_pool(i_m1s1) = i_micr1 + cascade_receiver_pool(i_m1s1) = i_soil1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = 1.0_r8 + + i_m1s2 = 12 + decomp_cascade_con%cascade_step_name(i_m1s2) = 'M1S2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = rf_m1s2 + cascade_donor_pool(i_m1s2) = i_micr1 + cascade_receiver_pool(i_m1s2) = i_soil2 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = 1.0_r8 + + i_m1s3 = 13 + decomp_cascade_con%cascade_step_name(i_m1s3) = 'M1S3' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = rf_m1s3 + cascade_donor_pool(i_m1s3) = i_micr1 + cascade_receiver_pool(i_m1s3) = i_soil3 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = 1.0_r8 + + i_m2s1 = 15 + decomp_cascade_con%cascade_step_name(i_m2s1) = 'M2S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = rf_m2s1 + cascade_donor_pool(i_m2s1) = i_micr2 + cascade_receiver_pool(i_m2s1) = i_soil1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = 1.0_r8 + + i_m2s2 = 16 + decomp_cascade_con%cascade_step_name(i_m2s2) = 'M2S2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = rf_m2s2 + cascade_donor_pool(i_m2s2) = i_micr2 + cascade_receiver_pool(i_m2s2) = i_soil2 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = 1.0_r8 + + i_m2s3 = 17 + decomp_cascade_con%cascade_step_name(i_m2s3) = 'M2S3' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = rf_m2s3 + cascade_donor_pool(i_m2s3) = i_micr2 + cascade_receiver_pool(i_m2s3) = i_soil3 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = 1.0_r8 + + ! TODO slevis: Keep these? if (.not. use_fates) then - i_cwdl2 = 9 + i_cwdl2 = 18 decomp_cascade_con%cascade_step_name(i_cwdl2) = 'CWDL2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 cascade_donor_pool(i_cwdl2) = i_cwd cascade_receiver_pool(i_cwdl2) = i_litr2 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fcel - i_cwdl3 = 10 + i_cwdl3 = 19 decomp_cascade_con%cascade_step_name(i_cwdl3) = 'CWDL3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = rf_cwdl3 cascade_donor_pool(i_cwdl3) = i_cwd @@ -626,22 +803,20 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = cwd_flig end if - deallocate(rf_s1s2) deallocate(rf_s1s3) - deallocate(f_s1s2) deallocate(f_s1s3) end associate - end subroutine init_decompcascade_bgc + end subroutine init_decompcascade_mimics !----------------------------------------------------------------------- - subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & + subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) ! ! !DESCRIPTION: - ! calculate rate constants and decomposition pathways for the CENTURY decomposition cascade model - ! written by C. Koven based on original CLM4 decomposition cascade + ! Calculate rate constants and decomposition pathways for the MIMICS + ! decomposition cascade model ! ! !USES: use clm_time_manager , only : get_days_per_year @@ -667,6 +842,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & real(r8):: k_s1 ! decomposition rate constant SOM 1 (1/sec) real(r8):: k_s2 ! decomposition rate constant SOM 2 (1/sec) real(r8):: k_s3 ! decomposition rate constant SOM 3 (1/sec) + real(r8):: k_m1 ! decomposition rate constant microbial 1 (1/sec) + real(r8):: k_m2 ! decomposition rate constant microbial 2 (1/sec) real(r8):: k_frag ! fragmentation rate constant CWD (1/sec) real(r8):: cwdc_loss ! fragmentation rate for CWD carbon (gC/m2/s) real(r8):: cwdn_loss ! fragmentation rate for CWD nitrogen (gN/m2/s) @@ -687,6 +864,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & real(r8):: spinup_geogterm_s1(bounds%begc:bounds%endc) ! geographically-varying spinup term for s1 real(r8):: spinup_geogterm_s2(bounds%begc:bounds%endc) ! geographically-varying spinup term for s2 real(r8):: spinup_geogterm_s3(bounds%begc:bounds%endc) ! geographically-varying spinup term for s3 + real(r8):: spinup_geogterm_m1(bounds%begc:bounds%endc) ! geographically-varying spinup term for m1 + real(r8):: spinup_geogterm_m2(bounds%begc:bounds%endc) ! geographically-varying spinup term for m2 !----------------------------------------------------------------------- @@ -729,12 +908,71 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! Set "decomp_depth_efolding" parameter decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding +! TODO slevis: tau params are changing; map to Wieder et al. 2015 +! From testbed code +! ------------------ + +! Vmax, tau*, and Km are time-dependent + +! Table B1 Wieder et al. 2015 gives +! Vslope = 0.063, Vint = 5.47, av = 8e-6 +! Vmod_r = 10,2,10, Vmod_K = 3,3,2 (for LITm,s,SOMa --> MICr,K respectively) + +! Vmax(npt,R1) = exp(Vslope(R1) * Tsoi_day_avg_C + Vint(R1)) * av * Vmod(R1) +! Vmax(npt,R2) = exp(Vslope(R2) * Tsoi_day_avg_C + Vint(R2)) * av * Vmod(R2) +! Vmax(npt,R3) = exp(Vslope(R3) * Tsoi_day_avg_C + Vint(R3)) * av * Vmod(R3) +! Vmax(npt,K1) = exp(Vslope(K1) * Tsoi_day_avg_C + Vint(K1)) * av * Vmod(K1) +! Vmax(npt,K2) = exp(Vslope(K2) * Tsoi_day_avg_C + Vint(K2)) * av * Vmod(K2) +! Vmax(npt,K3) = exp(Vslope(K3) * Tsoi_day_avg_C + Vint(K3)) * av * Vmod(K3) + +! --- +! Solving for tauR (tau_m1 here?) & tauK (tau_m2 here?) + +! fmet_p(1) = 0.85, fmet_p(2) = 0.85, fmet_p(3) = 0.013 +! ligninNratioAvg(npt) = & +! ( ligninNratio(npt,leaf) * (cleaf2met(npt) + cleaf2str(npt)) & +! + ligninNratio(npt,froot) * (croot2met(npt) + croot2str(npt)) & +! + ligninNratio(npt,wood) * (cwd2str(npt)) ) & +! / max(0.001, cleaf2met(npt)+cleaf2str(npt)+croot2met(npt)+croot2str(npt)+cwd2str(npt)) +! set limits on Lignin:N to keep fmet > 0.2 +! necessary for litter quality in boreal forests with high cwd flux +! ligninNratioAvg(npt) = min(40.0, ligninNratioAvg(npt)) +! fmet(npt) = fmet_p(1) * (fmet_p(2) - fmet_p(3) * ligninNratioAvg(npt)) + +! tauModDenom = 100, tauMod_min = 0.8, tauMod_max = 1.2 +! tauMod(npt) = sqrt(avg_ann_npp_gC_m2_yr / tauModDenom) +! tauMod(npt) = min(tauMod_max, max(tauMod_min, tauMod(npt))) + +! tauR is tau_m1, right? tau_r(1) = 5.2e-4_r8, tau_r(2) = 0.3_r8 or 0.4? +! tauR(npt) = tau_r(1) * exp(tau_r(2) * fmet(npt)) * tauMod(npt) + +! tauK is tau_m2, right? tau_k(1) = 2.4e-4_r8, tau_k(2) = 0.1_r8 +! tauK(npt) = tau_k(1) * exp(tau_k(2) * fmet(npt)) * tauMod(npt) +! --- + +! Table B1 Wieder et al. 2015 gives +! Kslope = 0.017, 0.027, 0.017 (for LITm,s,SOMa --> MICr and K) +! Kint = 3.19, aK = 10 +! Kmod_r = 0.125,0.5,0.25*P_scalar, Kmod_K = 0.5,0.25,0.167*P_scalar +! P_scalar = (2 * exp(-2 * sqrt(fclay)))**(-1) + +! Km(npt,R1) = exp(Kslope(R1) * Tsoi_day_avg_C + Kint(R1)) * ak / Kmod(npt,R1) +! Km(npt,R2) = exp(Kslope(R2) * Tsoi_day_avg_C + Kint(R2)) * ak / Kmod(npt,R2) +! Km(npt,R3) = exp(Kslope(R3) * Tsoi_day_avg_C + Kint(R3)) * ak / Kmod(npt,R3) +! Km(npt,K1) = exp(Kslope(K1) * Tsoi_day_avg_C + Kint(K1)) * ak / Kmod(npt,K1) +! Km(npt,K2) = exp(Kslope(K2) * Tsoi_day_avg_C + Kint(K2)) * ak / Kmod(npt,K2) +! Km(npt,K3) = exp(Kslope(K3) * Tsoi_day_avg_C + Kint(K3)) * ak / Kmod(npt,K3) + +! STILL MISSING N-related stuff: DIN... + ! translate to per-second time constant k_l1 = 1._r8 / (secspday * days_per_year * params_inst%tau_l1_bgc) k_l2_l3 = 1._r8 / (secspday * days_per_year * params_inst%tau_l2_l3_bgc) k_s1 = 1._r8 / (secspday * days_per_year * params_inst%tau_s1_bgc) k_s2 = 1._r8 / (secspday * days_per_year * params_inst%tau_s2_bgc) k_s3 = 1._r8 / (secspday * days_per_year * params_inst%tau_s3_bgc) + k_m1 = 1._r8 / (secspday * days_per_year * params_inst%tau_m1_mimics) + k_m2 = 1._r8 / (secspday * days_per_year * params_inst%tau_m2_mimics) k_frag = 1._r8 / (secspday * days_per_year * params_inst%tau_cwd_bgc) ! calc ref rate @@ -782,6 +1020,18 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & spinup_geogterm_s3(c) = 1._r8 endif ! + if ( abs(spinup_factor(i_micr1) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_m1(c) = spinup_factor(i_micr1) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + else + spinup_geogterm_m1(c) = 1._r8 + endif + ! + if ( abs(spinup_factor(i_micr2) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_m2(c) = spinup_factor(i_micr2) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + else + spinup_geogterm_m2(c) = 1._r8 + endif + ! end do else do fc = 1,num_soilc @@ -792,10 +1042,21 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & spinup_geogterm_s1(c) = 1._r8 spinup_geogterm_s2(c) = 1._r8 spinup_geogterm_s3(c) = 1._r8 + spinup_geogterm_m1(c) = 1._r8 + spinup_geogterm_m2(c) = 1._r8 end do endif !--- time dependent coefficients-----! + ! TODO slevis: Not immediately obvious how to reduce the if-else + ! repetition, bc t_scalar, w_scalar, o_scalar sum all j + ! to layer 1 in the if, while they do not in the else. + ! Other changes that would be necessary: + ! - set fr = 1 in the else, + ! - use a new nlevd = nlev_soildecomp_standard in the if and + ! nlevd = nlevdecomp in the else, + ! - keep if (j==1) t_scalar(c,:) = 0._r8 from the if? + ! - keep P. Thornton's comment from the else if ( nlevdecomp .eq. 1 ) then ! calculate function to weight the temperature and water potential scalars @@ -805,7 +1066,6 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! the following normalizes values in fr so that they ! sum to 1.0 across top nlevdecomp levels on a column frw(bounds%begc:bounds%endc) = 0._r8 - nlev_soildecomp_standard=5 allocate(fr(bounds%begc:bounds%endc,nlev_soildecomp_standard)) do j=1,nlev_soildecomp_standard do fc = 1,num_soilc @@ -975,84 +1235,68 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & end if - if ( normalize_q10_to_century_tfunc ) then - ! scale all decomposition rates by a constant to compensate for offset between original CENTURY temp func and Q10 - normalization_factor = (catanf(normalization_tref)/catanf_30) / (q10**((normalization_tref-25._r8)/10._r8)) - do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - t_scalar(c,j) = t_scalar(c,j) * normalization_factor - end do - end do - endif - - if (use_vertsoilc) then - ! add a term to reduce decomposition rate at depth - ! for now used a fixed e-folding depth - do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - depth_scalar(c,j) = exp(-zsoi(j)/decomp_depth_efolding) - end do +! ! TODO slevis: Commented out. Should I have kept these lines? +! if ( normalize_q10_to_century_tfunc ) then +! ! scale all decomposition rates by a constant to compensate for offset between original CENTURY temp func and Q10 +! normalization_factor = (catanf(normalization_tref)/catanf_30) / (q10**((normalization_tref-25._r8)/10._r8)) +! do j = 1, nlevdecomp +! do fc = 1,num_soilc +! c = filter_soilc(fc) +! t_scalar(c,j) = t_scalar(c,j) * normalization_factor +! end do +! end do +! endif + + ! Term that reduces decomposition rate at depth + ! TODO slevis: Reduced code repetition by defining + ! depth_scalar(c,j) = 1.0_r8 in the else instead of + ! repeating the decomp_k lines. + do j = 1, nlevdecomp + do fc = 1, num_soilc + c = filter_soilc(fc) + if (use_vertsoilc) then + ! Using fixed e-folding depth as in + ! SoilBiogeochemDecompCascadeBGCMod.F90 + depth_scalar(c,j) = exp(-zsoi(j) / decomp_depth_efolding) + else + depth_scalar(c,j) = 1.0_r8 + end if end do - end if + end do ! calculate rate constants for all litter and som pools - if (use_vertsoilc) then - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - decomp_k(c,j,i_litr1) = k_l1 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & - * spinup_geogterm_l1(c) - decomp_k(c,j,i_litr2) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & - * spinup_geogterm_l23(c) - decomp_k(c,j,i_litr3) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & - * spinup_geogterm_l23(c) - decomp_k(c,j,i_soil1) = k_s1 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & - * spinup_geogterm_s1(c) - decomp_k(c,j,i_soil2) = k_s2 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & - * spinup_geogterm_s2(c) - decomp_k(c,j,i_soil3) = k_s3 * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) & - * spinup_geogterm_s3(c) - end do - end do - else - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - decomp_k(c,j,i_litr1) = k_l1 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l1(c) - decomp_k(c,j,i_litr2) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l23(c) - decomp_k(c,j,i_litr3) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l23(c) - decomp_k(c,j,i_soil1) = k_s1 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s1(c) - decomp_k(c,j,i_soil2) = k_s2 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s2(c) - decomp_k(c,j,i_soil3) = k_s3 * t_scalar(c,j) * w_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s3(c) - end do + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + decomp_k(c,j,i_litr1) = k_l1 * t_scalar(c,j) * w_scalar(c,j) * & + depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l1(c) + decomp_k(c,j,i_litr2) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * & + depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l23(c) + decomp_k(c,j,i_litr3) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * & + depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l23(c) + + decomp_k(c,j,i_micr1) = k_m1 * t_scalar(c,j) * w_scalar(c,j) * & + depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_m1(c) + decomp_k(c,j,i_micr2) = k_m2 * t_scalar(c,j) * w_scalar(c,j) * & + depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_m2(c) + + decomp_k(c,j,i_soil1) = k_s1 * t_scalar(c,j) * w_scalar(c,j) * & + depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s1(c) + decomp_k(c,j,i_soil2) = k_s2 * t_scalar(c,j) * w_scalar(c,j) * & + depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s2(c) + decomp_k(c,j,i_soil3) = k_s3 * t_scalar(c,j) * w_scalar(c,j) * & + depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s3(c) + ! Same for cwd but only if fates not enabled; fates handles cwd on + ! its own structure + if (.not. use_fates) then + decomp_k(c,j,i_cwd) = k_frag * t_scalar(c,j) * w_scalar(c,j) * & + depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_cwd(c) + end if end do - end if - - ! do the same for cwd, but only if fates is not enabled, because fates handles CWD on its own structure - if (.not. use_fates) then - if (use_vertsoilc) then - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - decomp_k(c,j,i_cwd) = k_frag * t_scalar(c,j) * w_scalar(c,j) * depth_scalar(c,j) * & - o_scalar(c,j) * spinup_geogterm_cwd(c) - end do - end do - else - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - decomp_k(c,j,i_cwd) = k_frag * t_scalar(c,j) * w_scalar(c,j) * & - o_scalar(c,j) * spinup_geogterm_cwd(c) - end do - end do - end if - end if + end do end associate - end subroutine decomp_rate_constants_bgc + end subroutine decomp_rate_constants_mimics -end module SoilBiogeochemDecompCascadeBGCMod +end module SoilBiogeochemDecompCascadeMIMICSMod From d963ada5b8cedb90e6336fcd120736b95f6307e5 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 1 Apr 2021 18:08:49 -0600 Subject: [PATCH 03/69] Updating SoilBiogeochemDecompCascadeMIMICSMod.F90 based on code review --- src/main/clm_varpar.F90 | 2 - .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 491 +++--------------- 2 files changed, 69 insertions(+), 424 deletions(-) diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index 0e409ffc73..ac7441aa20 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -64,8 +64,6 @@ module clm_varpar ! constants for decomposition cascade - integer, public, parameter :: i_micr_r = 1 - integer, public, parameter :: i_micr_k = i_micr_r + 1 integer, public, parameter :: i_met_lit = 1 integer, public, parameter :: i_cel_lit = i_met_lit + 1 integer, public, parameter :: i_lig_lit = i_cel_lit + 1 diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index eecd7c66dc..608c7ed504 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -10,7 +10,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod use shr_const_mod , only : SHR_CONST_TKFRZ use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : nlevdecomp - use clm_varpar , only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd + use clm_varpar , only : i_met_lit use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_vertsoilc, use_fates use clm_varcon , only : zsoi use decompMod , only : bounds_type @@ -38,68 +38,40 @@ module SoilBiogeochemDecompCascadeMIMICSMod public :: decomp_rate_constants_mimics ! Figure out decomposition rates ! ! !PUBLIC DATA MEMBERS - logical , public :: normalize_q10_to_century_tfunc = .true.! do we normalize the century decomp. rates so that they match the CLM Q10 at a given tep? - logical , public :: use_century_tfunc = .false. - real(r8), public :: normalization_tref = 15._r8 ! reference temperature for normalizaion (degrees C) ! ! !PRIVATE DATA MEMBERS - integer, private :: i_soil1 = -9 ! Soil Organic Matter (SOM) first pool - integer, private :: i_soil2 = -9 ! SOM second pool - integer, private :: i_soil3 = -9 ! SOM third pool integer, private, parameter :: nsompools = 3 ! Number of SOM pools integer, private, parameter :: i_litr1 = i_met_lit ! First litter pool, metobolic - integer, private, parameter :: i_litr2 = i_cel_lit ! Second litter pool, cellulose - integer, private, parameter :: i_litr3 = i_lig_lit ! Third litter pool, lignin - integer, private, parameter :: i_micr1 = i_micr_r ! First microbial pool, copiotrophic, as labeled in Wieder et al. 2015 - integer, private, parameter :: i_micr2 = i_micr_k ! Second microbial pool, oligotrophic, as labeled in Wieder et al. 2015 + integer, private :: i_litr2 = -9 ! Second litter pool, lignin in MIMICS + integer, private :: i_micr1 = -9 ! First microbial pool, copiotrophic, as labeled in Wieder et al. 2015 + integer, private :: i_micr2 = -9 ! Second microbial pool, oligotrophic, as labeled in Wieder et al. 2015 + integer, private :: i_cwd = -9 ! Coarse woody debris pool + integer, private :: i_soil1 = -9 ! Soil Organic Matter (SOM) first pool, protected SOM (som_p in Wieder et al. 2015) + integer, private :: i_soil2 = -9 ! SOM second pool, recalcitrant SOM (som_c in Wieder et al. 2015) + integer, private :: i_soil3 = -9 ! SOM third pool, available SOM (som_a in Wieder et al. 2015) type, private :: params_type - real(r8):: cn_s1_bgc !C:N for SOM 1 - real(r8):: cn_s2_bgc !C:N for SOM 2 - real(r8):: cn_s3_bgc !C:N for SOM 3 + ! TODO slevis: soil/litter C:N is not defined in MIMICS. Microbial C:N is + ! a parameter that varies with litter quality (fmet). ! TODO slevis: New rf params in MIMICS. Update params file accordingly. ! I haven't identified what these correspond to in testbed. - real(r8):: rf_l1m1_mimics !respiration fraction litter 1 -> microbial 1 + real(r8):: rf_l1m1_mimics ! respiration fraction litter 1 -> microbe 1 real(r8):: rf_l2m1_mimics - real(r8):: rf_l3m1_mimics - + real(r8):: rf_s3m1_mimics ! respiration fraction soil 3 -> microbe 1 real(r8):: rf_l1m2_mimics real(r8):: rf_l2m2_mimics - real(r8):: rf_l3m2_mimics - - real(r8):: rf_s1s3_mimics ! respiration fraction soil 1 -> soil 3 - real(r8):: rf_s2s3_mimics - real(r8):: rf_s3m1_mimics real(r8):: rf_s3m2_mimics - real(r8):: rf_m1s1_mimics - real(r8):: rf_m1s2_mimics - real(r8):: rf_m1s3_mimics - - real(r8):: rf_m2s1_mimics - real(r8):: rf_m2s2_mimics - real(r8):: rf_m2s3_mimics - - ! TODO slevis: Keep these? - real(r8):: rf_cwdl2_bgc - real(r8):: rf_cwdl3_bgc - - ! TODO slevis: tau params are functions (Vmax and Km) in MIMICS. Also new - ! tau params define microbial turnover to SOM. Update params - ! file if necessary. - real(r8):: tau_l1_mimics ! 1/turnover time of litter 1 (1/yr) - real(r8):: tau_l2_l3_mimics ! 1/turnover time of litter 2 and 3 (1/yr) - real(r8):: tau_s1_mimics ! 1/turnover time of SOM 1 (1/yr) - real(r8):: tau_s2_mimics ! 1/turnover time of SOM 2 (1/yr) - real(r8):: tau_s3_mimics ! 1/turnover time of SOM 3 (1/yr) + real(r8):: rf_cwdl2_mimics + + ! TODO slevis: Introduce Vmax and Km. Also tau params that define + ! microbial turnover to SOM are functions. real(r8):: tau_m1_mimics ! 1/turnover time of microbial 1 (1/yr) real(r8):: tau_m2_mimics ! 1/turnover time of microbial 2 (1/yr) - ! TODO slevis: Keep? real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) - real(r8) :: cwd_fcel_bgc !cellulose fraction for CWD real(r8) :: cwd_flig_bgc ! real(r8) :: k_frag_bgc !fragmentation rate for CWD @@ -206,29 +178,12 @@ subroutine readParams ( ncid ) !----------------------------------------------------------------------- ! Read off of netcdf file - ! TODO slevis: new params will be added here and in the params file - ! TODO slevis: Keep tau_cwd? + ! TODO slevis: Add new params here and in the params file tString='tau_cwd' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_cwd_bgc=tempr - tString='cn_s1_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cn_s1_bgc=tempr - - tString='cn_s2_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cn_s2_bgc=tempr - - tString='cn_s3_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cn_s3_bgc=tempr - - ! TODO slevis: rf params changing tString='rf_l1m1_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -239,10 +194,10 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l2m1_mimics=tempr - tString='rf_l3m1_mimics' + tString='rf_s3m1_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_l3m1_mimics=tempr + params_inst%rf_s3m1_mimics=tempr tString='rf_l1m2_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) @@ -254,75 +209,15 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l2m2_mimics=tempr - tString='rf_l3m2_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_l3m2_mimics=tempr - - tString='rf_s1s3_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_s1s3_mimics=tempr - - tString='rf_s2s3_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_s2s3_mimics=tempr - - tString='rf_s3m1_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_s3m1_mimics=tempr - tString='rf_s3m2_mimics' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_s3m2_mimics=tempr - tString='rf_m1s1_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_m1s1_mimics=tempr - - tString='rf_m1s2_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_m1s2_mimics=tempr - - tString='rf_m1s3_mimics' + tString='rf_cwdl2_bgc' ! MIMICS value of this same as BGC value (= 0) call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_m1s3_mimics=tempr - - tString='rf_m2s1_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_m2s1_mimics=tempr - - tString='rf_m2s2_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_m2s2_mimics=tempr - - tString='rf_m2s3_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_m2s3_mimics=tempr - - tString='rf_cwdl2_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_cwdl2_bgc=tempr - - tString='rf_cwdl3_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_cwdl3_bgc=tempr - - tString='cwd_fcel' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cwd_fcel_bgc=tempr + params_inst%rf_cwdl2_mimics=tempr tString='k_frag' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) @@ -364,53 +259,26 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate !-- properties of each decomposing pool real(r8) :: rf_l1m1 real(r8) :: rf_l2m1 - real(r8) :: rf_l3m1 + real(r8) :: rf_s3m1 real(r8) :: rf_l1m2 real(r8) :: rf_l2m2 - real(r8) :: rf_l3m2 - real(r8) :: rf_s1s3 - real(r8) :: rf_s2s3 - real(r8) :: rf_s3m1 real(r8) :: rf_s3m2 - real(r8) :: rf_m1s1 - real(r8) :: rf_m1s2 - real(r8) :: rf_m1s3 - real(r8) :: rf_m2s1 - real(r8) :: rf_m2s2 - real(r8) :: rf_m2s3 - ! TODO slevis: Already exists as scalar but keep temporarily as a template + ! TODO slevis: Keeping temporarily as a template ! for new params not coming from the params file. ! Also keeping other params that I'm not sure about, yet. real(r8), allocatable :: rf_s1s3(:,:) real(r8) :: rf_cwdl2 - real(r8) :: rf_cwdl3 - real(r8) :: cwd_fcel real(r8) :: cwd_flig - real(r8) :: cn_s1 - real(r8) :: cn_s2 - real(r8) :: cn_s3 real(r8), allocatable :: f_s1s3(:,:) real(r8) :: f_s2s3 integer :: i_l1m1 integer :: i_l2m1 - integer :: i_l3m1 + integer :: i_s3m1 integer :: i_l1m2 integer :: i_l2m2 - integer :: i_l3m2 - integer :: i_s1s3 - integer :: i_s2s3 - integer :: i_s3m1 integer :: i_s3m2 - integer :: i_s3m3 - integer :: i_m1s1 - integer :: i_m1s2 - integer :: i_m1s3 - integer :: i_m2s1 - integer :: i_m2s2 - integer :: i_m2s3 integer :: i_cwdl2 - integer :: i_cwdl3 real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. integer :: c, j ! indices @@ -444,34 +312,17 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate allocate(f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp)) !------- time-constant coefficients ---------- ! - ! set soil organic matter compartment C:N ratios - cn_s1 = params_inst%cn_s1_bgc - cn_s2 = params_inst%cn_s2_bgc - cn_s3 = params_inst%cn_s3_bgc - ! set respiration fractions for fluxes between compartments rf_l1m1 = params_inst%rf_l1m1_mimics rf_l2m1 = params_inst%rf_l2m1_mimics - rf_l3m1 = params_inst%rf_l3m1_mimics + rf_s3m1 = params_inst%rf_s3m1_mimics rf_l1m2 = params_inst%rf_l1m2_mimics rf_l2m2 = params_inst%rf_l2m2_mimics - rf_l3m2 = params_inst%rf_l3m2_mimics - rf_s1s3 = params_inst%rf_s1s3_mimics - rf_s2s3 = params_inst%rf_s2s3_mimics - rf_s3m1 = params_inst%rf_s3m1_mimics rf_s3m2 = params_inst%rf_s3m2_mimics - rf_m1s1 = params_inst%rf_m1s1_mimics - rf_m1s2 = params_inst%rf_m1s2_mimics - rf_m1s3 = params_inst%rf_m1s3_mimics - rf_m2s1 = params_inst%rf_m2s1_mimics - rf_m2s2 = params_inst%rf_m2s2_mimics - rf_m2s3 = params_inst%rf_m2s3_mimics - - rf_cwdl2 = params_inst%rf_cwdl2_bgc - rf_cwdl3 = params_inst%rf_cwdl3_bgc - - ! set the cellulose and lignin fractions for coarse woody debris - cwd_fcel = params_inst%cwd_fcel_bgc + + rf_cwdl2 = params_inst%rf_cwdl2_mimics + + ! set the lignin fractions for coarse woody debris cwd_flig = params_inst%cwd_flig_bgc ! set path fractions @@ -508,6 +359,7 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_cellulose(i_litr1) = .false. is_lignin(i_litr1) = .false. + i_litr2 = i_litr1 + 1 floating_cn_ratio_decomp_pools(i_litr2) = .true. decomp_cascade_con%decomp_pool_name_restart(i_litr2) = 'litr2' decomp_cascade_con%decomp_pool_name_history(i_litr2) = 'LITR2' @@ -520,26 +372,16 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate initial_cn_ratio(i_litr2) = 90._r8 initial_stock(i_litr2) = 0._r8 is_metabolic(i_litr2) = .false. - is_cellulose(i_litr2) = .true. - is_lignin(i_litr2) = .false. - - floating_cn_ratio_decomp_pools(i_litr3) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_litr3) = 'litr3' - decomp_cascade_con%decomp_pool_name_history(i_litr3) = 'LITR3' - decomp_cascade_con%decomp_pool_name_long(i_litr3) = 'litter 3' - decomp_cascade_con%decomp_pool_name_short(i_litr3) = 'L3' - is_microbe(i_litr3) = .false. - is_litter(i_litr3) = .true. - is_soil(i_litr3) = .false. - is_cwd(i_litr3) = .false. - initial_cn_ratio(i_litr3) = 90._r8 - initial_stock(i_litr3) = 0._r8 - is_metabolic(i_litr3) = .false. - is_cellulose(i_litr3) = .false. - is_lignin(i_litr3) = .true. + is_cellulose(i_litr2) = .true. ! TODO ?? + is_lignin(i_litr2) = .true. + ! TODO slevis: clm_varpar hardwires i_cwd = 4 or = 0 if (use_fates) + ! I recommend replacing the hardwired value with one that we + ! update here on the fly. Same for i_soil1,2,3 & i_micr1,2. + i_cwd = i_litr2 if (.not. use_fates) then ! CWD + i_cwd = i_litr2 + 1 floating_cn_ratio_decomp_pools(i_cwd) = .true. decomp_cascade_con%decomp_pool_name_restart(i_cwd) = 'cwd' decomp_cascade_con%decomp_pool_name_history(i_cwd) = 'CWD' @@ -556,11 +398,7 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_lignin(i_cwd) = .false. endif - if (.not. use_fates) then - i_soil1 = 5 - else - i_soil1 = 4 - endif + i_soil1 = i_cwd + 1 floating_cn_ratio_decomp_pools(i_soil1) = .false. decomp_cascade_con%decomp_pool_name_restart(i_soil1) = 'soil1' decomp_cascade_con%decomp_pool_name_history(i_soil1) = 'SOIL1' @@ -570,17 +408,13 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_soil1) = .false. is_soil(i_soil1) = .true. is_cwd(i_soil1) = .false. - initial_cn_ratio(i_soil1) = cn_s1 + initial_cn_ratio(i_soil1) = cn_s1 ! TODO ?? initial_stock(i_soil1) = params_inst%initial_Cstocks(1) is_metabolic(i_soil1) = .false. is_cellulose(i_soil1) = .false. is_lignin(i_soil1) = .false. - if (.not. use_fates) then - i_soil2 = 6 - else - i_soil2 = 5 - endif + i_soil2 = i_soil1 + 1 floating_cn_ratio_decomp_pools(i_soil2) = .false. decomp_cascade_con%decomp_pool_name_restart(i_soil2) = 'soil2' decomp_cascade_con%decomp_pool_name_history(i_soil2) = 'SOIL2' @@ -590,17 +424,13 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_soil2) = .false. is_soil(i_soil2) = .true. is_cwd(i_soil2) = .false. - initial_cn_ratio(i_soil2) = cn_s2 + initial_cn_ratio(i_soil2) = cn_s2 ! TODO ?? initial_stock(i_soil2) = params_inst%initial_Cstocks(2) is_metabolic(i_soil2) = .false. is_cellulose(i_soil2) = .false. is_lignin(i_soil2) = .false. - if (.not. use_fates) then - i_soil3 = 7 - else - i_soil3 = 6 - endif + i_soil3 = i_soil2 + 1 floating_cn_ratio_decomp_pools(i_soil3) = .false. decomp_cascade_con%decomp_pool_name_restart(i_soil3) = 'soil3' decomp_cascade_con%decomp_pool_name_history(i_soil3) = 'SOIL3' @@ -610,12 +440,13 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_soil3) = .false. is_soil(i_soil3) = .true. is_cwd(i_soil3) = .false. - initial_cn_ratio(i_soil3) = cn_s3 + initial_cn_ratio(i_soil3) = cn_s3 ! TODO ?? initial_stock(i_soil3) = params_inst%initial_Cstocks(3) is_metabolic(i_soil3) = .false. is_cellulose(i_soil3) = .false. is_lignin(i_soil3) = .false. + i_micr1 = i_soil3 + 1 floating_cn_ratio_decomp_pools(i_micr1) = .true. decomp_cascade_con%decomp_pool_name_restart(i_micr1) = 'micr1' decomp_cascade_con%decomp_pool_name_history(i_micr1) = 'MICR1' @@ -631,6 +462,7 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_cellulose(i_micr1) = .false. is_lignin(i_micr1) = .false. + i_micr2 = i_micr1 + 1 floating_cn_ratio_decomp_pools(i_micr2) = .true. decomp_cascade_con%decomp_pool_name_restart(i_micr2) = 'micr2' decomp_cascade_con%decomp_pool_name_history(i_micr2) = 'MICR2' @@ -646,22 +478,20 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_cellulose(i_micr2) = .false. is_lignin(i_micr2) = .false. - speedup_fac = 1._r8 !lit1 spinup_factor(i_litr1) = 1._r8 - !lit2,3 + !lit2 spinup_factor(i_litr2) = 1._r8 - spinup_factor(i_litr3) = 1._r8 !CWD - ! TODO slevis: tau params changing if (.not. use_fates) then spinup_factor(i_cwd) = max(1._r8, (speedup_fac * params_inst%tau_cwd_bgc / 2._r8 )) end if !som1 spinup_factor(i_soil1) = 1._r8 !som2,3 + ! TODO slevis: change these to 1? spinup_factor(i_soil2) = max(1._r8, (speedup_fac * params_inst%tau_s2_bgc)) spinup_factor(i_soil3) = max(1._r8, (speedup_fac * params_inst%tau_s3_bgc)) ! micr1,2 @@ -688,12 +518,12 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate cascade_receiver_pool(i_l2m1) = i_micr1 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1)= 1.0_r8 - i_l3m1 = 3 - decomp_cascade_con%cascade_step_name(i_l3m1) = 'L3M1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3m1) = rf_l3m1 - cascade_donor_pool(i_l3m1) = i_litr3 - cascade_receiver_pool(i_l3m1) = i_micr1 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3m1)= 1.0_r8 + i_s3m1 = 3 + decomp_cascade_con%cascade_step_name(i_s3m1) = 'S3M1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = rf_s3m1 + cascade_donor_pool(i_s3m1) = i_soil3 + cascade_receiver_pool(i_s3m1) = i_micr1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = 1.0_r8 i_l1m2 = 4 decomp_cascade_con%cascade_step_name(i_l1m2) = 'L1M2' @@ -709,98 +539,20 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate cascade_receiver_pool(i_l2m2) = i_micr2 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2)= 1.0_r8 - i_l3m2 = 6 - decomp_cascade_con%cascade_step_name(i_l3m2) = 'L3M2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3m2) = rf_l3m2 - cascade_donor_pool(i_l3m2) = i_litr3 - cascade_receiver_pool(i_l3m2) = i_micr2 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3m2)= 1.0_r8 - - i_s1s3 = 7 - decomp_cascade_con%cascade_step_name(i_s1s3) = 'S1S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) - cascade_donor_pool(i_s1s3) = i_soil1 - cascade_receiver_pool(i_s1s3) = i_soil3 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) - - i_s2s3 = 8 - decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 - cascade_donor_pool(i_s2s3) = i_soil2 - cascade_receiver_pool(i_s2s3) = i_soil3 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = f_s2s3 - - i_s3m1 = 9 - decomp_cascade_con%cascade_step_name(i_s3m1) = 'S3M1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = rf_s3m1 - cascade_donor_pool(i_s3m1) = i_soil3 - cascade_receiver_pool(i_s3m1) = i_micr1 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = 1.0_r8 - - i_s3m2 = 10 + i_s3m2 = 6 decomp_cascade_con%cascade_step_name(i_s3m2) = 'S3M2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = rf_s3m2 cascade_donor_pool(i_s3m2) = i_soil3 cascade_receiver_pool(i_s3m2) = i_micr2 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = 1.0_r8 - i_m1s1 = 11 - decomp_cascade_con%cascade_step_name(i_m1s1) = 'M1S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = rf_m1s1 - cascade_donor_pool(i_m1s1) = i_micr1 - cascade_receiver_pool(i_m1s1) = i_soil1 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = 1.0_r8 - - i_m1s2 = 12 - decomp_cascade_con%cascade_step_name(i_m1s2) = 'M1S2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = rf_m1s2 - cascade_donor_pool(i_m1s2) = i_micr1 - cascade_receiver_pool(i_m1s2) = i_soil2 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = 1.0_r8 - - i_m1s3 = 13 - decomp_cascade_con%cascade_step_name(i_m1s3) = 'M1S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = rf_m1s3 - cascade_donor_pool(i_m1s3) = i_micr1 - cascade_receiver_pool(i_m1s3) = i_soil3 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = 1.0_r8 - - i_m2s1 = 15 - decomp_cascade_con%cascade_step_name(i_m2s1) = 'M2S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = rf_m2s1 - cascade_donor_pool(i_m2s1) = i_micr2 - cascade_receiver_pool(i_m2s1) = i_soil1 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = 1.0_r8 - - i_m2s2 = 16 - decomp_cascade_con%cascade_step_name(i_m2s2) = 'M2S2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = rf_m2s2 - cascade_donor_pool(i_m2s2) = i_micr2 - cascade_receiver_pool(i_m2s2) = i_soil2 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = 1.0_r8 - - i_m2s3 = 17 - decomp_cascade_con%cascade_step_name(i_m2s3) = 'M2S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = rf_m2s3 - cascade_donor_pool(i_m2s3) = i_micr2 - cascade_receiver_pool(i_m2s3) = i_soil3 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = 1.0_r8 - - ! TODO slevis: Keep these? if (.not. use_fates) then - i_cwdl2 = 18 + i_cwdl2 = 7 decomp_cascade_con%cascade_step_name(i_cwdl2) = 'CWDL2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 cascade_donor_pool(i_cwdl2) = i_cwd cascade_receiver_pool(i_cwdl2) = i_litr2 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fcel - - i_cwdl3 = 19 - decomp_cascade_con%cascade_step_name(i_cwdl3) = 'CWDL3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = rf_cwdl3 - cascade_donor_pool(i_cwdl3) = i_cwd - cascade_receiver_pool(i_cwdl3) = i_litr3 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = cwd_flig + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_flig end if deallocate(rf_s1s3) @@ -820,7 +572,6 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & ! ! !USES: use clm_time_manager , only : get_days_per_year - use shr_const_mod , only : SHR_CONST_PI use clm_varcon , only : secspday ! ! !ARGUMENTS: @@ -836,9 +587,8 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & real(r8):: frw(bounds%begc:bounds%endc) ! rooting fraction weight real(r8), allocatable:: fr(:,:) ! column-level rooting fraction by soil depth real(r8):: psi ! temporary soilpsi for water scalar - real(r8):: rate_scalar ! combined rate scalar for decomp real(r8):: k_l1 ! decomposition rate constant litter 1 (1/sec) - real(r8):: k_l2_l3 ! decomposition rate constant litter 2 and litter 3 (1/sec) + real(r8):: k_l2 ! decomposition rate constant litter 2 (1/sec) real(r8):: k_s1 ! decomposition rate constant SOM 1 (1/sec) real(r8):: k_s2 ! decomposition rate constant SOM 2 (1/sec) real(r8):: k_s3 ! decomposition rate constant SOM 3 (1/sec) @@ -847,19 +597,13 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & real(r8):: k_frag ! fragmentation rate constant CWD (1/sec) real(r8):: cwdc_loss ! fragmentation rate for CWD carbon (gC/m2/s) real(r8):: cwdn_loss ! fragmentation rate for CWD nitrogen (gN/m2/s) - real(r8):: Q10 ! temperature dependence - real(r8):: froz_q10 ! separate q10 for frozen soil respiration rates. default to same as above zero rates real(r8):: decomp_depth_efolding ! (meters) e-folding depth for reduction in decomposition [ integer :: c, fc, j, k, l - real(r8):: catanf ! hyperbolic temperature function from CENTURY - real(r8):: catanf_30 ! reference rate at 30C - real(r8):: t1 ! temperature argument - real(r8):: normalization_factor ! factor by which to offset the decomposition rates frm century to a q10 formulation real(r8):: days_per_year ! days per year real(r8):: depth_scalar(bounds%begc:bounds%endc,1:nlevdecomp) real(r8):: mino2lim !minimum anaerobic decomposition rate real(r8):: spinup_geogterm_l1(bounds%begc:bounds%endc) ! geographically-varying spinup term for l1 - real(r8):: spinup_geogterm_l23(bounds%begc:bounds%endc) ! geographically-varying spinup term for l2 and l3 + real(r8):: spinup_geogterm_l2(bounds%begc:bounds%endc) ! geographically-varying spinup term for l2 real(r8):: spinup_geogterm_cwd(bounds%begc:bounds%endc) ! geographically-varying spinup term for cwd real(r8):: spinup_geogterm_s1(bounds%begc:bounds%endc) ! geographically-varying spinup term for s1 real(r8):: spinup_geogterm_s2(bounds%begc:bounds%endc) ! geographically-varying spinup term for s2 @@ -869,9 +613,6 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & !----------------------------------------------------------------------- - !----- CENTURY T response function - catanf(t1) = 11.75_r8 +(29.7_r8 / SHR_CONST_PI) * atan( SHR_CONST_PI * 0.031_r8 * ( t1 - 15.4_r8 )) - associate( & minpsi => params_inst%minpsi_bgc , & ! Input: [real(r8) ] minimum soil suction (mm) maxpsi => params_inst%maxpsi_bgc , & ! Input: [real(r8) ] maximum soil suction (mm) @@ -883,7 +624,6 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & o2stress_unsat => ch4_inst%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area - t_scalar => soilbiogeochem_carbonflux_inst%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) @@ -892,19 +632,8 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & mino2lim = CNParamsShareInst%mino2lim - if ( use_century_tfunc .and. normalize_q10_to_century_tfunc ) then - call endrun(msg='ERROR: cannot have both use_century_tfunc and normalize_q10_to_century_tfunc set as true'//& - errMsg(sourcefile, __LINE__)) - endif - days_per_year = get_days_per_year() - ! set "Q10" parameter - Q10 = CNParamsShareInst%Q10 - - ! set "froz_q10" parameter - froz_q10 = CNParamsShareInst%froz_q10 - ! Set "decomp_depth_efolding" parameter decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding @@ -967,7 +696,7 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & ! translate to per-second time constant k_l1 = 1._r8 / (secspday * days_per_year * params_inst%tau_l1_bgc) - k_l2_l3 = 1._r8 / (secspday * days_per_year * params_inst%tau_l2_l3_bgc) + k_l2 = 1._r8 / (secspday * days_per_year * params_inst%tau_l2_bgc) k_s1 = 1._r8 / (secspday * days_per_year * params_inst%tau_s1_bgc) k_s2 = 1._r8 / (secspday * days_per_year * params_inst%tau_s2_bgc) k_s3 = 1._r8 / (secspday * days_per_year * params_inst%tau_s3_bgc) @@ -976,8 +705,6 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & k_frag = 1._r8 / (secspday * days_per_year * params_inst%tau_cwd_bgc) ! calc ref rate - catanf_30 = catanf(30._r8) - if ( spinup_state >= 1 ) then do fc = 1,num_soilc c = filter_soilc(fc) @@ -1049,14 +776,12 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & !--- time dependent coefficients-----! ! TODO slevis: Not immediately obvious how to reduce the if-else - ! repetition, bc t_scalar, w_scalar, o_scalar sum all j + ! repetition bc w_scalar, o_scalar sum all j ! to layer 1 in the if, while they do not in the else. ! Other changes that would be necessary: ! - set fr = 1 in the else, ! - use a new nlevd = nlev_soildecomp_standard in the if and ! nlevd = nlevdecomp in the else, - ! - keep if (j==1) t_scalar(c,:) = 0._r8 from the if? - ! - keep P. Thornton's comment from the else if ( nlevdecomp .eq. 1 ) then ! calculate function to weight the temperature and water potential scalars @@ -1084,38 +809,6 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & end do end do - if ( .not. use_century_tfunc ) then - ! calculate rate constant scalar for soil temperature - ! assuming that the base rate constants are assigned for non-moisture - ! limiting conditions at 25 C. - - do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) - if (j==1) t_scalar(c,:) = 0._r8 - if (t_soisno(c,j) >= SHR_CONST_TKFRZ) then - t_scalar(c,1)=t_scalar(c,1) + & - (Q10**((t_soisno(c,j)-(SHR_CONST_TKFRZ+25._r8))/10._r8))*fr(c,j) - else - t_scalar(c,1)=t_scalar(c,1) + & - (Q10**(-25._r8/10._r8))*(froz_q10**((t_soisno(c,j)-SHR_CONST_TKFRZ)/10._r8))*fr(c,j) - endif - end do - end do - - else - ! original century uses an arctangent function to calculate the temperature dependence of decomposition - do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) - if (j==1) t_scalar(c,:) = 0._r8 - - t_scalar(c,1)=t_scalar(c,1) +max(catanf(t_soisno(c,j)-SHR_CONST_TKFRZ)/catanf_30*fr(c,j),0.01_r8) - end do - end do - - endif - ! calculate the rate constant scalar for soil water content. ! Uses the log relationship with water potential given in ! Andren, O., and K. Paustian, 1987. Barley straw decomposition in the field: @@ -1161,38 +854,6 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & else - if ( .not. use_century_tfunc ) then - ! calculate rate constant scalar for soil temperature - ! assuming that the base rate constants are assigned for non-moisture - ! limiting conditions at 25 C. - ! Peter Thornton: 3/13/09 - ! Replaced the Lloyd and Taylor function with a Q10 formula, with Q10 = 1.5 - ! as part of the modifications made to improve the seasonal cycle of - ! atmospheric CO2 concentration in global simulations. This does not impact - ! the base rates at 25 C, which are calibrated from microcosm studies. - - do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - if (t_soisno(c,j) >= SHR_CONST_TKFRZ) then - t_scalar(c,j)= (Q10**((t_soisno(c,j)-(SHR_CONST_TKFRZ+25._r8))/10._r8)) - else - t_scalar(c,j)= (Q10**(-25._r8/10._r8))*(froz_q10**((t_soisno(c,j)-SHR_CONST_TKFRZ)/10._r8)) - endif - end do - end do - - else - - do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - t_scalar(c,j)= max(catanf(t_soisno(c,j)-SHR_CONST_TKFRZ)/catanf_30, 0.01_r8) - end do - end do - - endif - ! calculate the rate constant scalar for soil water content. ! Uses the log relationship with water potential given in ! Andren, O., and K. Paustian, 1987. Barley straw decomposition in the field: @@ -1235,18 +896,6 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & end if -! ! TODO slevis: Commented out. Should I have kept these lines? -! if ( normalize_q10_to_century_tfunc ) then -! ! scale all decomposition rates by a constant to compensate for offset between original CENTURY temp func and Q10 -! normalization_factor = (catanf(normalization_tref)/catanf_30) / (q10**((normalization_tref-25._r8)/10._r8)) -! do j = 1, nlevdecomp -! do fc = 1,num_soilc -! c = filter_soilc(fc) -! t_scalar(c,j) = t_scalar(c,j) * normalization_factor -! end do -! end do -! endif - ! Term that reduces decomposition rate at depth ! TODO slevis: Reduced code repetition by defining ! depth_scalar(c,j) = 1.0_r8 in the else instead of @@ -1268,28 +917,26 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & do j = 1,nlevdecomp do fc = 1,num_soilc c = filter_soilc(fc) - decomp_k(c,j,i_litr1) = k_l1 * t_scalar(c,j) * w_scalar(c,j) * & + decomp_k(c,j,i_litr1) = k_l1 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l1(c) - decomp_k(c,j,i_litr2) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * & - depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l23(c) - decomp_k(c,j,i_litr3) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * & - depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l23(c) + decomp_k(c,j,i_litr2) = k_l2 * w_scalar(c,j) * & + depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l2(c) - decomp_k(c,j,i_micr1) = k_m1 * t_scalar(c,j) * w_scalar(c,j) * & + decomp_k(c,j,i_micr1) = k_m1 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_m1(c) - decomp_k(c,j,i_micr2) = k_m2 * t_scalar(c,j) * w_scalar(c,j) * & + decomp_k(c,j,i_micr2) = k_m2 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_m2(c) - decomp_k(c,j,i_soil1) = k_s1 * t_scalar(c,j) * w_scalar(c,j) * & + decomp_k(c,j,i_soil1) = k_s1 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s1(c) - decomp_k(c,j,i_soil2) = k_s2 * t_scalar(c,j) * w_scalar(c,j) * & + decomp_k(c,j,i_soil2) = k_s2 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s2(c) - decomp_k(c,j,i_soil3) = k_s3 * t_scalar(c,j) * w_scalar(c,j) * & + decomp_k(c,j,i_soil3) = k_s3 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s3(c) ! Same for cwd but only if fates not enabled; fates handles cwd on ! its own structure if (.not. use_fates) then - decomp_k(c,j,i_cwd) = k_frag * t_scalar(c,j) * w_scalar(c,j) * & + decomp_k(c,j,i_cwd) = k_frag * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_cwd(c) end if end do From 5dd9ff241c9dbc20c5a934665b24aebc7459e6ae Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 3 Apr 2021 15:28:20 -0600 Subject: [PATCH 04/69] Updating SoilBiogeochemDecompCascadeMIMICSMod.F90 based on meeting Largely updating the comments. Partly also updating code. --- src/main/clm_varpar.F90 | 9 +- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 257 ++++++++---------- 2 files changed, 123 insertions(+), 143 deletions(-) diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index ac7441aa20..6990274e7a 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -228,25 +228,30 @@ subroutine clm_varpar_init(actual_maxsoil_patches, actual_numcft) write(iulog, *) end if + ! TODO BFB refactor: How to derive these instead of hardwiring? if ( use_fates ) then + ! TODO BFB refactor: Rm i_cwd from here and replace everywhere with my + ! corresponding MIMICS implementation i_cwd = 0 if (use_century_decomp) then ndecomp_pools = 6 ndecomp_cascade_transitions = 8 else if (use_mimics_decomp) then - ndecomp_pools = ? ! TODO slevis: derive inst. of hardwiring? + ndecomp_pools = ? ndecomp_cascade_transitions = ? else ndecomp_pools = 7 ndecomp_cascade_transitions = 7 end if else + ! TODO BFB refactor: Rm i_cwd from here and replace everywhere with my + ! corresponding MIMICS implementation i_cwd = 4 if (use_century_decomp) then ndecomp_pools = 7 ndecomp_cascade_transitions = 10 else if (use_mimics_decomp) then - ndecomp_pools = ? ! TODO slevis: derive inst. of hardwiring? + ndecomp_pools = ? ndecomp_cascade_transitions = ? else ndecomp_pools = 8 diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 608c7ed504..a79be83e6f 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -35,15 +35,15 @@ module SoilBiogeochemDecompCascadeMIMICSMod public :: DecompCascadeMIMICSreadNML ! Read in namelist public :: readParams ! Read in parameters from params file public :: init_decompcascade_mimics ! Initialization - public :: decomp_rate_constants_mimics ! Figure out decomposition rates + public :: decomp_rates_mimics ! Figure out decomposition rates ! ! !PUBLIC DATA MEMBERS ! ! !PRIVATE DATA MEMBERS - integer, private, parameter :: nsompools = 3 ! Number of SOM pools + integer, private, parameter :: npools = 8 ! Number of pools integer, private, parameter :: i_litr1 = i_met_lit ! First litter pool, metobolic - integer, private :: i_litr2 = -9 ! Second litter pool, lignin in MIMICS + integer, private :: i_litr2 = -9 ! Second litter pool, structural in MIMICS (cellulose + lignin) integer, private :: i_micr1 = -9 ! First microbial pool, copiotrophic, as labeled in Wieder et al. 2015 integer, private :: i_micr2 = -9 ! Second microbial pool, oligotrophic, as labeled in Wieder et al. 2015 integer, private :: i_cwd = -9 ! Coarse woody debris pool @@ -52,9 +52,6 @@ module SoilBiogeochemDecompCascadeMIMICSMod integer, private :: i_soil3 = -9 ! SOM third pool, available SOM (som_a in Wieder et al. 2015) type, private :: params_type - ! TODO slevis: soil/litter C:N is not defined in MIMICS. Microbial C:N is - ! a parameter that varies with litter quality (fmet). - ! TODO slevis: New rf params in MIMICS. Update params file accordingly. ! I haven't identified what these correspond to in testbed. real(r8):: rf_l1m1_mimics ! respiration fraction litter 1 -> microbe 1 @@ -66,20 +63,22 @@ module SoilBiogeochemDecompCascadeMIMICSMod real(r8):: rf_cwdl2_mimics - ! TODO slevis: Introduce Vmax and Km. Also tau params that define - ! microbial turnover to SOM are functions. - real(r8):: tau_m1_mimics ! 1/turnover time of microbial 1 (1/yr) - real(r8):: tau_m2_mimics ! 1/turnover time of microbial 2 (1/yr) real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) real(r8) :: cwd_flig_bgc ! - real(r8) :: k_frag_bgc !fragmentation rate for CWD real(r8) :: minpsi_bgc !minimum soil water potential for heterotrophic resp real(r8) :: maxpsi_bgc !maximum soil water potential for heterotrophic resp - real(r8) :: initial_Cstocks(nsompools) ! Initial Carbon stocks for a cold-start - real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start + ! TODO BFB refactor: We will first merge a refactor branch to CTSM main + ! TODO BFB refactor: Add these two to the params file and rm the + ! subroutines that read these params from the namelist + ! If Melannie's values from the testbed differ from the + ! values used for BGC, may need separate _mimics _bgc + ! params. BGC default values here were 200 and 0.3 + ! TODO keeping the depth param in case needed for spin-ups + real(r8) :: initial_Cstocks(npools) ! Initial Carbon stocks for a cold-start + real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start end type params_type ! @@ -92,72 +91,6 @@ module SoilBiogeochemDecompCascadeMIMICSMod contains - !----------------------------------------------------------------------- - subroutine DecompCascadeMIMCSreadNML( NLFilename ) - ! - ! !DESCRIPTION: - ! Read the namelist for soil MIMICS Decomposition Cascade - ! TODO slevis: Modify for MIMICS if necessary - ! - ! !USES: - use fileutils , only : getavu, relavu, opnfil - use shr_nl_mod , only : shr_nl_find_group_name - use spmdMod , only : masterproc, mpicom - use shr_mpi_mod , only : shr_mpi_bcast - use clm_varctl , only : iulog - use shr_log_mod , only : errMsg => shr_log_errMsg - use abortutils , only : endrun - ! - ! !ARGUMENTS: - character(len=*), intent(in) :: NLFilename ! Namelist filename - ! - ! !LOCAL VARIABLES: - integer :: ierr ! error code - integer :: unitn ! unit for namelist file - - character(len=*), parameter :: subname = 'DecompCascadeMIMICSreadNML' - character(len=*), parameter :: nmlname = 'CENTURY_soilBGCDecompCascade' - !----------------------------------------------------------------------- - real(r8) :: initial_Cstocks(nsompools), initial_Cstocks_depth - namelist /CENTURY_soilBGCDecompCascade/ initial_Cstocks, initial_Cstocks_depth - - ! Initialize options to default values, in case they are not specified in - ! the namelist - - initial_Cstocks(:) = 200._r8 - initial_Cstocks_depth = 0.3 - - if (masterproc) then - unitn = getavu() - write(iulog,*) 'Read in '//nmlname//' namelist' - call opnfil (NLFilename, unitn, 'F') - call shr_nl_find_group_name(unitn, nmlname, status=ierr) - if (ierr == 0) then - read(unitn, nml=CENTURY_soilBGCDecompCascade, iostat=ierr) - if (ierr /= 0) then - call endrun(msg="ERROR reading "//nmlname//"namelist"//errmsg(__FILE__, __LINE__)) - end if - else - call endrun(msg="ERROR could NOT find "//nmlname//"namelist"//errmsg(__FILE__, __LINE__)) - end if - call relavu( unitn ) - end if - - call shr_mpi_bcast (initial_Cstocks , mpicom) - call shr_mpi_bcast (initial_Cstocks_depth, mpicom) - - if (masterproc) then - write(iulog,*) ' ' - write(iulog,*) nmlname//' settings:' - write(iulog,nml=CENTURY_soilBGCDecompCascade) - write(iulog,*) ' ' - end if - - params_inst%initial_Cstocks(:) = initial_Cstocks(:) - params_inst%initial_Cstocks_depth = initial_Cstocks_depth - - end subroutine DecompCascadeMIMICSreadNML - !----------------------------------------------------------------------- subroutine readParams ( ncid ) ! @@ -178,7 +111,12 @@ subroutine readParams ( ncid ) !----------------------------------------------------------------------- ! Read off of netcdf file - ! TODO slevis: Add new params here and in the params file + ! TODO slevis: Add new params here and in the params file. + ! Read MIMICS-specific params here and shared params like this: + ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding + ! TODO BFB refactor: Remove k_frag everywhere and from params file + ! TODO BFB refactor: Rename tau_cwd and cwd_flig to *_bgc + ! TODO BFB refactor: *bgc are examples of shared params so chg accordingly tString='tau_cwd' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -219,11 +157,6 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_cwdl2_mimics=tempr - tString='k_frag' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%k_frag_bgc=tempr - tString='minpsi_hr' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -234,15 +167,16 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%maxpsi_bgc=tempr + ! TODO cwd_flig is used in cwd --> l2 so keeping for now tString='cwd_flig' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cwd_flig_bgc=tempr - + end subroutine readParams !----------------------------------------------------------------------- - subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate_inst ) + subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstate_inst ) ! ! !DESCRIPTION: ! initialize rate constants and decomposition pathways following the @@ -278,6 +212,8 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate integer :: i_l1m2 integer :: i_l2m2 integer :: i_s3m2 + integer :: i_s1s3 + integer :: i_s2s3 integer :: i_cwdl2 real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. @@ -330,9 +266,8 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate ! some of these are dependent on the soil texture properties ! TODO slevis: Template for calculated mimics params? - ! But soil texture remains const with time. - ! So one-time initializations here and time-dep params - ! in subr. decomp_rate_constants_mimics. + ! One-time initializations here and time-dep params + ! in subr. decomp_rates_mimics. do c = bounds%begc, bounds%endc do j = 1, nlevdecomp @@ -353,8 +288,8 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_litr1) = .true. is_soil(i_litr1) = .false. is_cwd(i_litr1) = .false. - initial_cn_ratio(i_litr1) = 90._r8 - initial_stock(i_litr1) = 0._r8 + initial_cn_ratio(i_litr1) = 10._r8 ! 90 in BGC; not used in MIMICS + initial_stock(i_litr1) = params_inst%initial_Cstocks(i_litr1) is_metabolic(i_litr1) = .true. is_cellulose(i_litr1) = .false. is_lignin(i_litr1) = .false. @@ -369,15 +304,12 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_litr2) = .true. is_soil(i_litr2) = .false. is_cwd(i_litr2) = .false. - initial_cn_ratio(i_litr2) = 90._r8 - initial_stock(i_litr2) = 0._r8 + initial_cn_ratio(i_litr2) = 10._r8 ! 90 in BGC; not used in MIMICS + initial_stock(i_litr2) = params_inst%initial_Cstocks(i_litr2) is_metabolic(i_litr2) = .false. - is_cellulose(i_litr2) = .true. ! TODO ?? + is_cellulose(i_litr2) = .true. is_lignin(i_litr2) = .true. - ! TODO slevis: clm_varpar hardwires i_cwd = 4 or = 0 if (use_fates) - ! I recommend replacing the hardwired value with one that we - ! update here on the fly. Same for i_soil1,2,3 & i_micr1,2. i_cwd = i_litr2 if (.not. use_fates) then ! CWD @@ -391,15 +323,15 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_cwd) = .false. is_soil(i_cwd) = .false. is_cwd(i_cwd) = .true. - initial_cn_ratio(i_cwd) = 90._r8 - initial_stock(i_cwd) = 0._r8 + initial_cn_ratio(i_cwd) = 10._r8 ! 90 in BGC; not used in MIMICS + initial_stock(i_cwd) = params_inst%initial_Cstocks(i_cwd) is_metabolic(i_cwd) = .false. is_cellulose(i_cwd) = .false. is_lignin(i_cwd) = .false. endif i_soil1 = i_cwd + 1 - floating_cn_ratio_decomp_pools(i_soil1) = .false. + floating_cn_ratio_decomp_pools(i_soil1) = .true. decomp_cascade_con%decomp_pool_name_restart(i_soil1) = 'soil1' decomp_cascade_con%decomp_pool_name_history(i_soil1) = 'SOIL1' decomp_cascade_con%decomp_pool_name_long(i_soil1) = 'soil 1' @@ -408,14 +340,14 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_soil1) = .false. is_soil(i_soil1) = .true. is_cwd(i_soil1) = .false. - initial_cn_ratio(i_soil1) = cn_s1 ! TODO ?? - initial_stock(i_soil1) = params_inst%initial_Cstocks(1) + initial_cn_ratio(i_soil1) = 10._r8 ! cn_s1 in BGC; not used in MIMICS + initial_stock(i_soil1) = params_inst%initial_Cstocks(i_soil1) is_metabolic(i_soil1) = .false. is_cellulose(i_soil1) = .false. is_lignin(i_soil1) = .false. i_soil2 = i_soil1 + 1 - floating_cn_ratio_decomp_pools(i_soil2) = .false. + floating_cn_ratio_decomp_pools(i_soil2) = .true. decomp_cascade_con%decomp_pool_name_restart(i_soil2) = 'soil2' decomp_cascade_con%decomp_pool_name_history(i_soil2) = 'SOIL2' decomp_cascade_con%decomp_pool_name_long(i_soil2) = 'soil 2' @@ -424,14 +356,14 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_soil2) = .false. is_soil(i_soil2) = .true. is_cwd(i_soil2) = .false. - initial_cn_ratio(i_soil2) = cn_s2 ! TODO ?? - initial_stock(i_soil2) = params_inst%initial_Cstocks(2) + initial_cn_ratio(i_soil2) = 10._r8 ! cn_s2 in BGC; not used in MIMICS + initial_stock(i_soil2) = params_inst%initial_Cstocks(i_soil2) is_metabolic(i_soil2) = .false. is_cellulose(i_soil2) = .false. is_lignin(i_soil2) = .false. i_soil3 = i_soil2 + 1 - floating_cn_ratio_decomp_pools(i_soil3) = .false. + floating_cn_ratio_decomp_pools(i_soil3) = .true. decomp_cascade_con%decomp_pool_name_restart(i_soil3) = 'soil3' decomp_cascade_con%decomp_pool_name_history(i_soil3) = 'SOIL3' decomp_cascade_con%decomp_pool_name_long(i_soil3) = 'soil 3' @@ -440,8 +372,8 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_soil3) = .false. is_soil(i_soil3) = .true. is_cwd(i_soil3) = .false. - initial_cn_ratio(i_soil3) = cn_s3 ! TODO ?? - initial_stock(i_soil3) = params_inst%initial_Cstocks(3) + initial_cn_ratio(i_soil3) = 10._r8 ! cn_s3 in BGC; not used in MIMICS + initial_stock(i_soil3) = params_inst%initial_Cstocks(i_soil3) is_metabolic(i_soil3) = .false. is_cellulose(i_soil3) = .false. is_lignin(i_soil3) = .false. @@ -456,8 +388,8 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_micr1) = .false. is_soil(i_micr1) = .false. is_cwd(i_micr1) = .false. - initial_cn_ratio(i_micr1) = 90._r8 - initial_stock(i_micr1) = 0._r8 + initial_cn_ratio(i_micr1) = 10._r8 ! MIMICS may use this + initial_stock(i_micr1) = params_inst%initial_Cstocks(i_micr1) is_metabolic(i_micr1) = .false. is_cellulose(i_micr1) = .false. is_lignin(i_micr1) = .false. @@ -472,28 +404,25 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate is_litter(i_micr2) = .false. is_soil(i_micr2) = .false. is_cwd(i_micr2) = .false. - initial_cn_ratio(i_micr2) = 90._r8 - initial_stock(i_micr2) = 0._r8 + initial_cn_ratio(i_micr2) = 10._r8 ! MIMICS may use this + initial_stock(i_micr2) = params_inst%initial_Cstocks(i_micr2) is_metabolic(i_micr2) = .false. is_cellulose(i_micr2) = .false. is_lignin(i_micr2) = .false. speedup_fac = 1._r8 - !lit1 + !lit1,2 spinup_factor(i_litr1) = 1._r8 - !lit2 spinup_factor(i_litr2) = 1._r8 !CWD if (.not. use_fates) then spinup_factor(i_cwd) = max(1._r8, (speedup_fac * params_inst%tau_cwd_bgc / 2._r8 )) end if - !som1 + !som1,2,3 spinup_factor(i_soil1) = 1._r8 - !som2,3 - ! TODO slevis: change these to 1? - spinup_factor(i_soil2) = max(1._r8, (speedup_fac * params_inst%tau_s2_bgc)) - spinup_factor(i_soil3) = max(1._r8, (speedup_fac * params_inst%tau_s3_bgc)) + spinup_factor(i_soil2) = 1._r8 ! BGC used same formula as for cwd but... + spinup_factor(i_soil3) = 1._r8 ! ...w the respective tau_s values ! micr1,2 spinup_factor(i_micr1) = 1._r8 spinup_factor(i_micr2) = 1._r8 @@ -546,8 +475,23 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate cascade_receiver_pool(i_s3m2) = i_micr2 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = 1.0_r8 + ! TODO Should I have kept code corresponding to the s1_s3 s2_s3 transfers? + i_s1s3 = 7 + decomp_cascade_con%cascade_step_name(i_s1s3) = 'S1S3' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3 + cascade_donor_pool(i_s1s3) = i_soil1 + cascade_receiver_pool(i_s1s3) = i_soil3 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = 1.0_r8 + + i_s2s3 = 8 + decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 + cascade_donor_pool(i_s2s3) = i_soil2 + cascade_receiver_pool(i_s2s3) = i_soil3 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = 1.0_r8 + if (.not. use_fates) then - i_cwdl2 = 7 + i_cwdl2 = 9 decomp_cascade_con%cascade_step_name(i_cwdl2) = 'CWDL2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 cascade_donor_pool(i_cwdl2) = i_cwd @@ -563,7 +507,7 @@ subroutine init_decompcascade_mimcs(bounds, soilbiogeochem_state_inst, soilstate end subroutine init_decompcascade_mimics !----------------------------------------------------------------------- - subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & + subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) ! ! !DESCRIPTION: @@ -587,16 +531,33 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & real(r8):: frw(bounds%begc:bounds%endc) ! rooting fraction weight real(r8), allocatable:: fr(:,:) ! column-level rooting fraction by soil depth real(r8):: psi ! temporary soilpsi for water scalar - real(r8):: k_l1 ! decomposition rate constant litter 1 (1/sec) - real(r8):: k_l2 ! decomposition rate constant litter 2 (1/sec) - real(r8):: k_s1 ! decomposition rate constant SOM 1 (1/sec) - real(r8):: k_s2 ! decomposition rate constant SOM 2 (1/sec) - real(r8):: k_s3 ! decomposition rate constant SOM 3 (1/sec) + real(r8):: k_l1_m1 ! decomposition rate constant litter 1 (1/sec) + real(r8):: k_l2_m1 ! decomposition rate constant litter 2 (1/sec) + real(r8):: k_s3_m1 ! decomposition rate constant SOM 3 (1/sec) + real(r8):: k_l1_m2 ! decomposition rate constant litter 1 (1/sec) + real(r8):: k_l2_m2 ! decomposition rate constant litter 2 (1/sec) + real(r8):: k_s3_m2 ! decomposition rate constant SOM 3 (1/sec) + real(r8):: k_s1_s3 ! decomposition rate constant SOM 1 (1/sec) + real(r8):: k_s2_s3 ! decomposition rate constant SOM 2 (1/sec) real(r8):: k_m1 ! decomposition rate constant microbial 1 (1/sec) real(r8):: k_m2 ! decomposition rate constant microbial 2 (1/sec) real(r8):: k_frag ! fragmentation rate constant CWD (1/sec) - real(r8):: cwdc_loss ! fragmentation rate for CWD carbon (gC/m2/s) - real(r8):: cwdn_loss ! fragmentation rate for CWD nitrogen (gN/m2/s) + real(r8):: vmax_l1_m1_mimics ! + real(r8):: vmax_l2_m1_mimics ! + real(r8):: vmax_s3_m1_mimics ! + real(r8):: vmax_l1_m2_mimics ! + real(r8):: vmax_l2_m2_mimics ! + real(r8):: vmax_s3_m2_mimics ! + real(r8):: tau_s1_s3_mimics ! + real(r8):: tau_s2_s3_mimics ! + real(r8):: tau_m1_mimics ! + real(r8):: tau_m2_mimics ! + real(r8):: km_l1_m1_mimics ! + real(r8):: km_l2_m1_mimics ! + real(r8):: km_s3_m1_mimics ! + real(r8):: km_l1_m2_mimics ! + real(r8):: km_l2_m2_mimics ! + real(r8):: km_s3_m2_mimics ! real(r8):: decomp_depth_efolding ! (meters) e-folding depth for reduction in decomposition [ integer :: c, fc, j, k, l real(r8):: days_per_year ! days per year @@ -695,14 +656,23 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & ! STILL MISSING N-related stuff: DIN... ! translate to per-second time constant - k_l1 = 1._r8 / (secspday * days_per_year * params_inst%tau_l1_bgc) - k_l2 = 1._r8 / (secspday * days_per_year * params_inst%tau_l2_bgc) - k_s1 = 1._r8 / (secspday * days_per_year * params_inst%tau_s1_bgc) - k_s2 = 1._r8 / (secspday * days_per_year * params_inst%tau_s2_bgc) - k_s3 = 1._r8 / (secspday * days_per_year * params_inst%tau_s3_bgc) - k_m1 = 1._r8 / (secspday * days_per_year * params_inst%tau_m1_mimics) - k_m2 = 1._r8 / (secspday * days_per_year * params_inst%tau_m2_mimics) - k_frag = 1._r8 / (secspday * days_per_year * params_inst%tau_cwd_bgc) + ! TODO Vmax terms replace k_* terms (easy) but Km terms and biomass pools + ! need to come in and be used where currently only the decomp_k + ! terms are in use. Refactor the hooks to make them general so that + ! they can work for both BGC and MIMICS? OR make separate sections + ! of code for use_century_decomp vs use_mimics_decomp. + ! TODO Should I have kept code corresponding to the s1_s3 s2_s3 transfers? + k_l1_m1 = 1._r8 / (secspday * days_per_year * vmax_l1_m1_mimics) + k_l2_m1 = 1._r8 / (secspday * days_per_year * vmax_l2_m1_mimics) + k_s3_m1 = 1._r8 / (secspday * days_per_year * vmax_s3_m1_mimics) + k_l1_m2 = 1._r8 / (secspday * days_per_year * vmax_l1_m2_mimics) + k_l2_m2 = 1._r8 / (secspday * days_per_year * vmax_l2_m2_mimics) + k_s3_m2 = 1._r8 / (secspday * days_per_year * vmax_s3_m2_mimics) + k_s1_s3 = 1._r8 / (secspday * days_per_year * tau_s1_s3_mimics) + k_s2_s3 = 1._r8 / (secspday * days_per_year * tau_s2_s3_mimics) + k_m1 = 1._r8 / (secspday * days_per_year * tau_m1_mimics) + k_m2 = 1._r8 / (secspday * days_per_year * tau_m2_mimics) + k_frag = 1._r8 / (secspday * days_per_year * tau_cwd_bgc) ! calc ref rate if ( spinup_state >= 1 ) then @@ -897,9 +867,9 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & end if ! Term that reduces decomposition rate at depth - ! TODO slevis: Reduced code repetition by defining - ! depth_scalar(c,j) = 1.0_r8 in the else instead of - ! repeating the decomp_k lines. + ! TODO BFB refactor: Reduced code repetition by defining + ! depth_scalar(c,j) = 1.0_r8 in the else instead of repeating the + ! decomp_k lines. Do this in BGC, too. do j = 1, nlevdecomp do fc = 1, num_soilc c = filter_soilc(fc) @@ -914,6 +884,11 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & end do ! calculate rate constants for all litter and som pools + ! TODO I will start updating this section when I feel confident in my list + ! of k_ factors. For example + ! - Should decomp_k be dimensioned (c,j,i_l1m1) instead? + ! - Should there be two sets of decomp_k, the first corresponding to + ! vmax and the second to km? do j = 1,nlevdecomp do fc = 1,num_soilc c = filter_soilc(fc) @@ -944,6 +919,6 @@ subroutine decomp_rate_constants_mimics(bounds, num_soilc, filter_soilc, & end associate - end subroutine decomp_rate_constants_mimics + end subroutine decomp_rates_mimics end module SoilBiogeochemDecompCascadeMIMICSMod From 8601f6e1f996f370efba5d3d5618ffc4e634b64c Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 12 Apr 2021 18:03:45 -0600 Subject: [PATCH 05/69] Mainly changed "rate constants" to "rates" in the comments --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index a79be83e6f..e3684da7f9 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -511,7 +511,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) ! ! !DESCRIPTION: - ! Calculate rate constants and decomposition pathways for the MIMICS + ! Calculate rates and decomposition pathways for the MIMICS ! decomposition cascade model ! ! !USES: @@ -531,16 +531,16 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & real(r8):: frw(bounds%begc:bounds%endc) ! rooting fraction weight real(r8), allocatable:: fr(:,:) ! column-level rooting fraction by soil depth real(r8):: psi ! temporary soilpsi for water scalar - real(r8):: k_l1_m1 ! decomposition rate constant litter 1 (1/sec) - real(r8):: k_l2_m1 ! decomposition rate constant litter 2 (1/sec) - real(r8):: k_s3_m1 ! decomposition rate constant SOM 3 (1/sec) - real(r8):: k_l1_m2 ! decomposition rate constant litter 1 (1/sec) - real(r8):: k_l2_m2 ! decomposition rate constant litter 2 (1/sec) - real(r8):: k_s3_m2 ! decomposition rate constant SOM 3 (1/sec) - real(r8):: k_s1_s3 ! decomposition rate constant SOM 1 (1/sec) - real(r8):: k_s2_s3 ! decomposition rate constant SOM 2 (1/sec) - real(r8):: k_m1 ! decomposition rate constant microbial 1 (1/sec) - real(r8):: k_m2 ! decomposition rate constant microbial 2 (1/sec) + real(r8):: k_l1_m1 ! decomposition rate litter 1 (1/sec) + real(r8):: k_l2_m1 ! decomposition rate litter 2 (1/sec) + real(r8):: k_s3_m1 ! decomposition rate SOM 3 (1/sec) + real(r8):: k_l1_m2 ! decomposition rate litter 1 (1/sec) + real(r8):: k_l2_m2 ! decomposition rate litter 2 (1/sec) + real(r8):: k_s3_m2 ! decomposition rate SOM 3 (1/sec) + real(r8):: k_s1_s3 ! decomposition rate SOM 1 (1/sec) + real(r8):: k_s2_s3 ! decomposition rate SOM 2 (1/sec) + real(r8):: k_m1 ! decomposition rate microbe 1 (1/sec) + real(r8):: k_m2 ! decomposition rate microbe 2 (1/sec) real(r8):: k_frag ! fragmentation rate constant CWD (1/sec) real(r8):: vmax_l1_m1_mimics ! real(r8):: vmax_l2_m1_mimics ! @@ -587,7 +587,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia - decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) + decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate for decomposition (1./sec) spinup_factor => decomp_cascade_con%spinup_factor & ! Input: [real(r8) (:) ] factor for AD spinup associated with each pool ) @@ -799,6 +799,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do + ! TODO Discuss @wwieder's concerns about breaking the methane code if (use_lch4) then ! Calculate ANOXIA if (anoxia) then @@ -883,7 +884,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do - ! calculate rate constants for all litter and som pools + ! calculate rates for all litter and som pools ! TODO I will start updating this section when I feel confident in my list ! of k_ factors. For example ! - Should decomp_k be dimensioned (c,j,i_l1m1) instead? From 5995cc011e2ca20e6de720ff97eee5635fc631fd Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 13 Apr 2021 18:20:34 -0600 Subject: [PATCH 06/69] Add new and remove old TODO BFB refactor comments --- src/biogeochem/CNCStateUpdate1Mod.F90 | 8 ++++++++ src/main/clm_varpar.F90 | 5 ----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/biogeochem/CNCStateUpdate1Mod.F90 b/src/biogeochem/CNCStateUpdate1Mod.F90 index c5a717f2bc..557a6e2c01 100644 --- a/src/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/biogeochem/CNCStateUpdate1Mod.F90 @@ -69,6 +69,14 @@ subroutine CStateUpdateDynPatch(bounds, num_soilc_with_inactive, filter_soilc_wi do j = 1,nlevdecomp do fc = 1, num_soilc_with_inactive c = filter_soilc_with_inactive(fc) + ! TODO BFB refactor: In loops like this, we will run into trouble + ! with MIMICS bc we will have 2 instead of 3 litter pools. Can + ! address with if statements (NOT ideal) or + ! turn these repetitive lines into a loop BUT to do that + ! we need to turn dwt_frootc_to_litr_* into a 3d var. + ! There are 3 such loops here, 2 in CNCStateUpdate2, and one + ! in CNCStateUpdate1 and the pattern repeats in the + ! corresponding N modules. cs_soil%decomp_cpools_vr_col(c,j,i_met_lit) = cs_soil%decomp_cpools_vr_col(c,j,i_met_lit) + & cf_veg%dwt_frootc_to_litr_met_c_col(c,j) * dt cs_soil%decomp_cpools_vr_col(c,j,i_cel_lit) = cs_soil%decomp_cpools_vr_col(c,j,i_cel_lit) + & diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index 6990274e7a..261c86d2f8 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -228,10 +228,7 @@ subroutine clm_varpar_init(actual_maxsoil_patches, actual_numcft) write(iulog, *) end if - ! TODO BFB refactor: How to derive these instead of hardwiring? if ( use_fates ) then - ! TODO BFB refactor: Rm i_cwd from here and replace everywhere with my - ! corresponding MIMICS implementation i_cwd = 0 if (use_century_decomp) then ndecomp_pools = 6 @@ -244,8 +241,6 @@ subroutine clm_varpar_init(actual_maxsoil_patches, actual_numcft) ndecomp_cascade_transitions = 7 end if else - ! TODO BFB refactor: Rm i_cwd from here and replace everywhere with my - ! corresponding MIMICS implementation i_cwd = 4 if (use_century_decomp) then ndecomp_pools = 7 From e6833ea449946d7d4a0f811a524a5046a4e2723b Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 13 Apr 2021 19:48:10 -0600 Subject: [PATCH 07/69] Remove old TODO BFB refactor comment --- src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index e3684da7f9..e71f777ce3 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -868,9 +868,6 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end if ! Term that reduces decomposition rate at depth - ! TODO BFB refactor: Reduced code repetition by defining - ! depth_scalar(c,j) = 1.0_r8 in the else instead of repeating the - ! decomp_k lines. Do this in BGC, too. do j = 1, nlevdecomp do fc = 1, num_soilc c = filter_soilc(fc) From 446b58772d00ae17169afb4b27ec136595e7f5a0 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sun, 18 Apr 2021 16:54:27 -0600 Subject: [PATCH 08/69] Minor mods to ...DecompCascadeMIMICSMod based on refactor branch --- src/biogeochem/CNCStateUpdate1Mod.F90 | 8 -- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 95 +++++++++---------- 2 files changed, 45 insertions(+), 58 deletions(-) diff --git a/src/biogeochem/CNCStateUpdate1Mod.F90 b/src/biogeochem/CNCStateUpdate1Mod.F90 index 557a6e2c01..c5a717f2bc 100644 --- a/src/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/biogeochem/CNCStateUpdate1Mod.F90 @@ -69,14 +69,6 @@ subroutine CStateUpdateDynPatch(bounds, num_soilc_with_inactive, filter_soilc_wi do j = 1,nlevdecomp do fc = 1, num_soilc_with_inactive c = filter_soilc_with_inactive(fc) - ! TODO BFB refactor: In loops like this, we will run into trouble - ! with MIMICS bc we will have 2 instead of 3 litter pools. Can - ! address with if statements (NOT ideal) or - ! turn these repetitive lines into a loop BUT to do that - ! we need to turn dwt_frootc_to_litr_* into a 3d var. - ! There are 3 such loops here, 2 in CNCStateUpdate2, and one - ! in CNCStateUpdate1 and the pattern repeats in the - ! corresponding N modules. cs_soil%decomp_cpools_vr_col(c,j,i_met_lit) = cs_soil%decomp_cpools_vr_col(c,j,i_met_lit) + & cf_veg%dwt_frootc_to_litr_met_c_col(c,j) * dt cs_soil%decomp_cpools_vr_col(c,j,i_cel_lit) = cs_soil%decomp_cpools_vr_col(c,j,i_cel_lit) + & diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index e71f777ce3..a419de9831 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -9,8 +9,8 @@ module SoilBiogeochemDecompCascadeMIMICSMod use shr_kind_mod , only : r8 => shr_kind_r8 use shr_const_mod , only : SHR_CONST_TKFRZ use shr_log_mod , only : errMsg => shr_log_errMsg - use clm_varpar , only : nlevdecomp - use clm_varpar , only : i_met_lit + use clm_varpar , only : nlevdecomp, ndecomp_pools_max + use clm_varpar , only : i_met_lit, i_litr2, i_litr3, i_cwd use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_vertsoilc, use_fates use clm_varcon , only : zsoi use decompMod , only : bounds_type @@ -32,7 +32,6 @@ module SoilBiogeochemDecompCascadeMIMICSMod private ! ! !PUBLIC MEMBER FUNCTIONS: - public :: DecompCascadeMIMICSreadNML ! Read in namelist public :: readParams ! Read in parameters from params file public :: init_decompcascade_mimics ! Initialization public :: decomp_rates_mimics ! Figure out decomposition rates @@ -41,17 +40,15 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! ! !PRIVATE DATA MEMBERS - integer, private, parameter :: npools = 8 ! Number of pools - integer, private, parameter :: i_litr1 = i_met_lit ! First litter pool, metobolic - integer, private :: i_litr2 = -9 ! Second litter pool, structural in MIMICS (cellulose + lignin) integer, private :: i_micr1 = -9 ! First microbial pool, copiotrophic, as labeled in Wieder et al. 2015 integer, private :: i_micr2 = -9 ! Second microbial pool, oligotrophic, as labeled in Wieder et al. 2015 - integer, private :: i_cwd = -9 ! Coarse woody debris pool integer, private :: i_soil1 = -9 ! Soil Organic Matter (SOM) first pool, protected SOM (som_p in Wieder et al. 2015) integer, private :: i_soil2 = -9 ! SOM second pool, recalcitrant SOM (som_c in Wieder et al. 2015) integer, private :: i_soil3 = -9 ! SOM third pool, available SOM (som_a in Wieder et al. 2015) + integer, private, parameter :: i_litr1 = i_met_lit ! First litter pool, metobolic type, private :: params_type + ! TODO BFB refactor: First merge the refactor branch to CTSM main ! TODO slevis: New rf params in MIMICS. Update params file accordingly. ! I haven't identified what these correspond to in testbed. real(r8):: rf_l1m1_mimics ! respiration fraction litter 1 -> microbe 1 @@ -65,19 +62,15 @@ module SoilBiogeochemDecompCascadeMIMICSMod real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) - real(r8) :: cwd_flig_bgc ! + real(r8) :: cwd_flig real(r8) :: minpsi_bgc !minimum soil water potential for heterotrophic resp real(r8) :: maxpsi_bgc !maximum soil water potential for heterotrophic resp - ! TODO BFB refactor: We will first merge a refactor branch to CTSM main - ! TODO BFB refactor: Add these two to the params file and rm the - ! subroutines that read these params from the namelist - ! If Melannie's values from the testbed differ from the - ! values used for BGC, may need separate _mimics _bgc - ! params. BGC default values here were 200 and 0.3 - ! TODO keeping the depth param in case needed for spin-ups - real(r8) :: initial_Cstocks(npools) ! Initial Carbon stocks for a cold-start + ! TODO slevis: If Melannie's values from the testbed differ from the + ! values used for BGC, make separate _mimics params. + ! Keeping the _depth param in case needed for spin-ups. + real(r8), allocatable :: initial_Cstocks(:) ! Initial Carbon stocks for a cold-start real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start end type params_type @@ -114,10 +107,8 @@ subroutine readParams ( ncid ) ! TODO slevis: Add new params here and in the params file. ! Read MIMICS-specific params here and shared params like this: ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding - ! TODO BFB refactor: Remove k_frag everywhere and from params file - ! TODO BFB refactor: Rename tau_cwd and cwd_flig to *_bgc - ! TODO BFB refactor: *bgc are examples of shared params so chg accordingly - tString='tau_cwd' + ! TODO BFB refactor: *_bgc are shared params so chg them accordingly + tString='tau_cwd_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_cwd_bgc=tempr @@ -171,7 +162,17 @@ subroutine readParams ( ncid ) tString='cwd_flig' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cwd_flig_bgc=tempr + params_inst%cwd_flig=tempr + + allocate(params_inst%initial_Cstocks(ndecomp_pools_max)) + tString='initial_Cstocks_bgc' + call ncd_io(trim(tString), params_inst%initial_Cstocks(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + tString='initial_Cstocks_depth_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%initial_Cstocks_depth=tempr end subroutine readParams @@ -259,7 +260,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_cwdl2 = params_inst%rf_cwdl2_mimics ! set the lignin fractions for coarse woody debris - cwd_flig = params_inst%cwd_flig_bgc + cwd_flig = params_inst%cwd_flig ! set path fractions f_s2s3 = 0.03_r8/(0.45_r8) @@ -310,27 +311,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cellulose(i_litr2) = .true. is_lignin(i_litr2) = .true. - i_cwd = i_litr2 - if (.not. use_fates) then - ! CWD - i_cwd = i_litr2 + 1 - floating_cn_ratio_decomp_pools(i_cwd) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_cwd) = 'cwd' - decomp_cascade_con%decomp_pool_name_history(i_cwd) = 'CWD' - decomp_cascade_con%decomp_pool_name_long(i_cwd) = 'coarse woody debris' - decomp_cascade_con%decomp_pool_name_short(i_cwd) = 'CWD' - is_microbe(i_cwd) = .false. - is_litter(i_cwd) = .false. - is_soil(i_cwd) = .false. - is_cwd(i_cwd) = .true. - initial_cn_ratio(i_cwd) = 10._r8 ! 90 in BGC; not used in MIMICS - initial_stock(i_cwd) = params_inst%initial_Cstocks(i_cwd) - is_metabolic(i_cwd) = .false. - is_cellulose(i_cwd) = .false. - is_lignin(i_cwd) = .false. - endif - - i_soil1 = i_cwd + 1 + i_soil1 = i_litr2 + 1 floating_cn_ratio_decomp_pools(i_soil1) = .true. decomp_cascade_con%decomp_pool_name_restart(i_soil1) = 'soil1' decomp_cascade_con%decomp_pool_name_history(i_soil1) = 'SOIL1' @@ -410,6 +391,26 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cellulose(i_micr2) = .false. is_lignin(i_micr2) = .false. + i_cwd = i_micr2 + if (.not. use_fates) then + ! CWD + i_cwd = i_micr2 + 1 + floating_cn_ratio_decomp_pools(i_cwd) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_cwd) = 'cwd' + decomp_cascade_con%decomp_pool_name_history(i_cwd) = 'CWD' + decomp_cascade_con%decomp_pool_name_long(i_cwd) = 'coarse woody debris' + decomp_cascade_con%decomp_pool_name_short(i_cwd) = 'CWD' + is_microbe(i_cwd) = .false. + is_litter(i_cwd) = .false. + is_soil(i_cwd) = .false. + is_cwd(i_cwd) = .true. + initial_cn_ratio(i_cwd) = 10._r8 ! 90 in BGC; not used in MIMICS + initial_stock(i_cwd) = params_inst%initial_Cstocks(i_cwd) + is_metabolic(i_cwd) = .false. + is_cellulose(i_cwd) = .false. + is_lignin(i_cwd) = .false. + endif + speedup_fac = 1._r8 !lit1,2 @@ -501,6 +502,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat deallocate(rf_s1s3) deallocate(f_s1s3) + deallocate(params_inst%initial_Cstocks) end associate @@ -745,13 +747,6 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & endif !--- time dependent coefficients-----! - ! TODO slevis: Not immediately obvious how to reduce the if-else - ! repetition bc w_scalar, o_scalar sum all j - ! to layer 1 in the if, while they do not in the else. - ! Other changes that would be necessary: - ! - set fr = 1 in the else, - ! - use a new nlevd = nlev_soildecomp_standard in the if and - ! nlevd = nlevdecomp in the else, if ( nlevdecomp .eq. 1 ) then ! calculate function to weight the temperature and water potential scalars From 2f67c21c4e9ff37bee7682b5f45ff628fbb6f626 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 5 Jun 2021 14:40:57 -0600 Subject: [PATCH 09/69] Making ...CascadeMIMICSMod.F90 consistent w pre-MIMICS refactor --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 358 +++++++++--------- 1 file changed, 184 insertions(+), 174 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index a419de9831..22385de7b5 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -10,7 +10,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod use shr_const_mod , only : SHR_CONST_TKFRZ use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : nlevdecomp, ndecomp_pools_max - use clm_varpar , only : i_met_lit, i_litr2, i_litr3, i_cwd + use clm_varpar , only : i_litr_min, i_litr_max, i_met_lit, i_cwd use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_vertsoilc, use_fates use clm_varcon , only : zsoi use decompMod , only : bounds_type @@ -39,16 +39,14 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! !PUBLIC DATA MEMBERS ! ! !PRIVATE DATA MEMBERS - - integer, private :: i_micr1 = -9 ! First microbial pool, copiotrophic, as labeled in Wieder et al. 2015 - integer, private :: i_micr2 = -9 ! Second microbial pool, oligotrophic, as labeled in Wieder et al. 2015 - integer, private :: i_soil1 = -9 ! Soil Organic Matter (SOM) first pool, protected SOM (som_p in Wieder et al. 2015) - integer, private :: i_soil2 = -9 ! SOM second pool, recalcitrant SOM (som_c in Wieder et al. 2015) - integer, private :: i_soil3 = -9 ! SOM third pool, available SOM (som_a in Wieder et al. 2015) - integer, private, parameter :: i_litr1 = i_met_lit ! First litter pool, metobolic + integer, private :: i_pro_som ! index of protected Soil Organic Matter (SOM) + integer, private :: i_rec_som ! index of recalcitrant SOM + integer, private :: i_avl_som ! index of available SOM + integer, private :: i_str_lit ! index of structural litter pool + integer, private :: i_cop_mic ! index of copiotrophic microbial pool + integer, private :: i_oli_mic ! index of oligotrophic microbial pool type, private :: params_type - ! TODO BFB refactor: First merge the refactor branch to CTSM main ! TODO slevis: New rf params in MIMICS. Update params file accordingly. ! I haven't identified what these correspond to in testbed. real(r8):: rf_l1m1_mimics ! respiration fraction litter 1 -> microbe 1 @@ -71,7 +69,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! values used for BGC, make separate _mimics params. ! Keeping the _depth param in case needed for spin-ups. real(r8), allocatable :: initial_Cstocks(:) ! Initial Carbon stocks for a cold-start - real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start + real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start end type params_type ! @@ -105,9 +103,8 @@ subroutine readParams ( ncid ) ! Read off of netcdf file ! TODO slevis: Add new params here and in the params file. - ! Read MIMICS-specific params here and shared params like this: + ! Read MIMICS-specific params here & shared ones (eg *_bgc) like this: ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding - ! TODO BFB refactor: *_bgc are shared params so chg them accordingly tString='tau_cwd_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -259,7 +256,8 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_cwdl2 = params_inst%rf_cwdl2_mimics - ! set the lignin fractions for coarse woody debris + ! set the structural fractions for coarse woody debris + ! TODO slevis: If will use, rename to cwd_fstr? Or remove? cwd_flig = params_inst%cwd_flig ! set path fractions @@ -280,121 +278,132 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat initial_stock_soildepth = params_inst%initial_Cstocks_depth !------------------- list of pools and their attributes ------------ - floating_cn_ratio_decomp_pools(i_litr1) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_litr1) = 'litr1' - decomp_cascade_con%decomp_pool_name_history(i_litr1) = 'LITR1' - decomp_cascade_con%decomp_pool_name_long(i_litr1) = 'litter 1' - decomp_cascade_con%decomp_pool_name_short(i_litr1) = 'L1' - is_microbe(i_litr1) = .false. - is_litter(i_litr1) = .true. - is_soil(i_litr1) = .false. - is_cwd(i_litr1) = .false. - initial_cn_ratio(i_litr1) = 10._r8 ! 90 in BGC; not used in MIMICS - initial_stock(i_litr1) = params_inst%initial_Cstocks(i_litr1) - is_metabolic(i_litr1) = .true. - is_cellulose(i_litr1) = .false. - is_lignin(i_litr1) = .false. - - i_litr2 = i_litr1 + 1 - floating_cn_ratio_decomp_pools(i_litr2) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_litr2) = 'litr2' - decomp_cascade_con%decomp_pool_name_history(i_litr2) = 'LITR2' - decomp_cascade_con%decomp_pool_name_long(i_litr2) = 'litter 2' - decomp_cascade_con%decomp_pool_name_short(i_litr2) = 'L2' - is_microbe(i_litr2) = .false. - is_litter(i_litr2) = .true. - is_soil(i_litr2) = .false. - is_cwd(i_litr2) = .false. - initial_cn_ratio(i_litr2) = 10._r8 ! 90 in BGC; not used in MIMICS - initial_stock(i_litr2) = params_inst%initial_Cstocks(i_litr2) - is_metabolic(i_litr2) = .false. - is_cellulose(i_litr2) = .true. - is_lignin(i_litr2) = .true. - - i_soil1 = i_litr2 + 1 - floating_cn_ratio_decomp_pools(i_soil1) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_soil1) = 'soil1' - decomp_cascade_con%decomp_pool_name_history(i_soil1) = 'SOIL1' - decomp_cascade_con%decomp_pool_name_long(i_soil1) = 'soil 1' - decomp_cascade_con%decomp_pool_name_short(i_soil1) = 'S1' - is_microbe(i_soil1) = .false. - is_litter(i_soil1) = .false. - is_soil(i_soil1) = .true. - is_cwd(i_soil1) = .false. - initial_cn_ratio(i_soil1) = 10._r8 ! cn_s1 in BGC; not used in MIMICS - initial_stock(i_soil1) = params_inst%initial_Cstocks(i_soil1) - is_metabolic(i_soil1) = .false. - is_cellulose(i_soil1) = .false. - is_lignin(i_soil1) = .false. - - i_soil2 = i_soil1 + 1 - floating_cn_ratio_decomp_pools(i_soil2) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_soil2) = 'soil2' - decomp_cascade_con%decomp_pool_name_history(i_soil2) = 'SOIL2' - decomp_cascade_con%decomp_pool_name_long(i_soil2) = 'soil 2' - decomp_cascade_con%decomp_pool_name_short(i_soil2) = 'S2' - is_microbe(i_soil2) = .false. - is_litter(i_soil2) = .false. - is_soil(i_soil2) = .true. - is_cwd(i_soil2) = .false. - initial_cn_ratio(i_soil2) = 10._r8 ! cn_s2 in BGC; not used in MIMICS - initial_stock(i_soil2) = params_inst%initial_Cstocks(i_soil2) - is_metabolic(i_soil2) = .false. - is_cellulose(i_soil2) = .false. - is_lignin(i_soil2) = .false. - - i_soil3 = i_soil2 + 1 - floating_cn_ratio_decomp_pools(i_soil3) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_soil3) = 'soil3' - decomp_cascade_con%decomp_pool_name_history(i_soil3) = 'SOIL3' - decomp_cascade_con%decomp_pool_name_long(i_soil3) = 'soil 3' - decomp_cascade_con%decomp_pool_name_short(i_soil3) = 'S3' - is_microbe(i_soil3) = .false. - is_litter(i_soil3) = .false. - is_soil(i_soil3) = .true. - is_cwd(i_soil3) = .false. - initial_cn_ratio(i_soil3) = 10._r8 ! cn_s3 in BGC; not used in MIMICS - initial_stock(i_soil3) = params_inst%initial_Cstocks(i_soil3) - is_metabolic(i_soil3) = .false. - is_cellulose(i_soil3) = .false. - is_lignin(i_soil3) = .false. - - i_micr1 = i_soil3 + 1 - floating_cn_ratio_decomp_pools(i_micr1) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_micr1) = 'micr1' - decomp_cascade_con%decomp_pool_name_history(i_micr1) = 'MICR1' - decomp_cascade_con%decomp_pool_name_long(i_micr1) = 'microbial 1' - decomp_cascade_con%decomp_pool_name_short(i_micr1) = 'M1' - is_microbe(i_micr1) = .true. - is_litter(i_micr1) = .false. - is_soil(i_micr1) = .false. - is_cwd(i_micr1) = .false. - initial_cn_ratio(i_micr1) = 10._r8 ! MIMICS may use this - initial_stock(i_micr1) = params_inst%initial_Cstocks(i_micr1) - is_metabolic(i_micr1) = .false. - is_cellulose(i_micr1) = .false. - is_lignin(i_micr1) = .false. - - i_micr2 = i_micr1 + 1 - floating_cn_ratio_decomp_pools(i_micr2) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_micr2) = 'micr2' - decomp_cascade_con%decomp_pool_name_history(i_micr2) = 'MICR2' - decomp_cascade_con%decomp_pool_name_long(i_micr2) = 'microbial 2' - decomp_cascade_con%decomp_pool_name_short(i_micr2) = 'M2' - is_microbe(i_micr2) = .true. - is_litter(i_micr2) = .false. - is_soil(i_micr2) = .false. - is_cwd(i_micr2) = .false. - initial_cn_ratio(i_micr2) = 10._r8 ! MIMICS may use this - initial_stock(i_micr2) = params_inst%initial_Cstocks(i_micr2) - is_metabolic(i_micr2) = .false. - is_cellulose(i_micr2) = .false. - is_lignin(i_micr2) = .false. - - i_cwd = i_micr2 + i_litr_min = 1 + i_met_lit = i_litr_min + floating_cn_ratio_decomp_pools(i_met_lit) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_met_lit) = 'litr1' + decomp_cascade_con%decomp_pool_name_history(i_met_lit) = 'LITR1' + decomp_cascade_con%decomp_pool_name_long(i_met_lit) = 'litter 1' + decomp_cascade_con%decomp_pool_name_short(i_met_lit) = 'L1' + is_microbe(i_met_lit) = .false. + is_litter(i_met_lit) = .true. + is_soil(i_met_lit) = .false. + is_cwd(i_met_lit) = .false. + initial_cn_ratio(i_met_lit) = 10._r8 ! 90 in BGC; not used in MIMICS + initial_stock(i_met_lit) = params_inst%initial_Cstocks(i_met_lit) + is_metabolic(i_met_lit) = .true. + is_cellulose(i_met_lit) = .false. + is_lignin(i_met_lit) = .false. + + i_str_lit = i_met_lit + 1 + floating_cn_ratio_decomp_pools(i_str_lit) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_str_lit) = 'litr2' + decomp_cascade_con%decomp_pool_name_history(i_str_lit) = 'LITR2' + decomp_cascade_con%decomp_pool_name_long(i_str_lit) = 'litter 2' + decomp_cascade_con%decomp_pool_name_short(i_str_lit) = 'L2' + is_microbe(i_str_lit) = .false. + is_litter(i_str_lit) = .true. + is_soil(i_str_lit) = .false. + is_cwd(i_str_lit) = .false. + initial_cn_ratio(i_str_lit) = 10._r8 ! 90 in BGC; not used in MIMICS + initial_stock(i_str_lit) = params_inst%initial_Cstocks(i_str_lit) + is_metabolic(i_str_lit) = .false. + is_cellulose(i_str_lit) = .true. + is_lignin(i_str_lit) = .true. + + i_litr_max = i_str_lit + if (i_litr_min /= 1 .or. i_litr_max < 2 .or. i_litr_max > 3) then + write(iulog,*) 'Expecting i_litr_min = 1 and i_litr_max = 2 or 3.' + write(iulog,*) 'See pftconMod, SoilBiogeochemCarbonFluxType, and' + write(iulog,*) 'clmfates_interfaceMod for ramifications of changing' + write(iulog,*) 'this assumption.' + call endrun(msg='ERROR: i_litr_min and/or i_litr_max out of range '// & + errMsg(sourcefile, __LINE__)) + end if + + i_pro_som = i_str_lit + 1 + floating_cn_ratio_decomp_pools(i_pro_som) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_pro_som) = 'soil1' + decomp_cascade_con%decomp_pool_name_history(i_pro_som) = 'SOIL1' + decomp_cascade_con%decomp_pool_name_long(i_pro_som) = 'soil 1' + decomp_cascade_con%decomp_pool_name_short(i_pro_som) = 'S1' + is_microbe(i_pro_som) = .false. + is_litter(i_pro_som) = .false. + is_soil(i_pro_som) = .true. + is_cwd(i_pro_som) = .false. + initial_cn_ratio(i_pro_som) = 10._r8 ! cn_s1 in BGC; not used in MIMICS + initial_stock(i_pro_som) = params_inst%initial_Cstocks(i_pro_som) + is_metabolic(i_pro_som) = .false. + is_cellulose(i_pro_som) = .false. + is_lignin(i_pro_som) = .false. + + i_rec_som = i_pro_som + 1 + floating_cn_ratio_decomp_pools(i_rec_som) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_rec_som) = 'soil2' + decomp_cascade_con%decomp_pool_name_history(i_rec_som) = 'SOIL2' + decomp_cascade_con%decomp_pool_name_long(i_rec_som) = 'soil 2' + decomp_cascade_con%decomp_pool_name_short(i_rec_som) = 'S2' + is_microbe(i_rec_som) = .false. + is_litter(i_rec_som) = .false. + is_soil(i_rec_som) = .true. + is_cwd(i_rec_som) = .false. + initial_cn_ratio(i_rec_som) = 10._r8 ! cn_s2 in BGC; not used in MIMICS + initial_stock(i_rec_som) = params_inst%initial_Cstocks(i_rec_som) + is_metabolic(i_rec_som) = .false. + is_cellulose(i_rec_som) = .false. + is_lignin(i_rec_som) = .false. + + i_avl_som = i_rec_som + 1 + floating_cn_ratio_decomp_pools(i_avl_som) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_avl_som) = 'soil3' + decomp_cascade_con%decomp_pool_name_history(i_avl_som) = 'SOIL3' + decomp_cascade_con%decomp_pool_name_long(i_avl_som) = 'soil 3' + decomp_cascade_con%decomp_pool_name_short(i_avl_som) = 'S3' + is_microbe(i_avl_som) = .false. + is_litter(i_avl_som) = .false. + is_soil(i_avl_som) = .true. + is_cwd(i_avl_som) = .false. + initial_cn_ratio(i_avl_som) = 10._r8 ! cn_s3 in BGC; not used in MIMICS + initial_stock(i_avl_som) = params_inst%initial_Cstocks(i_avl_som) + is_metabolic(i_avl_som) = .false. + is_cellulose(i_avl_som) = .false. + is_lignin(i_avl_som) = .false. + + i_cop_mic = i_avl_som + 1 + floating_cn_ratio_decomp_pools(i_cop_mic) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_cop_mic) = 'micr1' + decomp_cascade_con%decomp_pool_name_history(i_cop_mic) = 'MICR1' + decomp_cascade_con%decomp_pool_name_long(i_cop_mic) = 'microbial 1' + decomp_cascade_con%decomp_pool_name_short(i_cop_mic) = 'M1' + is_microbe(i_cop_mic) = .true. + is_litter(i_cop_mic) = .false. + is_soil(i_cop_mic) = .false. + is_cwd(i_cop_mic) = .false. + initial_cn_ratio(i_cop_mic) = 10._r8 ! MIMICS may use this + initial_stock(i_cop_mic) = params_inst%initial_Cstocks(i_cop_mic) + is_metabolic(i_cop_mic) = .false. + is_cellulose(i_cop_mic) = .false. + is_lignin(i_cop_mic) = .false. + + i_oli_mic = i_cop_mic + 1 + floating_cn_ratio_decomp_pools(i_oli_mic) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_oli_mic) = 'micr2' + decomp_cascade_con%decomp_pool_name_history(i_oli_mic) = 'MICR2' + decomp_cascade_con%decomp_pool_name_long(i_oli_mic) = 'microbial 2' + decomp_cascade_con%decomp_pool_name_short(i_oli_mic) = 'M2' + is_microbe(i_oli_mic) = .true. + is_litter(i_oli_mic) = .false. + is_soil(i_oli_mic) = .false. + is_cwd(i_oli_mic) = .false. + initial_cn_ratio(i_oli_mic) = 10._r8 ! MIMICS may use this + initial_stock(i_oli_mic) = params_inst%initial_Cstocks(i_oli_mic) + is_metabolic(i_oli_mic) = .false. + is_cellulose(i_oli_mic) = .false. + is_lignin(i_oli_mic) = .false. + if (.not. use_fates) then ! CWD - i_cwd = i_micr2 + 1 + i_cwd = i_oli_mic + 1 floating_cn_ratio_decomp_pools(i_cwd) = .true. decomp_cascade_con%decomp_pool_name_restart(i_cwd) = 'cwd' decomp_cascade_con%decomp_pool_name_history(i_cwd) = 'CWD' @@ -414,19 +423,19 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat speedup_fac = 1._r8 !lit1,2 - spinup_factor(i_litr1) = 1._r8 - spinup_factor(i_litr2) = 1._r8 + spinup_factor(i_met_lit) = 1._r8 + spinup_factor(i_str_lit) = 1._r8 !CWD if (.not. use_fates) then spinup_factor(i_cwd) = max(1._r8, (speedup_fac * params_inst%tau_cwd_bgc / 2._r8 )) end if !som1,2,3 - spinup_factor(i_soil1) = 1._r8 - spinup_factor(i_soil2) = 1._r8 ! BGC used same formula as for cwd but... - spinup_factor(i_soil3) = 1._r8 ! ...w the respective tau_s values + spinup_factor(i_pro_som) = 1._r8 + spinup_factor(i_rec_som) = 1._r8 ! BGC used same formula as for cwd but... + spinup_factor(i_avl_som) = 1._r8 ! ...w the respective tau_s values ! micr1,2 - spinup_factor(i_micr1) = 1._r8 - spinup_factor(i_micr2) = 1._r8 + spinup_factor(i_cop_mic) = 1._r8 + spinup_factor(i_oli_mic) = 1._r8 if ( masterproc ) then write(iulog,*) 'Spinup_state ',spinup_state @@ -437,58 +446,59 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_l1m1 = 1 decomp_cascade_con%cascade_step_name(i_l1m1) = 'L1M1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = rf_l1m1 - cascade_donor_pool(i_l1m1) = i_litr1 - cascade_receiver_pool(i_l1m1) = i_micr1 + cascade_donor_pool(i_l1m1) = i_met_lit + cascade_receiver_pool(i_l1m1) = i_cop_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = 1.0_r8 i_l2m1 = 2 decomp_cascade_con%cascade_step_name(i_l2m1) = 'L2M1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1) = rf_l2m1 - cascade_donor_pool(i_l2m1) = i_litr2 - cascade_receiver_pool(i_l2m1) = i_micr1 + cascade_donor_pool(i_l2m1) = i_str_lit + cascade_receiver_pool(i_l2m1) = i_cop_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1)= 1.0_r8 i_s3m1 = 3 decomp_cascade_con%cascade_step_name(i_s3m1) = 'S3M1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = rf_s3m1 - cascade_donor_pool(i_s3m1) = i_soil3 - cascade_receiver_pool(i_s3m1) = i_micr1 + cascade_donor_pool(i_s3m1) = i_avl_som + cascade_receiver_pool(i_s3m1) = i_cop_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = 1.0_r8 i_l1m2 = 4 decomp_cascade_con%cascade_step_name(i_l1m2) = 'L1M2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = rf_l1m2 - cascade_donor_pool(i_l1m2) = i_litr1 - cascade_receiver_pool(i_l1m2) = i_micr2 + cascade_donor_pool(i_l1m2) = i_met_lit + cascade_receiver_pool(i_l1m2) = i_oli_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = 1.0_r8 i_l2m2 = 5 decomp_cascade_con%cascade_step_name(i_l2m2) = 'L2M2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2) = rf_l2m2 - cascade_donor_pool(i_l2m2) = i_litr2 - cascade_receiver_pool(i_l2m2) = i_micr2 + cascade_donor_pool(i_l2m2) = i_str_lit + cascade_receiver_pool(i_l2m2) = i_oli_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2)= 1.0_r8 i_s3m2 = 6 decomp_cascade_con%cascade_step_name(i_s3m2) = 'S3M2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = rf_s3m2 - cascade_donor_pool(i_s3m2) = i_soil3 - cascade_receiver_pool(i_s3m2) = i_micr2 + cascade_donor_pool(i_s3m2) = i_avl_som + cascade_receiver_pool(i_s3m2) = i_oli_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = 1.0_r8 - ! TODO Should I have kept code corresponding to the s1_s3 s2_s3 transfers? + ! TODO Should I keep this code corresponding to the s1_s3 s2_s3 xfers? + ! If so, is pathfrac = 1 correct or should it be f_s1s3, f_s2s3? i_s1s3 = 7 decomp_cascade_con%cascade_step_name(i_s1s3) = 'S1S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3 - cascade_donor_pool(i_s1s3) = i_soil1 - cascade_receiver_pool(i_s1s3) = i_soil3 + cascade_donor_pool(i_s1s3) = i_pro_som + cascade_receiver_pool(i_s1s3) = i_avl_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = 1.0_r8 i_s2s3 = 8 decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 - cascade_donor_pool(i_s2s3) = i_soil2 - cascade_receiver_pool(i_s2s3) = i_soil3 + cascade_donor_pool(i_s2s3) = i_rec_som + cascade_receiver_pool(i_s2s3) = i_avl_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = 1.0_r8 if (.not. use_fates) then @@ -496,7 +506,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat decomp_cascade_con%cascade_step_name(i_cwdl2) = 'CWDL2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 cascade_donor_pool(i_cwdl2) = i_cwd - cascade_receiver_pool(i_cwdl2) = i_litr2 + cascade_receiver_pool(i_cwdl2) = i_str_lit pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_flig end if @@ -681,16 +691,16 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & do fc = 1,num_soilc c = filter_soilc(fc) ! - if ( abs(spinup_factor(i_litr1) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_l1(c) = spinup_factor(i_litr1) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_met_lit) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_l1(c) = spinup_factor(i_met_lit) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_l1(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_litr2) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_l23(c) = spinup_factor(i_litr2) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_str_lit) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_l2(c) = spinup_factor(i_str_lit) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else - spinup_geogterm_l23(c) = 1._r8 + spinup_geogterm_l2(c) = 1._r8 endif ! if ( .not. use_fates ) then @@ -701,32 +711,32 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & endif endif ! - if ( abs(spinup_factor(i_soil1) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_s1(c) = spinup_factor(i_soil1) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_pro_som) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s1(c) = spinup_factor(i_pro_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s1(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_soil2) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_s2(c) = spinup_factor(i_soil2) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_rec_som) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s2(c) = spinup_factor(i_rec_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s2(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_soil3) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_s3(c) = spinup_factor(i_soil3) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_avl_som) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s3(c) = spinup_factor(i_avl_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s3(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_micr1) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_m1(c) = spinup_factor(i_micr1) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_cop_mic) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_m1(c) = spinup_factor(i_cop_mic) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_m1(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_micr2) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_m2(c) = spinup_factor(i_micr2) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_oli_mic) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_m2(c) = spinup_factor(i_oli_mic) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_m2(c) = 1._r8 endif @@ -736,7 +746,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & do fc = 1,num_soilc c = filter_soilc(fc) spinup_geogterm_l1(c) = 1._r8 - spinup_geogterm_l23(c) = 1._r8 + spinup_geogterm_l2(c) = 1._r8 spinup_geogterm_cwd(c) = 1._r8 spinup_geogterm_s1(c) = 1._r8 spinup_geogterm_s2(c) = 1._r8 @@ -885,21 +895,21 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & do j = 1,nlevdecomp do fc = 1,num_soilc c = filter_soilc(fc) - decomp_k(c,j,i_litr1) = k_l1 * w_scalar(c,j) * & + decomp_k(c,j,i_met_lit) = k_l1 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l1(c) - decomp_k(c,j,i_litr2) = k_l2 * w_scalar(c,j) * & + decomp_k(c,j,i_str_lit) = k_l2 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l2(c) - decomp_k(c,j,i_micr1) = k_m1 * w_scalar(c,j) * & + decomp_k(c,j,i_cop_mic) = k_m1 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_m1(c) - decomp_k(c,j,i_micr2) = k_m2 * w_scalar(c,j) * & + decomp_k(c,j,i_oli_mic) = k_m2 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_m2(c) - decomp_k(c,j,i_soil1) = k_s1 * w_scalar(c,j) * & + decomp_k(c,j,i_pro_som) = k_s1 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s1(c) - decomp_k(c,j,i_soil2) = k_s2 * w_scalar(c,j) * & + decomp_k(c,j,i_rec_som) = k_s2 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s2(c) - decomp_k(c,j,i_soil3) = k_s3 * w_scalar(c,j) * & + decomp_k(c,j,i_avl_som) = k_s3 * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s3(c) ! Same for cwd but only if fates not enabled; fates handles cwd on ! its own structure From e962b0e5d39906207300db33ca264b7133dc5256 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 11 Jun 2021 11:28:31 -0600 Subject: [PATCH 10/69] Ongoing work in SoilBiogeochemDecompCascadeMIMICSMod.F90 Several TODOs pending --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 474 ++++++++++-------- 1 file changed, 277 insertions(+), 197 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 22385de7b5..ed3e3bae00 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -47,29 +47,29 @@ module SoilBiogeochemDecompCascadeMIMICSMod integer, private :: i_oli_mic ! index of oligotrophic microbial pool type, private :: params_type - ! TODO slevis: New rf params in MIMICS. Update params file accordingly. - ! I haven't identified what these correspond to in testbed. - real(r8):: rf_l1m1_mimics ! respiration fraction litter 1 -> microbe 1 - real(r8):: rf_l2m1_mimics - real(r8):: rf_s3m1_mimics ! respiration fraction soil 3 -> microbe 1 - real(r8):: rf_l1m2_mimics - real(r8):: rf_l2m2_mimics - real(r8):: rf_s3m2_mimics - - real(r8):: rf_cwdl2_mimics - + real(r8):: rf_s2s3_bgc + ! Respiration fraction cwd --> structural litter (keep comment sep for dif) + real(r8):: rf_cwdl2_bgc + real(r8):: tau_s1_bgc ! 1/turnover time of SOM 1 from Century (1/7.3) (1/yr) + real(r8):: tau_s2_bgc ! 1/turnover time of SOM 2 from Century (1/0.2) (1/yr) real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) - real(r8) :: cwd_flig + real(r8) :: cwd_fcel_bgc !cellulose fraction for CWD + real(r8) :: cwd_flig_bgc ! real(r8) :: minpsi_bgc !minimum soil water potential for heterotrophic resp real(r8) :: maxpsi_bgc !maximum soil water potential for heterotrophic resp - ! TODO slevis: If Melannie's values from the testbed differ from the - ! values used for BGC, make separate _mimics params. - ! Keeping the _depth param in case needed for spin-ups. - real(r8), allocatable :: initial_Cstocks(:) ! Initial Carbon stocks for a cold-start + ! TODO Need for spin-ups? real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start + real(r8), allocatable :: initial_Cstocks(:) ! Initial Carbon stocks for a cold-start + real(r8), allocatable :: mge(:) ! Microbial growth efficiency (mg/mg) + real(r8), allocatable :: vmod(:) ! + real(r8), allocatable :: vslope(:) ! + real(r8), allocatable :: vint(:) ! + real(r8), allocatable :: kmod(:) ! + real(r8), allocatable :: kslope(:) ! + real(r8), allocatable :: kint(:) ! end type params_type ! @@ -102,48 +102,43 @@ subroutine readParams ( ncid ) !----------------------------------------------------------------------- ! Read off of netcdf file - ! TODO slevis: Add new params here and in the params file. - ! Read MIMICS-specific params here & shared ones (eg *_bgc) like this: + ! TODO Add new params here and in the params file. + ! TODO tau_s1, tau_s2, etc may need _bgc added/removed here/params file + ! TODO Read MIMICS-specific params here & shared ones (eg *_bgc) like this: ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding - tString='tau_cwd_bgc' + ! TODO If Melannie's testbed values differ from the BGC values, + ! make separate _mimics params. + ! TODO When ready for all final params values, talk to @wwieder + tString='tau_s1_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_cwd_bgc=tempr + params_inst%tau_s1_bgc=tempr - tString='rf_l1m1_mimics' + tString='tau_s2_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_l1m1_mimics=tempr + params_inst%tau_s2_bgc=tempr - tString='rf_l2m1_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_l2m1_mimics=tempr - - tString='rf_s3m1_mimics' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_s3m1_mimics=tempr - - tString='rf_l1m2_mimics' + tString='tau_cwd_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_l1m2_mimics=tempr + params_inst%tau_cwd_bgc=tempr - tString='rf_l2m2_mimics' + tString='rf_s2s3_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_l2m2_mimics=tempr + params_inst%rf_s2s3_bgc=tempr - tString='rf_s3m2_mimics' + ! MIMICS value = 0 (same as BGC value) + tString='rf_cwdl2_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_s3m2_mimics=tempr + params_inst%rf_cwdl2_bgc=tempr - tString='rf_cwdl2_bgc' ! MIMICS value of this same as BGC value (= 0) + tString='cwd_fcel' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_cwdl2_mimics=tempr + params_inst%cwd_fcel_bgc=tempr tString='minpsi_hr' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) @@ -155,21 +150,55 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%maxpsi_bgc=tempr - ! TODO cwd_flig is used in cwd --> l2 so keeping for now tString='cwd_flig' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cwd_flig=tempr + params_inst%cwd_flig_bgc=tempr + + tString='initial_Cstocks_depth_bgc' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%initial_Cstocks_depth=tempr allocate(params_inst%initial_Cstocks(ndecomp_pools_max)) tString='initial_Cstocks_bgc' call ncd_io(trim(tString), params_inst%initial_Cstocks(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - tString='initial_Cstocks_depth_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + allocate(params_inst%mge(ndecomp_pools_max)) + tString='mge_mimics' + call ncd_io(trim(tString), params_inst%mge(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%vmod(ndecomp_pools_max)) + tString='vmod_mimics' + call ncd_io(trim(tString), params_inst%vmod(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%vslope(ndecomp_pools_max)) + tString='vslope_mimics' + call ncd_io(trim(tString), params_inst%vslope(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%vint(ndecomp_pools_max)) + tString='vint_mimics' + call ncd_io(trim(tString), params_inst%vint(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%kmod(ndecomp_pools_max)) + tString='kmod_mimics' + call ncd_io(trim(tString), params_inst%kmod(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%kslope(ndecomp_pools_max)) + tString='kslope_mimics' + call ncd_io(trim(tString), params_inst%kslope(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%kint(ndecomp_pools_max)) + tString='kint_mimics' + call ncd_io(trim(tString), params_inst%kint(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%initial_Cstocks_depth=tempr end subroutine readParams @@ -195,14 +224,14 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat real(r8) :: rf_l1m2 real(r8) :: rf_l2m2 real(r8) :: rf_s3m2 - ! TODO slevis: Keeping temporarily as a template - ! for new params not coming from the params file. - ! Also keeping other params that I'm not sure about, yet. real(r8), allocatable :: rf_s1s3(:,:) + real(r8) :: rf_s2s3 real(r8) :: rf_cwdl2 + real(r8) :: cwd_fcel real(r8) :: cwd_flig real(r8), allocatable :: f_s1s3(:,:) real(r8) :: f_s2s3 + real(r8), allocatable :: p_scalar(:,:) integer :: i_l1m1 integer :: i_l2m1 @@ -224,6 +253,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) cellsand => soilstate_inst%cellsand_col , & ! Input: [real(r8) (:,:) ] column 3D sand + cellclay => soilstate_inst%cellclay_col , & ! Input: [real(r8) (:,:) ] column 3D clay cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Output: [integer (:) ] which pool is C taken from for a given decomposition step cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & ! Output: [integer (:) ] which pool is C added to for a given decomposition step @@ -244,35 +274,80 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat allocate(rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp)) allocate(f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp)) + allocate(p_scalar(bounds%begc:bounds%endc,1:nlevdecomp)) !------- time-constant coefficients ---------- ! ! set respiration fractions for fluxes between compartments - rf_l1m1 = params_inst%rf_l1m1_mimics - rf_l2m1 = params_inst%rf_l2m1_mimics - rf_s3m1 = params_inst%rf_s3m1_mimics - rf_l1m2 = params_inst%rf_l1m2_mimics - rf_l2m2 = params_inst%rf_l2m2_mimics - rf_s3m2 = params_inst%rf_s3m2_mimics - - rf_cwdl2 = params_inst%rf_cwdl2_mimics - - ! set the structural fractions for coarse woody debris - ! TODO slevis: If will use, rename to cwd_fstr? Or remove? - cwd_flig = params_inst%cwd_flig + rf_l1m1 = 1.0_r8 - params_inst%mge(1) + rf_l2m1 = 1.0_r8 - params_inst%mge(2) + rf_s3m1 = 1.0_r8 - params_inst%mge(3) + rf_l1m2 = 1.0_r8 - params_inst%mge(4) + rf_l2m2 = 1.0_r8 - params_inst%mge(5) + rf_s3m2 = 1.0_r8 - params_inst%mge(6) + + rf_s2s3 = params_inst%rf_s2s3_bgc + rf_cwdl2 = params_inst%rf_cwdl2_bgc + + ! set the structural fraction for coarse woody debris + ! TODO Renamed LHS to cwd_fstr. Make RHS = sum or avg of the two? + cwd_fstr = min(1.0_r8, & + params_inst%cwd_fcel_bgc + params_inst%cwd_flig_bgc) + + ! vmod = "old" vmod * av AND kmod = ak / "old" kmod + ! Table B1 Wieder et al. (2015) and MIMICS params file give different + ! ak and av values. I used the params file values. + vmod_l1m1 = params_inst%vmod(1) + vmod_l2m1 = params_inst%vmod(2) + vmod_s3m1 = params_inst%vmod(3) + vmod_l1m2 = params_inst%vmod(4) + vmod_l2m2 = params_inst%vmod(5) + vmod_s3m2 = params_inst%vmod(6) + kmod_l1m1 = params_inst%kmod(1) + kmod_l2m1 = params_inst%kmod(2) + kmod_s3m1 = params_inst%kmod(3) + kmod_l1m2 = params_inst%kmod(4) + kmod_l2m2 = params_inst%kmod(5) + kmod_s3m2 = params_inst%kmod(6) + vslope_l1m1 = params_inst%vslope(1) + vslope_l2m1 = params_inst%vslope(2) + vslope_s3m1 = params_inst%vslope(3) + vslope_l1m2 = params_inst%vslope(4) + vslope_l2m2 = params_inst%vslope(5) + vslope_s3m2 = params_inst%vslope(6) + kslope_l1m1 = params_inst%kslope(1) + kslope_l2m1 = params_inst%kslope(2) + kslope_s3m1 = params_inst%kslope(3) + kslope_l1m2 = params_inst%kslope(4) + kslope_l2m2 = params_inst%kslope(5) + kslope_s3m2 = params_inst%kslope(6) + vint_l1m1 = params_inst%vint(1) + vint_l2m1 = params_inst%vint(2) + vint_s3m1 = params_inst%vint(3) + vint_l1m2 = params_inst%vint(4) + vint_l2m2 = params_inst%vint(5) + vint_s3m2 = params_inst%vint(6) + kint_l1m1 = params_inst%kint(1) + kint_l2m1 = params_inst%kint(2) + kint_s3m1 = params_inst%kint(3) + kint_l1m2 = params_inst%kint(4) + kint_l2m2 = params_inst%kint(5) + kint_s3m2 = params_inst%kint(6) ! set path fractions f_s2s3 = 0.03_r8/(0.45_r8) ! some of these are dependent on the soil texture properties - ! TODO slevis: Template for calculated mimics params? - ! One-time initializations here and time-dep params - ! in subr. decomp_rates_mimics. + ! TODO rf_s1s3 -> rf_decomp_cascade as template for p_scalar? + ! One-time initializations here. + ! Time-dep params in subr. decomp_rates_mimics. do c = bounds%begc, bounds%endc do j = 1, nlevdecomp t = 0.85_r8 - 0.68_r8 * 0.01_r8 * (100._r8 - cellsand(c,j)) f_s1s3(c,j) = .004_r8 / (1._r8 - t) rf_s1s3(c,j) = t + p_scalar(c,j) = (0.8_r8 * exp(-3.0_r8 * sqrt(cellclay(c,j))))** & + (-1.0_r8) end do end do initial_stock_soildepth = params_inst%initial_Cstocks_depth @@ -431,7 +506,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat end if !som1,2,3 spinup_factor(i_pro_som) = 1._r8 - spinup_factor(i_rec_som) = 1._r8 ! BGC used same formula as for cwd but... + spinup_factor(i_rec_som) = 1._r8 ! BGC used cwd formula above but spinup_factor(i_avl_som) = 1._r8 ! ...w the respective tau_s values ! micr1,2 spinup_factor(i_cop_mic) = 1._r8 @@ -485,21 +560,20 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_receiver_pool(i_s3m2) = i_oli_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = 1.0_r8 - ! TODO Should I keep this code corresponding to the s1_s3 s2_s3 xfers? - ! If so, is pathfrac = 1 correct or should it be f_s1s3, f_s2s3? + ! TODO If keeping s1_s3 & s2_s3 code, is pathfrac correct or should = 1? i_s1s3 = 7 decomp_cascade_con%cascade_step_name(i_s1s3) = 'S1S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) cascade_donor_pool(i_s1s3) = i_pro_som cascade_receiver_pool(i_s1s3) = i_avl_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) i_s2s3 = 8 decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 cascade_donor_pool(i_s2s3) = i_rec_som cascade_receiver_pool(i_s2s3) = i_avl_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = f_s2s3 if (.not. use_fates) then i_cwdl2 = 9 @@ -507,11 +581,19 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 cascade_donor_pool(i_cwdl2) = i_cwd cascade_receiver_pool(i_cwdl2) = i_str_lit - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_flig + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fstr end if deallocate(rf_s1s3) deallocate(f_s1s3) + deallocate(p_scalar) + deallocate(params_inst%mge) + deallocate(params_inst%vmod) + deallocate(params_inst%vslope) + deallocate(params_inst%vint) + deallocate(params_inst%kmod) + deallocate(params_inst%kslope) + deallocate(params_inst%kint) deallocate(params_inst%initial_Cstocks) end associate @@ -543,46 +625,41 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & real(r8):: frw(bounds%begc:bounds%endc) ! rooting fraction weight real(r8), allocatable:: fr(:,:) ! column-level rooting fraction by soil depth real(r8):: psi ! temporary soilpsi for water scalar - real(r8):: k_l1_m1 ! decomposition rate litter 1 (1/sec) - real(r8):: k_l2_m1 ! decomposition rate litter 2 (1/sec) - real(r8):: k_s3_m1 ! decomposition rate SOM 3 (1/sec) - real(r8):: k_l1_m2 ! decomposition rate litter 1 (1/sec) - real(r8):: k_l2_m2 ! decomposition rate litter 2 (1/sec) - real(r8):: k_s3_m2 ! decomposition rate SOM 3 (1/sec) - real(r8):: k_s1_s3 ! decomposition rate SOM 1 (1/sec) - real(r8):: k_s2_s3 ! decomposition rate SOM 2 (1/sec) - real(r8):: k_m1 ! decomposition rate microbe 1 (1/sec) - real(r8):: k_m2 ! decomposition rate microbe 2 (1/sec) + real(r8):: k_s1_s3 ! decomposition rate SOM 1 (1/sec) + real(r8):: k_s2_s3 ! decomposition rate SOM 2 (1/sec) real(r8):: k_frag ! fragmentation rate constant CWD (1/sec) - real(r8):: vmax_l1_m1_mimics ! - real(r8):: vmax_l2_m1_mimics ! - real(r8):: vmax_s3_m1_mimics ! - real(r8):: vmax_l1_m2_mimics ! - real(r8):: vmax_l2_m2_mimics ! - real(r8):: vmax_s3_m2_mimics ! - real(r8):: tau_s1_s3_mimics ! - real(r8):: tau_s2_s3_mimics ! - real(r8):: tau_m1_mimics ! - real(r8):: tau_m2_mimics ! - real(r8):: km_l1_m1_mimics ! - real(r8):: km_l2_m1_mimics ! - real(r8):: km_s3_m1_mimics ! - real(r8):: km_l1_m2_mimics ! - real(r8):: km_l2_m2_mimics ! - real(r8):: km_s3_m2_mimics ! + real(r8):: vmax_l1_m1 ! + real(r8):: vmax_l2_m1 ! + real(r8):: vmax_s3_m1 ! + real(r8):: vmax_l1_m2 ! + real(r8):: vmax_l2_m2 ! + real(r8):: vmax_s3_m2 ! + real(r8):: km_l1_m1 ! + real(r8):: km_l2_m1 ! + real(r8):: km_s3_m1 ! + real(r8):: km_l1_m2 ! + real(r8):: km_l2_m2 ! + real(r8):: km_s3_m2 ! + real(r8):: tau_m1_s1 ! + real(r8):: tau_m1_s2 ! + real(r8):: tau_m1_s3 ! + real(r8):: tau_m2_s1 ! + real(r8):: tau_m2_s2 ! + real(r8):: tau_m2_s3 ! real(r8):: decomp_depth_efolding ! (meters) e-folding depth for reduction in decomposition [ integer :: c, fc, j, k, l real(r8):: days_per_year ! days per year real(r8):: depth_scalar(bounds%begc:bounds%endc,1:nlevdecomp) + real(r8):: w_d_o_scalars ! product of w_scalar * depth_scalar * o_scalar real(r8):: mino2lim !minimum anaerobic decomposition rate real(r8):: spinup_geogterm_l1(bounds%begc:bounds%endc) ! geographically-varying spinup term for l1 - real(r8):: spinup_geogterm_l2(bounds%begc:bounds%endc) ! geographically-varying spinup term for l2 + real(r8):: spinup_geogterm_l2(bounds%begc:bounds%endc) ! geographically-varying spinup term for l2 real(r8):: spinup_geogterm_cwd(bounds%begc:bounds%endc) ! geographically-varying spinup term for cwd real(r8):: spinup_geogterm_s1(bounds%begc:bounds%endc) ! geographically-varying spinup term for s1 real(r8):: spinup_geogterm_s2(bounds%begc:bounds%endc) ! geographically-varying spinup term for s2 real(r8):: spinup_geogterm_s3(bounds%begc:bounds%endc) ! geographically-varying spinup term for s3 - real(r8):: spinup_geogterm_m1(bounds%begc:bounds%endc) ! geographically-varying spinup term for m1 - real(r8):: spinup_geogterm_m2(bounds%begc:bounds%endc) ! geographically-varying spinup term for m2 + real(r8):: spinup_geogterm_m1(bounds%begc:bounds%endc) ! geographically-varying spinup term for m1 + real(r8):: spinup_geogterm_m2(bounds%begc:bounds%endc) ! geographically-varying spinup term for m2 !----------------------------------------------------------------------- @@ -610,81 +687,11 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Set "decomp_depth_efolding" parameter decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding -! TODO slevis: tau params are changing; map to Wieder et al. 2015 -! From testbed code -! ------------------ - -! Vmax, tau*, and Km are time-dependent - -! Table B1 Wieder et al. 2015 gives -! Vslope = 0.063, Vint = 5.47, av = 8e-6 -! Vmod_r = 10,2,10, Vmod_K = 3,3,2 (for LITm,s,SOMa --> MICr,K respectively) - -! Vmax(npt,R1) = exp(Vslope(R1) * Tsoi_day_avg_C + Vint(R1)) * av * Vmod(R1) -! Vmax(npt,R2) = exp(Vslope(R2) * Tsoi_day_avg_C + Vint(R2)) * av * Vmod(R2) -! Vmax(npt,R3) = exp(Vslope(R3) * Tsoi_day_avg_C + Vint(R3)) * av * Vmod(R3) -! Vmax(npt,K1) = exp(Vslope(K1) * Tsoi_day_avg_C + Vint(K1)) * av * Vmod(K1) -! Vmax(npt,K2) = exp(Vslope(K2) * Tsoi_day_avg_C + Vint(K2)) * av * Vmod(K2) -! Vmax(npt,K3) = exp(Vslope(K3) * Tsoi_day_avg_C + Vint(K3)) * av * Vmod(K3) - -! --- -! Solving for tauR (tau_m1 here?) & tauK (tau_m2 here?) - -! fmet_p(1) = 0.85, fmet_p(2) = 0.85, fmet_p(3) = 0.013 -! ligninNratioAvg(npt) = & -! ( ligninNratio(npt,leaf) * (cleaf2met(npt) + cleaf2str(npt)) & -! + ligninNratio(npt,froot) * (croot2met(npt) + croot2str(npt)) & -! + ligninNratio(npt,wood) * (cwd2str(npt)) ) & -! / max(0.001, cleaf2met(npt)+cleaf2str(npt)+croot2met(npt)+croot2str(npt)+cwd2str(npt)) -! set limits on Lignin:N to keep fmet > 0.2 -! necessary for litter quality in boreal forests with high cwd flux -! ligninNratioAvg(npt) = min(40.0, ligninNratioAvg(npt)) -! fmet(npt) = fmet_p(1) * (fmet_p(2) - fmet_p(3) * ligninNratioAvg(npt)) - -! tauModDenom = 100, tauMod_min = 0.8, tauMod_max = 1.2 -! tauMod(npt) = sqrt(avg_ann_npp_gC_m2_yr / tauModDenom) -! tauMod(npt) = min(tauMod_max, max(tauMod_min, tauMod(npt))) - -! tauR is tau_m1, right? tau_r(1) = 5.2e-4_r8, tau_r(2) = 0.3_r8 or 0.4? -! tauR(npt) = tau_r(1) * exp(tau_r(2) * fmet(npt)) * tauMod(npt) - -! tauK is tau_m2, right? tau_k(1) = 2.4e-4_r8, tau_k(2) = 0.1_r8 -! tauK(npt) = tau_k(1) * exp(tau_k(2) * fmet(npt)) * tauMod(npt) -! --- - -! Table B1 Wieder et al. 2015 gives -! Kslope = 0.017, 0.027, 0.017 (for LITm,s,SOMa --> MICr and K) -! Kint = 3.19, aK = 10 -! Kmod_r = 0.125,0.5,0.25*P_scalar, Kmod_K = 0.5,0.25,0.167*P_scalar -! P_scalar = (2 * exp(-2 * sqrt(fclay)))**(-1) - -! Km(npt,R1) = exp(Kslope(R1) * Tsoi_day_avg_C + Kint(R1)) * ak / Kmod(npt,R1) -! Km(npt,R2) = exp(Kslope(R2) * Tsoi_day_avg_C + Kint(R2)) * ak / Kmod(npt,R2) -! Km(npt,R3) = exp(Kslope(R3) * Tsoi_day_avg_C + Kint(R3)) * ak / Kmod(npt,R3) -! Km(npt,K1) = exp(Kslope(K1) * Tsoi_day_avg_C + Kint(K1)) * ak / Kmod(npt,K1) -! Km(npt,K2) = exp(Kslope(K2) * Tsoi_day_avg_C + Kint(K2)) * ak / Kmod(npt,K2) -! Km(npt,K3) = exp(Kslope(K3) * Tsoi_day_avg_C + Kint(K3)) * ak / Kmod(npt,K3) - -! STILL MISSING N-related stuff: DIN... - ! translate to per-second time constant - ! TODO Vmax terms replace k_* terms (easy) but Km terms and biomass pools - ! need to come in and be used where currently only the decomp_k - ! terms are in use. Refactor the hooks to make them general so that - ! they can work for both BGC and MIMICS? OR make separate sections - ! of code for use_century_decomp vs use_mimics_decomp. - ! TODO Should I have kept code corresponding to the s1_s3 s2_s3 transfers? - k_l1_m1 = 1._r8 / (secspday * days_per_year * vmax_l1_m1_mimics) - k_l2_m1 = 1._r8 / (secspday * days_per_year * vmax_l2_m1_mimics) - k_s3_m1 = 1._r8 / (secspday * days_per_year * vmax_s3_m1_mimics) - k_l1_m2 = 1._r8 / (secspday * days_per_year * vmax_l1_m2_mimics) - k_l2_m2 = 1._r8 / (secspday * days_per_year * vmax_l2_m2_mimics) - k_s3_m2 = 1._r8 / (secspday * days_per_year * vmax_s3_m2_mimics) - k_s1_s3 = 1._r8 / (secspday * days_per_year * tau_s1_s3_mimics) - k_s2_s3 = 1._r8 / (secspday * days_per_year * tau_s2_s3_mimics) - k_m1 = 1._r8 / (secspday * days_per_year * tau_m1_mimics) - k_m2 = 1._r8 / (secspday * days_per_year * tau_m2_mimics) - k_frag = 1._r8 / (secspday * days_per_year * tau_cwd_bgc) + ! TODO vmax, km, tau terms replaced (most?) k_ terms; CONFIRM s-1 UNITS + k_s1_s3 = 1._r8 / (secspday * days_per_year * params_inst%tau_s1_bgc) + k_s2_s3 = 1._r8 / (secspday * days_per_year * params_inst%tau_s2_bgc) + k_frag = 1._r8 / (secspday * days_per_year * params_inst%tau_cwd_bgc) ! calc ref rate if ( spinup_state >= 1 ) then @@ -804,7 +811,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do - ! TODO Discuss @wwieder's concerns about breaking the methane code + ! TODO @wwieder concerned about breaking ch4 code if (use_lch4) then ! Calculate ANOXIA if (anoxia) then @@ -887,35 +894,108 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do ! calculate rates for all litter and som pools - ! TODO I will start updating this section when I feel confident in my list - ! of k_ factors. For example - ! - Should decomp_k be dimensioned (c,j,i_l1m1) instead? - ! - Should there be two sets of decomp_k, the first corresponding to - ! vmax and the second to km? do j = 1,nlevdecomp do fc = 1,num_soilc c = filter_soilc(fc) - decomp_k(c,j,i_met_lit) = k_l1 * w_scalar(c,j) * & - depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l1(c) - decomp_k(c,j,i_str_lit) = k_l2 * w_scalar(c,j) * & - depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l2(c) - - decomp_k(c,j,i_cop_mic) = k_m1 * w_scalar(c,j) * & - depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_m1(c) - decomp_k(c,j,i_oli_mic) = k_m2 * w_scalar(c,j) * & - depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_m2(c) - - decomp_k(c,j,i_pro_som) = k_s1 * w_scalar(c,j) * & - depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s1(c) - decomp_k(c,j,i_rec_som) = k_s2 * w_scalar(c,j) * & - depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s2(c) - decomp_k(c,j,i_avl_som) = k_s3 * w_scalar(c,j) * & - depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_s3(c) + ! vmax, tau, and km are time-dependent terms. + ! Table B1 Wieder et al. (2015) & MIMICS params file give different + ! kslope. I used the params file value(s). + ! TODO Introduce t_soi24_degC_col following t_veg24_patch (running + ! mean) or t_mo_patch (30-d avg) or ... + vmax_l1_m1 = exp(vslope_l1_m1 * t_soi24_degC_col(c,j) + vint_l1_m1) * vmod_l1_m1 + vmax_l1_m2 = exp(vslope_l1_m2 * t_soi24_degC_col(c,j) + vint_l1_m2) * vmod_l1_m2 + vmax_l2_m1 = exp(vslope_l2_m1 * t_soi24_degC_col(c,j) + vint_l2_m1) * vmod_l2_m1 + vmax_l2_m2 = exp(vslope_l2_m2 * t_soi24_degC_col(c,j) + vint_l2_m2) * vmod_l2_m2 + vmax_s3_m1 = exp(vslope_s3_m1 * t_soi24_degC_col(c,j) + vint_s3_m1) * vmod_l2_m1 + vmax_s3_m2 = exp(vslope_s3_m2 * t_soi24_degC_col(c,j) + vint_s3_m2) * vmod_l2_m2 + + km_l1_m1 = exp(kslope_l1_m1 * t_soi24_degC_col(c,j) + kint_l1_m1) * kmod_l1_m1 + km_l1_m2 = exp(kslope_l1_m2 * t_soi24_degC_col(c,j) + kint_l1_m2) * kmod_l1_m2 + km_l2_m1 = exp(kslope_l2_m1 * t_soi24_degC_col(c,j) + kint_l2_m1) * kmod_l2_m1 + km_l2_m2 = exp(kslope_l2_m2 * t_soi24_degC_col(c,j) + kint_l2_m2) * kmod_l2_m2 + km_s3_m1 = exp(kslope_s3_m1 * t_soi24_degC_col(c,j) + kint_s3_m1) * kmod_s3_m1 / p_scalar(c,j) + km_s3_m2 = exp(kslope_s3_m2 * t_soi24_degC_col(c,j) + kint_s3_m2) * kmod_s3_m2 / p_scalar(c,j) + +! TODO mapping tau params to Wieder et al. 2015 & testbed code +! -------------------------------------------------------------- +! tau* are time-dependent + +! Solving for tauR (tau_m1_s* here) & tauK (tau_m2_s* here) + +! fmet_p(1) = 0.85, fmet_p(2) = 0.85, fmet_p(3) = 0.013 +! ligninNratioAvg(npt) = & +! ( ligninNratio(npt,leaf) * (cleaf2met(npt) + cleaf2str(npt)) & +! + ligninNratio(npt,froot) * (croot2met(npt) + croot2str(npt)) & +! + ligninNratio(npt,wood) * (cwd2str(npt)) ) & +! / max(0.001, cleaf2met(npt)+cleaf2str(npt)+croot2met(npt)+croot2str(npt)+cwd2str(npt)) +! set limits on Lignin:N to keep fmet > 0.2 +! necessary for litter quality in boreal forests with high cwd flux +! ligninNratioAvg(npt) = min(40.0, ligninNratioAvg(npt)) +! fmet(npt) = fmet_p(1) * (fmet_p(2) - fmet_p(3) * ligninNratioAvg(npt)) + +! tauModDenom = 100, tauMod_min = 0.8, tauMod_max = 1.2 +! tauMod(npt) = sqrt(avg_ann_npp_gC_m2_yr / tauModDenom) +! tauMod(npt) = min(tauMod_max, max(tauMod_min, tauMod(npt))) + +! tau_r(1) = 5.2e-4_r8, tau_r(2) = 0.3_r8 or 0.4? +! tauR(npt) = tau_r(1) * exp(tau_r(2) * fmet(npt)) * tauMod(npt) + +! tau_k(1) = 2.4e-4_r8, tau_k(2) = 0.1_r8 +! tauK(npt) = tau_k(1) * exp(tau_k(2) * fmet(npt)) * tauMod(npt) +! -------------------------------------------------------------- +! TODO STILL MISSING N-related stuff: DIN... + + ! Product of w_scalar * depth_scalar * o_scalar + w_d_o_scalars = w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) + + ! decomp_k used in SoilBiogeochemPotentialMod.F90 + ! TODO Defined correctly here? + ! TODO Combine multiple terms of same donor pools... + ! TODO Where to calculate m1_pool and m2_pool? + ! TODO When to introduce litter/soil biomass to the calculation? + ! TODO Excluded spinup terms for now. See cwd below how used. + decomp_k(c,j,i_met_lit) = (vmax_l1_m1 * m1_pool(c,j) / & + (km_l1_m1 + m1_pool(c,j))) * & + w_d_o_scalars + decomp_k(c,j,i_met_lit) = (vmax_l1_m2 * m2_pool(c,j) / & + (km_l1_m2 + m2_pool(c,j))) * & + w_d_o_scalars + + decomp_k(c,j,i_str_lit) = (vmax_l2_m1 * m1_pool(c,j) / & + (km_l2_m1 + m1_pool(c,j))) * & + w_d_o_scalars + decomp_k(c,j,i_str_lit) = (vmax_l2_m2 * m2_pool(c,j) / & + (km_l2_m2 + m2_pool(c,j))) * & + w_d_o_scalars + + decomp_k(c,j,i_avl_som) = (vmax_s3_m1 * m1_pool(c,j) / & + (km_s3_m1 + m1_pool(c,j))) * & + w_d_o_scalars + decomp_k(c,j,i_avl_som) = (vmax_s3_m2 * m2_pool(c,j) / & + (km_s3_m2 + m2_pool(c,j))) * & + w_d_o_scalars + + decomp_k(c,j,i_pro_som) = k_s1_s3 * w_d_o_scalars + decomp_k(c,j,i_rec_som) = k_s2_s3 * w_d_o_scalars + + decomp_k(c,j,i_cop_mic) = tau_m1_s1 * m1_pool(c,j)**(densdep) * & + fphys(c) * w_d_o_scalars + decomp_k(c,j,i_cop_mic) = tau_m1_s2 * m1_pool(c,j)**(densdep) * & + fchem(c) * w_d_o_scalars + decomp_k(c,j,i_cop_mic) = tau_m1_s3 * m1_pool(c,j)**(densdep) * & + faval(c) *w_d_o_scalars + decomp_k(c,j,i_oli_mic) = tau_m2_s1 * m2_pool(c,j)**(densdep) * & + fphys(c) * w_d_o_scalars + decomp_k(c,j,i_oli_mic) = tau_m2_s2 * m2_pool(c,j)**(densdep) * & + fchem(c) * w_d_o_scalars + decomp_k(c,j,i_oli_mic) = tau_m2_s3 * m2_pool(c,j)**(densdep) * & + faval(c) * w_d_o_scalars ! Same for cwd but only if fates not enabled; fates handles cwd on ! its own structure + ! TODO Kept cwd bc we do not have a MIMICS replacement for it. + ! Also this shows what the BGC decomp_k formulas looked like. if (.not. use_fates) then - decomp_k(c,j,i_cwd) = k_frag * w_scalar(c,j) * & - depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_cwd(c) + decomp_k(c,j,i_cwd) = k_frag * w_d_o_scalars * spinup_geogterm_cwd(c) end if end do end do From 487f5b32eb7a412f361d01082bdf0037654e4fa5 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 12 Jul 2021 14:22:42 -0600 Subject: [PATCH 11/69] Updates to MIMICSMod.F90 for consistency w corresponding BGC refactors --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 158 +++++++++--------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index ed3e3bae00..85a5753bc0 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -39,9 +39,9 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! !PUBLIC DATA MEMBERS ! ! !PRIVATE DATA MEMBERS - integer, private :: i_pro_som ! index of protected Soil Organic Matter (SOM) - integer, private :: i_rec_som ! index of recalcitrant SOM - integer, private :: i_avl_som ! index of available SOM + integer, private :: i_pas_som ! index of passive (aka protected) Soil Organic Matter (SOM) + integer, private :: i_slo_som ! index of slow (aka recalcitrant) SOM + integer, private :: i_act_som ! index of active (aka available) SOM integer, private :: i_str_lit ! index of structural litter pool integer, private :: i_cop_mic ! index of copiotrophic microbial pool integer, private :: i_oli_mic ! index of oligotrophic microbial pool @@ -357,8 +357,8 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_met_lit = i_litr_min floating_cn_ratio_decomp_pools(i_met_lit) = .true. decomp_cascade_con%decomp_pool_name_restart(i_met_lit) = 'litr1' - decomp_cascade_con%decomp_pool_name_history(i_met_lit) = 'LITR1' - decomp_cascade_con%decomp_pool_name_long(i_met_lit) = 'litter 1' + decomp_cascade_con%decomp_pool_name_history(i_met_lit) = 'MET_LIT' + decomp_cascade_con%decomp_pool_name_long(i_met_lit) = 'metabolic litter' decomp_cascade_con%decomp_pool_name_short(i_met_lit) = 'L1' is_microbe(i_met_lit) = .false. is_litter(i_met_lit) = .true. @@ -373,8 +373,8 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_str_lit = i_met_lit + 1 floating_cn_ratio_decomp_pools(i_str_lit) = .true. decomp_cascade_con%decomp_pool_name_restart(i_str_lit) = 'litr2' - decomp_cascade_con%decomp_pool_name_history(i_str_lit) = 'LITR2' - decomp_cascade_con%decomp_pool_name_long(i_str_lit) = 'litter 2' + decomp_cascade_con%decomp_pool_name_history(i_str_lit) = 'STR_LIT' + decomp_cascade_con%decomp_pool_name_long(i_str_lit) = 'structural litter' decomp_cascade_con%decomp_pool_name_short(i_str_lit) = 'L2' is_microbe(i_str_lit) = .false. is_litter(i_str_lit) = .true. @@ -396,59 +396,59 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat errMsg(sourcefile, __LINE__)) end if - i_pro_som = i_str_lit + 1 - floating_cn_ratio_decomp_pools(i_pro_som) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_pro_som) = 'soil1' - decomp_cascade_con%decomp_pool_name_history(i_pro_som) = 'SOIL1' - decomp_cascade_con%decomp_pool_name_long(i_pro_som) = 'soil 1' - decomp_cascade_con%decomp_pool_name_short(i_pro_som) = 'S1' - is_microbe(i_pro_som) = .false. - is_litter(i_pro_som) = .false. - is_soil(i_pro_som) = .true. - is_cwd(i_pro_som) = .false. - initial_cn_ratio(i_pro_som) = 10._r8 ! cn_s1 in BGC; not used in MIMICS - initial_stock(i_pro_som) = params_inst%initial_Cstocks(i_pro_som) - is_metabolic(i_pro_som) = .false. - is_cellulose(i_pro_som) = .false. - is_lignin(i_pro_som) = .false. - - i_rec_som = i_pro_som + 1 - floating_cn_ratio_decomp_pools(i_rec_som) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_rec_som) = 'soil2' - decomp_cascade_con%decomp_pool_name_history(i_rec_som) = 'SOIL2' - decomp_cascade_con%decomp_pool_name_long(i_rec_som) = 'soil 2' - decomp_cascade_con%decomp_pool_name_short(i_rec_som) = 'S2' - is_microbe(i_rec_som) = .false. - is_litter(i_rec_som) = .false. - is_soil(i_rec_som) = .true. - is_cwd(i_rec_som) = .false. - initial_cn_ratio(i_rec_som) = 10._r8 ! cn_s2 in BGC; not used in MIMICS - initial_stock(i_rec_som) = params_inst%initial_Cstocks(i_rec_som) - is_metabolic(i_rec_som) = .false. - is_cellulose(i_rec_som) = .false. - is_lignin(i_rec_som) = .false. - - i_avl_som = i_rec_som + 1 - floating_cn_ratio_decomp_pools(i_avl_som) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_avl_som) = 'soil3' - decomp_cascade_con%decomp_pool_name_history(i_avl_som) = 'SOIL3' - decomp_cascade_con%decomp_pool_name_long(i_avl_som) = 'soil 3' - decomp_cascade_con%decomp_pool_name_short(i_avl_som) = 'S3' - is_microbe(i_avl_som) = .false. - is_litter(i_avl_som) = .false. - is_soil(i_avl_som) = .true. - is_cwd(i_avl_som) = .false. - initial_cn_ratio(i_avl_som) = 10._r8 ! cn_s3 in BGC; not used in MIMICS - initial_stock(i_avl_som) = params_inst%initial_Cstocks(i_avl_som) - is_metabolic(i_avl_som) = .false. - is_cellulose(i_avl_som) = .false. - is_lignin(i_avl_som) = .false. - - i_cop_mic = i_avl_som + 1 + i_act_som = i_str_lit + 1 + floating_cn_ratio_decomp_pools(i_act_som) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_act_som) = 'soil1' + decomp_cascade_con%decomp_pool_name_history(i_act_som) = 'ACT_SOM' + decomp_cascade_con%decomp_pool_name_long(i_act_som) = 'active soil organic matter' + decomp_cascade_con%decomp_pool_name_short(i_act_som) = 'S1' + is_microbe(i_act_som) = .false. + is_litter(i_act_som) = .false. + is_soil(i_act_som) = .true. + is_cwd(i_act_som) = .false. + initial_cn_ratio(i_act_som) = 10._r8 ! cn_s1 in BGC; not used in MIMICS + initial_stock(i_act_som) = params_inst%initial_Cstocks(i_act_som) + is_metabolic(i_act_som) = .false. + is_cellulose(i_act_som) = .false. + is_lignin(i_act_som) = .false. + + i_slo_som = i_act_som + 1 + floating_cn_ratio_decomp_pools(i_slo_som) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_slo_som) = 'soil2' + decomp_cascade_con%decomp_pool_name_history(i_slo_som) = 'SLO_SOM' + decomp_cascade_con%decomp_pool_name_long(i_slo_som) = 'slow soil organic matter' + decomp_cascade_con%decomp_pool_name_short(i_slo_som) = 'S2' + is_microbe(i_slo_som) = .false. + is_litter(i_slo_som) = .false. + is_soil(i_slo_som) = .true. + is_cwd(i_slo_som) = .false. + initial_cn_ratio(i_slo_som) = 10._r8 ! cn_s2 in BGC; not used in MIMICS + initial_stock(i_slo_som) = params_inst%initial_Cstocks(i_slo_som) + is_metabolic(i_slo_som) = .false. + is_cellulose(i_slo_som) = .false. + is_lignin(i_slo_som) = .false. + + i_pas_som = i_slo_som + 1 + floating_cn_ratio_decomp_pools(i_pas_som) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_pas_som) = 'soil3' + decomp_cascade_con%decomp_pool_name_history(i_pas_som) = 'PAS_SOM' + decomp_cascade_con%decomp_pool_name_long(i_pas_som) = 'passive soil organic matter' + decomp_cascade_con%decomp_pool_name_short(i_pas_som) = 'S3' + is_microbe(i_pas_som) = .false. + is_litter(i_pas_som) = .false. + is_soil(i_pas_som) = .true. + is_cwd(i_pas_som) = .false. + initial_cn_ratio(i_pas_som) = 10._r8 ! cn_s3 in BGC; not used in MIMICS + initial_stock(i_pas_som) = params_inst%initial_Cstocks(i_pas_som) + is_metabolic(i_pas_som) = .false. + is_cellulose(i_pas_som) = .false. + is_lignin(i_pas_som) = .false. + + i_cop_mic = i_pas_som + 1 floating_cn_ratio_decomp_pools(i_cop_mic) = .true. decomp_cascade_con%decomp_pool_name_restart(i_cop_mic) = 'micr1' - decomp_cascade_con%decomp_pool_name_history(i_cop_mic) = 'MICR1' - decomp_cascade_con%decomp_pool_name_long(i_cop_mic) = 'microbial 1' + decomp_cascade_con%decomp_pool_name_history(i_cop_mic) = 'COP_MIC' + decomp_cascade_con%decomp_pool_name_long(i_cop_mic) = 'copiotrophic microbes' decomp_cascade_con%decomp_pool_name_short(i_cop_mic) = 'M1' is_microbe(i_cop_mic) = .true. is_litter(i_cop_mic) = .false. @@ -463,8 +463,8 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_oli_mic = i_cop_mic + 1 floating_cn_ratio_decomp_pools(i_oli_mic) = .true. decomp_cascade_con%decomp_pool_name_restart(i_oli_mic) = 'micr2' - decomp_cascade_con%decomp_pool_name_history(i_oli_mic) = 'MICR2' - decomp_cascade_con%decomp_pool_name_long(i_oli_mic) = 'microbial 2' + decomp_cascade_con%decomp_pool_name_history(i_oli_mic) = 'OLI_MIC' + decomp_cascade_con%decomp_pool_name_long(i_oli_mic) = 'oligotrophic microbes' decomp_cascade_con%decomp_pool_name_short(i_oli_mic) = 'M2' is_microbe(i_oli_mic) = .true. is_litter(i_oli_mic) = .false. @@ -505,9 +505,9 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat spinup_factor(i_cwd) = max(1._r8, (speedup_fac * params_inst%tau_cwd_bgc / 2._r8 )) end if !som1,2,3 - spinup_factor(i_pro_som) = 1._r8 - spinup_factor(i_rec_som) = 1._r8 ! BGC used cwd formula above but - spinup_factor(i_avl_som) = 1._r8 ! ...w the respective tau_s values + spinup_factor(i_act_som) = 1._r8 + spinup_factor(i_slo_som) = 1._r8 ! BGC used cwd formula above but + spinup_factor(i_pas_som) = 1._r8 ! ...w the respective tau_s values ! micr1,2 spinup_factor(i_cop_mic) = 1._r8 spinup_factor(i_oli_mic) = 1._r8 @@ -535,7 +535,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_s3m1 = 3 decomp_cascade_con%cascade_step_name(i_s3m1) = 'S3M1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = rf_s3m1 - cascade_donor_pool(i_s3m1) = i_avl_som + cascade_donor_pool(i_s3m1) = i_pas_som cascade_receiver_pool(i_s3m1) = i_cop_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = 1.0_r8 @@ -556,7 +556,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_s3m2 = 6 decomp_cascade_con%cascade_step_name(i_s3m2) = 'S3M2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = rf_s3m2 - cascade_donor_pool(i_s3m2) = i_avl_som + cascade_donor_pool(i_s3m2) = i_pas_som cascade_receiver_pool(i_s3m2) = i_oli_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = 1.0_r8 @@ -564,15 +564,15 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_s1s3 = 7 decomp_cascade_con%cascade_step_name(i_s1s3) = 'S1S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) - cascade_donor_pool(i_s1s3) = i_pro_som - cascade_receiver_pool(i_s1s3) = i_avl_som + cascade_donor_pool(i_s1s3) = i_act_som + cascade_receiver_pool(i_s1s3) = i_pas_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) i_s2s3 = 8 decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 - cascade_donor_pool(i_s2s3) = i_rec_som - cascade_receiver_pool(i_s2s3) = i_avl_som + cascade_donor_pool(i_s2s3) = i_slo_som + cascade_receiver_pool(i_s2s3) = i_pas_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = f_s2s3 if (.not. use_fates) then @@ -718,20 +718,20 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & endif endif ! - if ( abs(spinup_factor(i_pro_som) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_s1(c) = spinup_factor(i_pro_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_act_som) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s1(c) = spinup_factor(i_act_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s1(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_rec_som) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_s2(c) = spinup_factor(i_rec_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_slo_som) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s2(c) = spinup_factor(i_slo_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s2(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_avl_som) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_s3(c) = spinup_factor(i_avl_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_pas_som) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s3(c) = spinup_factor(i_pas_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s3(c) = 1._r8 endif @@ -968,15 +968,15 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & (km_l2_m2 + m2_pool(c,j))) * & w_d_o_scalars - decomp_k(c,j,i_avl_som) = (vmax_s3_m1 * m1_pool(c,j) / & + decomp_k(c,j,i_pas_som) = (vmax_s3_m1 * m1_pool(c,j) / & (km_s3_m1 + m1_pool(c,j))) * & w_d_o_scalars - decomp_k(c,j,i_avl_som) = (vmax_s3_m2 * m2_pool(c,j) / & + decomp_k(c,j,i_pas_som) = (vmax_s3_m2 * m2_pool(c,j) / & (km_s3_m2 + m2_pool(c,j))) * & w_d_o_scalars - decomp_k(c,j,i_pro_som) = k_s1_s3 * w_d_o_scalars - decomp_k(c,j,i_rec_som) = k_s2_s3 * w_d_o_scalars + decomp_k(c,j,i_act_som) = k_s1_s3 * w_d_o_scalars + decomp_k(c,j,i_slo_som) = k_s2_s3 * w_d_o_scalars decomp_k(c,j,i_cop_mic) = tau_m1_s1 * m1_pool(c,j)**(densdep) * & fphys(c) * w_d_o_scalars From 65d47da0d81240281ec70b7419fb72f79268e3ef Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 12 Jul 2021 15:59:51 -0600 Subject: [PATCH 12/69] Working on the tau calculations --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 89 +++++++++++-------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 85a5753bc0..d71734f5be 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -104,11 +104,10 @@ subroutine readParams ( ncid ) ! Read off of netcdf file ! TODO Add new params here and in the params file. ! TODO tau_s1, tau_s2, etc may need _bgc added/removed here/params file - ! TODO Read MIMICS-specific params here & shared ones (eg *_bgc) like this: + ! TODO Read MIMICS-specific params here & shared ones (eg *_bgc) as: ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding - ! TODO If Melannie's testbed values differ from the BGC values, - ! make separate _mimics params. - ! TODO When ready for all final params values, talk to @wwieder + ! TODO When ready for all final params values, talk to @wwieder and, + ! if values differ from the BGC values, make separate _mimics params. tString='tau_s1_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -894,10 +893,54 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do ! calculate rates for all litter and som pools - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - ! vmax, tau, and km are time-dependent terms. + ! TODO Ok that I reversed order of do-loops for convenience? + do fc = 1,num_soilc + c = filter_soilc(fc) + + ! TODO Move all to the params files + fmet_p1 = 0.85 + fmet_p2 = 0.85 + fmet_p3 = 0.013 + tauMod_denom = 100.0_r8 ! For efficiency put _factor in params files + tauMod_factor = 1.0_r8 / tauMod_denom ! ...instead of _denom? + tauMod_min = 0.8_r8 + tauMod_max = 1.2_r8 + tau_r1 = 5.2e-4_r8 + tau_r2 = 0.3_r8 ! or 0.4? + tau_k1 = 2.4e-4_r8 + tau_k2 = 0.1_r8 + + ! Time-dependent params from Wieder et al. 2015 & testbed code + ! TODO STILL MISSING N-related stuff: DIN... + + ! TODO LOOK FOR EXISTING ligninNratioAvg or calculate as follows + ligninNratioAvg(c) = & + (ligninNratio(c,leaf) * (cleaf2met(c) + cleaf2str(c)) + & + ligninNratio(c,froot) * (croot2met(c) + croot2str(c)) + & + ligninNratio(c,wood) * (cwd2str(c))) / & + max(0.001, cleaf2met(c) + cleaf2str(c) + & + croot2met(c) + croot2str(c) + cwd2str(c)) + + ! Set limits on Lignin:N to keep fmet > 0.2 + ! Necessary for litter quality in boreal forests with high cwd flux + fmet = fmet_p1 * (fmet_p2 - fmet_p3 * min(40.0_r8, & + ligninNratioAvg(c))) + ! TODO LOOK FOR EXISTING avg_ann_npp_gC_m2_yr or calculate + tauMod = min(tauMod_max, max(tauMod_min, & + sqrt(avg_ann_npp_gC_m2_yr(c) * & + tauMod_factor))) + + ! tau_m1_s* are tauR and tau_m2_s* are tauK in Wieder et al. 2015 + ! and are time-dependent terms + tau_m1_s1 = tau_r1 * exp(tau_r2 * fmet) * tauMod + tau_m1_s2 = tau_r1 * exp(tau_r2 * fmet) * tauMod + tau_m1_s3 = tau_r1 * exp(tau_r2 * fmet) * tauMod + tau_m2_s1 = tau_k1 * exp(tau_k2 * fmet) * tauMod + tau_m2_s2 = tau_k1 * exp(tau_k2 * fmet) * tauMod + tau_m2_s3 = tau_k1 * exp(tau_k2 * fmet) * tauMod + + do j = 1,nlevdecomp + ! vmax are time-dependent terms ! Table B1 Wieder et al. (2015) & MIMICS params file give different ! kslope. I used the params file value(s). ! TODO Introduce t_soi24_degC_col following t_veg24_patch (running @@ -909,6 +952,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & vmax_s3_m1 = exp(vslope_s3_m1 * t_soi24_degC_col(c,j) + vint_s3_m1) * vmod_l2_m1 vmax_s3_m2 = exp(vslope_s3_m2 * t_soi24_degC_col(c,j) + vint_s3_m2) * vmod_l2_m2 + ! km are time-dependent terms km_l1_m1 = exp(kslope_l1_m1 * t_soi24_degC_col(c,j) + kint_l1_m1) * kmod_l1_m1 km_l1_m2 = exp(kslope_l1_m2 * t_soi24_degC_col(c,j) + kint_l1_m2) * kmod_l1_m2 km_l2_m1 = exp(kslope_l2_m1 * t_soi24_degC_col(c,j) + kint_l2_m1) * kmod_l2_m1 @@ -916,35 +960,6 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & km_s3_m1 = exp(kslope_s3_m1 * t_soi24_degC_col(c,j) + kint_s3_m1) * kmod_s3_m1 / p_scalar(c,j) km_s3_m2 = exp(kslope_s3_m2 * t_soi24_degC_col(c,j) + kint_s3_m2) * kmod_s3_m2 / p_scalar(c,j) -! TODO mapping tau params to Wieder et al. 2015 & testbed code -! -------------------------------------------------------------- -! tau* are time-dependent - -! Solving for tauR (tau_m1_s* here) & tauK (tau_m2_s* here) - -! fmet_p(1) = 0.85, fmet_p(2) = 0.85, fmet_p(3) = 0.013 -! ligninNratioAvg(npt) = & -! ( ligninNratio(npt,leaf) * (cleaf2met(npt) + cleaf2str(npt)) & -! + ligninNratio(npt,froot) * (croot2met(npt) + croot2str(npt)) & -! + ligninNratio(npt,wood) * (cwd2str(npt)) ) & -! / max(0.001, cleaf2met(npt)+cleaf2str(npt)+croot2met(npt)+croot2str(npt)+cwd2str(npt)) -! set limits on Lignin:N to keep fmet > 0.2 -! necessary for litter quality in boreal forests with high cwd flux -! ligninNratioAvg(npt) = min(40.0, ligninNratioAvg(npt)) -! fmet(npt) = fmet_p(1) * (fmet_p(2) - fmet_p(3) * ligninNratioAvg(npt)) - -! tauModDenom = 100, tauMod_min = 0.8, tauMod_max = 1.2 -! tauMod(npt) = sqrt(avg_ann_npp_gC_m2_yr / tauModDenom) -! tauMod(npt) = min(tauMod_max, max(tauMod_min, tauMod(npt))) - -! tau_r(1) = 5.2e-4_r8, tau_r(2) = 0.3_r8 or 0.4? -! tauR(npt) = tau_r(1) * exp(tau_r(2) * fmet(npt)) * tauMod(npt) - -! tau_k(1) = 2.4e-4_r8, tau_k(2) = 0.1_r8 -! tauK(npt) = tau_k(1) * exp(tau_k(2) * fmet(npt)) * tauMod(npt) -! -------------------------------------------------------------- -! TODO STILL MISSING N-related stuff: DIN... - ! Product of w_scalar * depth_scalar * o_scalar w_d_o_scalars = w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) From 39d51b68a2d0d4ca4a7e16666851e794fc0eb177 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 12 Jul 2021 16:53:06 -0600 Subject: [PATCH 13/69] Comment updates... --- src/biogeochem/CNNDynamicsMod.F90 | 2 +- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/biogeochem/CNNDynamicsMod.F90 b/src/biogeochem/CNNDynamicsMod.F90 index 216f8c23ff..205ff1e8f1 100644 --- a/src/biogeochem/CNNDynamicsMod.F90 +++ b/src/biogeochem/CNNDynamicsMod.F90 @@ -218,7 +218,7 @@ subroutine CNNFixation(num_soilc, filter_soilc, & !----------------------------------------------------------------------- associate( & - cannsum_npp => cnveg_carbonflux_inst%annsum_npp_col , & ! Input: [real(r8) (:)] nitrogen deposition rate (gN/m2/s) + cannsum_npp => cnveg_carbonflux_inst%annsum_npp_col , & ! Input: [real(r8) (:)] (gC/m2/yr) annual sum of NPP, averaged from patch-level col_lag_npp => cnveg_carbonflux_inst%lag_npp_col , & ! Input: [real(r8) (:)] (gC/m2/s) lagged net primary production nfix_to_sminn => soilbiogeochem_nitrogenflux_inst%nfix_to_sminn_col & ! Output: [real(r8) (:)] symbiotic/asymbiotic N fixation to soil mineral N (gN/m2/s) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index d71734f5be..aba88a0de1 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -913,7 +913,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Time-dependent params from Wieder et al. 2015 & testbed code ! TODO STILL MISSING N-related stuff: DIN... - ! TODO LOOK FOR EXISTING ligninNratioAvg or calculate as follows + ! TODO I don't see existing ligninNratioAvg, so calculate ligninNratioAvg(c) = & (ligninNratio(c,leaf) * (cleaf2met(c) + cleaf2str(c)) + & ligninNratio(c,froot) * (croot2met(c) + croot2str(c)) + & @@ -925,10 +925,12 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Necessary for litter quality in boreal forests with high cwd flux fmet = fmet_p1 * (fmet_p2 - fmet_p3 * min(40.0_r8, & ligninNratioAvg(c))) - ! TODO LOOK FOR EXISTING avg_ann_npp_gC_m2_yr or calculate + ! TODO USE cnveg_carbonflux_inst%annsum_npp_col (gC/m2/yr) updated 1/yr + ! OR annavg_[ag+bg]npp_patch (gC/m2/s) from ch4Mod + ! OR calculate an annual running mean with accumulMod? tauMod = min(tauMod_max, max(tauMod_min, & - sqrt(avg_ann_npp_gC_m2_yr(c) * & - tauMod_factor))) + sqrt(tauMod_factor * & + cnveg_carbonflux_inst%annsum_npp_col(c)))) ! tau_m1_s* are tauR and tau_m2_s* are tauK in Wieder et al. 2015 ! and are time-dependent terms From 7662239ff335b1c2a9946d50e2946da820acdbd6 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 13 Jul 2021 18:50:21 -0600 Subject: [PATCH 14/69] Updates from today's code review with @wwieder --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 420 +++++++++--------- 1 file changed, 203 insertions(+), 217 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index aba88a0de1..26b924a67f 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -41,17 +41,14 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! !PRIVATE DATA MEMBERS integer, private :: i_pas_som ! index of passive (aka protected) Soil Organic Matter (SOM) integer, private :: i_slo_som ! index of slow (aka recalcitrant) SOM - integer, private :: i_act_som ! index of active (aka available) SOM + integer, private :: i_avl_som ! index of available (aka active) SOM integer, private :: i_str_lit ! index of structural litter pool integer, private :: i_cop_mic ! index of copiotrophic microbial pool integer, private :: i_oli_mic ! index of oligotrophic microbial pool type, private :: params_type - real(r8):: rf_s2s3_bgc ! Respiration fraction cwd --> structural litter (keep comment sep for dif) real(r8):: rf_cwdl2_bgc - real(r8):: tau_s1_bgc ! 1/turnover time of SOM 1 from Century (1/7.3) (1/yr) - real(r8):: tau_s2_bgc ! 1/turnover time of SOM 2 from Century (1/0.2) (1/yr) real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) real(r8) :: cwd_fcel_bgc !cellulose fraction for CWD @@ -103,31 +100,16 @@ subroutine readParams ( ncid ) ! Read off of netcdf file ! TODO Add new params here and in the params file. - ! TODO tau_s1, tau_s2, etc may need _bgc added/removed here/params file + ! TODO Some may need _bgc added/removed here and in the params file ! TODO Read MIMICS-specific params here & shared ones (eg *_bgc) as: ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding ! TODO When ready for all final params values, talk to @wwieder and, ! if values differ from the BGC values, make separate _mimics params. - tString='tau_s1_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_s1_bgc=tempr - - tString='tau_s2_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_s2_bgc=tempr - tString='tau_cwd_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_cwd_bgc=tempr - tString='rf_s2s3_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_s2s3_bgc=tempr - ! MIMICS value = 0 (same as BGC value) tString='rf_cwdl2_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) @@ -219,39 +201,39 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat !-- properties of each decomposing pool real(r8) :: rf_l1m1 real(r8) :: rf_l2m1 - real(r8) :: rf_s3m1 + real(r8) :: rf_s1m1 real(r8) :: rf_l1m2 real(r8) :: rf_l2m2 - real(r8) :: rf_s3m2 - real(r8), allocatable :: rf_s1s3(:,:) - real(r8) :: rf_s2s3 + real(r8) :: rf_s1m2 real(r8) :: rf_cwdl2 real(r8) :: cwd_fcel real(r8) :: cwd_flig - real(r8), allocatable :: f_s1s3(:,:) - real(r8) :: f_s2s3 real(r8), allocatable :: p_scalar(:,:) integer :: i_l1m1 integer :: i_l2m1 - integer :: i_s3m1 + integer :: i_s1m1 integer :: i_l1m2 integer :: i_l2m2 - integer :: i_s3m2 - integer :: i_s1s3 - integer :: i_s2s3 + integer :: i_s1m2 + integer :: i_s3s1 + integer :: i_s2s1 + integer :: i_m1s1 + integer :: i_m1s2 + integer :: i_m1s3 + integer :: i_m2s1 + integer :: i_m2s2 + integer :: i_m2s3 integer :: i_cwdl2 real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. integer :: c, j ! indices - real(r8) :: t ! temporary variable !----------------------------------------------------------------------- associate( & rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) - cellsand => soilstate_inst%cellsand_col , & ! Input: [real(r8) (:,:) ] column 3D sand cellclay => soilstate_inst%cellclay_col , & ! Input: [real(r8) (:,:) ] column 3D clay cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Output: [integer (:) ] which pool is C taken from for a given decomposition step @@ -271,80 +253,65 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat ) - allocate(rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp)) - allocate(f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp)) allocate(p_scalar(bounds%begc:bounds%endc,1:nlevdecomp)) !------- time-constant coefficients ---------- ! ! set respiration fractions for fluxes between compartments rf_l1m1 = 1.0_r8 - params_inst%mge(1) rf_l2m1 = 1.0_r8 - params_inst%mge(2) - rf_s3m1 = 1.0_r8 - params_inst%mge(3) + rf_s1m1 = 1.0_r8 - params_inst%mge(3) rf_l1m2 = 1.0_r8 - params_inst%mge(4) rf_l2m2 = 1.0_r8 - params_inst%mge(5) - rf_s3m2 = 1.0_r8 - params_inst%mge(6) + rf_s1m2 = 1.0_r8 - params_inst%mge(6) - rf_s2s3 = params_inst%rf_s2s3_bgc rf_cwdl2 = params_inst%rf_cwdl2_bgc - ! set the structural fraction for coarse woody debris - ! TODO Renamed LHS to cwd_fstr. Make RHS = sum or avg of the two? - cwd_fstr = min(1.0_r8, & - params_inst%cwd_fcel_bgc + params_inst%cwd_flig_bgc) - ! vmod = "old" vmod * av AND kmod = ak / "old" kmod - ! Table B1 Wieder et al. (2015) and MIMICS params file give different + ! Table B1 Wieder et al. (2015) and MIMICS params file give diff ! ak and av values. I used the params file values. - vmod_l1m1 = params_inst%vmod(1) - vmod_l2m1 = params_inst%vmod(2) - vmod_s3m1 = params_inst%vmod(3) - vmod_l1m2 = params_inst%vmod(4) - vmod_l2m2 = params_inst%vmod(5) - vmod_s3m2 = params_inst%vmod(6) - kmod_l1m1 = params_inst%kmod(1) - kmod_l2m1 = params_inst%kmod(2) - kmod_s3m1 = params_inst%kmod(3) - kmod_l1m2 = params_inst%kmod(4) - kmod_l2m2 = params_inst%kmod(5) - kmod_s3m2 = params_inst%kmod(6) - vslope_l1m1 = params_inst%vslope(1) - vslope_l2m1 = params_inst%vslope(2) - vslope_s3m1 = params_inst%vslope(3) - vslope_l1m2 = params_inst%vslope(4) - vslope_l2m2 = params_inst%vslope(5) - vslope_s3m2 = params_inst%vslope(6) - kslope_l1m1 = params_inst%kslope(1) - kslope_l2m1 = params_inst%kslope(2) - kslope_s3m1 = params_inst%kslope(3) - kslope_l1m2 = params_inst%kslope(4) - kslope_l2m2 = params_inst%kslope(5) - kslope_s3m2 = params_inst%kslope(6) - vint_l1m1 = params_inst%vint(1) - vint_l2m1 = params_inst%vint(2) - vint_s3m1 = params_inst%vint(3) - vint_l1m2 = params_inst%vint(4) - vint_l2m2 = params_inst%vint(5) - vint_s3m2 = params_inst%vint(6) - kint_l1m1 = params_inst%kint(1) - kint_l2m1 = params_inst%kint(2) - kint_s3m1 = params_inst%kint(3) - kint_l1m2 = params_inst%kint(4) - kint_l2m2 = params_inst%kint(5) - kint_s3m2 = params_inst%kint(6) - - ! set path fractions - f_s2s3 = 0.03_r8/(0.45_r8) + vmod_l1_m1 = params_inst%vmod(1) + vmod_l2_m1 = params_inst%vmod(2) + vmod_s1_m1 = params_inst%vmod(3) + vmod_l1_m2 = params_inst%vmod(4) + vmod_l2_m2 = params_inst%vmod(5) + vmod_s1_m2 = params_inst%vmod(6) + kmod_l1_m1 = params_inst%kmod(1) + kmod_l2_m1 = params_inst%kmod(2) + kmod_s1_m1 = params_inst%kmod(3) + kmod_l1_m2 = params_inst%kmod(4) + kmod_l2_m2 = params_inst%kmod(5) + kmod_s1_m2 = params_inst%kmod(6) + vslope_l1_m1 = params_inst%vslope(1) + vslope_l2_m1 = params_inst%vslope(2) + vslope_s1_m1 = params_inst%vslope(3) + vslope_l1_m2 = params_inst%vslope(4) + vslope_l2_m2 = params_inst%vslope(5) + vslope_s1_m2 = params_inst%vslope(6) + kslope_l1_m1 = params_inst%kslope(1) + kslope_l2_m1 = params_inst%kslope(2) + kslope_s1_m1 = params_inst%kslope(3) + kslope_l1_m2 = params_inst%kslope(4) + kslope_l2_m2 = params_inst%kslope(5) + kslope_s1_m2 = params_inst%kslope(6) + vint_l1_m1 = params_inst%vint(1) + vint_l2_m1 = params_inst%vint(2) + vint_s1_m1 = params_inst%vint(3) + vint_l1_m2 = params_inst%vint(4) + vint_l2_m2 = params_inst%vint(5) + vint_s1_m2 = params_inst%vint(6) + kint_l1_m1 = params_inst%kint(1) + kint_l2_m1 = params_inst%kint(2) + kint_s1_m1 = params_inst%kint(3) + kint_l1_m2 = params_inst%kint(4) + kint_l2_m2 = params_inst%kint(5) + kint_s1_m2 = params_inst%kint(6) ! some of these are dependent on the soil texture properties - ! TODO rf_s1s3 -> rf_decomp_cascade as template for p_scalar? - ! One-time initializations here. + ! TODO One-time initializations here. ! Time-dep params in subr. decomp_rates_mimics. do c = bounds%begc, bounds%endc do j = 1, nlevdecomp - t = 0.85_r8 - 0.68_r8 * 0.01_r8 * (100._r8 - cellsand(c,j)) - f_s1s3(c,j) = .004_r8 / (1._r8 - t) - rf_s1s3(c,j) = t p_scalar(c,j) = (0.8_r8 * exp(-3.0_r8 * sqrt(cellclay(c,j))))** & (-1.0_r8) end do @@ -395,23 +362,23 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat errMsg(sourcefile, __LINE__)) end if - i_act_som = i_str_lit + 1 - floating_cn_ratio_decomp_pools(i_act_som) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_act_som) = 'soil1' - decomp_cascade_con%decomp_pool_name_history(i_act_som) = 'ACT_SOM' - decomp_cascade_con%decomp_pool_name_long(i_act_som) = 'active soil organic matter' - decomp_cascade_con%decomp_pool_name_short(i_act_som) = 'S1' - is_microbe(i_act_som) = .false. - is_litter(i_act_som) = .false. - is_soil(i_act_som) = .true. - is_cwd(i_act_som) = .false. - initial_cn_ratio(i_act_som) = 10._r8 ! cn_s1 in BGC; not used in MIMICS - initial_stock(i_act_som) = params_inst%initial_Cstocks(i_act_som) - is_metabolic(i_act_som) = .false. - is_cellulose(i_act_som) = .false. - is_lignin(i_act_som) = .false. - - i_slo_som = i_act_som + 1 + i_avl_som = i_str_lit + 1 + floating_cn_ratio_decomp_pools(i_avl_som) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_avl_som) = 'soil1' + decomp_cascade_con%decomp_pool_name_history(i_avl_som) = 'AVL_SOM' + decomp_cascade_con%decomp_pool_name_long(i_avl_som) = 'available soil organic matter' + decomp_cascade_con%decomp_pool_name_short(i_avl_som) = 'S1' + is_microbe(i_avl_som) = .false. + is_litter(i_avl_som) = .false. + is_soil(i_avl_som) = .true. + is_cwd(i_avl_som) = .false. + initial_cn_ratio(i_avl_som) = 10._r8 ! cn_s1 in BGC; not used in MIMICS + initial_stock(i_avl_som) = params_inst%initial_Cstocks(i_avl_som) + is_metabolic(i_avl_som) = .false. + is_cellulose(i_avl_som) = .false. + is_lignin(i_avl_som) = .false. + + i_slo_som = i_avl_som + 1 floating_cn_ratio_decomp_pools(i_slo_som) = .true. decomp_cascade_con%decomp_pool_name_restart(i_slo_som) = 'soil2' decomp_cascade_con%decomp_pool_name_history(i_slo_som) = 'SLO_SOM' @@ -504,7 +471,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat spinup_factor(i_cwd) = max(1._r8, (speedup_fac * params_inst%tau_cwd_bgc / 2._r8 )) end if !som1,2,3 - spinup_factor(i_act_som) = 1._r8 + spinup_factor(i_avl_som) = 1._r8 spinup_factor(i_slo_som) = 1._r8 ! BGC used cwd formula above but spinup_factor(i_pas_som) = 1._r8 ! ...w the respective tau_s values ! micr1,2 @@ -531,12 +498,12 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_receiver_pool(i_l2m1) = i_cop_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1)= 1.0_r8 - i_s3m1 = 3 - decomp_cascade_con%cascade_step_name(i_s3m1) = 'S3M1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = rf_s3m1 - cascade_donor_pool(i_s3m1) = i_pas_som - cascade_receiver_pool(i_s3m1) = i_cop_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m1) = 1.0_r8 + i_s1m1 = 3 + decomp_cascade_con%cascade_step_name(i_s1m1) = 'S1M1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = rf_s1m1 + cascade_donor_pool(i_s1m1) = i_avl_som + cascade_receiver_pool(i_s1m1) = i_cop_mic + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = 1.0_r8 i_l1m2 = 4 decomp_cascade_con%cascade_step_name(i_l1m2) = 'L1M2' @@ -552,39 +519,78 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_receiver_pool(i_l2m2) = i_oli_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2)= 1.0_r8 - i_s3m2 = 6 - decomp_cascade_con%cascade_step_name(i_s3m2) = 'S3M2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = rf_s3m2 - cascade_donor_pool(i_s3m2) = i_pas_som - cascade_receiver_pool(i_s3m2) = i_oli_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3m2) = 1.0_r8 - - ! TODO If keeping s1_s3 & s2_s3 code, is pathfrac correct or should = 1? - i_s1s3 = 7 - decomp_cascade_con%cascade_step_name(i_s1s3) = 'S1S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) - cascade_donor_pool(i_s1s3) = i_act_som - cascade_receiver_pool(i_s1s3) = i_pas_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) - - i_s2s3 = 8 - decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 - cascade_donor_pool(i_s2s3) = i_slo_som - cascade_receiver_pool(i_s2s3) = i_pas_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = f_s2s3 + i_s1m2 = 6 + decomp_cascade_con%cascade_step_name(i_s1m2) = 'S1M2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m2) = rf_s1m2 + cascade_donor_pool(i_s1m2) = i_avl_som + cascade_receiver_pool(i_s1m2) = i_oli_mic + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m2) = 1.0_r8 + + i_s3s1 = 7 + decomp_cascade_con%cascade_step_name(i_s3s1) = 'S3S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 0.0_r8 + cascade_donor_pool(i_s3s1) = i_pas_som + cascade_receiver_pool(i_s3s1) = i_avl_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 + + i_s2s1 = 8 + decomp_cascade_con%cascade_step_name(i_s2s1) = 'S2S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = 0.0_r8 + cascade_donor_pool(i_s2s1) = i_slo_som + cascade_receiver_pool(i_s2s1) = i_avl_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = 1.0_r8 + + i_m1s1 = 9 + decomp_cascade_con%cascade_step_name(i_m1s1) = 'M1S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = rf_m1s1 + cascade_donor_pool(i_m1s1) = i_cop_mic + cascade_receiver_pool(i_m1s1) = i_avl_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = fphys ! TODO fphys is a function of clay + + i_m1s2 = 10 + decomp_cascade_con%cascade_step_name(i_m1s2) = 'M1S2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = rf_m1s2 + cascade_donor_pool(i_m1s2) = i_cop_mic + cascade_receiver_pool(i_m1s2) = i_slo_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = fchem ! TODO fchem is a function of litter quality (fmet) + + i_m1s3 = 11 + decomp_cascade_con%cascade_step_name(i_m1s3) = 'M1S3' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = rf_m1s3 + cascade_donor_pool(i_m1s3) = i_cop_mic + cascade_receiver_pool(i_m1s3) = i_pas_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = faval ! TODO faval = 1 - fphys - fchem + + i_m2s1 = 12 + decomp_cascade_con%cascade_step_name(i_m2s1) = 'M2S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = rf_m2s1 + cascade_donor_pool(i_m2s1) = i_oli_mic + cascade_receiver_pool(i_m2s1) = i_avl_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = fphys + + i_m2s2 = 13 + decomp_cascade_con%cascade_step_name(i_m2s2) = 'M2S2' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = rf_m2s2 + cascade_donor_pool(i_m2s2) = i_oli_mic + cascade_receiver_pool(i_m2s2) = i_slo_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = fchem + + i_m2s3 = 14 + decomp_cascade_con%cascade_step_name(i_m2s3) = 'M2S3' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = rf_m2s3 + cascade_donor_pool(i_m2s3) = i_oli_mic + cascade_receiver_pool(i_m2s3) = i_pas_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = faval if (.not. use_fates) then - i_cwdl2 = 9 + i_cwdl2 = 15 decomp_cascade_con%cascade_step_name(i_cwdl2) = 'CWDL2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 cascade_donor_pool(i_cwdl2) = i_cwd cascade_receiver_pool(i_cwdl2) = i_str_lit - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fstr + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = 1.0_r8 end if - deallocate(rf_s1s3) - deallocate(f_s1s3) deallocate(p_scalar) deallocate(params_inst%mge) deallocate(params_inst%vmod) @@ -624,27 +630,21 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & real(r8):: frw(bounds%begc:bounds%endc) ! rooting fraction weight real(r8), allocatable:: fr(:,:) ! column-level rooting fraction by soil depth real(r8):: psi ! temporary soilpsi for water scalar - real(r8):: k_s1_s3 ! decomposition rate SOM 1 (1/sec) - real(r8):: k_s2_s3 ! decomposition rate SOM 2 (1/sec) real(r8):: k_frag ! fragmentation rate constant CWD (1/sec) real(r8):: vmax_l1_m1 ! real(r8):: vmax_l2_m1 ! - real(r8):: vmax_s3_m1 ! + real(r8):: vmax_s1_m1 ! real(r8):: vmax_l1_m2 ! real(r8):: vmax_l2_m2 ! - real(r8):: vmax_s3_m2 ! + real(r8):: vmax_s1_m2 ! real(r8):: km_l1_m1 ! real(r8):: km_l2_m1 ! - real(r8):: km_s3_m1 ! + real(r8):: km_s1_m1 ! real(r8):: km_l1_m2 ! real(r8):: km_l2_m2 ! - real(r8):: km_s3_m2 ! - real(r8):: tau_m1_s1 ! - real(r8):: tau_m1_s2 ! - real(r8):: tau_m1_s3 ! - real(r8):: tau_m2_s1 ! - real(r8):: tau_m2_s2 ! - real(r8):: tau_m2_s3 ! + real(r8):: km_s1_m2 ! + real(r8):: tau_m1 ! + real(r8):: tau_m2 ! real(r8):: decomp_depth_efolding ! (meters) e-folding depth for reduction in decomposition [ integer :: c, fc, j, k, l real(r8):: days_per_year ! days per year @@ -688,8 +688,6 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! translate to per-second time constant ! TODO vmax, km, tau terms replaced (most?) k_ terms; CONFIRM s-1 UNITS - k_s1_s3 = 1._r8 / (secspday * days_per_year * params_inst%tau_s1_bgc) - k_s2_s3 = 1._r8 / (secspday * days_per_year * params_inst%tau_s2_bgc) k_frag = 1._r8 / (secspday * days_per_year * params_inst%tau_cwd_bgc) ! calc ref rate @@ -717,8 +715,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & endif endif ! - if ( abs(spinup_factor(i_act_som) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_s1(c) = spinup_factor(i_act_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_avl_som) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s1(c) = spinup_factor(i_avl_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s1(c) = 1._r8 endif @@ -810,7 +808,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do - ! TODO @wwieder concerned about breaking ch4 code + ! TODO May need a hook from MIMICS to ch4 code for this to work if (use_lch4) then ! Calculate ANOXIA if (anoxia) then @@ -901,19 +899,22 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & fmet_p1 = 0.85 fmet_p2 = 0.85 fmet_p3 = 0.013 - tauMod_denom = 100.0_r8 ! For efficiency put _factor in params files - tauMod_factor = 1.0_r8 / tauMod_denom ! ...instead of _denom? + tauMod_factor = 0.01_r8 ! was tauMod_denom = 100 tauMod_min = 0.8_r8 tauMod_max = 1.2_r8 tau_r1 = 5.2e-4_r8 tau_r2 = 0.3_r8 ! or 0.4? tau_k1 = 2.4e-4_r8 tau_k2 = 0.1_r8 + densdep = 1.0_r8 ! Time-dependent params from Wieder et al. 2015 & testbed code ! TODO STILL MISSING N-related stuff: DIN... - ! TODO I don't see existing ligninNratioAvg, so calculate + ! TODO cleaf2met is leaf carbon to metabolic litter + ! Similarly the others + ! Rethink this as the sum of input to met + str litter? + ! @wwieder will investigate. ligninNratioAvg(c) = & (ligninNratio(c,leaf) * (cleaf2met(c) + cleaf2str(c)) + & ligninNratio(c,froot) * (croot2met(c) + croot2str(c)) + & @@ -925,92 +926,77 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Necessary for litter quality in boreal forests with high cwd flux fmet = fmet_p1 * (fmet_p2 - fmet_p3 * min(40.0_r8, & ligninNratioAvg(c))) - ! TODO USE cnveg_carbonflux_inst%annsum_npp_col (gC/m2/yr) updated 1/yr - ! OR annavg_[ag+bg]npp_patch (gC/m2/s) from ch4Mod - ! OR calculate an annual running mean with accumulMod? + ! TODO Need to mention cnveg_carbonflux_inst above somewhere tauMod = min(tauMod_max, max(tauMod_min, & sqrt(tauMod_factor * & cnveg_carbonflux_inst%annsum_npp_col(c)))) - ! tau_m1_s* are tauR and tau_m2_s* are tauK in Wieder et al. 2015 - ! and are time-dependent terms - tau_m1_s1 = tau_r1 * exp(tau_r2 * fmet) * tauMod - tau_m1_s2 = tau_r1 * exp(tau_r2 * fmet) * tauMod - tau_m1_s3 = tau_r1 * exp(tau_r2 * fmet) * tauMod - tau_m2_s1 = tau_k1 * exp(tau_k2 * fmet) * tauMod - tau_m2_s2 = tau_k1 * exp(tau_k2 * fmet) * tauMod - tau_m2_s3 = tau_k1 * exp(tau_k2 * fmet) * tauMod + ! tau_m1 is tauR and tau_m2 is tauK in Wieder et al. 2015 + ! They are time-dependent terms + tau_m1 = tau_r1 * exp(tau_r2 * fmet) * tauMod + tau_m2 = tau_k1 * exp(tau_k2 * fmet) * tauMod do j = 1,nlevdecomp ! vmax are time-dependent terms ! Table B1 Wieder et al. (2015) & MIMICS params file give different ! kslope. I used the params file value(s). - ! TODO Introduce t_soi24_degC_col following t_veg24_patch (running - ! mean) or t_mo_patch (30-d avg) or ... - vmax_l1_m1 = exp(vslope_l1_m1 * t_soi24_degC_col(c,j) + vint_l1_m1) * vmod_l1_m1 - vmax_l1_m2 = exp(vslope_l1_m2 * t_soi24_degC_col(c,j) + vint_l1_m2) * vmod_l1_m2 - vmax_l2_m1 = exp(vslope_l2_m1 * t_soi24_degC_col(c,j) + vint_l2_m1) * vmod_l2_m1 - vmax_l2_m2 = exp(vslope_l2_m2 * t_soi24_degC_col(c,j) + vint_l2_m2) * vmod_l2_m2 - vmax_s3_m1 = exp(vslope_s3_m1 * t_soi24_degC_col(c,j) + vint_s3_m1) * vmod_l2_m1 - vmax_s3_m2 = exp(vslope_s3_m2 * t_soi24_degC_col(c,j) + vint_s3_m2) * vmod_l2_m2 + t_soi_degC = t_soisno(c,j) + tfrz ! TODO find global const + vmax_l1_m1 = exp(vslope_l1_m1 * t_soi_degC + vint_l1_m1) * vmod_l1_m1 + vmax_l1_m2 = exp(vslope_l1_m2 * t_soi_degC + vint_l1_m2) * vmod_l1_m2 + vmax_l2_m1 = exp(vslope_l2_m1 * t_soi_degC + vint_l2_m1) * vmod_l2_m1 + vmax_l2_m2 = exp(vslope_l2_m2 * t_soi_degC + vint_l2_m2) * vmod_l2_m2 + vmax_s1_m1 = exp(vslope_s1_m1 * t_soi_degC + vint_s1_m1) * vmod_s1_m1 + vmax_s1_m2 = exp(vslope_s1_m2 * t_soi_degC + vint_s1_m2) * vmod_s1_m2 ! km are time-dependent terms - km_l1_m1 = exp(kslope_l1_m1 * t_soi24_degC_col(c,j) + kint_l1_m1) * kmod_l1_m1 - km_l1_m2 = exp(kslope_l1_m2 * t_soi24_degC_col(c,j) + kint_l1_m2) * kmod_l1_m2 - km_l2_m1 = exp(kslope_l2_m1 * t_soi24_degC_col(c,j) + kint_l2_m1) * kmod_l2_m1 - km_l2_m2 = exp(kslope_l2_m2 * t_soi24_degC_col(c,j) + kint_l2_m2) * kmod_l2_m2 - km_s3_m1 = exp(kslope_s3_m1 * t_soi24_degC_col(c,j) + kint_s3_m1) * kmod_s3_m1 / p_scalar(c,j) - km_s3_m2 = exp(kslope_s3_m2 * t_soi24_degC_col(c,j) + kint_s3_m2) * kmod_s3_m2 / p_scalar(c,j) + km_l1_m1 = exp(kslope_l1_m1 * t_soi_degC + kint_l1_m1) * kmod_l1_m1 + km_l1_m2 = exp(kslope_l1_m2 * t_soi_degC + kint_l1_m2) * kmod_l1_m2 + km_l2_m1 = exp(kslope_l2_m1 * t_soi_degC + kint_l2_m1) * kmod_l2_m1 + km_l2_m2 = exp(kslope_l2_m2 * t_soi_degC + kint_l2_m2) * kmod_l2_m2 + km_s1_m1 = exp(kslope_s1_m1 * t_soi_degC + kint_s1_m1) * kmod_s1_m1 / p_scalar(c,j) + km_s1_m2 = exp(kslope_s1_m2 * t_soi_degC + kint_s1_m2) * kmod_s1_m2 / p_scalar(c,j) ! Product of w_scalar * depth_scalar * o_scalar w_d_o_scalars = w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) ! decomp_k used in SoilBiogeochemPotentialMod.F90 - ! TODO Defined correctly here? - ! TODO Combine multiple terms of same donor pools... - ! TODO Where to calculate m1_pool and m2_pool? - ! TODO When to introduce litter/soil biomass to the calculation? - ! TODO Excluded spinup terms for now. See cwd below how used. - decomp_k(c,j,i_met_lit) = (vmax_l1_m1 * m1_pool(c,j) / & - (km_l1_m1 + m1_pool(c,j))) * & - w_d_o_scalars - decomp_k(c,j,i_met_lit) = (vmax_l1_m2 * m2_pool(c,j) / & - (km_l1_m2 + m2_pool(c,j))) * & + ! TODO Excluded spinup terms for now (except see cwd below) + ! TODO Calc m*_conc = m*_pool(c,j) / dz(j) layer thickness + ! mgC/cm3 = gC/m3 * (1e3 mg/g) / (1e6 cm3/m3) + ! TODO decomp_k will end up in units of per hour and we + ! need per s so apply conversion to the coeffs above + decomp_k(c,j,i_met_lit) = (vmax_l1_m1 * m1_conc(c,j) / & + (km_l1_m1 + m1_conc(c,j)) + & + vmax_l1_m2 * m2_conc(c,j) / & + (km_l1_m2 + m2_conc(c,j))) * & w_d_o_scalars - decomp_k(c,j,i_str_lit) = (vmax_l2_m1 * m1_pool(c,j) / & - (km_l2_m1 + m1_pool(c,j))) * & + decomp_k(c,j,i_str_lit) = (vmax_l2_m1 * m1_conc(c,j) / & + (km_l2_m1 + m1_conc(c,j)) + & + vmax_l2_m2 * m2_conc(c,j) / & + (km_l2_m2 + m2_conc(c,j))) * & w_d_o_scalars - decomp_k(c,j,i_str_lit) = (vmax_l2_m2 * m2_pool(c,j) / & - (km_l2_m2 + m2_pool(c,j))) * & + + decomp_k(c,j,i_avl_som) = (vmax_s1_m1 * m1_conc(c,j) / & + (km_s1_m1 + m1_conc(c,j)) + & + vmax_s1_m2 * m2_conc(c,j) / & + (km_s1_m2 + m2_conc(c,j))) * & w_d_o_scalars - decomp_k(c,j,i_pas_som) = (vmax_s3_m1 * m1_pool(c,j) / & - (km_s3_m1 + m1_pool(c,j))) * & +! TODO Near line 1145 I see desorption for s3_s1 + decomp_k(c,j,i_pas_som) = desorption * w_d_o_scalars +! Controlled by microbial biomass through OXIDAT (line 1145 in testbed) +! TODO OXIDAT = MICk * Vmax(K2) * SOMc / (KO(2) * Km(K2) + MICk) + & +! MICr * Vmax(R2) * SOMc / (KO(1) * Km(R2) + MICr) + decomp_k(c,j,i_slo_som) = TODO * w_d_o_scalars + + decomp_k(c,j,i_cop_mic) = tau_m1 * m1_conc(c,j)**(densdep) * & w_d_o_scalars - decomp_k(c,j,i_pas_som) = (vmax_s3_m2 * m2_pool(c,j) / & - (km_s3_m2 + m2_pool(c,j))) * & + decomp_k(c,j,i_oli_mic) = tau_m2 * m2_conc(c,j)**(densdep) * & w_d_o_scalars - - decomp_k(c,j,i_act_som) = k_s1_s3 * w_d_o_scalars - decomp_k(c,j,i_slo_som) = k_s2_s3 * w_d_o_scalars - - decomp_k(c,j,i_cop_mic) = tau_m1_s1 * m1_pool(c,j)**(densdep) * & - fphys(c) * w_d_o_scalars - decomp_k(c,j,i_cop_mic) = tau_m1_s2 * m1_pool(c,j)**(densdep) * & - fchem(c) * w_d_o_scalars - decomp_k(c,j,i_cop_mic) = tau_m1_s3 * m1_pool(c,j)**(densdep) * & - faval(c) *w_d_o_scalars - decomp_k(c,j,i_oli_mic) = tau_m2_s1 * m2_pool(c,j)**(densdep) * & - fphys(c) * w_d_o_scalars - decomp_k(c,j,i_oli_mic) = tau_m2_s2 * m2_pool(c,j)**(densdep) * & - fchem(c) * w_d_o_scalars - decomp_k(c,j,i_oli_mic) = tau_m2_s3 * m2_pool(c,j)**(densdep) * & - faval(c) * w_d_o_scalars ! Same for cwd but only if fates not enabled; fates handles cwd on ! its own structure - ! TODO Kept cwd bc we do not have a MIMICS replacement for it. - ! Also this shows what the BGC decomp_k formulas looked like. + ! TODO This shows how BGC applied the spinup coefficients if (.not. use_fates) then decomp_k(c,j,i_cwd) = k_frag * w_d_o_scalars * spinup_geogterm_cwd(c) end if From 0fde3987c18a3fc05f4f68afdf6067bad65bcd66 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 14 Jul 2021 18:47:55 -0600 Subject: [PATCH 15/69] Updates based on new comments from @wwieder --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 288 ++++++++++-------- 1 file changed, 163 insertions(+), 125 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 26b924a67f..2046f42ce7 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -22,6 +22,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type use SoilStateType , only : soilstate_type use TemperatureType , only : temperature_type + use CNveg_CarbonFlux_Type , only : cnveg_carbonflux_type use ch4Mod , only : ch4_type use ColumnType , only : col use GridcellType , only : grc @@ -39,8 +40,8 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! !PUBLIC DATA MEMBERS ! ! !PRIVATE DATA MEMBERS - integer, private :: i_pas_som ! index of passive (aka protected) Soil Organic Matter (SOM) - integer, private :: i_slo_som ! index of slow (aka recalcitrant) SOM + integer, private :: i_phys_som ! index of physically protected Soil Organic Matter (SOM) + integer, private :: i_chem_som ! index of chemically protected SOM integer, private :: i_avl_som ! index of available (aka active) SOM integer, private :: i_str_lit ! index of structural litter pool integer, private :: i_cop_mic ! index of copiotrophic microbial pool @@ -255,6 +256,11 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat allocate(p_scalar(bounds%begc:bounds%endc,1:nlevdecomp)) + params_inst%p_scalar_p1 = 0.8_r8 ! TODO Move to the params files + params_inst%p_scalar_p2 = -3.0_r8 + params_inst%desorp_p1 = 1.5e-5_r8 + params_inst%desorp_p2 = -1.5_r8 + !------- time-constant coefficients ---------- ! ! set respiration fractions for fluxes between compartments rf_l1m1 = 1.0_r8 - params_inst%mge(1) @@ -307,13 +313,18 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat kint_s1_m2 = params_inst%kint(6) ! some of these are dependent on the soil texture properties - ! TODO One-time initializations here. - ! Time-dep params in subr. decomp_rates_mimics. + ! One-time initializations here. + ! Time-dep params in subr. decomp_rates_mimics. do c = bounds%begc, bounds%endc + fchem(c) = ! TODO as a function of fmet (litter quality) do j = 1, nlevdecomp - p_scalar(c,j) = (0.8_r8 * exp(-3.0_r8 * sqrt(cellclay(c,j))))** & - (-1.0_r8) + fphys(c,j) = ! TODO as a function of cellclay(c,j) + favl(c,j) = 1.0_r8 - fphys(c,j) - fchem(c) + desorp(c,j) = desorp_p1 * exp(desorp_p2 * cellclay(c,j)) + p_scalar(c,j) = 1.0_r8 / (params_inst%p_scalar_p1 * & + exp(params_inst%p_scalar_p2 * & + sqrt(cellclay(c,j)))) end do end do initial_stock_soildepth = params_inst%initial_Cstocks_depth @@ -378,39 +389,39 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cellulose(i_avl_som) = .false. is_lignin(i_avl_som) = .false. - i_slo_som = i_avl_som + 1 - floating_cn_ratio_decomp_pools(i_slo_som) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_slo_som) = 'soil2' - decomp_cascade_con%decomp_pool_name_history(i_slo_som) = 'SLO_SOM' - decomp_cascade_con%decomp_pool_name_long(i_slo_som) = 'slow soil organic matter' - decomp_cascade_con%decomp_pool_name_short(i_slo_som) = 'S2' - is_microbe(i_slo_som) = .false. - is_litter(i_slo_som) = .false. - is_soil(i_slo_som) = .true. - is_cwd(i_slo_som) = .false. - initial_cn_ratio(i_slo_som) = 10._r8 ! cn_s2 in BGC; not used in MIMICS - initial_stock(i_slo_som) = params_inst%initial_Cstocks(i_slo_som) - is_metabolic(i_slo_som) = .false. - is_cellulose(i_slo_som) = .false. - is_lignin(i_slo_som) = .false. - - i_pas_som = i_slo_som + 1 - floating_cn_ratio_decomp_pools(i_pas_som) = .true. - decomp_cascade_con%decomp_pool_name_restart(i_pas_som) = 'soil3' - decomp_cascade_con%decomp_pool_name_history(i_pas_som) = 'PAS_SOM' - decomp_cascade_con%decomp_pool_name_long(i_pas_som) = 'passive soil organic matter' - decomp_cascade_con%decomp_pool_name_short(i_pas_som) = 'S3' - is_microbe(i_pas_som) = .false. - is_litter(i_pas_som) = .false. - is_soil(i_pas_som) = .true. - is_cwd(i_pas_som) = .false. - initial_cn_ratio(i_pas_som) = 10._r8 ! cn_s3 in BGC; not used in MIMICS - initial_stock(i_pas_som) = params_inst%initial_Cstocks(i_pas_som) - is_metabolic(i_pas_som) = .false. - is_cellulose(i_pas_som) = .false. - is_lignin(i_pas_som) = .false. - - i_cop_mic = i_pas_som + 1 + i_chem_som = i_avl_som + 1 + floating_cn_ratio_decomp_pools(i_chem_som) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_chem_som) = 'soil2' + decomp_cascade_con%decomp_pool_name_history(i_chem_som) = 'CHEM_SOM' + decomp_cascade_con%decomp_pool_name_long(i_chem_som) = 'chemically protected soil organic matter' + decomp_cascade_con%decomp_pool_name_short(i_chem_som) = 'S2' + is_microbe(i_chem_som) = .false. + is_litter(i_chem_som) = .false. + is_soil(i_chem_som) = .true. + is_cwd(i_chem_som) = .false. + initial_cn_ratio(i_chem_som) = 10._r8 ! cn_s2 in BGC; not used in MIMICS + initial_stock(i_chem_som) = params_inst%initial_Cstocks(i_chem_som) + is_metabolic(i_chem_som) = .false. + is_cellulose(i_chem_som) = .false. + is_lignin(i_chem_som) = .false. + + i_phys_som = i_chem_som + 1 + floating_cn_ratio_decomp_pools(i_phys_som) = .true. + decomp_cascade_con%decomp_pool_name_restart(i_phys_som) = 'soil3' + decomp_cascade_con%decomp_pool_name_history(i_phys_som) = 'PHYS_SOM' + decomp_cascade_con%decomp_pool_name_long(i_phys_som) = 'physically protected soil organic matter' + decomp_cascade_con%decomp_pool_name_short(i_phys_som) = 'S3' + is_microbe(i_phys_som) = .false. + is_litter(i_phys_som) = .false. + is_soil(i_phys_som) = .true. + is_cwd(i_phys_som) = .false. + initial_cn_ratio(i_phys_som) = 10._r8 ! cn_s3 in BGC; not used in MIMICS + initial_stock(i_phys_som) = params_inst%initial_Cstocks(i_phys_som) + is_metabolic(i_phys_som) = .false. + is_cellulose(i_phys_som) = .false. + is_lignin(i_phys_som) = .false. + + i_cop_mic = i_phys_som + 1 floating_cn_ratio_decomp_pools(i_cop_mic) = .true. decomp_cascade_con%decomp_pool_name_restart(i_cop_mic) = 'micr1' decomp_cascade_con%decomp_pool_name_history(i_cop_mic) = 'COP_MIC' @@ -472,8 +483,8 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat end if !som1,2,3 spinup_factor(i_avl_som) = 1._r8 - spinup_factor(i_slo_som) = 1._r8 ! BGC used cwd formula above but - spinup_factor(i_pas_som) = 1._r8 ! ...w the respective tau_s values + spinup_factor(i_chem_som) = 1._r8 ! BGC used cwd formula above but + spinup_factor(i_phys_som) = 1._r8 ! ...w the respective tau_s values ! micr1,2 spinup_factor(i_cop_mic) = 1._r8 spinup_factor(i_oli_mic) = 1._r8 @@ -529,14 +540,14 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_s3s1 = 7 decomp_cascade_con%cascade_step_name(i_s3s1) = 'S3S1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 0.0_r8 - cascade_donor_pool(i_s3s1) = i_pas_som + cascade_donor_pool(i_s3s1) = i_phys_som cascade_receiver_pool(i_s3s1) = i_avl_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 i_s2s1 = 8 decomp_cascade_con%cascade_step_name(i_s2s1) = 'S2S1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = 0.0_r8 - cascade_donor_pool(i_s2s1) = i_slo_som + cascade_donor_pool(i_s2s1) = i_chem_som cascade_receiver_pool(i_s2s1) = i_avl_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = 1.0_r8 @@ -545,42 +556,42 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = rf_m1s1 cascade_donor_pool(i_m1s1) = i_cop_mic cascade_receiver_pool(i_m1s1) = i_avl_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = fphys ! TODO fphys is a function of clay + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = favl(bounds%begc:bounds%endc,1:nlevdecomp) i_m1s2 = 10 decomp_cascade_con%cascade_step_name(i_m1s2) = 'M1S2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = rf_m1s2 cascade_donor_pool(i_m1s2) = i_cop_mic - cascade_receiver_pool(i_m1s2) = i_slo_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = fchem ! TODO fchem is a function of litter quality (fmet) + cascade_receiver_pool(i_m1s2) = i_chem_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = fchem(1:nlevdecomp) i_m1s3 = 11 decomp_cascade_con%cascade_step_name(i_m1s3) = 'M1S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = rf_m1s3 cascade_donor_pool(i_m1s3) = i_cop_mic - cascade_receiver_pool(i_m1s3) = i_pas_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = faval ! TODO faval = 1 - fphys - fchem + cascade_receiver_pool(i_m1s3) = i_phys_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = fphys(bounds%begc:bounds%endc,1:nlevdecomp) i_m2s1 = 12 decomp_cascade_con%cascade_step_name(i_m2s1) = 'M2S1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = rf_m2s1 cascade_donor_pool(i_m2s1) = i_oli_mic cascade_receiver_pool(i_m2s1) = i_avl_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = fphys + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = favl(bounds%begc:bounds%endc,1:nlevdecomp) i_m2s2 = 13 decomp_cascade_con%cascade_step_name(i_m2s2) = 'M2S2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = rf_m2s2 cascade_donor_pool(i_m2s2) = i_oli_mic - cascade_receiver_pool(i_m2s2) = i_slo_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = fchem + cascade_receiver_pool(i_m2s2) = i_chem_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = fchem(1:nlevdecomp) i_m2s3 = 14 decomp_cascade_con%cascade_step_name(i_m2s3) = 'M2S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = rf_m2s3 cascade_donor_pool(i_m2s3) = i_oli_mic - cascade_receiver_pool(i_m2s3) = i_pas_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = faval + cascade_receiver_pool(i_m2s3) = i_phys_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = fphys(bounds%begc:bounds%endc,1:nlevdecomp) if (.not. use_fates) then i_cwdl2 = 15 @@ -591,7 +602,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = 1.0_r8 end if - deallocate(p_scalar) deallocate(params_inst%mge) deallocate(params_inst%vmod) deallocate(params_inst%vslope) @@ -607,7 +617,8 @@ end subroutine init_decompcascade_mimics !----------------------------------------------------------------------- subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & - soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) + soilstate_inst, temperature_inst, cnveg_carbonflux_inst, & + ch4_inst, soilbiogeochem_carbonflux_inst) ! ! !DESCRIPTION: ! Calculate rates and decomposition pathways for the MIMICS @@ -615,7 +626,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! ! !USES: use clm_time_manager , only : get_days_per_year - use clm_varcon , only : secspday + use clm_varcon , only : secspday, secsphr, tfrz ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -623,6 +634,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & integer , intent(in) :: filter_soilc(:) ! filter for soil columns type(soilstate_type) , intent(in) :: soilstate_inst type(temperature_type) , intent(in) :: temperature_inst + type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst type(ch4_type) , intent(in) :: ch4_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst ! @@ -687,7 +699,6 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding ! translate to per-second time constant - ! TODO vmax, km, tau terms replaced (most?) k_ terms; CONFIRM s-1 UNITS k_frag = 1._r8 / (secspday * days_per_year * params_inst%tau_cwd_bgc) ! calc ref rate @@ -721,14 +732,14 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & spinup_geogterm_s1(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_slo_som) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_s2(c) = spinup_factor(i_slo_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_chem_som) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s2(c) = spinup_factor(i_chem_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s2(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_pas_som) - 1._r8) .gt. .000001_r8) then - spinup_geogterm_s3(c) = spinup_factor(i_pas_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + if ( abs(spinup_factor(i_phys_som) - 1._r8) .gt. .000001_r8) then + spinup_geogterm_s3(c) = spinup_factor(i_phys_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s3(c) = 1._r8 endif @@ -890,24 +901,28 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do + ! TODO Move to the params files + fmet_p1 = 0.85 + fmet_p2 = 0.85 + fmet_p3 = 0.013 + tauMod_factor = 0.01_r8 ! was tauMod_denom = 100 + tauMod_min = 0.8_r8 + tauMod_max = 1.2_r8 + tau_r1 = 5.2e-4_r8 + tau_r2 = 0.3_r8 ! or 0.4? + tau_k1 = 2.4e-4_r8 + tau_k2 = 0.1_r8 + ko_m1 = 4.0_r8 + ko_m2 = 4.0_r8 + densdep = 1.0_r8 + desorpQ10 = 1.1_r8 + t_soi_ref = 25.0_r8 ! deg C + ! calculate rates for all litter and som pools - ! TODO Ok that I reversed order of do-loops for convenience? + ! TODO Ok that I reversed order of do-loops? do fc = 1,num_soilc c = filter_soilc(fc) - ! TODO Move all to the params files - fmet_p1 = 0.85 - fmet_p2 = 0.85 - fmet_p3 = 0.013 - tauMod_factor = 0.01_r8 ! was tauMod_denom = 100 - tauMod_min = 0.8_r8 - tauMod_max = 1.2_r8 - tau_r1 = 5.2e-4_r8 - tau_r2 = 0.3_r8 ! or 0.4? - tau_k1 = 2.4e-4_r8 - tau_k2 = 0.1_r8 - densdep = 1.0_r8 - ! Time-dependent params from Wieder et al. 2015 & testbed code ! TODO STILL MISSING N-related stuff: DIN... @@ -915,7 +930,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Similarly the others ! Rethink this as the sum of input to met + str litter? ! @wwieder will investigate. - ligninNratioAvg(c) = & + ligninNratioAvg(c) = & (ligninNratio(c,leaf) * (cleaf2met(c) + cleaf2str(c)) + & ligninNratio(c,froot) * (croot2met(c) + croot2str(c)) + & ligninNratio(c,wood) * (cwd2str(c))) / & @@ -926,77 +941,100 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Necessary for litter quality in boreal forests with high cwd flux fmet = fmet_p1 * (fmet_p2 - fmet_p3 * min(40.0_r8, & ligninNratioAvg(c))) - ! TODO Need to mention cnveg_carbonflux_inst above somewhere tauMod = min(tauMod_max, max(tauMod_min, & sqrt(tauMod_factor * & - cnveg_carbonflux_inst%annsum_npp_col(c)))) + cnveg_carbonflux_inst%annsum_npp_col(c)))) ! tau_m1 is tauR and tau_m2 is tauK in Wieder et al. 2015 - ! They are time-dependent terms - tau_m1 = tau_r1 * exp(tau_r2 * fmet) * tauMod - tau_m2 = tau_k1 * exp(tau_k2 * fmet) * tauMod + ! tau ends up in units of per hour but is expected + ! in units of per second, so convert here; alternatively + ! place the conversion once in w_d_o_scalars + tau_m1 = tau_r1 * exp(tau_r2 * fmet) * tauMod * secsphr + tau_m2 = tau_k1 * exp(tau_k2 * fmet) * tauMod * secsphr do j = 1,nlevdecomp - ! vmax are time-dependent terms - ! Table B1 Wieder et al. (2015) & MIMICS params file give different + ! vmax ends up in units of per hour but is expected + ! in units of per second, so convert here; alternatively + ! place the conversion once in w_d_o_scalars + ! Table B1 Wieder et al. 2015 & MIMICS params file give diff ! kslope. I used the params file value(s). - t_soi_degC = t_soisno(c,j) + tfrz ! TODO find global const - vmax_l1_m1 = exp(vslope_l1_m1 * t_soi_degC + vint_l1_m1) * vmod_l1_m1 - vmax_l1_m2 = exp(vslope_l1_m2 * t_soi_degC + vint_l1_m2) * vmod_l1_m2 - vmax_l2_m1 = exp(vslope_l2_m1 * t_soi_degC + vint_l2_m1) * vmod_l2_m1 - vmax_l2_m2 = exp(vslope_l2_m2 * t_soi_degC + vint_l2_m2) * vmod_l2_m2 - vmax_s1_m1 = exp(vslope_s1_m1 * t_soi_degC + vint_s1_m1) * vmod_s1_m1 - vmax_s1_m2 = exp(vslope_s1_m2 * t_soi_degC + vint_s1_m2) * vmod_s1_m2 - - ! km are time-dependent terms - km_l1_m1 = exp(kslope_l1_m1 * t_soi_degC + kint_l1_m1) * kmod_l1_m1 - km_l1_m2 = exp(kslope_l1_m2 * t_soi_degC + kint_l1_m2) * kmod_l1_m2 - km_l2_m1 = exp(kslope_l2_m1 * t_soi_degC + kint_l2_m1) * kmod_l2_m1 - km_l2_m2 = exp(kslope_l2_m2 * t_soi_degC + kint_l2_m2) * kmod_l2_m2 - km_s1_m1 = exp(kslope_s1_m1 * t_soi_degC + kint_s1_m1) * kmod_s1_m1 / p_scalar(c,j) - km_s1_m2 = exp(kslope_s1_m2 * t_soi_degC + kint_s1_m2) * kmod_s1_m2 / p_scalar(c,j) + t_soi_degC = t_soisno(c,j) + tfrz + + vmax_l1_m1 = exp(vslope_l1_m1 * t_soi_degC + vint_l1_m1) * & + vmod_l1_m1 * secsphr + vmax_l1_m2 = exp(vslope_l1_m2 * t_soi_degC + vint_l1_m2) * & + vmod_l1_m2 * secsphr + vmax_l2_m1 = exp(vslope_l2_m1 * t_soi_degC + vint_l2_m1) * & + vmod_l2_m1 * secsphr + vmax_l2_m2 = exp(vslope_l2_m2 * t_soi_degC + vint_l2_m2) * & + vmod_l2_m2 * secsphr + vmax_s1_m1 = exp(vslope_s1_m1 * t_soi_degC + vint_s1_m1) * & + vmod_s1_m1 * secsphr + vmax_s1_m2 = exp(vslope_s1_m2 * t_soi_degC + vint_s1_m2) * & + vmod_s1_m2 * secsphr + + km_l1_m1 = exp(kslope_l1_m1 * t_soi_degC + kint_l1_m1) * & + kmod_l1_m1 + km_l1_m2 = exp(kslope_l1_m2 * t_soi_degC + kint_l1_m2) * & + kmod_l1_m2 + km_l2_m1 = exp(kslope_l2_m1 * t_soi_degC + kint_l2_m1) * & + kmod_l2_m1 + km_l2_m2 = exp(kslope_l2_m2 * t_soi_degC + kint_l2_m2) * & + kmod_l2_m2 + km_s1_m1 = exp(kslope_s1_m1 * t_soi_degC + kint_s1_m1) * & + kmod_s1_m1 + km_s1_m2 = exp(kslope_s1_m2 * t_soi_degC + kint_s1_m2) * & + kmod_s1_m2 + + ! Desorption a function of soil temperature and + ! Q10 = 1.1 w/ reference temperature of 25C. + ! Expected in units of per second, so convert; alternatively + ! place the conversion once in w_d_o_scalars + desorption = desorp(c,j) * desorpQ10 * secsphr * & + exp((t_soi_degC - t_soi_ref) / 10.0_r8) + + ! Microbial concentration in the expected units + ! mgC/cm3 = gC/m3 * (1e3 mg/g) / (1e6 cm3/m3) + m1_conc = (m1_pool(c,j) / col%dz(c,j)) * 1.0e3_r8 * 1.0e-6_r8 ! Product of w_scalar * depth_scalar * o_scalar w_d_o_scalars = w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) ! decomp_k used in SoilBiogeochemPotentialMod.F90 ! TODO Excluded spinup terms for now (except see cwd below) - ! TODO Calc m*_conc = m*_pool(c,j) / dz(j) layer thickness - ! mgC/cm3 = gC/m3 * (1e3 mg/g) / (1e6 cm3/m3) - ! TODO decomp_k will end up in units of per hour and we - ! need per s so apply conversion to the coeffs above - decomp_k(c,j,i_met_lit) = (vmax_l1_m1 * m1_conc(c,j) / & - (km_l1_m1 + m1_conc(c,j)) + & - vmax_l1_m2 * m2_conc(c,j) / & - (km_l1_m2 + m2_conc(c,j))) * & + decomp_k(c,j,i_met_lit) = (vmax_l1_m1 * m1_conc / & + (km_l1_m1 + m1_conc) + & + vmax_l1_m2 * m2_conc / & + (km_l1_m2 + m2_conc)) * & w_d_o_scalars - decomp_k(c,j,i_str_lit) = (vmax_l2_m1 * m1_conc(c,j) / & - (km_l2_m1 + m1_conc(c,j)) + & - vmax_l2_m2 * m2_conc(c,j) / & - (km_l2_m2 + m2_conc(c,j))) * & + decomp_k(c,j,i_str_lit) = (vmax_l2_m1 * m1_conc / & + (km_l2_m1 + m1_conc) + & + vmax_l2_m2 * m2_conc / & + (km_l2_m2 + m2_conc)) * & w_d_o_scalars - decomp_k(c,j,i_avl_som) = (vmax_s1_m1 * m1_conc(c,j) / & - (km_s1_m1 + m1_conc(c,j)) + & - vmax_s1_m2 * m2_conc(c,j) / & - (km_s1_m2 + m2_conc(c,j))) * & + decomp_k(c,j,i_avl_som) = (vmax_s1_m1 * m1_conc / & + (km_s1_m1 + m1_conc) + & + vmax_s1_m2 * m2_conc / & + (km_s1_m2 + m2_conc)) * & w_d_o_scalars -! TODO Near line 1145 I see desorption for s3_s1 - decomp_k(c,j,i_pas_som) = desorption * w_d_o_scalars -! Controlled by microbial biomass through OXIDAT (line 1145 in testbed) -! TODO OXIDAT = MICk * Vmax(K2) * SOMc / (KO(2) * Km(K2) + MICk) + & -! MICr * Vmax(R2) * SOMc / (KO(1) * Km(R2) + MICr) - decomp_k(c,j,i_slo_som) = TODO * w_d_o_scalars - - decomp_k(c,j,i_cop_mic) = tau_m1 * m1_conc(c,j)**(densdep) * & - w_d_o_scalars - decomp_k(c,j,i_oli_mic) = tau_m2 * m2_conc(c,j)**(densdep) * & + decomp_k(c,j,i_phys_som) = desorption * w_d_o_scalars +! The right hand side is called OXIDAT in the testbed (line 1145) + decomp_k(c,j,i_chem_som) = (vmax_l2_m1 * m1_conc / & + (ko_m1 * km_l2_m1 + m1_conc) + & + vmax_l2_m2 * m2_conc / & + (ko_m2 * km_l2_m2 + m2_conc)) * & w_d_o_scalars + + decomp_k(c,j,i_cop_mic) = tau_m1 * & + m1_conc**(densdep - 1.0_r8) * w_d_o_scalars + decomp_k(c,j,i_oli_mic) = tau_m2 * & + m2_conc**(densdep - 1.0_r8) * w_d_o_scalars ! Same for cwd but only if fates not enabled; fates handles cwd on ! its own structure - ! TODO This shows how BGC applied the spinup coefficients + ! TODO This shows how BGC applies the spinup coefficients if (.not. use_fates) then decomp_k(c,j,i_cwd) = k_frag * w_d_o_scalars * spinup_geogterm_cwd(c) end if From 030e9c53dfae93c658211d9daf192c883c2f9fdb Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 17 Jul 2021 16:40:01 -0600 Subject: [PATCH 16/69] Updates addressing comments in the PR --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 233 ++++++++++-------- 1 file changed, 132 insertions(+), 101 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 2046f42ce7..2076c44a07 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -10,7 +10,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod use shr_const_mod , only : SHR_CONST_TKFRZ use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : nlevdecomp, ndecomp_pools_max - use clm_varpar , only : i_litr_min, i_litr_max, i_met_lit, i_cwd + use clm_varpar , only : i_met_lit, i_litr_min, i_litr_max, i_cwd use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_vertsoilc, use_fates use clm_varcon , only : zsoi use decompMod , only : bounds_type @@ -46,15 +46,22 @@ module SoilBiogeochemDecompCascadeMIMICSMod integer, private :: i_str_lit ! index of structural litter pool integer, private :: i_cop_mic ! index of copiotrophic microbial pool integer, private :: i_oli_mic ! index of oligotrophic microbial pool + integer, private :: i_l1m1 ! indices of pool transfers needed in whole module + integer, private :: i_l1m2 + integer, private :: i_l2m1 + integer, private :: i_l2m2 + integer, private :: i_s1m1 + integer, private :: i_s1m2 + integer, private :: i_m1s1 + integer, private :: i_m1s2 + integer, private :: i_m2s1 + integer, private :: i_m2s2 type, private :: params_type ! Respiration fraction cwd --> structural litter (keep comment sep for dif) real(r8):: rf_cwdl2_bgc real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) - real(r8) :: cwd_fcel_bgc !cellulose fraction for CWD - real(r8) :: cwd_flig_bgc ! - real(r8) :: minpsi_bgc !minimum soil water potential for heterotrophic resp real(r8) :: maxpsi_bgc !maximum soil water potential for heterotrophic resp @@ -117,11 +124,6 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_cwdl2_bgc=tempr - tString='cwd_fcel' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cwd_fcel_bgc=tempr - tString='minpsi_hr' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -132,11 +134,6 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%maxpsi_bgc=tempr - tString='cwd_flig' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cwd_flig_bgc=tempr - tString='initial_Cstocks_depth_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -201,29 +198,26 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat ! !LOCAL VARIABLES !-- properties of each decomposing pool real(r8) :: rf_l1m1 - real(r8) :: rf_l2m1 - real(r8) :: rf_s1m1 real(r8) :: rf_l1m2 + real(r8) :: rf_l2m1 real(r8) :: rf_l2m2 + real(r8) :: rf_s1m1 real(r8) :: rf_s1m2 + real(r8) :: rf_m1s1 + real(r8) :: rf_m1s2 + real(r8) :: rf_m1s3 + real(r8) :: rf_m2s1 + real(r8) :: rf_m2s2 + real(r8) :: rf_m2s3 real(r8) :: rf_cwdl2 - real(r8) :: cwd_fcel - real(r8) :: cwd_flig + real(r8), allocatable :: desorp(:,:) + real(r8), allocatable :: fphys_m1(:,:) + real(r8), allocatable :: fphys_m2(:,:) real(r8), allocatable :: p_scalar(:,:) - integer :: i_l1m1 - integer :: i_l2m1 - integer :: i_s1m1 - integer :: i_l1m2 - integer :: i_l2m2 - integer :: i_s1m2 + integer :: i_s2s1 ! indices of pool transfers needed in this subr. only integer :: i_s3s1 - integer :: i_s2s1 - integer :: i_m1s1 - integer :: i_m1s2 integer :: i_m1s3 - integer :: i_m2s1 - integer :: i_m2s2 integer :: i_m2s3 integer :: i_cwdl2 real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. @@ -254,12 +248,19 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat ) + allocate(desorp(bounds%begc:bounds%endc,1:nlevdecomp)) + allocate(fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp)) + allocate(fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) allocate(p_scalar(bounds%begc:bounds%endc,1:nlevdecomp)) params_inst%p_scalar_p1 = 0.8_r8 ! TODO Move to the params files params_inst%p_scalar_p2 = -3.0_r8 params_inst%desorp_p1 = 1.5e-5_r8 params_inst%desorp_p2 = -1.5_r8 + params_inst%fphys_r_p1 = 0.3_r8 + params_inst%fphys_r_p2 = 1.3_r8 + params_inst%fphys_k_p1 = 0.2_r8 + params_inst%fphys_k_p2 = 0.8_r8 !------- time-constant coefficients ---------- ! ! set respiration fractions for fluxes between compartments @@ -270,6 +271,13 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_l2m2 = 1.0_r8 - params_inst%mge(5) rf_s1m2 = 1.0_r8 - params_inst%mge(6) + rf_m1s1 = ! TODO Set or calculate these... + rf_m1s2 = + rf_m1s3 = + rf_m2s1 = + rf_m2s2 = + rf_m2s3 = + rf_cwdl2 = params_inst%rf_cwdl2_bgc ! vmod = "old" vmod * av AND kmod = ak / "old" kmod @@ -317,11 +325,12 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat ! Time-dep params in subr. decomp_rates_mimics. do c = bounds%begc, bounds%endc - fchem(c) = ! TODO as a function of fmet (litter quality) do j = 1, nlevdecomp - fphys(c,j) = ! TODO as a function of cellclay(c,j) - favl(c,j) = 1.0_r8 - fphys(c,j) - fchem(c) desorp(c,j) = desorp_p1 * exp(desorp_p2 * cellclay(c,j)) + fphys_m1(c,j) = min(1.0_r8, max(0.0_r8, fphys_r_p1 * & + exp(fphys_r_p2 * cellclay(c,j)))) + fphys_m2(c,j) = min(1.0_r8, max(0.0_r8, fphys_k_p1 * & + exp(fphys_k_p2 * cellclay(c,j)))) p_scalar(c,j) = 1.0_r8 / (params_inst%p_scalar_p1 * & exp(params_inst%p_scalar_p2 * & sqrt(cellclay(c,j)))) @@ -500,98 +509,98 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = rf_l1m1 cascade_donor_pool(i_l1m1) = i_met_lit cascade_receiver_pool(i_l1m1) = i_cop_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = 0.5_r8 - i_l2m1 = 2 - decomp_cascade_con%cascade_step_name(i_l2m1) = 'L2M1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1) = rf_l2m1 - cascade_donor_pool(i_l2m1) = i_str_lit - cascade_receiver_pool(i_l2m1) = i_cop_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1)= 1.0_r8 - - i_s1m1 = 3 - decomp_cascade_con%cascade_step_name(i_s1m1) = 'S1M1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = rf_s1m1 - cascade_donor_pool(i_s1m1) = i_avl_som - cascade_receiver_pool(i_s1m1) = i_cop_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = 1.0_r8 - - i_l1m2 = 4 + i_l1m2 = 2 decomp_cascade_con%cascade_step_name(i_l1m2) = 'L1M2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = rf_l1m2 cascade_donor_pool(i_l1m2) = i_met_lit cascade_receiver_pool(i_l1m2) = i_oli_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = 0.5_r8 + + i_l2m1 = 3 + decomp_cascade_con%cascade_step_name(i_l2m1) = 'L2M1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1) = rf_l2m1 + cascade_donor_pool(i_l2m1) = i_str_lit + cascade_receiver_pool(i_l2m1) = i_cop_mic + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1)= 0.5_r8 - i_l2m2 = 5 + i_l2m2 = 4 decomp_cascade_con%cascade_step_name(i_l2m2) = 'L2M2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2) = rf_l2m2 cascade_donor_pool(i_l2m2) = i_str_lit cascade_receiver_pool(i_l2m2) = i_oli_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2)= 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2)= 0.5_r8 + + i_s1m1 = 5 + decomp_cascade_con%cascade_step_name(i_s1m1) = 'S1M1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = rf_s1m1 + cascade_donor_pool(i_s1m1) = i_avl_som + cascade_receiver_pool(i_s1m1) = i_cop_mic + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = 0.5_r8 i_s1m2 = 6 decomp_cascade_con%cascade_step_name(i_s1m2) = 'S1M2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m2) = rf_s1m2 cascade_donor_pool(i_s1m2) = i_avl_som cascade_receiver_pool(i_s1m2) = i_oli_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m2) = 1.0_r8 - - i_s3s1 = 7 - decomp_cascade_con%cascade_step_name(i_s3s1) = 'S3S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 0.0_r8 - cascade_donor_pool(i_s3s1) = i_phys_som - cascade_receiver_pool(i_s3s1) = i_avl_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m2) = 0.5_r8 - i_s2s1 = 8 + i_s2s1 = 7 decomp_cascade_con%cascade_step_name(i_s2s1) = 'S2S1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = 0.0_r8 cascade_donor_pool(i_s2s1) = i_chem_som cascade_receiver_pool(i_s2s1) = i_avl_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = 1.0_r8 + i_s3s1 = 8 + decomp_cascade_con%cascade_step_name(i_s3s1) = 'S3S1' + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 0.0_r8 + cascade_donor_pool(i_s3s1) = i_phys_som + cascade_receiver_pool(i_s3s1) = i_avl_som + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 + i_m1s1 = 9 decomp_cascade_con%cascade_step_name(i_m1s1) = 'M1S1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = rf_m1s1 cascade_donor_pool(i_m1s1) = i_cop_mic cascade_receiver_pool(i_m1s1) = i_avl_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = favl(bounds%begc:bounds%endc,1:nlevdecomp) + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = 0.5_r8 * (1.0_r8 - fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp)) i_m1s2 = 10 decomp_cascade_con%cascade_step_name(i_m1s2) = 'M1S2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = rf_m1s2 cascade_donor_pool(i_m1s2) = i_cop_mic cascade_receiver_pool(i_m1s2) = i_chem_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = fchem(1:nlevdecomp) + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = 0.5_r8 * (1.0_r8 - fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp)) i_m1s3 = 11 decomp_cascade_con%cascade_step_name(i_m1s3) = 'M1S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = rf_m1s3 cascade_donor_pool(i_m1s3) = i_cop_mic cascade_receiver_pool(i_m1s3) = i_phys_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = fphys(bounds%begc:bounds%endc,1:nlevdecomp) + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp) i_m2s1 = 12 decomp_cascade_con%cascade_step_name(i_m2s1) = 'M2S1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = rf_m2s1 cascade_donor_pool(i_m2s1) = i_oli_mic cascade_receiver_pool(i_m2s1) = i_avl_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = favl(bounds%begc:bounds%endc,1:nlevdecomp) + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = 0.5_r8 * (1.0_r8 - fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) i_m2s2 = 13 decomp_cascade_con%cascade_step_name(i_m2s2) = 'M2S2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = rf_m2s2 cascade_donor_pool(i_m2s2) = i_oli_mic cascade_receiver_pool(i_m2s2) = i_chem_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = fchem(1:nlevdecomp) + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = 0.5_r8 * (1.0_r8 - fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) i_m2s3 = 14 decomp_cascade_con%cascade_step_name(i_m2s3) = 'M2S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = rf_m2s3 cascade_donor_pool(i_m2s3) = i_oli_mic cascade_receiver_pool(i_m2s3) = i_phys_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = fphys(bounds%begc:bounds%endc,1:nlevdecomp) + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp) if (.not. use_fates) then i_cwdl2 = 15 @@ -902,9 +911,13 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do ! TODO Move to the params files - fmet_p1 = 0.85 - fmet_p2 = 0.85 - fmet_p3 = 0.013 + fmet_p1 = 0.85_r8 + fmet_p2 = 0.85_r8 + fmet_p3 = 0.013_r8 + fchem_r_p1 = 0.1_r8 + fchem_r_p2 = -3.0_r8 + fchem_k_p1 = 0.3_r8 + fchem_k_p2 = -3.0_r8 tauMod_factor = 0.01_r8 ! was tauMod_denom = 100 tauMod_min = 0.8_r8 tauMod_max = 1.2_r8 @@ -912,8 +925,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & tau_r2 = 0.3_r8 ! or 0.4? tau_k1 = 2.4e-4_r8 tau_k2 = 0.1_r8 - ko_m1 = 4.0_r8 - ko_m2 = 4.0_r8 + ko_r = 4.0_r8 + ko_k = 4.0_r8 densdep = 1.0_r8 desorpQ10 = 1.1_r8 t_soi_ref = 25.0_r8 ! deg C @@ -926,10 +939,9 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Time-dependent params from Wieder et al. 2015 & testbed code ! TODO STILL MISSING N-related stuff: DIN... - ! TODO cleaf2met is leaf carbon to metabolic litter - ! Similarly the others + ! TODO cleaf2met is leaf C to met litter; similarly the others ! Rethink this as the sum of input to met + str litter? - ! @wwieder will investigate. + ! @wwieder posted to the discussion in the PR. ligninNratioAvg(c) = & (ligninNratio(c,leaf) * (cleaf2met(c) + cleaf2str(c)) + & ligninNratio(c,froot) * (croot2met(c) + croot2str(c)) + & @@ -952,6 +964,11 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & tau_m1 = tau_r1 * exp(tau_r2 * fmet) * tauMod * secsphr tau_m2 = tau_k1 * exp(tau_k2 * fmet) * tauMod * secsphr + ! Used in the update of certain pathfrac terms that vary with time + ! in the next loop + fchem_m1 = min(1.0_r8, max(0.0_r8, fchem_r_p1 * exp(fchem_r_p2 * fmet))) + fchem_m2 = min(1.0_r8, max(0.0_r8, fchem_k_p1 * exp(fchem_k_p2 * fmet))) + do j = 1,nlevdecomp ! vmax ends up in units of per hour but is expected ! in units of per second, so convert here; alternatively @@ -993,50 +1010,64 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & desorption = desorp(c,j) * desorpQ10 * secsphr * & exp((t_soi_degC - t_soi_ref) / 10.0_r8) - ! Microbial concentration in the expected units + ! Microbial concentration with necessary unit conversions ! mgC/cm3 = gC/m3 * (1e3 mg/g) / (1e6 cm3/m3) - m1_conc = (m1_pool(c,j) / col%dz(c,j)) * 1.0e3_r8 * 1.0e-6_r8 + ! TODO Point to decomp_cpools_vr appropriately + m1_conc = (decomp_cpools_vr(c,j,i_cop_mic) / col%dz(c,j)) * & + 1.0e3_r8 * 1.0e-6_r8 + m2_conc = (decomp_cpools_vr(c,j,i_oli_mic) / col%dz(c,j)) * & + 1.0e3_r8 * 1.0e-6_r8 ! Product of w_scalar * depth_scalar * o_scalar w_d_o_scalars = w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) ! decomp_k used in SoilBiogeochemPotentialMod.F90 - ! TODO Excluded spinup terms for now (except see cwd below) - decomp_k(c,j,i_met_lit) = (vmax_l1_m1 * m1_conc / & - (km_l1_m1 + m1_conc) + & - vmax_l1_m2 * m2_conc / & - (km_l1_m2 + m2_conc)) * & - w_d_o_scalars - - decomp_k(c,j,i_str_lit) = (vmax_l2_m1 * m1_conc / & - (km_l2_m1 + m1_conc) + & - vmax_l2_m2 * m2_conc / & - (km_l2_m2 + m2_conc)) * & - w_d_o_scalars - - decomp_k(c,j,i_avl_som) = (vmax_s1_m1 * m1_conc / & - (km_s1_m1 + m1_conc) + & - vmax_s1_m2 * m2_conc / & - (km_s1_m2 + m2_conc)) * & - w_d_o_scalars + ! also updating pathfrac terms that vary with time + ! TODO No spinup terms for now (see cwd below) + ! TODO @wwieder wrote: Build in the efolding capability that would + ! modify decomp_k on all fluxes with depth + term_1 = vmax_l1_m1 * m1_conc / (km_l1_m1 + m1_conc) + term_2 = vmax_l1_m2 * m2_conc / (km_l1_m2 + m2_conc) + decomp_k(c,j,i_met_lit) = (term_1 + term_2) * w_d_o_scalars + pathfrac_decomp_cascade(c,j,i_l1m1) = term_1 / (term_1 + term_2) + pathfrac_decomp_cascade(c,j,i_l1m2) = term_2 / (term_1 + term_2) + + term_1 = vmax_l2_m1 * m1_conc / (km_l2_m1 + m1_conc) + term_2 = vmax_l2_m2 * m2_conc / (km_l2_m2 + m2_conc) + decomp_k(c,j,i_str_lit) = (term_1 + term_2) * w_d_o_scalars + pathfrac_decomp_cascade(c,j,i_l2m1) = term_1 / (term_1 + term_2) + pathfrac_decomp_cascade(c,j,i_l2m2) = term_2 / (term_1 + term_2) + + term_1 = vmax_s1_m1 * m1_conc / (km_s1_m1 + m1_conc) + term_2 = vmax_s1_m2 * m2_conc / (km_s1_m2 + m2_conc) + decomp_k(c,j,i_avl_som) = (term_1 + term_2) * w_d_o_scalars + pathfrac_decomp_cascade(c,j,i_s1m1) = term_1 / (term_1 + term_2) + pathfrac_decomp_cascade(c,j,i_s1m2) = term_2 / (term_1 + term_2) decomp_k(c,j,i_phys_som) = desorption * w_d_o_scalars -! The right hand side is called OXIDAT in the testbed (line 1145) - decomp_k(c,j,i_chem_som) = (vmax_l2_m1 * m1_conc / & - (ko_m1 * km_l2_m1 + m1_conc) + & - vmax_l2_m2 * m2_conc / & - (ko_m2 * km_l2_m2 + m2_conc)) * & - w_d_o_scalars + + term_1 = vmax_l2_m1 * m1_conc / (ko_r * km_l2_m1 + m1_conc) + term_2 = vmax_l2_m2 * m2_conc / (ko_k * km_l2_m2 + m2_conc) + ! The right hand side is OXIDAT in the testbed (line 1145) + decomp_k(c,j,i_chem_som) = (term_1 + term_2) * w_d_o_scalars decomp_k(c,j,i_cop_mic) = tau_m1 * & m1_conc**(densdep - 1.0_r8) * w_d_o_scalars + favl = min(1.0_r8, max(0.0_r8, 1.0_r8 - fphys_m1(c,j) - fchem_m1)) + pathfrac_decomp_cascade(c,j,i_m1s1) = favl + pathfrac_decomp_cascade(c,j,i_m1s2) = fchem_m1 + decomp_k(c,j,i_oli_mic) = tau_m2 * & m2_conc**(densdep - 1.0_r8) * w_d_o_scalars + favl = min(1.0_r8, max(0.0_r8, 1.0_r8 - fphys_m2(c,j) - fchem_m2)) + pathfrac_decomp_cascade(c,j,i_m2s1) = favl + pathfrac_decomp_cascade(c,j,i_m2s2) = fchem_m2 + ! Same for cwd but only if fates not enabled; fates handles cwd on ! its own structure ! TODO This shows how BGC applies the spinup coefficients if (.not. use_fates) then - decomp_k(c,j,i_cwd) = k_frag * w_d_o_scalars * spinup_geogterm_cwd(c) + decomp_k(c,j,i_cwd) = k_frag * w_d_o_scalars ! * spinup_geogterm_cwd(c) end if end do end do From 17fa68f86c66bce9c3aace6162804a3708d8a5e2 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 17 Jul 2021 17:21:18 -0600 Subject: [PATCH 17/69] Minor updates --- src/main/clm_varpar.F90 | 12 ++++++------ .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index 5f92be4ca5..961079488e 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -238,16 +238,16 @@ subroutine clm_varpar_init(actual_maxsoil_patches, actual_numcft) ! in InitAllocate (in SoilBiogeochemStateType) which is called earlier than ! init_decompcascade_bgc where they might have otherwise been derived on the ! fly. For reference, if they were determined in init_decompcascade_bgc: - ! ndecomp_pools would get the value of i_pas_som or i_cwd and - ! ndecomp_cascade_transitions would get the value of i_s3s1 or i_cwdl3 + ! ndecomp_pools would get the value of i_oli_mic or i_cwd and + ! ndecomp_cascade_transitions would get the value of i_m2s3 or i_cwdl2 ! depending on how use_fates is set. if ( use_fates ) then if (use_century_decomp) then ndecomp_pools = 6 ndecomp_cascade_transitions = 8 else if (use_mimics_decomp) then - ndecomp_pools = ? - ndecomp_cascade_transitions = ? + ndecomp_pools = 7 + ndecomp_cascade_transitions = 14 else ! TODO slevis: Currently for CN (deprecated) ndecomp_pools = 7 ndecomp_cascade_transitions = 7 @@ -257,8 +257,8 @@ subroutine clm_varpar_init(actual_maxsoil_patches, actual_numcft) ndecomp_pools = 7 ndecomp_cascade_transitions = 10 else if (use_mimics_decomp) then - ndecomp_pools = ? - ndecomp_cascade_transitions = ? + ndecomp_pools = 8 + ndecomp_cascade_transitions = 15 else ! TODO slevis: Currently for CN (deprecated) ndecomp_pools = 8 ndecomp_cascade_transitions = 9 diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 2076c44a07..7b3fabe99d 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -272,7 +272,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_s1m2 = 1.0_r8 - params_inst%mge(6) rf_m1s1 = ! TODO Set or calculate these... - rf_m1s2 = + rf_m1s2 = ! Or are all six of them zero? rf_m1s3 = rf_m2s1 = rf_m2s2 = From 0860aa4c543540916047b0ca58ba39db60593968 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 19 Jul 2021 12:47:51 -0600 Subject: [PATCH 18/69] Rm unnecessary associate assignments as I look through the whole model --- src/biogeochem/CNFUNMod.F90 | 1 - src/biogeochem/CNGRespMod.F90 | 1 - src/biogeochem/CNGapMortalityMod.F90 | 1 - 3 files changed, 3 deletions(-) diff --git a/src/biogeochem/CNFUNMod.F90 b/src/biogeochem/CNFUNMod.F90 index 57e8e11c86..1fba6cf1b9 100644 --- a/src/biogeochem/CNFUNMod.F90 +++ b/src/biogeochem/CNFUNMod.F90 @@ -505,7 +505,6 @@ subroutine CNFUN(bounds,num_soilc, filter_soilc,num_soilp& !--------------------------------- associate(ivt => patch%itype , & ! Input: [integer (:) ] p leafcn => pftcon%leafcn , & ! Input: leaf C:N (gC/gN) - lflitcn => pftcon%lflitcn , & ! Input: leaf litter C:N (gC/gN) season_decid => pftcon%season_decid , & ! Input: binary flag for seasonal ! -deciduous leaf habit (0 or 1) stress_decid => pftcon%stress_decid , & ! Input: binary flag for stress diff --git a/src/biogeochem/CNGRespMod.F90 b/src/biogeochem/CNGRespMod.F90 index d95761e61f..44a2225548 100644 --- a/src/biogeochem/CNGRespMod.F90 +++ b/src/biogeochem/CNGRespMod.F90 @@ -60,7 +60,6 @@ subroutine CNGResp(num_soilp, filter_soilp, cnveg_carbonflux_inst, canopystate_i grperc => pftcon%grperc , & ! Input: growth respiration parameter grpnow => pftcon%grpnow , & ! Input: growth respiration parameter leafcn => pftcon%leafcn , & ! Input: leaf C:N (gC/gN) - frootcn => pftcon%frootcn , & ! Input: fine root C:N (gC/gN) livewdcn => pftcon%livewdcn , & ! Input: live wood (phloem and ray parenchyma) C:N (gC/gN) laisun => canopystate_inst%laisun_patch , & ! Input: [real(r8) (:)] sunlit projected leaf area index diff --git a/src/biogeochem/CNGapMortalityMod.F90 b/src/biogeochem/CNGapMortalityMod.F90 index 060a183688..0bd06e0e5a 100644 --- a/src/biogeochem/CNGapMortalityMod.F90 +++ b/src/biogeochem/CNGapMortalityMod.F90 @@ -134,7 +134,6 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so heatstress => dgvs_inst%heatstress_patch , & ! Input: [real(r8) (:) ] leafcn => pftcon%leafcn , & ! Input: [real(r8) (:)] leaf C:N (gC/gN) - frootcn => pftcon%frootcn , & ! Input: [real(r8) (:)] fine root C:N (gC/gN) livewdcn => pftcon%livewdcn , & ! Input: [real(r8) (:)] live wood (phloem and ray parenchyma) C:N (gC/gN) laisun => canopystate_inst%laisun_patch , & ! Input: [real(r8) (:) ] sunlit projected leaf area index laisha => canopystate_inst%laisha_patch , & ! Input: [real(r8) (:) ] shaded projected leaf area index From 8715ec57d8bd38382d8fc3c73cfc99d1649ff0e3 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 19 Jul 2021 16:21:07 -0600 Subject: [PATCH 19/69] First draft of the ligninNratioAvg calculation --- src/biogeochem/CNVegCarbonFluxType.F90 | 12 +++ .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 81 ++++++++++++------- 2 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index 9eb226d67f..7b551d89c8 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -4420,6 +4420,18 @@ subroutine Summary_carbonflux(this, & l2g_scale_type = 'unity') end if + if (use_mimics_decomp) then + call p2c(bounds, num_soilc, filter_soilc, & + this%leafc_to_litter_patch(bounds%begp:bounds%endp), & + this%leafc_to_litter_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_soilc, filter_soilc, & + this%frootc_to_litter_patch(bounds%begp:bounds%endp), & + this%frootc_to_litter_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_soilc, filter_soilc, & + this%m_deadstemc_to_litter_patch(bounds%begp:bounds%endp), & + this%m_deadstemc_to_litter_col(bounds%begc:bounds%endc)) + end if + call p2c(bounds, num_soilc, filter_soilc, & this%fire_closs_patch(bounds%begp:bounds%endp), & this%fire_closs_p2c_col(bounds%begc:bounds%endc)) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 7b3fabe99d..d2480707ac 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -61,7 +61,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! Respiration fraction cwd --> structural litter (keep comment sep for dif) real(r8):: rf_cwdl2_bgc real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) - + real(r8) :: cwd_flig_bgc ! real(r8) :: minpsi_bgc !minimum soil water potential for heterotrophic resp real(r8) :: maxpsi_bgc !maximum soil water potential for heterotrophic resp @@ -134,6 +134,11 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%maxpsi_bgc=tempr + tString='cwd_flig' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%cwd_flig_bgc=tempr + tString='initial_Cstocks_depth_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -271,8 +276,8 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_l2m2 = 1.0_r8 - params_inst%mge(5) rf_s1m2 = 1.0_r8 - params_inst%mge(6) - rf_m1s1 = ! TODO Set or calculate these... - rf_m1s2 = ! Or are all six of them zero? + rf_m1s1 = ! TODO Set or calculate these here OR + rf_m1s2 = ! are all six of them zero? rf_m1s3 = rf_m2s1 = rf_m2s2 = @@ -684,12 +689,21 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & !----------------------------------------------------------------------- associate( & + annsum_npp_col => cnveg_carbonflux_inst%annsum_npp_col , & ! Input: [real(r8) (:) ] annual sum of NPP at the column level (gC/m2/yr) + leafc_to_litter => cnveg_carbonflux_inst%leafc_to_litter_col , & ! Input: [real(r8) (:) ] leaf C litterfall at the column level (gC/m2/s) + frootc_to_litter => cnveg_carbonflux_inst%frootc_to_litter_col, & ! Input: [real(r8) (:) ] fine root C litterfall at the column level (gC/m2/s) + m_deadstemc_to_litter => cnveg_carbonflux_inst%m_deadstemc_to_litter_col , & ! Input: [real(r8) (:)] dead stem C mortality (gC/m2/s) + + ! TODO pftcon% or params_inst% and are these already read in pftcon? + lflitcn => pftcon%lflitcn , & ! Input: [real(r8) (:) ] leaf litter C:N (gC/gN) + frootcn => pftcon%frootcn , & ! Input: [real(r8) (:) ] fine root C:N (gC/gN) + lf_flig => pftcon%lf_flig , & ! Input: [real(r8) (:) ] fraction of lignin in leaves (0 to 1) + fr_flig => pftcon%fr_flig , & ! Input: [real(r8) (:) ] fraction of lignin in fine roots (0 to 1) + cwd_flig => params_inst%cwd_flig , & ! Input: [real(r8) ] fraction of lignin in cwd (0 to 1) minpsi => params_inst%minpsi_bgc , & ! Input: [real(r8) ] minimum soil suction (mm) maxpsi => params_inst%maxpsi_bgc , & ! Input: [real(r8) ] maximum soil suction (mm) soilpsi => soilstate_inst%soilpsi_col , & ! Input: [real(r8) (:,:) ] soil water potential in each soil layer (MPa) - t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) - o2stress_sat => ch4_inst%o2stress_sat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) o2stress_unsat => ch4_inst%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area @@ -914,6 +928,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & fmet_p1 = 0.85_r8 fmet_p2 = 0.85_r8 fmet_p3 = 0.013_r8 + fmet_p4 = 40.0_r8 fchem_r_p1 = 0.1_r8 fchem_r_p2 = -3.0_r8 fchem_k_p1 = 0.3_r8 @@ -921,10 +936,10 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & tauMod_factor = 0.01_r8 ! was tauMod_denom = 100 tauMod_min = 0.8_r8 tauMod_max = 1.2_r8 - tau_r1 = 5.2e-4_r8 - tau_r2 = 0.3_r8 ! or 0.4? - tau_k1 = 2.4e-4_r8 - tau_k2 = 0.1_r8 + tau_r_p1 = 5.2e-4_r8 + tau_r_p2 = 0.3_r8 ! or 0.4? + tau_k_p1 = 2.4e-4_r8 + tau_k_p2 = 0.1_r8 ko_r = 4.0_r8 ko_k = 4.0_r8 densdep = 1.0_r8 @@ -939,30 +954,41 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Time-dependent params from Wieder et al. 2015 & testbed code ! TODO STILL MISSING N-related stuff: DIN... - ! TODO cleaf2met is leaf C to met litter; similarly the others - ! Rethink this as the sum of input to met + str litter? - ! @wwieder posted to the discussion in the PR. - ligninNratioAvg(c) = & - (ligninNratio(c,leaf) * (cleaf2met(c) + cleaf2str(c)) + & - ligninNratio(c,froot) * (croot2met(c) + croot2str(c)) + & - ligninNratio(c,wood) * (cwd2str(c))) / & - max(0.001, cleaf2met(c) + cleaf2str(c) + & - croot2met(c) + croot2str(c) + cwd2str(c)) + ! TODO Did I translate this testbed code correctly? + ! ligninNratioAvg(c) = & + ! (ligninNratio(c,leaf) * (cleaf2met(c) + cleaf2str(c)) + & + ! ligninNratio(c,froot) * (croot2met(c) + croot2str(c)) + & + ! ligninNratio(c,wood) * (cwd2str(c))) / & + ! max(0.001, cleaf2met(c) + cleaf2str(c) + & + ! croot2met(c) + croot2str(c) + cwd2str(c)) + ! Concerns: + ! - all-pft avg of ratios .ne. to ratios of the averages + ! so better to calculate all-pft avg ligninNratios in pftconMod + ! - Or should we even calculate them only for pfts that are present? + ! If so, we could do that just before call p2c and then call p2c only + ! once for the column-level ligninNratioAvg + ligninNratioAvg = ((sum(lf_flig(1:)) / size(lf_flig(1:))) * & + (sum(lflitcn(1:) / size(lflitcn(1:)))) * & + leafc_to_litter(c) + & + (sum(fr_flig(1:)) / size(fr_flig(1:))) * & + (sum(frootcn(1:)) / size(frootcn(1:))) * & + frootc_to_litter(c) + & + cwd_flig * (cwdc_col(c) / cwdn_col(c)) * m_deadstem_to_litter(c)) / & + max(1.0e-3_r8, leafc_to_litter(c) + frootc_to_litter(c) + & + m_deadstem_to_litter(c)) ! Set limits on Lignin:N to keep fmet > 0.2 ! Necessary for litter quality in boreal forests with high cwd flux - fmet = fmet_p1 * (fmet_p2 - fmet_p3 * min(40.0_r8, & - ligninNratioAvg(c))) + fmet = fmet_p1 * (fmet_p2 - fmet_p3 * min(fmet_p4, ligninNratioAvg(c))) tauMod = min(tauMod_max, max(tauMod_min, & - sqrt(tauMod_factor * & - cnveg_carbonflux_inst%annsum_npp_col(c)))) + sqrt(tauMod_factor * annsum_npp_col(c)))) ! tau_m1 is tauR and tau_m2 is tauK in Wieder et al. 2015 ! tau ends up in units of per hour but is expected ! in units of per second, so convert here; alternatively ! place the conversion once in w_d_o_scalars - tau_m1 = tau_r1 * exp(tau_r2 * fmet) * tauMod * secsphr - tau_m2 = tau_k1 * exp(tau_k2 * fmet) * tauMod * secsphr + tau_m1 = tau_r_p1 * exp(tau_r_p2 * fmet) * tauMod * secsphr + tau_m2 = tau_k_p1 * exp(tau_k_p2 * fmet) * tauMod * secsphr ! Used in the update of certain pathfrac terms that vary with time ! in the next loop @@ -1012,7 +1038,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Microbial concentration with necessary unit conversions ! mgC/cm3 = gC/m3 * (1e3 mg/g) / (1e6 cm3/m3) - ! TODO Point to decomp_cpools_vr appropriately + ! TODO Does the CTSM have (these) unit conversions parameterized? m1_conc = (decomp_cpools_vr(c,j,i_cop_mic) / col%dz(c,j)) * & 1.0e3_r8 * 1.0e-6_r8 m2_conc = (decomp_cpools_vr(c,j,i_oli_mic) / col%dz(c,j)) * & @@ -1024,8 +1050,9 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! decomp_k used in SoilBiogeochemPotentialMod.F90 ! also updating pathfrac terms that vary with time ! TODO No spinup terms for now (see cwd below) - ! TODO @wwieder wrote: Build in the efolding capability that would - ! modify decomp_k on all fluxes with depth + ! TODO wwieder: Build in the efolding capability that would modify + ! decomp_k on all fluxes with depth. + ! slevis: Already in place with decomp_depth_efolding? term_1 = vmax_l1_m1 * m1_conc / (km_l1_m1 + m1_conc) term_2 = vmax_l1_m2 * m2_conc / (km_l1_m2 + m2_conc) decomp_k(c,j,i_met_lit) = (term_1 + term_2) * w_d_o_scalars From 3ba4ad3b458658c93578f3d21342524966c1c8e6 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 19 Jul 2021 17:20:55 -0600 Subject: [PATCH 20/69] Made parameters of some two unit conversions --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index d2480707ac..dae1b7dc26 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -1038,11 +1038,12 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Microbial concentration with necessary unit conversions ! mgC/cm3 = gC/m3 * (1e3 mg/g) / (1e6 cm3/m3) - ! TODO Does the CTSM have (these) unit conversions parameterized? + g_to_mg = 1.0e3_r8 ! put unit conversions in clm_varcon? + cm3_to_m3 = 1.0e-6_r8 m1_conc = (decomp_cpools_vr(c,j,i_cop_mic) / col%dz(c,j)) * & - 1.0e3_r8 * 1.0e-6_r8 + g_to_mg * cm3_to_m3 m2_conc = (decomp_cpools_vr(c,j,i_oli_mic) / col%dz(c,j)) * & - 1.0e3_r8 * 1.0e-6_r8 + g_to_mg * cm3_to_m3 ! Product of w_scalar * depth_scalar * o_scalar w_d_o_scalars = w_scalar(c,j) * depth_scalar(c,j) * o_scalar(c,j) From 5222227fe28f79ffecf7822cdca1502d982e1c33 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 22 Jul 2021 17:26:51 -0600 Subject: [PATCH 21/69] Working on the calculation of ligninNratioAve --- src/biogeochem/CNVegCarbonFluxType.F90 | 43 +++++++-- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 88 +++++-------------- 2 files changed, 59 insertions(+), 72 deletions(-) diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index 7b551d89c8..bbaab4b6bb 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -17,7 +17,7 @@ module CNVegCarbonFluxType use clm_varctl , only : use_grainproduct use clm_varctl , only : iulog use landunit_varcon , only : istsoil, istcrop, istdlak - use pftconMod , only : npcropmin + use pftconMod , only : npcropmin, pftcon use LandunitType , only : lun use ColumnType , only : col use PatchType , only : patch @@ -4396,6 +4396,18 @@ subroutine Summary_carbonflux(this, & this%hrv_gresp_storage_to_litter_patch(p) + & this%hrv_gresp_xfer_to_litter_patch(p) + if (use_mimics_decomp) then + ! Calculate ligninNratio for leaves and fine roots + ! TODO Declare ligninNratio vars wherever they need to be. + associate(ivt => patch%itype) ! Input: [integer (:)] patch plant type + ligninNratio_leaf_patch(p) = pftcon%lf_flig(ivt(p)) * & + pftcon%lflitcn(ivt(p)) * & + this%leafc_to_litter_patch(p) + ligninNratio_froot_patch(p) = pftcon%fr_flig(ivt(p)) * & + pftcon%frootcn(ivt(p)) * & + this%frootc_to_litter_patch(p) + end associate + end if end do ! end of patches loop !------------------------------------------------ @@ -4421,15 +4433,18 @@ subroutine Summary_carbonflux(this, & end if if (use_mimics_decomp) then + call p2c(bounds, num_soilc, filter_soilc, & + ligninNratio_leaf_patch(bounds%begp:bounds%endp), & + ligninNratio_leaf_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_soilc, filter_soilc, & + ligninNratio_froot_patch(bounds%begp:bounds%endp), & + ligninNratio_froot_col(bounds%begc:bounds%endc)) call p2c(bounds, num_soilc, filter_soilc, & this%leafc_to_litter_patch(bounds%begp:bounds%endp), & - this%leafc_to_litter_col(bounds%begc:bounds%endc)) + leafc_to_litter_col(bounds%begc:bounds%endc)) call p2c(bounds, num_soilc, filter_soilc, & this%frootc_to_litter_patch(bounds%begp:bounds%endp), & - this%frootc_to_litter_col(bounds%begc:bounds%endc)) - call p2c(bounds, num_soilc, filter_soilc, & - this%m_deadstemc_to_litter_patch(bounds%begp:bounds%endp), & - this%m_deadstemc_to_litter_col(bounds%begc:bounds%endc)) + frootc_to_litter_col(bounds%begc:bounds%endc)) end if call p2c(bounds, num_soilc, filter_soilc, & @@ -4452,6 +4467,22 @@ subroutine Summary_carbonflux(this, & this%gpp_patch(bounds%begp:bounds%endp), & this%gpp_col(bounds%begc:bounds%endc)) + if (use_mimics_decomp) then + ! Calculate ligninNratioAve + ! TODO define new var cwdc_to_litter as the flux from cwdl2 transition + ! TODO See how *CascadeBGC gets cwd_flig but prob needs to be read as + ! a shared param now + do fc = 1,num_soilc + c = filter_soilc(fc) + this%ligninNratioAvg_col(c) = & + (ligninNratio_leaf_col(c) + ligninNratio_froot_col(c) + & + cwd_flig * (this%cwdc_col(c) / this%cwdn_col(c)) * cwdc_to_litter(c)) / & + max(1.0e-3_r8, leafc_to_litter_col(c) + & + frootc_to_litter_col(c) + & + cwdc_to_litter(c)) + end do + end if + ! this code is to calculate an exponentially-relaxed npp value for use in NDynamics code if ( trim(isotope) == 'bulk') then diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index dae1b7dc26..53f195acc3 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -61,7 +61,6 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! Respiration fraction cwd --> structural litter (keep comment sep for dif) real(r8):: rf_cwdl2_bgc real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) - real(r8) :: cwd_flig_bgc ! real(r8) :: minpsi_bgc !minimum soil water potential for heterotrophic resp real(r8) :: maxpsi_bgc !maximum soil water potential for heterotrophic resp @@ -108,7 +107,9 @@ subroutine readParams ( ncid ) ! Read off of netcdf file ! TODO Add new params here and in the params file. - ! TODO Some may need _bgc added/removed here and in the params file + ! TODO Some may need _bgc or _mimics added/removed here and in the params + ! file. Nicer to add as prefix instead of as suffix because params will + ! then appear grouped in the file. Need approval from Bill/Erik. ! TODO Read MIMICS-specific params here & shared ones (eg *_bgc) as: ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding ! TODO When ready for all final params values, talk to @wwieder and, @@ -134,11 +135,6 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%maxpsi_bgc=tempr - tString='cwd_flig' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cwd_flig_bgc=tempr - tString='initial_Cstocks_depth_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -208,12 +204,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat real(r8) :: rf_l2m2 real(r8) :: rf_s1m1 real(r8) :: rf_s1m2 - real(r8) :: rf_m1s1 - real(r8) :: rf_m1s2 - real(r8) :: rf_m1s3 - real(r8) :: rf_m2s1 - real(r8) :: rf_m2s2 - real(r8) :: rf_m2s3 real(r8) :: rf_cwdl2 real(r8), allocatable :: desorp(:,:) real(r8), allocatable :: fphys_m1(:,:) @@ -276,13 +266,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_l2m2 = 1.0_r8 - params_inst%mge(5) rf_s1m2 = 1.0_r8 - params_inst%mge(6) - rf_m1s1 = ! TODO Set or calculate these here OR - rf_m1s2 = ! are all six of them zero? - rf_m1s3 = - rf_m2s1 = - rf_m2s2 = - rf_m2s3 = - rf_cwdl2 = params_inst%rf_cwdl2_bgc ! vmod = "old" vmod * av AND kmod = ak / "old" kmod @@ -567,42 +550,42 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_m1s1 = 9 decomp_cascade_con%cascade_step_name(i_m1s1) = 'M1S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = rf_m1s1 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = 0.0_r8 cascade_donor_pool(i_m1s1) = i_cop_mic cascade_receiver_pool(i_m1s1) = i_avl_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = 0.5_r8 * (1.0_r8 - fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp)) i_m1s2 = 10 decomp_cascade_con%cascade_step_name(i_m1s2) = 'M1S2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = rf_m1s2 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = 0.0_r8 cascade_donor_pool(i_m1s2) = i_cop_mic cascade_receiver_pool(i_m1s2) = i_chem_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = 0.5_r8 * (1.0_r8 - fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp)) i_m1s3 = 11 decomp_cascade_con%cascade_step_name(i_m1s3) = 'M1S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = rf_m1s3 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = 0.0_r8 cascade_donor_pool(i_m1s3) = i_cop_mic cascade_receiver_pool(i_m1s3) = i_phys_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp) i_m2s1 = 12 decomp_cascade_con%cascade_step_name(i_m2s1) = 'M2S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = rf_m2s1 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = 0.0_r8 cascade_donor_pool(i_m2s1) = i_oli_mic cascade_receiver_pool(i_m2s1) = i_avl_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = 0.5_r8 * (1.0_r8 - fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) i_m2s2 = 13 decomp_cascade_con%cascade_step_name(i_m2s2) = 'M2S2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = rf_m2s2 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = 0.0_r8 cascade_donor_pool(i_m2s2) = i_oli_mic cascade_receiver_pool(i_m2s2) = i_chem_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = 0.5_r8 * (1.0_r8 - fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) i_m2s3 = 14 decomp_cascade_con%cascade_step_name(i_m2s3) = 'M2S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = rf_m2s3 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = 0.0_r8 cascade_donor_pool(i_m2s3) = i_oli_mic cascade_receiver_pool(i_m2s3) = i_phys_som pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp) @@ -690,16 +673,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & associate( & annsum_npp_col => cnveg_carbonflux_inst%annsum_npp_col , & ! Input: [real(r8) (:) ] annual sum of NPP at the column level (gC/m2/yr) - leafc_to_litter => cnveg_carbonflux_inst%leafc_to_litter_col , & ! Input: [real(r8) (:) ] leaf C litterfall at the column level (gC/m2/s) - frootc_to_litter => cnveg_carbonflux_inst%frootc_to_litter_col, & ! Input: [real(r8) (:) ] fine root C litterfall at the column level (gC/m2/s) - m_deadstemc_to_litter => cnveg_carbonflux_inst%m_deadstemc_to_litter_col , & ! Input: [real(r8) (:)] dead stem C mortality (gC/m2/s) - - ! TODO pftcon% or params_inst% and are these already read in pftcon? - lflitcn => pftcon%lflitcn , & ! Input: [real(r8) (:) ] leaf litter C:N (gC/gN) - frootcn => pftcon%frootcn , & ! Input: [real(r8) (:) ] fine root C:N (gC/gN) - lf_flig => pftcon%lf_flig , & ! Input: [real(r8) (:) ] fraction of lignin in leaves (0 to 1) - fr_flig => pftcon%fr_flig , & ! Input: [real(r8) (:) ] fraction of lignin in fine roots (0 to 1) - cwd_flig => params_inst%cwd_flig , & ! Input: [real(r8) ] fraction of lignin in cwd (0 to 1) + ligninNratioAvg => cnveg_carbonflux_inst%ligninNratioAvg_col , & ! Input: [real(r8) (:) ] column-level lignin to nitrogen ratio (TODO Are numerator/denominator units the same as in testbed?) + minpsi => params_inst%minpsi_bgc , & ! Input: [real(r8) ] minimum soil suction (mm) maxpsi => params_inst%maxpsi_bgc , & ! Input: [real(r8) ] maximum soil suction (mm) soilpsi => soilstate_inst%soilpsi_col , & ! Input: [real(r8) (:,:) ] soil water potential in each soil layer (MPa) @@ -911,13 +886,15 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end if ! Term that reduces decomposition rate at depth + ! Placeholder. For now depth_scalar = 1. do j = 1, nlevdecomp do fc = 1, num_soilc c = filter_soilc(fc) if (use_vertsoilc) then ! Using fixed e-folding depth as in ! SoilBiogeochemDecompCascadeBGCMod.F90 - depth_scalar(c,j) = exp(-zsoi(j) / decomp_depth_efolding) +! depth_scalar(c,j) = exp(-zsoi(j) / decomp_depth_efolding) + depth_scalar(c,j) = 1.0_r8 else depth_scalar(c,j) = 1.0_r8 end if @@ -943,7 +920,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ko_r = 4.0_r8 ko_k = 4.0_r8 densdep = 1.0_r8 - desorpQ10 = 1.1_r8 + desorpQ10 = 1.0_r8 t_soi_ref = 25.0_r8 ! deg C ! calculate rates for all litter and som pools @@ -952,33 +929,15 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & c = filter_soilc(fc) ! Time-dependent params from Wieder et al. 2015 & testbed code - ! TODO STILL MISSING N-related stuff: DIN... - - ! TODO Did I translate this testbed code correctly? - ! ligninNratioAvg(c) = & - ! (ligninNratio(c,leaf) * (cleaf2met(c) + cleaf2str(c)) + & - ! ligninNratio(c,froot) * (croot2met(c) + croot2str(c)) + & - ! ligninNratio(c,wood) * (cwd2str(c))) / & - ! max(0.001, cleaf2met(c) + cleaf2str(c) + & - ! croot2met(c) + croot2str(c) + cwd2str(c)) - ! Concerns: - ! - all-pft avg of ratios .ne. to ratios of the averages - ! so better to calculate all-pft avg ligninNratios in pftconMod - ! - Or should we even calculate them only for pfts that are present? - ! If so, we could do that just before call p2c and then call p2c only - ! once for the column-level ligninNratioAvg - ligninNratioAvg = ((sum(lf_flig(1:)) / size(lf_flig(1:))) * & - (sum(lflitcn(1:) / size(lflitcn(1:)))) * & - leafc_to_litter(c) + & - (sum(fr_flig(1:)) / size(fr_flig(1:))) * & - (sum(frootcn(1:)) / size(frootcn(1:))) * & - frootc_to_litter(c) + & - cwd_flig * (cwdc_col(c) / cwdn_col(c)) * m_deadstem_to_litter(c)) / & - max(1.0e-3_r8, leafc_to_litter(c) + frootc_to_litter(c) + & - m_deadstem_to_litter(c)) + ! TODO STILL MISSING N-related stuff (DIN... in the testbed). + ! Start looking in NitrogenCompetitionMod. We will need hooks to + ! the ctsm no3 and nh4 terms. The nh4 fluxes are "nmin". ! Set limits on Lignin:N to keep fmet > 0.2 ! Necessary for litter quality in boreal forests with high cwd flux + ! TODO Check for high-freq variations in ligninNratioAvg. To avoid, + ! replace pool_to_litter terms with ann or other long term mean + ! in CNVegCarbonFluxType. fmet = fmet_p1 * (fmet_p2 - fmet_p3 * min(fmet_p4, ligninNratioAvg(c))) tauMod = min(tauMod_max, max(tauMod_min, & sqrt(tauMod_factor * annsum_npp_col(c)))) @@ -1051,9 +1010,6 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! decomp_k used in SoilBiogeochemPotentialMod.F90 ! also updating pathfrac terms that vary with time ! TODO No spinup terms for now (see cwd below) - ! TODO wwieder: Build in the efolding capability that would modify - ! decomp_k on all fluxes with depth. - ! slevis: Already in place with decomp_depth_efolding? term_1 = vmax_l1_m1 * m1_conc / (km_l1_m1 + m1_conc) term_2 = vmax_l1_m2 * m2_conc / (km_l1_m2 + m2_conc) decomp_k(c,j,i_met_lit) = (term_1 + term_2) * w_d_o_scalars @@ -1072,7 +1028,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & pathfrac_decomp_cascade(c,j,i_s1m1) = term_1 / (term_1 + term_2) pathfrac_decomp_cascade(c,j,i_s1m2) = term_2 / (term_1 + term_2) - decomp_k(c,j,i_phys_som) = desorption * w_d_o_scalars + decomp_k(c,j,i_phys_som) = desorption * depth_scalar(c,j) term_1 = vmax_l2_m1 * m1_conc / (ko_r * km_l2_m1 + m1_conc) term_2 = vmax_l2_m2 * m2_conc / (ko_k * km_l2_m2 + m2_conc) From ae3b11b6699e6c0ce8c436ed812676d085143fce Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 22 Jul 2021 19:01:10 -0600 Subject: [PATCH 22/69] Closer to completing calculation of ligninNratioAve --- src/biogeochem/CNVegCarbonFluxType.F90 | 35 ++++++++++--------- src/main/clm_varpar.F90 | 2 ++ .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 4 +-- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index bbaab4b6bb..1d0eb8ef1c 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -11,7 +11,7 @@ module CNVegCarbonFluxType use decompMod , only : bounds_type use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools - use clm_varpar , only : nlevdecomp_full, nlevdecomp, i_litr_min, i_litr_max + use clm_varpar , only : nlevdecomp_full, nlevdecomp, i_litr_min, i_litr_max, i_cwdl2 use clm_varcon , only : spval, dzsoi_decomp use clm_varctl , only : use_cndv, use_c13, use_nitrif_denitrif, use_crop use clm_varctl , only : use_grainproduct @@ -4432,21 +4432,6 @@ subroutine Summary_carbonflux(this, & l2g_scale_type = 'unity') end if - if (use_mimics_decomp) then - call p2c(bounds, num_soilc, filter_soilc, & - ligninNratio_leaf_patch(bounds%begp:bounds%endp), & - ligninNratio_leaf_col(bounds%begc:bounds%endc)) - call p2c(bounds, num_soilc, filter_soilc, & - ligninNratio_froot_patch(bounds%begp:bounds%endp), & - ligninNratio_froot_col(bounds%begc:bounds%endc)) - call p2c(bounds, num_soilc, filter_soilc, & - this%leafc_to_litter_patch(bounds%begp:bounds%endp), & - leafc_to_litter_col(bounds%begc:bounds%endc)) - call p2c(bounds, num_soilc, filter_soilc, & - this%frootc_to_litter_patch(bounds%begp:bounds%endp), & - frootc_to_litter_col(bounds%begc:bounds%endc)) - end if - call p2c(bounds, num_soilc, filter_soilc, & this%fire_closs_patch(bounds%begp:bounds%endp), & this%fire_closs_p2c_col(bounds%begc:bounds%endc)) @@ -4468,15 +4453,31 @@ subroutine Summary_carbonflux(this, & this%gpp_col(bounds%begc:bounds%endc)) if (use_mimics_decomp) then + call p2c(bounds, num_soilc, filter_soilc, & + ligninNratio_leaf_patch(bounds%begp:bounds%endp), & + ligninNratio_leaf_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_soilc, filter_soilc, & + ligninNratio_froot_patch(bounds%begp:bounds%endp), & + ligninNratio_froot_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_soilc, filter_soilc, & + this%leafc_to_litter_patch(bounds%begp:bounds%endp), & + leafc_to_litter_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_soilc, filter_soilc, & + this%frootc_to_litter_patch(bounds%begp:bounds%endp), & + frootc_to_litter_col(bounds%begc:bounds%endc)) + ! Calculate ligninNratioAve ! TODO define new var cwdc_to_litter as the flux from cwdl2 transition ! TODO See how *CascadeBGC gets cwd_flig but prob needs to be read as ! a shared param now do fc = 1,num_soilc c = filter_soilc(fc) + ligninNratio_cwd = cwd_flig * & + (this%cwdc_col(c) / this%cwdn_col(c)) * & + this%decomp_cascade_ctransfer_col(c,i_cwdl2) this%ligninNratioAvg_col(c) = & (ligninNratio_leaf_col(c) + ligninNratio_froot_col(c) + & - cwd_flig * (this%cwdc_col(c) / this%cwdn_col(c)) * cwdc_to_litter(c)) / & + ligninNratio_cwd) / & max(1.0e-3_r8, leafc_to_litter_col(c) + & frootc_to_litter_col(c) + & cwdc_to_litter(c)) diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index 961079488e..8546e327a9 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -73,6 +73,8 @@ module clm_varpar integer, public :: i_litr_max = -9 ! max index of litter pools; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_met_lit = -9 ! index of metabolic litter pool; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_cwd = -9 ! index of cwd pool; overwritten in SoilBiogeochemDecompCascade*Mod + ! TODO Not necessary but cleaner to use this copy of i_cwdl2 in *CascadeBGC? + integer, public :: i_cwdl2 = -9 ! index of cwd to l2 transition; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: ndecomp_pools_max integer, public :: ndecomp_pools diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 53f195acc3..9ed7c02f12 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -10,7 +10,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod use shr_const_mod , only : SHR_CONST_TKFRZ use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : nlevdecomp, ndecomp_pools_max - use clm_varpar , only : i_met_lit, i_litr_min, i_litr_max, i_cwd + use clm_varpar , only : i_met_lit, i_litr_min, i_litr_max, i_cwd, i_cwdl2 use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_vertsoilc, use_fates use clm_varcon , only : zsoi use decompMod , only : bounds_type @@ -214,7 +214,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat integer :: i_s3s1 integer :: i_m1s3 integer :: i_m2s3 - integer :: i_cwdl2 real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. integer :: c, j ! indices @@ -997,6 +996,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Microbial concentration with necessary unit conversions ! mgC/cm3 = gC/m3 * (1e3 mg/g) / (1e6 cm3/m3) + ! TODO Check that decomp_cpools_vr is populating for microbial pools g_to_mg = 1.0e3_r8 ! put unit conversions in clm_varcon? cm3_to_m3 = 1.0e-6_r8 m1_conc = (decomp_cpools_vr(c,j,i_cop_mic) / col%dz(c,j)) * & From d5d83e457278571d9997e85c3fcae5029ec8ecb6 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 23 Jul 2021 16:11:06 -0600 Subject: [PATCH 23/69] Some clean-up and corrections before starting on the nitrogen By this I do not mean that everything other than N is done :-) --- src/biogeochem/CNVegCarbonFluxType.F90 | 13 ++++++------- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 3 +-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index 1d0eb8ef1c..3a159c8593 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -4004,7 +4004,7 @@ subroutine Summary_carbonflux(this, & use clm_varctl , only: nfix_timeconst, carbon_resp_opt use subgridAveMod , only: p2c, c2g use SoilBiogeochemDecompCascadeConType , only: decomp_cascade_con - use CNSharedParamsMod , only: use_fun + use CNSharedParamsMod , only: use_fun, CNParamsShareInst ! ! !ARGUMENTS: class(cnveg_carbonflux_type) :: this @@ -4398,7 +4398,8 @@ subroutine Summary_carbonflux(this, & if (use_mimics_decomp) then ! Calculate ligninNratio for leaves and fine roots - ! TODO Declare ligninNratio vars wherever they need to be. + ! TODO Declare ligninNratio vars wherever they need to be and + ! initialize if necessary for call p2c to work correctly associate(ivt => patch%itype) ! Input: [integer (:)] patch plant type ligninNratio_leaf_patch(p) = pftcon%lf_flig(ivt(p)) * & pftcon%lflitcn(ivt(p)) * & @@ -4467,12 +4468,10 @@ subroutine Summary_carbonflux(this, & frootc_to_litter_col(bounds%begc:bounds%endc)) ! Calculate ligninNratioAve - ! TODO define new var cwdc_to_litter as the flux from cwdl2 transition - ! TODO See how *CascadeBGC gets cwd_flig but prob needs to be read as - ! a shared param now do fc = 1,num_soilc c = filter_soilc(fc) - ligninNratio_cwd = cwd_flig * & + ! TODO Use cwd_flig in *CascadeBGC the same way for consistency? + ligninNratio_cwd = CNParamsShareInst%cwd_flig * & (this%cwdc_col(c) / this%cwdn_col(c)) * & this%decomp_cascade_ctransfer_col(c,i_cwdl2) this%ligninNratioAvg_col(c) = & @@ -4480,7 +4479,7 @@ subroutine Summary_carbonflux(this, & ligninNratio_cwd) / & max(1.0e-3_r8, leafc_to_litter_col(c) + & frootc_to_litter_col(c) + & - cwdc_to_litter(c)) + this%decomp_cascade_ctransfer_col(c,i_cwdl2)) end do end if diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 9ed7c02f12..a9bef887bb 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -672,7 +672,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & associate( & annsum_npp_col => cnveg_carbonflux_inst%annsum_npp_col , & ! Input: [real(r8) (:) ] annual sum of NPP at the column level (gC/m2/yr) - ligninNratioAvg => cnveg_carbonflux_inst%ligninNratioAvg_col , & ! Input: [real(r8) (:) ] column-level lignin to nitrogen ratio (TODO Are numerator/denominator units the same as in testbed?) + ligninNratioAvg => cnveg_carbonflux_inst%ligninNratioAvg_col , & ! Input: [real(r8) (:) ] column-level lignin to nitrogen ratio minpsi => params_inst%minpsi_bgc , & ! Input: [real(r8) ] minimum soil suction (mm) maxpsi => params_inst%maxpsi_bgc , & ! Input: [real(r8) ] maximum soil suction (mm) @@ -996,7 +996,6 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Microbial concentration with necessary unit conversions ! mgC/cm3 = gC/m3 * (1e3 mg/g) / (1e6 cm3/m3) - ! TODO Check that decomp_cpools_vr is populating for microbial pools g_to_mg = 1.0e3_r8 ! put unit conversions in clm_varcon? cm3_to_m3 = 1.0e-6_r8 m1_conc = (decomp_cpools_vr(c,j,i_cop_mic) / col%dz(c,j)) * & From 0b91a02bf6a2f1296d7e093f9648b78e56c49915 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sun, 25 Jul 2021 10:07:51 -0600 Subject: [PATCH 24/69] Negligible changes but pushing to have access to latest during downtime --- src/biogeochem/CNNDynamicsMod.F90 | 2 +- src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/biogeochem/CNNDynamicsMod.F90 b/src/biogeochem/CNNDynamicsMod.F90 index 205ff1e8f1..bc1d8d30da 100644 --- a/src/biogeochem/CNNDynamicsMod.F90 +++ b/src/biogeochem/CNNDynamicsMod.F90 @@ -125,7 +125,7 @@ subroutine CNNDeposition( bounds, & ! directly into the canopy and mineral N entering the soil pool. ! ! !USES: - use CNSharedParamsMod , only: use_fun + ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds type(atm2lnd_type) , intent(in) :: atm2lnd_inst diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index a9bef887bb..941f0b4add 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -928,9 +928,9 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & c = filter_soilc(fc) ! Time-dependent params from Wieder et al. 2015 & testbed code - ! TODO STILL MISSING N-related stuff (DIN... in the testbed). - ! Start looking in NitrogenCompetitionMod. We will need hooks to - ! the ctsm no3 and nh4 terms. The nh4 fluxes are "nmin". + ! TODO STILL MISSING N-related stuff: + ! - DIN... in the testbed + ! - Need hooks to no3, nh4 terms. The nh4 fluxes are "nmin". ! Set limits on Lignin:N to keep fmet > 0.2 ! Necessary for litter quality in boreal forests with high cwd flux From 63cfa3d7f2604b6ec06d18fe6758c47b28c5b1cb Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 31 Jul 2021 18:52:08 -0600 Subject: [PATCH 25/69] Mods originally from @wwieder for the MIMICS nitrogen hooks @wwieder and I converged on this code in yesterday's mtg. I have cleaned it up a bit. Also I have tried to make the logic consistent with pre-existing code. I have not addressed all TODOs. --- .../SoilBiogeochemCompetitionMod.F90 | 35 +++++++++ .../SoilBiogeochemPotentialMod.F90 | 74 ++++++++++++++++++- 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 6f5580bb8b..e40313557e 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -364,6 +364,41 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do end do + ! TODO slevis: Add c_overflow_vr to the heterotrophic resp flux + if (use_mimics) then + do j = 1, nlevdecomp + do fc=1,num_soilc + c = filter_soilc(fc) + + fpi_vr(c,j) = 0.0_r8 + + do k = 1, ndecomp_cascade_transitions + ! TODO slevis: correct to identify as receiver pools? + if (cascade_decomp_receiver(k) == i_cop_mic .or. & + cascade_decomp_receiver(k) == i_oli_mic) then + if (pmnf_immob_vr(c,j,k) > 0.0_r8 .and. & + sum_ndemand_vr(c,j) > 0.0_r8) then + amnf_immob_vr = (sminn_vr(c,j) / dt) * & + (pmnf_immob_vr(c,j,k) / & + sum_ndemand_vr(c,j)) + n_deficit_vr = pmnf_immob_vr(c,j,k) - & + amnf_immob_vr + c_overflow_vr(c,j,k) = n_deficit_vr * & + p_decomp_cn_gain(c,j,k) + else + c_overflow_vr(c,j,k) = 0.0_r8 + end if + else + c_overflow_vr(c,j,k) = 0.0_r8 + end if + end do + end do + end do + else ! not use_mimics + c_overflow_vr(:,:,:) = 0.0_r8 + c_overflow_vr(:,:,:) = 0.0_r8 + end if + if ( local_use_fun ) then call t_startf( 'CNFUN' ) call CNFUN(bounds,num_soilc,filter_soilc,num_soilp,filter_soilp,waterstatebulk_inst, & diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index d7d6ed727f..4119a5ed22 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -165,6 +165,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & decomp_k(c,j,cascade_donor_pool(k)) > 0._r8 ) then p_decomp_cpool_loss(c,j,k) = decomp_cpools_vr(c,j,cascade_donor_pool(k)) & * decomp_k(c,j,cascade_donor_pool(k)) * pathfrac_decomp_cascade(c,j,k) + if ( .not. floating_cn_ratio_decomp_pools(cascade_receiver_pool(k)) ) then !! not transition of cwd to litter if (cascade_receiver_pool(k) /= i_atm ) then ! not 100% respiration @@ -180,9 +181,29 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & else ! 100% respiration pmnf_decomp_cascade(c,j,k) = - p_decomp_cpool_loss(c,j,k) / cn_decomp_pools(c,j,cascade_donor_pool(k)) endif - - else ! CWD -> litter + else ! CWD -> litter OR use_mimics is true pmnf_decomp_cascade(c,j,k) = 0._r8 + + if (use_mimics) then + ! N:C ratio of donor pools (N:C instead of C:N because + ! already checked that we're not dividing by zero) + decomp_nc_loss_donor = & + decomp_npools_vr(c,j,cascade_donor_pool(k)) / & + decomp_cpools_vr(c,j,cascade_donor_pool(k)) + ! calculate N fluxes from donor pools + p_decomp_npool_loss(c,j,k) = & + p_decomp_cpool_loss(c,j,k) * decomp_nc_loss_donor + ! Track N lost to DIN from messy eating, ie the + ! diff between p_decomp_npool_loss (pertains to + ! donor) and p_decomp_npool_gain (receiver) + p_decomp_cpool_gain(c,j,k) = p_decomp_cpool_loss(c,j,k) * & + (1.0_r8 - rf_decomp_cascade(c,j,k)) + ! TODO slevis: nue = 0.85 for anything going into microbial biomass; else 1 + p_decomp_npool_gain(c,j,k) = p_decomp_npool_loss(c,j,k) * & + nue_decomp_cascade(k) + p_decomp_npool_to_din(c,j,k) = p_decomp_npool_loss(c,j,k) - & + p_decomp_npool_gain(c,j,k) + end if end if end if end do @@ -190,6 +211,52 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & end do end do + ! Determine immobilization vs. mineralization by comparing the + ! cn_gain into microbial biomass compared with the target C:N + ! ratio of microbial biomass pools + if (use_mimics) then + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + ! Sum C and N fluxes from all transitions into m1 and m2 pools + do k = 1, ndecomp_cascade_transitions + if (cascade_receiver_pool(k) == i_cop_mic .or. + cascade_receiver_pool(k) == i_oli_mic) then + p_decomp_cpool_gain_sum(c,j,cascade_receiver_pool(k)) = & + p_decomp_cpool_gain_sum_cop_mic(c,j,cascade_receiver_pool(k)) + & + p_decomp_cpool_gain(c,j,k) + p_decomp_npool_gain_sum(c,j,cascade_receiver_pool(k)) = & + p_decomp_npool_gain_sum(c,j,cascade_receiver_pool(k)) + & + p_decomp_npool_gain(c,j,k) + ! Once k-loop completes, the left hand side should + ! contain the correct cn ratio + if (p_decomp_npool_gain_sum(c,j,cascade_receiver_pool(k)) > 0.0_r8) then + p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) = & + p_decomp_cpool_gain_sum(c,j,cascade_receiver_pool(k)) / & + p_decomp_npool_gain_sum(c,j,cascade_receiver_pool(k)) + end if + end if + end do + do k = 1, ndecomp_cascade_transitions + if (cascade_receiver_pool(k) == i_cop_mic .or. + cascade_receiver_pool(k) == i_oli_mic) then + ! TODO slevis: CNmic is a function of a CN parameterization, modified by fMET + ! https://github.com/wwieder/biogeochem_testbed_1.1/blob/Testbed_CN/SOURCE_CODE/mimics_cycle_CN.f90#L1613 + ! if p_decomp_cn_diff < 0 N mineralization + ! > 0 immobilization + p_decomp_cn_diff_ratio = & + (p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) - & + CNmic(...)) / CNmic(...) + ! Actual amount of N that's mineralized or that would need to be immobilized + ! negative=mineralization: add to the DIN pool + ! positive=immobilizaiton: compete for N with plants to see how much we get + pmnf_decomp_cascade(c,j,k) = p_decomp_cn_diff_ratio * p_decomp_npool_gain(c,j,k) + end if + end do + end do + end do + end if + ! Sum up all the potential immobilization fluxes (positive pmnf flux) ! and all the mineralization fluxes (negative pmnf flux) do j = 1,nlevdecomp @@ -207,6 +274,9 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & else gross_nmin_vr(c,j) = gross_nmin_vr(c,j) - pmnf_decomp_cascade(c,j,k) end if + if (use_mimics) then + gross_nmin_vr(c,j) = gross_nmin_vr(c,j) + p_decomp_npool_to_din(c,j,k) + end if end do end do end do From bf87bd31f3b1ba3f6c846918d94494566b2cc469 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 5 Aug 2021 17:07:08 -0600 Subject: [PATCH 26/69] Variable declarations and other loose ends from prev commit --- src/biogeochem/CNDriverMod.F90 | 2 +- src/biogeochem/CNVegCarbonFluxType.F90 | 13 ++++- src/main/clm_varpar.F90 | 2 + .../SoilBiogeochemCarbonFluxType.F90 | 5 ++ .../SoilBiogeochemCompetitionMod.F90 | 20 +++++-- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 58 ++++++++++++++----- .../SoilBiogeochemDecompMod.F90 | 5 +- .../SoilBiogeochemPotentialMod.F90 | 10 ++-- .../SoilBiogeochemStateType.F90 | 3 + 9 files changed, 87 insertions(+), 31 deletions(-) diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index 84f9164b16..1373ef696a 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -398,7 +398,7 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('soilbiogeochemcompetition') - call SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, waterstatebulk_inst, & + call SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, pmnf_decomp_cascade, waterstatebulk_inst, & waterfluxbulk_inst,temperature_inst,soilstate_inst,cnveg_state_inst, & cnveg_carbonstate_inst ,& cnveg_carbonflux_inst,cnveg_nitrogenstate_inst,cnveg_nitrogenflux_inst, & diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index 3a159c8593..895a245ccb 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -334,6 +334,9 @@ module CNVegCarbonFluxType real(r8), pointer :: nbp_grc (:) ! (gC/m2/s) net biome production, includes fire, landuse, harvest and hrv_xsmrpool flux, positive for sink (same as net carbon exchange between land and atmosphere) real(r8), pointer :: nee_grc (:) ! (gC/m2/s) net ecosystem exchange of carbon, includes fire and hrv_xsmrpool, excludes landuse and harvest flux, positive for source + ! Lignin to N ratio + real(r8), pointer :: ligninNratioAvg_col(:) ! Average of leaf, fine root, and CWD lignin to N ratio + ! Dynamic landcover fluxnes real(r8), pointer :: landuseflux_grc(:) ! (gC/m2/s) dwt_conv_cflux+product_closs real(r8), pointer :: npp_Nactive_patch (:) ! C used by mycorrhizal uptake (gC/m2/s) @@ -697,6 +700,8 @@ subroutine InitAllocate(this, bounds, carbon_type) allocate(this%annsum_npp_col (begc:endc)) ; this%annsum_npp_col (:) = nan allocate(this%lag_npp_col (begc:endc)) ; this%lag_npp_col (:) = spval + allocate(this%ligninNratioAvg_col (begc:endc)) ; this%ligninNratioAvg_col (:) = nan + allocate(this%nep_col (begc:endc)) ; this%nep_col (:) = nan allocate(this%nbp_grc (begg:endg)) ; this%nbp_grc (:) = nan allocate(this%nee_grc (begg:endg)) ; this%nee_grc (:) = nan @@ -4025,6 +4030,11 @@ subroutine Summary_carbonflux(this, & integer :: fp,fc ! lake filter indices real(r8) :: nfixlags, dtime ! temp variables for making lagged npp real(r8) :: maxdepth ! depth to integrate soil variables + real(r8) :: ligninNratio_cwd ! lignin to N ratio of CWD + real(r8) :: ligninNratio_leaf_patch(bounds%begp:bounds%endp) ! lignin to N ratio of leaves, patch level + real(r8) :: ligninNratio_froot_patch(bounds%begp:bounds%endp) ! lignin to N ratio of fine roots, patch level + real(r8) :: ligninNratio_leaf_col(bounds%begc:bounds%endc) ! lignin to N ratio of leaves, column level + real(r8) :: ligninNratio_froot_col(bounds%begc:bounds%endc) ! lignin to N ratio of fine roots, column level real(r8) :: nep_grc(bounds%begg:bounds%endg) ! nep_col averaged to gridcell real(r8) :: fire_closs_grc(bounds%begg:bounds%endg) ! fire_closs_col averaged to gridcell real(r8) :: hrv_xsmrpool_to_atm_grc(bounds%begg:bounds%endg) ! hrv_xsmrpool_to_atm_col averaged to gridcell (gC/m2/s) @@ -4398,8 +4408,7 @@ subroutine Summary_carbonflux(this, & if (use_mimics_decomp) then ! Calculate ligninNratio for leaves and fine roots - ! TODO Declare ligninNratio vars wherever they need to be and - ! initialize if necessary for call p2c to work correctly + ! TODO init. ligninNratio vars if nec. for call p2c to work associate(ivt => patch%itype) ! Input: [integer (:)] patch plant type ligninNratio_leaf_patch(p) = pftcon%lf_flig(ivt(p)) * & pftcon%lflitcn(ivt(p)) * & diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index 8546e327a9..78e394bf88 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -72,6 +72,8 @@ module clm_varpar integer, public :: i_litr_min = -9 ! min index of litter pools; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_litr_max = -9 ! max index of litter pools; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_met_lit = -9 ! index of metabolic litter pool; overwritten in SoilBiogeochemDecompCascade*Mod + integer, public :: i_cop_mic = -9 ! index of copiotrophic microbial pool; overwritten in SoilBiogeochemDecompCascade*Mod + integer, public :: i_oli_mic = -9 ! index of oligotrophic microbial pool; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_cwd = -9 ! index of cwd pool; overwritten in SoilBiogeochemDecompCascade*Mod ! TODO Not necessary but cleaner to use this copy of i_cwdl2 in *CascadeBGC? integer, public :: i_cwdl2 = -9 ! index of cwd to l2 transition; overwritten in SoilBiogeochemDecompCascade*Mod diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 index 0e4879fb4a..fc3f337a6e 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 @@ -25,6 +25,7 @@ module SoilBiogeochemCarbonFluxType ! decomposition fluxes real(r8), pointer :: decomp_cpools_sourcesink_col (:,:,:) ! change in decomposing c pools. Used to update concentrations concurrently with vertical transport (gC/m3/timestep) + real(r8), pointer :: c_overflow_vr (:,:,:) ! vertically-resolved C rejected by microbes that cannot process it (gC/m3/s) real(r8), pointer :: decomp_cascade_hr_vr_col (:,:,:) ! vertically-resolved het. resp. from decomposing C pools (gC/m3/s) real(r8), pointer :: decomp_cascade_hr_col (:,:) ! vertically-integrated (diagnostic) het. resp. from decomposing C pools (gC/m2/s) real(r8), pointer :: decomp_cascade_ctransfer_vr_col (:,:,:) ! vertically-resolved C transferred along deomposition cascade (gC/m3/s) @@ -109,6 +110,9 @@ subroutine InitAllocate(this, bounds) allocate(this%decomp_cpools_sourcesink_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) this%decomp_cpools_sourcesink_col(:,:,:)= nan + allocate(this%c_overflow_vr(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)) + this%c_overflow_vr(:,:,:) = nan + allocate(this%decomp_cascade_hr_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)) this%decomp_cascade_hr_vr_col(:,:,:)= spval @@ -690,6 +694,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) do fi = 1,num_column i = filter_column(fi) this%decomp_cascade_hr_col(i,l) = value_column + this%c_overflow_vr(i,j,l) = value_column this%decomp_cascade_hr_vr_col(i,j,l) = value_column this%decomp_cascade_ctransfer_col(i,l) = value_column this%decomp_cascade_ctransfer_vr_col(i,j,l) = value_column diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index e40313557e..41c3825b57 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -165,7 +165,8 @@ subroutine SoilBiogeochemCompetitionInit ( bounds) end subroutine SoilBiogeochemCompetitionInit !----------------------------------------------------------------------- - subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, waterstatebulk_inst, & + subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, & + pmnf_decomp_cascade, waterstatebulk_inst, & waterfluxbulk_inst, temperature_inst,soilstate_inst, & cnveg_state_inst,cnveg_carbonstate_inst, & cnveg_carbonflux_inst,cnveg_nitrogenstate_inst,cnveg_nitrogenflux_inst, & @@ -176,6 +177,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! !USES: use clm_varctl , only: cnallocate_carbon_only, iulog use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions + use clm_varpar , only: i_cop_mic, i_oli_mic use clm_varcon , only: nitrif_n2o_loss_frac use CNSharedParamsMod, only: use_fun use CNFUNMod , only: CNFUN @@ -188,6 +190,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, integer , intent(in) :: filter_soilc(:) ! filter for soil columns integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches + real(r8) , intent(in) :: pmnf_decomp_cascade(bounds%begc:,1:,1:) ! potential mineral N flux from one pool to another (gN/m3/s) type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst type(waterfluxbulk_type) , intent(in) :: waterfluxbulk_inst type(temperature_type) , intent(in) :: temperature_inst @@ -208,6 +211,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, integer :: c,p,l,pi,j ! indices integer :: fc ! filter column index logical :: local_use_fun ! local version of use_fun + real(r8) :: amnf_immob_vr ! actual mineral N flux from immobilization (gN/m3/s) + real(r8) :: n_deficit_vr ! microbial N deficit, vertically resolved (gN/m3/s) real(r8) :: compet_plant_no3 ! (unitless) relative compettiveness of plants for NO3 real(r8) :: compet_plant_nh4 ! (unitless) relative compettiveness of plants for NH4 real(r8) :: compet_decomp_no3 ! (unitless) relative competitiveness of immobilizers for NO3 @@ -247,6 +252,9 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, smin_nh4_vr => soilbiogeochem_nitrogenstate_inst%smin_nh4_vr_col , & ! Input: [real(r8) (:,:) ] (gN/m3) soil mineral NH4 smin_no3_vr => soilbiogeochem_nitrogenstate_inst%smin_no3_vr_col , & ! Input: [real(r8) (:,:) ] (gN/m3) soil mineral NO3 + c_overflow_vr => soilbiogeochem_carbonflux_inst%c_overflow_vr , & ! Output: [real(r8) (:,:,:)] (gC/m3/s) vertically-resolved C rejected by microbes that cannot process it + cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & ! Input: [integer (:) ] which pool is C added to for a given decomposition step + pot_f_nit_vr => soilbiogeochem_nitrogenflux_inst%pot_f_nit_vr_col , & ! Input: [real(r8) (:,:) ] (gN/m3/s) potential soil nitrification flux pot_f_denit_vr => soilbiogeochem_nitrogenflux_inst%pot_f_denit_vr_col , & ! Input: [real(r8) (:,:) ] (gN/m3/s) potential soil denitrification flux f_nit_vr => soilbiogeochem_nitrogenflux_inst%f_nit_vr_col , & ! Output: [real(r8) (:,:) ] (gN/m3/s) soil nitrification flux @@ -374,14 +382,14 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, do k = 1, ndecomp_cascade_transitions ! TODO slevis: correct to identify as receiver pools? - if (cascade_decomp_receiver(k) == i_cop_mic .or. & - cascade_decomp_receiver(k) == i_oli_mic) then - if (pmnf_immob_vr(c,j,k) > 0.0_r8 .and. & + if (cascade_receiver_pool(k) == i_cop_mic .or. & + cascade_receiver_pool(k) == i_oli_mic) then + if (pmnf_decomp_cascade(c,j,k) > 0.0_r8 .and. & sum_ndemand_vr(c,j) > 0.0_r8) then amnf_immob_vr = (sminn_vr(c,j) / dt) * & - (pmnf_immob_vr(c,j,k) / & + (pmnf_decomp_cascade(c,j,k) / & sum_ndemand_vr(c,j)) - n_deficit_vr = pmnf_immob_vr(c,j,k) - & + n_deficit_vr = pmnf_decomp_cascade(c,j,k) - & amnf_immob_vr c_overflow_vr(c,j,k) = n_deficit_vr * & p_decomp_cn_gain(c,j,k) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 941f0b4add..da0cd95fb9 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -10,7 +10,8 @@ module SoilBiogeochemDecompCascadeMIMICSMod use shr_const_mod , only : SHR_CONST_TKFRZ use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : nlevdecomp, ndecomp_pools_max - use clm_varpar , only : i_met_lit, i_litr_min, i_litr_max, i_cwd, i_cwdl2 + use clm_varpar , only : i_met_lit, i_cop_mic, i_oli_mic, i_cwd + use clm_varpar , only : i_litr_min, i_litr_max, i_cwdl2 use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_vertsoilc, use_fates use clm_varcon , only : zsoi use decompMod , only : bounds_type @@ -221,7 +222,8 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat associate( & rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) - pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) + nue_decomp_cascade => soilbiogeochem_state_inst%nue_decomp_cascade_col , & ! Output: [real(r8) (:) ] N use efficiency for a given transition (TODO) + pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) cellclay => soilstate_inst%cellclay_col , & ! Input: [real(r8) (:,:) ] column 3D clay @@ -247,14 +249,15 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat allocate(fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) allocate(p_scalar(bounds%begc:bounds%endc,1:nlevdecomp)) - params_inst%p_scalar_p1 = 0.8_r8 ! TODO Move to the params files - params_inst%p_scalar_p2 = -3.0_r8 + params_inst%p_scalar_p1 = 0.8_r8 ! TODO Move to the params files after + params_inst%p_scalar_p2 = -3.0_r8 ! ... reading TODOs in subr. readParams (above) params_inst%desorp_p1 = 1.5e-5_r8 params_inst%desorp_p2 = -1.5_r8 params_inst%fphys_r_p1 = 0.3_r8 params_inst%fphys_r_p2 = 1.3_r8 params_inst%fphys_k_p1 = 0.2_r8 params_inst%fphys_k_p2 = 0.8_r8 + params_inst%nue_into_mic = 0.85_r8 !------- time-constant coefficients ---------- ! ! set respiration fractions for fluxes between compartments @@ -496,6 +499,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = rf_l1m1 cascade_donor_pool(i_l1m1) = i_met_lit cascade_receiver_pool(i_l1m1) = i_cop_mic + nue_decomp_cascade(i_l1m1) = nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = 0.5_r8 i_l1m2 = 2 @@ -503,6 +507,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = rf_l1m2 cascade_donor_pool(i_l1m2) = i_met_lit cascade_receiver_pool(i_l1m2) = i_oli_mic + nue_decomp_cascade(i_l1m2) = nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = 0.5_r8 i_l2m1 = 3 @@ -510,6 +515,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1) = rf_l2m1 cascade_donor_pool(i_l2m1) = i_str_lit cascade_receiver_pool(i_l2m1) = i_cop_mic + nue_decomp_cascade(i_l2m1) = nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1)= 0.5_r8 i_l2m2 = 4 @@ -517,6 +523,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2) = rf_l2m2 cascade_donor_pool(i_l2m2) = i_str_lit cascade_receiver_pool(i_l2m2) = i_oli_mic + nue_decomp_cascade(i_l2m2) = nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2)= 0.5_r8 i_s1m1 = 5 @@ -524,6 +531,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = rf_s1m1 cascade_donor_pool(i_s1m1) = i_avl_som cascade_receiver_pool(i_s1m1) = i_cop_mic + nue_decomp_cascade(i_s1m1) = nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = 0.5_r8 i_s1m2 = 6 @@ -531,6 +539,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m2) = rf_s1m2 cascade_donor_pool(i_s1m2) = i_avl_som cascade_receiver_pool(i_s1m2) = i_oli_mic + nue_decomp_cascade(i_s1m2) = nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m2) = 0.5_r8 i_s2s1 = 7 @@ -538,6 +547,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = 0.0_r8 cascade_donor_pool(i_s2s1) = i_chem_som cascade_receiver_pool(i_s2s1) = i_avl_som + nue_decomp_cascade(i_s2s1) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = 1.0_r8 i_s3s1 = 8 @@ -545,6 +555,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 0.0_r8 cascade_donor_pool(i_s3s1) = i_phys_som cascade_receiver_pool(i_s3s1) = i_avl_som + nue_decomp_cascade(i_s3s1) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 i_m1s1 = 9 @@ -552,6 +563,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = 0.0_r8 cascade_donor_pool(i_m1s1) = i_cop_mic cascade_receiver_pool(i_m1s1) = i_avl_som + nue_decomp_cascade(i_m1s1) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = 0.5_r8 * (1.0_r8 - fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp)) i_m1s2 = 10 @@ -559,6 +571,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = 0.0_r8 cascade_donor_pool(i_m1s2) = i_cop_mic cascade_receiver_pool(i_m1s2) = i_chem_som + nue_decomp_cascade(i_m1s2) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = 0.5_r8 * (1.0_r8 - fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp)) i_m1s3 = 11 @@ -566,6 +579,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = 0.0_r8 cascade_donor_pool(i_m1s3) = i_cop_mic cascade_receiver_pool(i_m1s3) = i_phys_som + nue_decomp_cascade(i_m1s3) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp) i_m2s1 = 12 @@ -573,6 +587,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = 0.0_r8 cascade_donor_pool(i_m2s1) = i_oli_mic cascade_receiver_pool(i_m2s1) = i_avl_som + nue_decomp_cascade(i_m2s1) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = 0.5_r8 * (1.0_r8 - fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) i_m2s2 = 13 @@ -580,6 +595,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = 0.0_r8 cascade_donor_pool(i_m2s2) = i_oli_mic cascade_receiver_pool(i_m2s2) = i_chem_som + nue_decomp_cascade(i_m2s2) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = 0.5_r8 * (1.0_r8 - fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) i_m2s3 = 14 @@ -587,6 +603,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = 0.0_r8 cascade_donor_pool(i_m2s3) = i_oli_mic cascade_receiver_pool(i_m2s3) = i_phys_som + nue_decomp_cascade(i_m2s3) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp) if (.not. use_fates) then @@ -595,6 +612,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 cascade_donor_pool(i_cwdl2) = i_cwd cascade_receiver_pool(i_cwdl2) = i_str_lit + nue_decomp_cascade(i_cwdl2) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = 1.0_r8 end if @@ -684,6 +702,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia + cn_col => cnveg_carbonflux_inst%cn_col , & ! Output: [real(r8) (:,:) ] C:N ratio decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate for decomposition (1./sec) spinup_factor => decomp_cascade_con%spinup_factor & ! Input: [real(r8) (:) ] factor for AD spinup associated with each pool ) @@ -900,7 +919,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do - ! TODO Move to the params files + ! TODO Move to the params files after + ! ... reading TODOs in subr. readParams (above) fmet_p1 = 0.85_r8 fmet_p2 = 0.85_r8 fmet_p3 = 0.013_r8 @@ -909,9 +929,9 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & fchem_r_p2 = -3.0_r8 fchem_k_p1 = 0.3_r8 fchem_k_p2 = -3.0_r8 - tauMod_factor = 0.01_r8 ! was tauMod_denom = 100 - tauMod_min = 0.8_r8 - tauMod_max = 1.2_r8 + tau_mod_factor = 0.01_r8 ! was tau_mod_denom = 100 + tau_mod_min = 0.8_r8 + tau_mod_max = 1.2_r8 tau_r_p1 = 5.2e-4_r8 tau_r_p2 = 0.3_r8 ! or 0.4? tau_k_p1 = 2.4e-4_r8 @@ -921,6 +941,9 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & densdep = 1.0_r8 desorpQ10 = 1.0_r8 t_soi_ref = 25.0_r8 ! deg C + cn_mod_num = 1.0_r8 ! TODO slevis: I don't see values in the testbed + cn_r = 1.0_r8 ! ... or in the testbed's params file + cn_k = 1.0_r8 ! ... for these three ! calculate rates for all litter and som pools ! TODO Ok that I reversed order of do-loops? @@ -928,9 +951,6 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & c = filter_soilc(fc) ! Time-dependent params from Wieder et al. 2015 & testbed code - ! TODO STILL MISSING N-related stuff: - ! - DIN... in the testbed - ! - Need hooks to no3, nh4 terms. The nh4 fluxes are "nmin". ! Set limits on Lignin:N to keep fmet > 0.2 ! Necessary for litter quality in boreal forests with high cwd flux @@ -938,15 +958,23 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! replace pool_to_litter terms with ann or other long term mean ! in CNVegCarbonFluxType. fmet = fmet_p1 * (fmet_p2 - fmet_p3 * min(fmet_p4, ligninNratioAvg(c))) - tauMod = min(tauMod_max, max(tauMod_min, & - sqrt(tauMod_factor * annsum_npp_col(c)))) + tau_mod = min(tau_mod_max, max(tau_mod_min, & + sqrt(tau_mod_factor * & + annsum_npp_col(c)))) ! tau_m1 is tauR and tau_m2 is tauK in Wieder et al. 2015 ! tau ends up in units of per hour but is expected ! in units of per second, so convert here; alternatively ! place the conversion once in w_d_o_scalars - tau_m1 = tau_r_p1 * exp(tau_r_p2 * fmet) * tauMod * secsphr - tau_m2 = tau_k_p1 * exp(tau_k_p2 * fmet) * tauMod * secsphr + tau_m1 = tau_r_p1 * exp(tau_r_p2 * fmet) * tau_mod * secsphr + tau_m2 = tau_k_p1 * exp(tau_k_p2 * fmet) * tau_mod * secsphr + + ! These two get used in SoilBiogeochemPotentialMod.F90 + ! cn(c,i_cop_mic), cn(c,i_oli_mic) are CN_r, CN_k in the testbed code + ! cn_r, cn_k are CNr, CNk in the testbed code + ! https://github.com/wwieder/biogeochem_testbed_1.1/blob/Testbed_CN/SOURCE_CODE/mimics_cycle_CN.f90#L1613 + cn_col(c,i_cop_mic) = cn_r * sqrt(cn_mod_num / fmet) + cn_col(c,i_oli_mic) = cn_k * sqrt(cn_mod_num / fmet) ! Used in the update of certain pathfrac terms that vary with time ! in the next loop diff --git a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 index 43b817c65b..cfcb752d1f 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 @@ -125,6 +125,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, net_nmin => soilbiogeochem_nitrogenflux_inst%net_nmin_col , & ! Output: [real(r8) (:) ] net rate of N mineralization (gN/m2/s) w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Input: [real(r8) (:,:) ] fraction by which decomposition is limited by moisture availability + c_overflow_vr => soilbiogeochem_carbonflux_inst%c_overflow_vr , & ! Input: [real(r8) (:,:,:) ] vertically-resolved C rejected by microbes that cannot process it (gC/m3/s) decomp_cascade_hr_vr => soilbiogeochem_carbonflux_inst%decomp_cascade_hr_vr_col , & ! Output: [real(r8) (:,:,:) ] vertically-resolved het. resp. from decomposing C pools (gC/m3/s) decomp_cascade_ctransfer_vr => soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_vr_col , & ! Output: [real(r8) (:,:,:) ] vertically-resolved het. resp. from decomposing C pools (gC/m3/s) phr_vr => soilbiogeochem_carbonflux_inst%phr_vr_col , & ! Input: [real(r8) (:,:) ] potential HR (gC/m3/s) @@ -182,7 +183,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, sminn_to_denit_decomp_cascade_vr(c,j,k) = -params_inst%dnp * pmnf_decomp_cascade(c,j,k) end if end if - decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) + decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) + c_overflow_vr(c,j,k) decomp_cascade_ctransfer_vr(c,j,k) = (1._r8 - rf_decomp_cascade(c,j,k)) * p_decomp_cpool_loss(c,j,k) if (decomp_npools_vr(c,j,cascade_donor_pool(k)) > 0._r8 .and. cascade_receiver_pool(k) /= i_atm) then decomp_cascade_ntransfer_vr(c,j,k) = p_decomp_cpool_loss(c,j,k) / cn_decomp_pools(c,j,cascade_donor_pool(k)) @@ -212,7 +213,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, do fc = 1,num_soilc c = filter_soilc(fc) ! - decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) + decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) + c_overflow_vr(c,j,k) ! decomp_cascade_ctransfer_vr(c,j,k) = (1._r8 - rf_decomp_cascade(c,j,k)) * p_decomp_cpool_loss(c,j,k) ! diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index 4119a5ed22..32b48bab47 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -10,6 +10,7 @@ module SoilBiogeochemPotentialMod use shr_kind_mod , only : r8 => shr_kind_r8 use decompMod , only : bounds_type use clm_varpar , only : nlevdecomp, ndecomp_cascade_transitions, ndecomp_pools + use clm_varpar , only : i_cop_mic, i_oli_mic use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con use SoilBiogeochemStateType , only : soilbiogeochem_state_type use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type @@ -110,6 +111,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & initial_cn_ratio => decomp_cascade_con%initial_cn_ratio , & ! Input: [real(r8) (:) ] c:n ratio for initialization of pools rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) + nue_decomp_cascade => soilbiogeochem_state_inst%nue_decomp_cascade_col , & ! Input: [real(r8) (:) ] N use efficiency for a given transition (TODO) pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) decomp_npools_vr => soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) N pools @@ -119,7 +121,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & potential_immob_vr => soilbiogeochem_nitrogenflux_inst%potential_immob_vr_col , & ! Output: [real(r8) (:,:) ] gross_nmin_vr => soilbiogeochem_nitrogenflux_inst%gross_nmin_vr_col , & ! Output: [real(r8) (:,:) ] - decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) + cn_col => cnveg_carbonflux_inst%cn_col , & ! Input: [real(r8) (:,:) ] cn ratio + decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Input: [real(r8) (:,:,:) ] decomposition rate coefficient (1./sec) phr_vr => soilbiogeochem_carbonflux_inst%phr_vr_col & ! Output: [real(r8) (:,:) ] potential HR (gC/m3/s) ) @@ -198,7 +201,6 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! donor) and p_decomp_npool_gain (receiver) p_decomp_cpool_gain(c,j,k) = p_decomp_cpool_loss(c,j,k) * & (1.0_r8 - rf_decomp_cascade(c,j,k)) - ! TODO slevis: nue = 0.85 for anything going into microbial biomass; else 1 p_decomp_npool_gain(c,j,k) = p_decomp_npool_loss(c,j,k) * & nue_decomp_cascade(k) p_decomp_npool_to_din(c,j,k) = p_decomp_npool_loss(c,j,k) - & @@ -240,13 +242,11 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & do k = 1, ndecomp_cascade_transitions if (cascade_receiver_pool(k) == i_cop_mic .or. cascade_receiver_pool(k) == i_oli_mic) then - ! TODO slevis: CNmic is a function of a CN parameterization, modified by fMET - ! https://github.com/wwieder/biogeochem_testbed_1.1/blob/Testbed_CN/SOURCE_CODE/mimics_cycle_CN.f90#L1613 ! if p_decomp_cn_diff < 0 N mineralization ! > 0 immobilization p_decomp_cn_diff_ratio = & (p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) - & - CNmic(...)) / CNmic(...) + cn_col(c,cascade_receiver_pool(k))) / cn_col(c,cascade_receiver_pool(k)) ! Actual amount of N that's mineralized or that would need to be immobilized ! negative=mineralization: add to the DIN pool ! positive=immobilizaiton: compete for N with plants to see how much we get diff --git a/src/soilbiogeochem/SoilBiogeochemStateType.F90 b/src/soilbiogeochem/SoilBiogeochemStateType.F90 index 118c42d3a9..65efa3128c 100644 --- a/src/soilbiogeochem/SoilBiogeochemStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemStateType.F90 @@ -34,6 +34,7 @@ module SoilBiogeochemStateType real(r8) , pointer :: fpi_col (:) ! (no units) fraction of potential immobilization real(r8), pointer :: fpg_col (:) ! (no units) fraction of potential gpp real(r8) , pointer :: rf_decomp_cascade_col (:,:,:) ! (frac) respired fraction in decomposition step + real(r8) , pointer :: nue_decomp_cascade_col (:) ! (TODO) N use efficiency for a given transition real(r8) , pointer :: pathfrac_decomp_cascade_col (:,:,:) ! (frac) what fraction of C leaving a given pool passes through a given transition real(r8) , pointer :: nfixation_prof_col (:,:) ! (1/m) profile for N fixation additions real(r8) , pointer :: ndep_prof_col (:,:) ! (1/m) profile for N fixation additions @@ -104,6 +105,8 @@ subroutine InitAllocate(this, bounds) allocate(this%rf_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)); this%rf_decomp_cascade_col(:,:,:) = nan + allocate(this%nue_decomp_cascade_col(1:ndecomp_cascade_transitions)); + this%nue_decomp_cascade_col(:) = nan allocate(this%pathfrac_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)); this%pathfrac_decomp_cascade_col(:,:,:) = nan From 3cf47eb6182c01610a709c2021e34d4bc08e874d Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 5 Aug 2021 18:09:03 -0600 Subject: [PATCH 27/69] Adding use_mimics_decomp where needed in the fortran We plan to replace use_mimics_decomp and use_century_decomp with one namelist variable by which we specify the decomp method, but I'm treating that as a refactor not handled in this PR. I haven't, yet, added use_mimics_decomp to files in /bld. --- src/biogeochem/CNDriverMod.F90 | 7 +++++-- src/biogeochem/CNVegCarbonFluxType.F90 | 2 +- src/biogeochem/CNVegCarbonStateType.F90 | 2 -- src/biogeochem/CNVegNitrogenStateType.F90 | 8 ++------ src/biogeochem/EDBGCDynMod.F90 | 6 +++++- src/main/clm_initializeMod.F90 | 2 +- src/main/clm_instMod.F90 | 8 ++++++-- src/main/clm_varctl.F90 | 1 + src/main/controlMod.F90 | 4 +++- src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 | 2 -- src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 | 6 ++++-- src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 | 3 ++- 12 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index 1373ef696a..c20dd2ca81 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -11,7 +11,7 @@ module CNDriverMod use decompMod , only : bounds_type use perf_mod , only : t_startf, t_stopf use clm_varctl , only : use_century_decomp, use_nitrif_denitrif, use_nguardrail - use clm_varctl , only : use_crop + use clm_varctl , only : use_mimics_decomp, use_crop use CNSharedParamsMod , only : use_fun use CNVegStateType , only : cnveg_state_type use CNVegCarbonStateType , only : cnveg_carbonstate_type @@ -314,7 +314,10 @@ subroutine CNDriverNoLeaching(bounds, if (use_century_decomp) then call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) - else + else if (use_mimics_decomp) then + call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & + soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, soilbiogeochem_carbonflux_inst) + else ! deprecated call decomp_rate_constants_cn(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) end if diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index 895a245ccb..31ca1decd8 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -4006,7 +4006,7 @@ subroutine Summary_carbonflux(this, & ! !USES: use clm_time_manager , only: get_step_size_real use clm_varcon , only: secspday - use clm_varctl , only: nfix_timeconst, carbon_resp_opt + use clm_varctl , only: nfix_timeconst, carbon_resp_opt, use_mimics_decomp use subgridAveMod , only: p2c, c2g use SoilBiogeochemDecompCascadeConType , only: decomp_cascade_con use CNSharedParamsMod , only: use_fun, CNParamsShareInst diff --git a/src/biogeochem/CNVegCarbonStateType.F90 b/src/biogeochem/CNVegCarbonStateType.F90 index 28cf07869b..b4e69cc089 100644 --- a/src/biogeochem/CNVegCarbonStateType.F90 +++ b/src/biogeochem/CNVegCarbonStateType.F90 @@ -1077,8 +1077,6 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, integer :: idata logical :: exit_spinup = .false. logical :: enter_spinup = .false. - ! flags for comparing the model and restart decomposition cascades - integer :: decomp_cascade_state, restart_file_decomp_cascade_state ! spinup state as read from restart file, for determining whether to enter or exit spinup mode. integer :: restart_file_spinup_state integer :: total_num_reseed_patch ! Total number of patches to reseed across all processors diff --git a/src/biogeochem/CNVegNitrogenStateType.F90 b/src/biogeochem/CNVegNitrogenStateType.F90 index 10a191ded9..1a74c6c7f1 100644 --- a/src/biogeochem/CNVegNitrogenStateType.F90 +++ b/src/biogeochem/CNVegNitrogenStateType.F90 @@ -4,17 +4,13 @@ module CNVegNitrogenStateType use shr_kind_mod , only : r8 => shr_kind_r8 use shr_infnan_mod , only : isnan => shr_infnan_isnan, nan => shr_infnan_nan, assignment(=) - use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, nlevcan - use clm_varpar , only : nlevdecomp_full, nlevdecomp - use clm_varcon , only : spval, ispval, dzsoi_decomp, zisoi + use clm_varcon , only : spval use landunit_varcon , only : istcrop, istsoil - use clm_varctl , only : use_nitrif_denitrif, use_vertsoilc, use_century_decomp - use clm_varctl , only : iulog, override_bgc_restart_mismatch_dump + use clm_varctl , only : iulog use clm_varctl , only : use_crop use CNSharedParamsMod , only : use_fun use decompMod , only : bounds_type use pftconMod , only : npcropmin, noveg, pftcon - use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con use abortutils , only : endrun use spmdMod , only : masterproc use LandunitType , only : lun diff --git a/src/biogeochem/EDBGCDynMod.F90 b/src/biogeochem/EDBGCDynMod.F90 index e4150e7789..06cd1e8974 100644 --- a/src/biogeochem/EDBGCDynMod.F90 +++ b/src/biogeochem/EDBGCDynMod.F90 @@ -11,6 +11,7 @@ module EDBGCDynMod use shr_log_mod , only : errMsg => shr_log_errMsg use abortutils , only : endrun use clm_varctl , only : use_century_decomp, use_nitrif_denitrif + use clm_varctl , only : use_mimics_decomp use CNVegCarbonStateType , only : cnveg_carbonstate_type use CNVegCarbonFluxType , only : cnveg_carbonflux_type use SoilBiogeochemStateType , only : soilbiogeochem_state_type @@ -181,7 +182,10 @@ subroutine EDBGCDyn(bounds, & if (use_century_decomp) then call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) - else + else if (use_mimics_decomp) then + call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & + soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, soilbiogeochem_carbonflux_inst) + else ! deprecated call decomp_rate_constants_cn(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) end if diff --git a/src/main/clm_initializeMod.F90 b/src/main/clm_initializeMod.F90 index 17b52bb49e..8fc4fce5be 100644 --- a/src/main/clm_initializeMod.F90 +++ b/src/main/clm_initializeMod.F90 @@ -116,7 +116,7 @@ subroutine initialize2(ni,nj) use clm_varpar , only : nlevsno use clm_varctl , only : fsurdat use clm_varctl , only : finidat, finidat_interp_source, finidat_interp_dest, fsurdat - use clm_varctl , only : use_century_decomp, use_cn, use_fates + use clm_varctl , only : use_cn, use_fates use clm_varctl , only : use_crop, ndep_from_cpl, fates_spitfire_mode use clm_varorb , only : eccen, mvelpp, lambm0, obliqr use landunit_varcon , only : landunit_varcon_init, max_lunit diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90 index 440d45c76c..e8786cef53 100644 --- a/src/main/clm_instMod.F90 +++ b/src/main/clm_instMod.F90 @@ -10,6 +10,7 @@ module clm_instMod use clm_varpar , only : ndecomp_pools, nlevdecomp_full use clm_varctl , only : use_cn, use_c13, use_c14, use_lch4, use_cndv, use_fates use clm_varctl , only : use_century_decomp, use_crop, snow_cover_fraction_method, paramfile + use clm_varctl , only : use_mimics_decomp use clm_varcon , only : bdsno, c13ratio, c14ratio use landunit_varcon , only : istice, istsoil use perf_mod , only : t_startf, t_stopf @@ -379,11 +380,14 @@ subroutine clm_instInit(bounds) ! Note that init_decompcascade_bgc and init_decompcascade_cn need ! soilbiogeochem_state_inst to be initialized - call init_decomp_cascade_constants( use_century_decomp ) + call init_decomp_cascade_constants( use_century_decomp, use_mimics_decomp ) if (use_century_decomp) then call init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, & soilstate_inst ) - else + else if (use_mimics_decomp) then + call init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, & + soilstate_inst) + else ! deprecated call init_decompcascade_cn(bounds, soilbiogeochem_state_inst) end if diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index 796fa086fa..02640a0949 100644 --- a/src/main/clm_varctl.F90 +++ b/src/main/clm_varctl.F90 @@ -376,6 +376,7 @@ module clm_varctl logical, public :: use_extralakelayers = .false. logical, public :: use_vichydro = .false. logical, public :: use_century_decomp = .false. + logical, public :: use_mimics_decomp = .false. logical, public :: use_cn = .false. logical, public :: use_cndv = .false. logical, public :: use_grainproduct = .false. diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index e91f853e32..7b2a71a40d 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -274,7 +274,7 @@ subroutine control_init(dtime) use_lch4, use_nitrif_denitrif, use_vertsoilc, use_extralakelayers, & use_vichydro, use_century_decomp, use_cn, use_cndv, use_crop, use_fertilizer, use_ozone, & use_grainproduct, use_snicar_frc, use_vancouver, use_mexicocity, use_noio, & - use_nguardrail + use_nguardrail, use_mimics_decomp ! ---------------------------------------------------------------------- @@ -621,6 +621,7 @@ subroutine control_spmd() call mpi_bcast (use_extralakelayers, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_vichydro, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_century_decomp, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_mimics_decomp, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_cn, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_cndv, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_nguardrail, 1, MPI_LOGICAL, 0, mpicom, ier) @@ -865,6 +866,7 @@ subroutine control_print () write(iulog,*) ' use_extralakelayers = ', use_extralakelayers write(iulog,*) ' use_vichydro = ', use_vichydro write(iulog,*) ' use_century_decomp = ', use_century_decomp + write(iulog,*) ' use_mimics_decomp = ', use_mimics_decomp write(iulog,*) ' use_cn = ', use_cn write(iulog,*) ' use_cndv = ', use_cndv write(iulog,*) ' use_crop = ', use_crop diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 index d7ab333ed9..dcf36fb537 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 @@ -510,8 +510,6 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, totvegc_col, c12_so integer :: idata logical :: exit_spinup = .false. logical :: enter_spinup = .false. - ! flags for comparing the model and restart decomposition cascades - integer :: decomp_cascade_state, restart_file_decomp_cascade_state !------------------------------------------------------------------------ if (carbon_type == 'c12') then diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 index cb6be6f4ed..0ca6203022 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 @@ -47,17 +47,19 @@ module SoilBiogeochemDecompCascadeConType contains !------------------------------------------------------------------------ - subroutine init_decomp_cascade_constants( use_century_decomp ) + subroutine init_decomp_cascade_constants( use_century_decomp, & + use_mimics_decomp ) ! ! !DESCRIPTION: ! Initialize decomposition cascade state !------------------------------------------------------------------------ ! !ARGUMENTS: logical, intent(IN) :: use_century_decomp + logical, intent(in) :: use_mimics_decomp ! !LOGAL VARIABLES: integer :: ibeg ! Beginning index for allocated arrays - if ( use_century_decomp ) then + if ( use_century_decomp .or. use_mimics_decomp ) then ibeg = 1 else ibeg = i_atm diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 index 93216db170..23781a8782 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 @@ -12,6 +12,7 @@ module SoilBiogeochemNitrogenStateType use clm_varpar , only : nlevdecomp_full, nlevdecomp, nlevsoi use clm_varcon , only : spval, dzsoi_decomp, zisoi use clm_varctl , only : use_nitrif_denitrif, use_vertsoilc, use_century_decomp + use clm_varctl , only : use_mimics_decomp use clm_varctl , only : iulog, override_bgc_restart_mismatch_dump, spinup_state use landunit_varcon , only : istcrop, istsoil use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con @@ -532,7 +533,7 @@ subroutine Restart ( this, bounds, ncid, flag, totvegc_col ) ! matches what the restart file was generated with. ! add info about the SOM decomposition cascade - if (use_century_decomp) then + if (use_century_decomp .or. use_mimics_decomp) then decomp_cascade_state = 1 else decomp_cascade_state = 0 From 043d8bce553976a9c1123cdb09e204c3ee698a8a Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 6 Aug 2021 18:21:56 -0600 Subject: [PATCH 28/69] Corrections and minor cleanup --- src/biogeochem/CNDriverMod.F90 | 6 ++++++ src/biogeochem/CNVegCarbonFluxType.F90 | 11 ++++++++--- src/main/clm_varpar.F90 | 5 ++++- src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 | 2 -- src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 | 12 ++++++------ 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index c20dd2ca81..dc56c360bc 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -1043,6 +1043,8 @@ subroutine CNDriverSummarizeFluxes(bounds, & soilbiogeochem_lithr_col=soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & soilbiogeochem_decomp_cascade_ctransfer_col=& soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & + soilbiogeochem_cwdc_col=soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & + soilbiogeochem_cwdn_col=soilbiogeochem_nitrogenstate_inst%cwdn_col(begc:endc), & product_closs_grc=c_products_inst%product_loss_grc(begg:endg)) if ( use_c13 ) then @@ -1053,6 +1055,8 @@ subroutine CNDriverSummarizeFluxes(bounds, & soilbiogeochem_lithr_col=c13_soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & soilbiogeochem_decomp_cascade_ctransfer_col=& c13_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & + soilbiogeochem_cwdc_col=c13_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & + soilbiogeochem_cwdn_col=soilbiogeochem_nitrogenstate_inst%cwdn_col(begc:endc), & product_closs_grc=c13_products_inst%product_loss_grc(begg:endg)) end if @@ -1064,6 +1068,8 @@ subroutine CNDriverSummarizeFluxes(bounds, & soilbiogeochem_lithr_col=c14_soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & soilbiogeochem_decomp_cascade_ctransfer_col=& c14_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & + soilbiogeochem_cwdc_col=c14_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & + soilbiogeochem_cwdn_col=soilbiogeochem_nitrogenstate_inst%cwdn_col(begc:endc), & product_closs_grc=c14_products_inst%product_loss_grc(begg:endg)) end if diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index 31ca1decd8..445665b7c2 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -3998,6 +3998,7 @@ subroutine Summary_carbonflux(this, & bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, isotope, & soilbiogeochem_hr_col, soilbiogeochem_cwdhr_col, soilbiogeochem_lithr_col, & soilbiogeochem_decomp_cascade_ctransfer_col, & + soilbiogeochem_cwdc_col, soilbiogeochem_cwdn_col, & product_closs_grc) ! ! !DESCRIPTION: @@ -4023,6 +4024,8 @@ subroutine Summary_carbonflux(this, & real(r8) , intent(in) :: soilbiogeochem_cwdhr_col(bounds%begc:) real(r8) , intent(in) :: soilbiogeochem_lithr_col(bounds%begc:) real(r8) , intent(in) :: soilbiogeochem_decomp_cascade_ctransfer_col(bounds%begc:,1:) + real(r8) , intent(in) :: soilbiogeochem_cwdc_col(bounds%begc:) + real(r8) , intent(in) :: soilbiogeochem_cwdn_col(bounds%begc:) real(r8) , intent(in) :: product_closs_grc(bounds%begg:) ! ! !LOCAL VARIABLES: @@ -4035,6 +4038,8 @@ subroutine Summary_carbonflux(this, & real(r8) :: ligninNratio_froot_patch(bounds%begp:bounds%endp) ! lignin to N ratio of fine roots, patch level real(r8) :: ligninNratio_leaf_col(bounds%begc:bounds%endc) ! lignin to N ratio of leaves, column level real(r8) :: ligninNratio_froot_col(bounds%begc:bounds%endc) ! lignin to N ratio of fine roots, column level + real(r8) :: leafc_to_litter_col(bounds%begc:bounds%endc) ! leaf C to litter C, column level + real(r8) :: frootc_to_litter_col(bounds%begc:bounds%endc) ! fine root C to litter C, column level real(r8) :: nep_grc(bounds%begg:bounds%endg) ! nep_col averaged to gridcell real(r8) :: fire_closs_grc(bounds%begg:bounds%endg) ! fire_closs_col averaged to gridcell real(r8) :: hrv_xsmrpool_to_atm_grc(bounds%begg:bounds%endg) ! hrv_xsmrpool_to_atm_col averaged to gridcell (gC/m2/s) @@ -4481,14 +4486,14 @@ subroutine Summary_carbonflux(this, & c = filter_soilc(fc) ! TODO Use cwd_flig in *CascadeBGC the same way for consistency? ligninNratio_cwd = CNParamsShareInst%cwd_flig * & - (this%cwdc_col(c) / this%cwdn_col(c)) * & - this%decomp_cascade_ctransfer_col(c,i_cwdl2) + (soilbiogeochem_cwdc_col(c) / soilbiogeochem_cwdn_col(c)) * & + soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2) this%ligninNratioAvg_col(c) = & (ligninNratio_leaf_col(c) + ligninNratio_froot_col(c) + & ligninNratio_cwd) / & max(1.0e-3_r8, leafc_to_litter_col(c) + & frootc_to_litter_col(c) + & - this%decomp_cascade_ctransfer_col(c,i_cwdl2)) + soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2)) end do end if diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index 78e394bf88..d698df3a07 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -242,9 +242,12 @@ subroutine clm_varpar_init(actual_maxsoil_patches, actual_numcft) ! in InitAllocate (in SoilBiogeochemStateType) which is called earlier than ! init_decompcascade_bgc where they might have otherwise been derived on the ! fly. For reference, if they were determined in init_decompcascade_bgc: + ! ndecomp_pools would get the value of i_pas_som or i_cwd and + ! ndecomp_cascade_transitions would get the value of i_s3s1 or i_cwdl3 + ! If they were determined in init_decompcascade_mimics: ! ndecomp_pools would get the value of i_oli_mic or i_cwd and ! ndecomp_cascade_transitions would get the value of i_m2s3 or i_cwdl2 - ! depending on how use_fates is set. + ! (...always depending on how use_fates is set) if ( use_fates ) then if (use_century_decomp) then ndecomp_pools = 6 diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 41c3825b57..5adcaee227 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -372,7 +372,6 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do end do - ! TODO slevis: Add c_overflow_vr to the heterotrophic resp flux if (use_mimics) then do j = 1, nlevdecomp do fc=1,num_soilc @@ -404,7 +403,6 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do else ! not use_mimics c_overflow_vr(:,:,:) = 0.0_r8 - c_overflow_vr(:,:,:) = 0.0_r8 end if if ( local_use_fun ) then diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index 32b48bab47..7b98b4658f 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -199,12 +199,12 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! Track N lost to DIN from messy eating, ie the ! diff between p_decomp_npool_loss (pertains to ! donor) and p_decomp_npool_gain (receiver) - p_decomp_cpool_gain(c,j,k) = p_decomp_cpool_loss(c,j,k) * & - (1.0_r8 - rf_decomp_cascade(c,j,k)) - p_decomp_npool_gain(c,j,k) = p_decomp_npool_loss(c,j,k) * & - nue_decomp_cascade(k) - p_decomp_npool_to_din(c,j,k) = p_decomp_npool_loss(c,j,k) - & - p_decomp_npool_gain(c,j,k) + p_decomp_cpool_gain(c,j,k) = & + p_decomp_cpool_loss(c,j,k) * (1.0_r8 - rf_decomp_cascade(c,j,k)) + p_decomp_npool_gain(c,j,k) = & + p_decomp_npool_loss(c,j,k) * nue_decomp_cascade(k) + p_decomp_npool_to_din(c,j,k) = & + p_decomp_npool_loss(c,j,k) - p_decomp_npool_gain(c,j,k) end if end if end if From ed35311d2ef8e11ccf8361db444647fddf58fbb3 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 9 Aug 2021 15:54:54 -0600 Subject: [PATCH 29/69] Code corrections from attempting to build (part 1) Probably many more to go. --- src/biogeochem/CNDriverMod.F90 | 5 +- src/biogeochem/CNVegCarbonFluxType.F90 | 2 +- .../SoilBiogeochemCompetitionMod.F90 | 15 +++-- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 30 +++++----- .../SoilBiogeochemPotentialMod.F90 | 56 +++++++++++-------- .../SoilBiogeochemStateType.F90 | 5 +- 6 files changed, 67 insertions(+), 46 deletions(-) diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index dc56c360bc..81485a75f4 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -200,6 +200,7 @@ subroutine CNDriverNoLeaching(bounds, real(r8):: cn_decomp_pools(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) real(r8):: p_decomp_cpool_loss(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential C loss from one pool to another real(r8):: pmnf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential mineral N flux, from one pool to another + real(r8):: p_decomp_cn_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! C:N ratio of the flux gained by the receiver pool real(r8):: arepr(bounds%begp:bounds%endp) ! reproduction allocation coefficient (only used for use_crop) real(r8):: aroot(bounds%begp:bounds%endp) ! root allocation coefficient (only used for use_crop) integer :: begp,endp @@ -328,6 +329,7 @@ subroutine CNDriverNoLeaching(bounds, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & + p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) ! calculate vertical profiles for distributing soil and litter C and N (previously subroutine decomp_vertprofiles called from CNDecompAlloc) @@ -401,7 +403,8 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('soilbiogeochemcompetition') - call SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, pmnf_decomp_cascade, waterstatebulk_inst, & + call SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, & + p_decomp_cn_gain, pmnf_decomp_cascade, waterstatebulk_inst, & waterfluxbulk_inst,temperature_inst,soilstate_inst,cnveg_state_inst, & cnveg_carbonstate_inst ,& cnveg_carbonflux_inst,cnveg_nitrogenstate_inst,cnveg_nitrogenflux_inst, & diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index 445665b7c2..6adf004c7f 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -334,7 +334,7 @@ module CNVegCarbonFluxType real(r8), pointer :: nbp_grc (:) ! (gC/m2/s) net biome production, includes fire, landuse, harvest and hrv_xsmrpool flux, positive for sink (same as net carbon exchange between land and atmosphere) real(r8), pointer :: nee_grc (:) ! (gC/m2/s) net ecosystem exchange of carbon, includes fire and hrv_xsmrpool, excludes landuse and harvest flux, positive for source - ! Lignin to N ratio + ! Plant C to N ratios real(r8), pointer :: ligninNratioAvg_col(:) ! Average of leaf, fine root, and CWD lignin to N ratio ! Dynamic landcover fluxnes diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 5adcaee227..da11047618 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -166,7 +166,7 @@ end subroutine SoilBiogeochemCompetitionInit !----------------------------------------------------------------------- subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, & - pmnf_decomp_cascade, waterstatebulk_inst, & + p_decomp_cn_gain, pmnf_decomp_cascade, waterstatebulk_inst, & waterfluxbulk_inst, temperature_inst,soilstate_inst, & cnveg_state_inst,cnveg_carbonstate_inst, & cnveg_carbonflux_inst,cnveg_nitrogenstate_inst,cnveg_nitrogenflux_inst, & @@ -176,6 +176,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! ! !USES: use clm_varctl , only: cnallocate_carbon_only, iulog + use clm_varctl , only: use_mimics_decomp use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions use clm_varpar , only: i_cop_mic, i_oli_mic use clm_varcon , only: nitrif_n2o_loss_frac @@ -183,6 +184,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, use CNFUNMod , only: CNFUN use subgridAveMod , only: p2c use perf_mod , only : t_startf, t_stopf + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -191,6 +193,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches real(r8) , intent(in) :: pmnf_decomp_cascade(bounds%begc:,1:,1:) ! potential mineral N flux from one pool to another (gN/m3/s) + real(r8) , intent(in) :: p_decomp_cn_gain(bounds%begc:,1:,1:) ! C:N ratio of the flux gained by the receiver pool type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst type(waterfluxbulk_type) , intent(in) :: waterfluxbulk_inst type(temperature_type) , intent(in) :: temperature_inst @@ -208,7 +211,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! ! ! !LOCAL VARIABLES: - integer :: c,p,l,pi,j ! indices + integer :: c,p,l,pi,j,k ! indices integer :: fc ! filter column index logical :: local_use_fun ! local version of use_fun real(r8) :: amnf_immob_vr ! actual mineral N flux from immobilization (gN/m3/s) @@ -372,7 +375,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do end do - if (use_mimics) then + if (use_mimics_decomp) then do j = 1, nlevdecomp do fc=1,num_soilc c = filter_soilc(fc) @@ -390,8 +393,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, sum_ndemand_vr(c,j)) n_deficit_vr = pmnf_decomp_cascade(c,j,k) - & amnf_immob_vr - c_overflow_vr(c,j,k) = n_deficit_vr * & - p_decomp_cn_gain(c,j,k) + c_overflow_vr(c,j,k) = & + n_deficit_vr * p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) else c_overflow_vr(c,j,k) = 0.0_r8 end if @@ -401,7 +404,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do end do end do - else ! not use_mimics + else ! not use_mimics_decomp c_overflow_vr(:,:,:) = 0.0_r8 end if diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index da0cd95fb9..6068967cdc 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -23,7 +23,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type use SoilStateType , only : soilstate_type use TemperatureType , only : temperature_type - use CNveg_CarbonFlux_Type , only : cnveg_carbonflux_type + use CNVegCarbonFluxType , only : cnveg_carbonflux_type use ch4Mod , only : ch4_type use ColumnType , only : col use GridcellType , only : grc @@ -45,8 +45,6 @@ module SoilBiogeochemDecompCascadeMIMICSMod integer, private :: i_chem_som ! index of chemically protected SOM integer, private :: i_avl_som ! index of available (aka active) SOM integer, private :: i_str_lit ! index of structural litter pool - integer, private :: i_cop_mic ! index of copiotrophic microbial pool - integer, private :: i_oli_mic ! index of oligotrophic microbial pool integer, private :: i_l1m1 ! indices of pool transfers needed in whole module integer, private :: i_l1m2 integer, private :: i_l2m1 @@ -249,15 +247,17 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat allocate(fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) allocate(p_scalar(bounds%begc:bounds%endc,1:nlevdecomp)) - params_inst%p_scalar_p1 = 0.8_r8 ! TODO Move to the params files after - params_inst%p_scalar_p2 = -3.0_r8 ! ... reading TODOs in subr. readParams (above) - params_inst%desorp_p1 = 1.5e-5_r8 - params_inst%desorp_p2 = -1.5_r8 - params_inst%fphys_r_p1 = 0.3_r8 - params_inst%fphys_r_p2 = 1.3_r8 - params_inst%fphys_k_p1 = 0.2_r8 - params_inst%fphys_k_p2 = 0.8_r8 - params_inst%nue_into_mic = 0.85_r8 + ! TODO Prefix these parameters w params_inst% to move to params file(s). + ! First read TODOs in subr. readParams above. + p_scalar_p1 = 0.8_r8 + p_scalar_p2 = -3.0_r8 + desorp_p1 = 1.5e-5_r8 + desorp_p2 = -1.5_r8 + fphys_r_p1 = 0.3_r8 + fphys_r_p2 = 1.3_r8 + fphys_k_p1 = 0.2_r8 + fphys_k_p2 = 0.8_r8 + nue_into_mic = 0.85_r8 !------- time-constant coefficients ---------- ! ! set respiration fractions for fluxes between compartments @@ -321,8 +321,8 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat exp(fphys_r_p2 * cellclay(c,j)))) fphys_m2(c,j) = min(1.0_r8, max(0.0_r8, fphys_k_p1 * & exp(fphys_k_p2 * cellclay(c,j)))) - p_scalar(c,j) = 1.0_r8 / (params_inst%p_scalar_p1 * & - exp(params_inst%p_scalar_p2 * & + p_scalar(c,j) = 1.0_r8 / (p_scalar_p1 * & + exp(p_scalar_p2 * & sqrt(cellclay(c,j)))) end do end do @@ -702,7 +702,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia - cn_col => cnveg_carbonflux_inst%cn_col , & ! Output: [real(r8) (:,:) ] C:N ratio + cn_col => soilbiogeochem_state_inst%cn_col , & ! Output: [real(r8) (:,:) ] C:N ratio decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate for decomposition (1./sec) spinup_factor => decomp_cascade_con%spinup_factor & ! Input: [real(r8) (:) ] factor for AD spinup associated with each pool ) diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index 7b98b4658f..ef3864bcaa 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -17,7 +17,7 @@ module SoilBiogeochemPotentialMod use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type use SoilBiogeochemNitrogenFluxType , only : soilbiogeochem_nitrogenflux_type - use clm_varctl , only : use_fates, iulog + use clm_varctl , only : use_mimics_decomp, use_fates, iulog ! implicit none private @@ -71,7 +71,7 @@ end subroutine readParams subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & - cn_decomp_pools, p_decomp_cpool_loss, pmnf_decomp_cascade) + cn_decomp_pools, p_decomp_cpool_loss, p_decomp_cn_gain, pmnf_decomp_cascade) ! ! !USES: use shr_log_mod , only : errMsg => shr_log_errMsg @@ -89,18 +89,28 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & real(r8) , intent(out) :: cn_decomp_pools(bounds%begc:,1:,1:) ! c:n ratios of applicable pools real(r8) , intent(out) :: p_decomp_cpool_loss(bounds%begc:,1:,1:) ! potential C loss from one pool to another real(r8) , intent(out) :: pmnf_decomp_cascade(bounds%begc:,1:,1:) ! potential mineral N flux, from one pool to another + real(r8) , intent(out) :: p_decomp_cn_gain(bounds%begc:,1:,1:) ! C:N ratio of the flux gained by the receiver pool ! ! !LOCAL VARIABLES: integer :: c,j,k,l,m !indices integer :: fc !filter column index integer :: begc,endc !bounds real(r8):: immob(bounds%begc:bounds%endc,1:nlevdecomp) !potential N immobilization + real(r8):: p_decomp_cpool_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential C gain by receiver pool + real(r8):: p_decomp_npool_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential N gain by receiver pool + real(r8):: p_decomp_npool_to_din(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential flux to dissolved inorganic N + real(r8):: p_decomp_cpool_gain_sum(1:ndecomp_pools) ! total potential C gain by receiver pool (only microbial pools) + real(r8):: p_decomp_npool_gain_sum(1:ndecomp_pools) ! total potential N gain by receiver pool (only microbial pools) + real(r8):: decomp_nc_loss_donor ! N:C ratio of donor pool + real(r8):: p_decomp_cn_diff_ratio ! relative change in receiver pool C:N + real(r8):: p_decomp_npool_loss ! potential N flux out of donor pool real(r8):: ratio !temporary variable !----------------------------------------------------------------------- begc = bounds%begc; endc = bounds%endc SHR_ASSERT_ALL_FL((ubound(cn_decomp_pools) == (/endc,nlevdecomp,ndecomp_pools/)) , sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(p_decomp_cn_gain) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(p_decomp_cpool_loss) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(pmnf_decomp_cascade) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) @@ -121,7 +131,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & potential_immob_vr => soilbiogeochem_nitrogenflux_inst%potential_immob_vr_col , & ! Output: [real(r8) (:,:) ] gross_nmin_vr => soilbiogeochem_nitrogenflux_inst%gross_nmin_vr_col , & ! Output: [real(r8) (:,:) ] - cn_col => cnveg_carbonflux_inst%cn_col , & ! Input: [real(r8) (:,:) ] cn ratio + cn_col => soilbiogeochem_state_inst%cn_col , & ! Input: [real(r8) (:,:) ] C:N ratio decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Input: [real(r8) (:,:,:) ] decomposition rate coefficient (1./sec) phr_vr => soilbiogeochem_carbonflux_inst%phr_vr_col & ! Output: [real(r8) (:,:) ] potential HR (gC/m3/s) ) @@ -184,17 +194,17 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & else ! 100% respiration pmnf_decomp_cascade(c,j,k) = - p_decomp_cpool_loss(c,j,k) / cn_decomp_pools(c,j,cascade_donor_pool(k)) endif - else ! CWD -> litter OR use_mimics is true + else ! CWD -> litter OR use_mimics_decomp is true pmnf_decomp_cascade(c,j,k) = 0._r8 - if (use_mimics) then + if (use_mimics_decomp) then ! N:C ratio of donor pools (N:C instead of C:N because ! already checked that we're not dividing by zero) decomp_nc_loss_donor = & decomp_npools_vr(c,j,cascade_donor_pool(k)) / & decomp_cpools_vr(c,j,cascade_donor_pool(k)) ! calculate N fluxes from donor pools - p_decomp_npool_loss(c,j,k) = & + p_decomp_npool_loss = & p_decomp_cpool_loss(c,j,k) * decomp_nc_loss_donor ! Track N lost to DIN from messy eating, ie the ! diff between p_decomp_npool_loss (pertains to @@ -202,9 +212,9 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & p_decomp_cpool_gain(c,j,k) = & p_decomp_cpool_loss(c,j,k) * (1.0_r8 - rf_decomp_cascade(c,j,k)) p_decomp_npool_gain(c,j,k) = & - p_decomp_npool_loss(c,j,k) * nue_decomp_cascade(k) + p_decomp_npool_loss * nue_decomp_cascade(k) p_decomp_npool_to_din(c,j,k) = & - p_decomp_npool_loss(c,j,k) - p_decomp_npool_gain(c,j,k) + p_decomp_npool_loss - p_decomp_npool_gain(c,j,k) end if end if end if @@ -216,31 +226,33 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! Determine immobilization vs. mineralization by comparing the ! cn_gain into microbial biomass compared with the target C:N ! ratio of microbial biomass pools - if (use_mimics) then + if (use_mimics_decomp) then do j = 1,nlevdecomp do fc = 1,num_soilc c = filter_soilc(fc) - ! Sum C and N fluxes from all transitions into m1 and m2 pools + ! Sum C & N fluxes from all transitions into m1 & m2 pools. + ! Had to form a new loop for the summation due to the order + ! necessary, ie do k as the innermost loop. do k = 1, ndecomp_cascade_transitions - if (cascade_receiver_pool(k) == i_cop_mic .or. + if (cascade_receiver_pool(k) == i_cop_mic .or. & cascade_receiver_pool(k) == i_oli_mic) then - p_decomp_cpool_gain_sum(c,j,cascade_receiver_pool(k)) = & - p_decomp_cpool_gain_sum_cop_mic(c,j,cascade_receiver_pool(k)) + & + p_decomp_cpool_gain_sum(cascade_receiver_pool(k)) = & + p_decomp_cpool_gain_sum(cascade_receiver_pool(k)) + & p_decomp_cpool_gain(c,j,k) - p_decomp_npool_gain_sum(c,j,cascade_receiver_pool(k)) = & - p_decomp_npool_gain_sum(c,j,cascade_receiver_pool(k)) + & + p_decomp_npool_gain_sum(cascade_receiver_pool(k)) = & + p_decomp_npool_gain_sum(cascade_receiver_pool(k)) + & p_decomp_npool_gain(c,j,k) - ! Once k-loop completes, the left hand side should - ! contain the correct cn ratio - if (p_decomp_npool_gain_sum(c,j,cascade_receiver_pool(k)) > 0.0_r8) then + ! Once k-loop completes, the left hand side should end up + ! with the correct cn ratio + if (p_decomp_npool_gain_sum(cascade_receiver_pool(k)) > 0.0_r8) then p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) = & - p_decomp_cpool_gain_sum(c,j,cascade_receiver_pool(k)) / & - p_decomp_npool_gain_sum(c,j,cascade_receiver_pool(k)) + p_decomp_cpool_gain_sum(cascade_receiver_pool(k)) / & + p_decomp_npool_gain_sum(cascade_receiver_pool(k)) end if end if end do do k = 1, ndecomp_cascade_transitions - if (cascade_receiver_pool(k) == i_cop_mic .or. + if (cascade_receiver_pool(k) == i_cop_mic .or. & cascade_receiver_pool(k) == i_oli_mic) then ! if p_decomp_cn_diff < 0 N mineralization ! > 0 immobilization @@ -274,7 +286,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & else gross_nmin_vr(c,j) = gross_nmin_vr(c,j) - pmnf_decomp_cascade(c,j,k) end if - if (use_mimics) then + if (use_mimics_decomp) then gross_nmin_vr(c,j) = gross_nmin_vr(c,j) + p_decomp_npool_to_din(c,j,k) end if end do diff --git a/src/soilbiogeochem/SoilBiogeochemStateType.F90 b/src/soilbiogeochem/SoilBiogeochemStateType.F90 index 65efa3128c..776deb9bb1 100644 --- a/src/soilbiogeochem/SoilBiogeochemStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemStateType.F90 @@ -7,7 +7,7 @@ module SoilBiogeochemStateType use abortutils , only : endrun use spmdMod , only : masterproc use clm_varpar , only : nlevsno, nlevgrnd, nlevlak, nlevsoifl, nlevsoi - use clm_varpar , only : ndecomp_cascade_transitions, nlevdecomp, nlevdecomp_full + use clm_varpar , only : ndecomp_pools, ndecomp_cascade_transitions, nlevdecomp, nlevdecomp_full use clm_varcon , only : spval, ispval, c14ratio, grlnd use landunit_varcon, only : istsoil, istcrop use clm_varpar , only : nlevsno, nlevgrnd, nlevlak @@ -34,6 +34,7 @@ module SoilBiogeochemStateType real(r8) , pointer :: fpi_col (:) ! (no units) fraction of potential immobilization real(r8), pointer :: fpg_col (:) ! (no units) fraction of potential gpp real(r8) , pointer :: rf_decomp_cascade_col (:,:,:) ! (frac) respired fraction in decomposition step + real(r8) , pointer :: cn_col (:,:) ! (gC/gN) C:N ratio by pool real(r8) , pointer :: nue_decomp_cascade_col (:) ! (TODO) N use efficiency for a given transition real(r8) , pointer :: pathfrac_decomp_cascade_col (:,:,:) ! (frac) what fraction of C leaving a given pool passes through a given transition real(r8) , pointer :: nfixation_prof_col (:,:) ! (1/m) profile for N fixation additions @@ -105,6 +106,8 @@ subroutine InitAllocate(this, bounds) allocate(this%rf_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)); this%rf_decomp_cascade_col(:,:,:) = nan + allocate(this%cn_col(begc:endc,1:ndecomp_pools)); + this%cn_col(:,:) = nan allocate(this%nue_decomp_cascade_col(1:ndecomp_cascade_transitions)); this%nue_decomp_cascade_col(:) = nan From ebadca9a2f43126e009817ea8d3cbae67f73e876 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 9 Aug 2021 17:03:29 -0600 Subject: [PATCH 30/69] Adding history variables for use with Newton-Krylov decomp_k was already in place (e.g. see master list in documentation) but it was dimensioned wrong, so I corrected it in this commit. --- src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 index 0e4879fb4a..d2028974bc 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 @@ -29,7 +29,7 @@ module SoilBiogeochemCarbonFluxType real(r8), pointer :: decomp_cascade_hr_col (:,:) ! vertically-integrated (diagnostic) het. resp. from decomposing C pools (gC/m2/s) real(r8), pointer :: decomp_cascade_ctransfer_vr_col (:,:,:) ! vertically-resolved C transferred along deomposition cascade (gC/m3/s) real(r8), pointer :: decomp_cascade_ctransfer_col (:,:) ! vertically-integrated (diagnostic) C transferred along decomposition cascade (gC/m2/s) - real(r8), pointer :: decomp_k_col (:,:,:) ! rate constant for decomposition (1./sec) + real(r8), pointer :: decomp_k_col (:,:,:) ! rate coefficient for decomposition (1./sec) real(r8), pointer :: hr_vr_col (:,:) ! (gC/m3/s) total vertically-resolved het. resp. from decomposing C pools real(r8), pointer :: o_scalar_col (:,:) ! fraction by which decomposition is limited by anoxia real(r8), pointer :: w_scalar_col (:,:) ! fraction by which decomposition is limited by moisture availability @@ -121,7 +121,7 @@ subroutine InitAllocate(this, bounds) allocate(this%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions)) this%decomp_cascade_ctransfer_col(:,:)= nan - allocate(this%decomp_k_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)) + allocate(this%decomp_k_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) this%decomp_k_col(:,:,:)= spval allocate(this%decomp_cpools_leached_col(begc:endc,1:ndecomp_pools)) @@ -693,7 +693,6 @@ subroutine SetValues ( this, num_column, filter_column, value_column) this%decomp_cascade_hr_vr_col(i,j,l) = value_column this%decomp_cascade_ctransfer_col(i,l) = value_column this%decomp_cascade_ctransfer_vr_col(i,j,l) = value_column - this%decomp_k_col(i,j,l) = value_column end do end do end do @@ -708,6 +707,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) i = filter_column(fi) this%decomp_cpools_transport_tendency_col(i,j,k) = value_column this%decomp_cpools_sourcesink_col(i,j,k) = value_column + this%decomp_k_col(i,j,k) = value_column end do end do end do From 5236864c3040d6ab97773ae5192d0319fab9e2b2 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 10 Aug 2021 17:04:13 -0600 Subject: [PATCH 31/69] Adding pathfrac_decomp_cascade to ctsm history --- doc/ChangeLog | 77 +++++++++++++++++++ doc/ChangeSum | 1 + .../SoilBiogeochemCarbonFluxType.F90 | 20 +++++ .../SoilBiogeochemDecompCascadeBGCMod.F90 | 63 ++++++++------- .../SoilBiogeochemDecompCascadeCNMod.F90 | 47 +++++------ .../SoilBiogeochemDecompMod.F90 | 1 - .../SoilBiogeochemPotentialMod.F90 | 2 +- .../SoilBiogeochemStateType.F90 | 4 - 8 files changed, 155 insertions(+), 60 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index bc8f75f4b0..fe17e5d69c 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,81 @@ =============================================================== +Tag name: ctsm5.1.dev053 +Originator(s): slevis (Samuel Levis,SLevis Consulting,303-665-1310) +Date: Tue Aug 10 16:22:24 MDT 2021 +One-line Summary: Adding history variables for use with Newton-Krylov + +Purpose and description of changes +---------------------------------- + + Considering @klindsay28's Newton-Krylov spin-up method for BGC and MIMICS. + Newton-Krylov needs decomp_k and pathfrac_decomp_cascade on ctsm history + files. + + decomp_k was already in place. + I have now also added pathfrac_decomp_cascade. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +Issues fixed (include CTSM Issue #): #1455 + +Known bugs found since the previous tag (include issue #): + I did not open an issue for this: decomp_k was dimensioned wrong, and I + corrected it in this PR without affecting answers. In particular I changed the + size of the third dimension from ndecomp_pools to ndecomp_cascade_transitions. + +Notes of particular relevance for users +--------------------------------------- +Substantial timing or memory changes: +[For timing changes, you should at least check the PFS test in the test + +Notes of particular relevance for developers: +--------------------------------------------- +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + This PR adds a variable to ctsm's history files; however, I have not updated + the corresponding master list in the documentation, yet. + +Testing summary: +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- + izumi ------- + + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- +Changes answers relative to baseline: No + + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/CTSM/pull/1457 + +=============================================================== +=============================================================== Tag name: ctsm5.1.dev051 Originator(s): Stefanie Falk, Sunniva Indrehus, Bill Sacks Date: Fri Aug 6 10:30:32 MDT 2021 diff --git a/doc/ChangeSum b/doc/ChangeSum index abb33da4a1..0175bc53a0 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.1.dev053 slevis 08/10/2021 Adding history variables for use with Newton-Krylov ctsm5.1.dev051 multiple 08/06/2021 New LUNA-specific ozone stress option ctsm5.1.dev050 sacks 08/02/2021 Improve and document method for getting diagnostics on a problem point ctsm5.1.dev049 jedwards 07/26/2021 Update externals, NEON updates, fix stop_option=date, move neon niwo test to match user_mods, local time option diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 index d2028974bc..1ae2afe6b2 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 @@ -29,6 +29,7 @@ module SoilBiogeochemCarbonFluxType real(r8), pointer :: decomp_cascade_hr_col (:,:) ! vertically-integrated (diagnostic) het. resp. from decomposing C pools (gC/m2/s) real(r8), pointer :: decomp_cascade_ctransfer_vr_col (:,:,:) ! vertically-resolved C transferred along deomposition cascade (gC/m3/s) real(r8), pointer :: decomp_cascade_ctransfer_col (:,:) ! vertically-integrated (diagnostic) C transferred along decomposition cascade (gC/m2/s) + real(r8), pointer :: pathfrac_decomp_cascade_col (:,:,:) ! (frac) how much C from the donor pool passes through a given transition real(r8), pointer :: decomp_k_col (:,:,:) ! rate coefficient for decomposition (1./sec) real(r8), pointer :: hr_vr_col (:,:) ! (gC/m3/s) total vertically-resolved het. resp. from decomposing C pools real(r8), pointer :: o_scalar_col (:,:) ! fraction by which decomposition is limited by anoxia @@ -121,6 +122,9 @@ subroutine InitAllocate(this, bounds) allocate(this%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions)) this%decomp_cascade_ctransfer_col(:,:)= nan + allocate(this%pathfrac_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)) + this%pathfrac_decomp_cascade_col(:,:,:) = nan + allocate(this%decomp_k_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) this%decomp_k_col(:,:,:)= spval @@ -247,6 +251,7 @@ subroutine InitHistory(this, bounds, carbon_type) this%decomp_cascade_hr_vr_col(begc:endc,:,:) = spval this%decomp_cascade_ctransfer_col(begc:endc,:) = spval this%decomp_cascade_ctransfer_vr_col(begc:endc,:,:) = spval + this%pathfrac_decomp_cascade_col(begc:endc,:,:) = spval do l = 1, ndecomp_cascade_transitions ! output the vertically integrated fluxes only as default @@ -323,6 +328,20 @@ subroutine InitHistory(this, bounds, carbon_type) call hist_addfld_decomp (fname=fieldname, units='gC/m^3/s', type2d='levdcmp', & avgflag='A', long_name=longname, & ptr_col=data2dptr, default='inactive') + + ! pathfrac_decomp_cascade_col needed when using + ! Newton-Krylov to spin up the decomposition + data2dptr => this%pathfrac_decomp_cascade_col(:,:,l) + fieldname = & + trim(decomp_cascade_con%decomp_pool_name_short(decomp_cascade_con%cascade_donor_pool(l)))//'_PATHFRAC_'//& + trim(decomp_cascade_con%decomp_pool_name_short(decomp_cascade_con%cascade_receiver_pool(l)))& + //trim(vr_suffix) + longname = 'PATHFRAC from '//& + trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_donor_pool(l)))//' to '// & + trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_receiver_pool(l))) + call hist_addfld_decomp (fname=fieldname, units='fraction', type2d='levdcmp', & + avgflag='A', long_name=longname, & + ptr_col=data2dptr, default='inactive') endif end if @@ -693,6 +712,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) this%decomp_cascade_hr_vr_col(i,j,l) = value_column this%decomp_cascade_ctransfer_col(i,l) = value_column this%decomp_cascade_ctransfer_vr_col(i,j,l) = value_column + this%pathfrac_decomp_cascade_col(i,j,l) = value_column end do end do end do diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index f6a2b50bfd..2e60bca9df 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -48,6 +48,24 @@ module SoilBiogeochemDecompCascadeBGCMod integer, private :: i_cel_lit ! index of cellulose litter pool integer, private :: i_lig_lit ! index of lignin litter pool + real(r8), private :: cwd_fcel + real(r8), private :: cwd_flig + real(r8), private, allocatable :: f_s1s2(:,:) + real(r8), private, allocatable :: f_s1s3(:,:) + real(r8), private :: f_s2s1 + real(r8), private :: f_s2s3 + + integer, private :: i_l1s1 + integer, private :: i_l2s1 + integer, private :: i_l3s2 + integer, private :: i_s1s2 + integer, private :: i_s1s3 + integer, private :: i_s2s1 + integer, private :: i_s2s3 + integer, private :: i_s3s1 + integer, private :: i_cwdl2 + integer, private :: i_cwdl3 + type, private :: params_type real(r8):: cn_s1_bgc !C:N for SOM 1 real(r8):: cn_s2_bgc !C:N for SOM 2 @@ -256,28 +274,9 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i real(r8) :: rf_s3s1 real(r8) :: rf_cwdl2 real(r8) :: rf_cwdl3 - real(r8) :: cwd_fcel - real(r8) :: cwd_flig real(r8) :: cn_s1 real(r8) :: cn_s2 real(r8) :: cn_s3 - !real(r8) :: f_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) - !real(r8) :: f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) - real(r8), allocatable :: f_s1s2(:,:) - real(r8), allocatable :: f_s1s3(:,:) - real(r8) :: f_s2s1 - real(r8) :: f_s2s3 - - integer :: i_l1s1 - integer :: i_l2s1 - integer :: i_l3s2 - integer :: i_s1s2 - integer :: i_s1s3 - integer :: i_s2s1 - integer :: i_s2s3 - integer :: i_s3s1 - integer :: i_cwdl2 - integer :: i_cwdl3 real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. integer :: c, j ! indices @@ -286,7 +285,6 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i associate( & rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) - pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) cellsand => soilstate_inst%cellsand_col , & ! Input: [real(r8) (:,:) ] column 3D sand @@ -496,56 +494,48 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = rf_l1s1 cascade_donor_pool(i_l1s1) = i_met_lit cascade_receiver_pool(i_l1s1) = i_act_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = 1.0_r8 i_l2s1 = 2 decomp_cascade_con%cascade_step_name(i_l2s1) = 'L2S1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1) = rf_l2s1 cascade_donor_pool(i_l2s1) = i_cel_lit cascade_receiver_pool(i_l2s1) = i_act_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1)= 1.0_r8 i_l3s2 = 3 decomp_cascade_con%cascade_step_name(i_l3s2) = 'L3S2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = rf_l3s2 cascade_donor_pool(i_l3s2) = i_lig_lit cascade_receiver_pool(i_l3s2) = i_slo_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = 1.0_r8 i_s1s2 = 4 decomp_cascade_con%cascade_step_name(i_s1s2) = 'S1S2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = rf_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) cascade_donor_pool(i_s1s2) = i_act_som cascade_receiver_pool(i_s1s2) = i_slo_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = f_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) i_s1s3 = 5 decomp_cascade_con%cascade_step_name(i_s1s3) = 'S1S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) cascade_donor_pool(i_s1s3) = i_act_som cascade_receiver_pool(i_s1s3) = i_pas_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) i_s2s1 = 6 decomp_cascade_con%cascade_step_name(i_s2s1) = 'S2S1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = rf_s2s1 cascade_donor_pool(i_s2s1) = i_slo_som cascade_receiver_pool(i_s2s1) = i_act_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = f_s2s1 i_s2s3 = 7 decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 cascade_donor_pool(i_s2s3) = i_slo_som cascade_receiver_pool(i_s2s3) = i_pas_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = f_s2s3 i_s3s1 = 8 decomp_cascade_con%cascade_step_name(i_s3s1) = 'S3S1' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = rf_s3s1 cascade_donor_pool(i_s3s1) = i_pas_som cascade_receiver_pool(i_s3s1) = i_act_som - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 if (.not. use_fates) then i_cwdl2 = 9 @@ -553,20 +543,16 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 cascade_donor_pool(i_cwdl2) = i_cwd cascade_receiver_pool(i_cwdl2) = i_cel_lit - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fcel i_cwdl3 = 10 decomp_cascade_con%cascade_step_name(i_cwdl3) = 'CWDL3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = rf_cwdl3 cascade_donor_pool(i_cwdl3) = i_cwd cascade_receiver_pool(i_cwdl3) = i_lig_lit - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = cwd_flig end if deallocate(rf_s1s2) deallocate(rf_s1s3) - deallocate(f_s1s2) - deallocate(f_s1s3) deallocate(params_inst%initial_Cstocks) end associate @@ -640,6 +626,7 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & o2stress_unsat => ch4_inst%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area + pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] how much C from the donor pool passes through a given transition (frac) t_scalar => soilbiogeochem_carbonflux_inst%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia @@ -959,6 +946,18 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & end if end do end do + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1)= 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = f_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = f_s2s1 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = f_s2s3 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 + if (.not. use_fates) then + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fcel + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = cwd_flig + end if end associate diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 index 5a198483e5..336ed24d58 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 @@ -39,6 +39,18 @@ module SoilBiogeochemDecompCascadeCNMod integer, private :: i_soil3 = -9 ! SOM third pool integer, private :: i_soil4 = -9 ! SOM fourth pool + real(r8), private :: cwd_fcel + real(r8), private :: cwd_flig + integer, private :: i_l1s1 + integer, private :: i_l2s2 + integer, private :: i_l3s3 + integer, private :: i_s1s2 + integer, private :: i_s2s3 + integer, private :: i_s3s4 + integer, private :: i_s4atm + integer, private :: i_cwdl2 + integer, private :: i_cwdl3 + type, private :: params_type real(r8):: cn_s1_cn !C:N for SOM 1 real(r8):: cn_s2_cn !C:N for SOM 2 @@ -243,28 +255,15 @@ subroutine init_decompcascade_cn(bounds, soilbiogeochem_state_inst) real(r8) :: rf_s1s2 !respiration fraction SOM 1 -> SOM 2 real(r8) :: rf_s2s3 !respiration fraction SOM 2 -> SOM 3 real(r8) :: rf_s3s4 !respiration fraction SOM 3 -> SOM 4 - real(r8) :: cwd_fcel - real(r8) :: cwd_flig real(r8) :: cn_s1 real(r8) :: cn_s2 real(r8) :: cn_s3 real(r8) :: cn_s4 - integer :: i_l1s1 - integer :: i_l2s2 - integer :: i_l3s3 - integer :: i_s1s2 - integer :: i_s2s3 - integer :: i_s3s4 - integer :: i_s4atm - integer :: i_cwdl2 - integer :: i_cwdl3 !----------------------------------------------------------------------- associate( & rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) - pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) - cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Output: [integer (:) ] which pool is C taken from for a given decomposition step cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & ! Output: [integer (:) ] which pool is C added to for a given decomposition step floating_cn_ratio_decomp_pools => decomp_cascade_con%floating_cn_ratio_decomp_pools , & ! Output: [logical (:) ] TRUE => pool has fixed C:N ratio @@ -455,49 +454,42 @@ subroutine init_decompcascade_cn(bounds, soilbiogeochem_state_inst) rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = rf_l1s1 cascade_donor_pool(i_l1s1) = i_litr1 cascade_receiver_pool(i_l1s1) = i_soil1 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = 1.0_r8 i_l2s2 = 2 decomp_cascade_con%cascade_step_name(i_l2s2) = 'L2S2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s2) = rf_l2s2 cascade_donor_pool(i_l2s2) = i_litr2 cascade_receiver_pool(i_l2s2) = i_soil2 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s2) = 1.0_r8 i_l3s3 = 3 decomp_cascade_con%cascade_step_name(i_l3s3) = 'L3S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s3) = rf_l3s3 cascade_donor_pool(i_l3s3) = i_litr3 cascade_receiver_pool(i_l3s3) = i_soil3 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s3) = 1.0_r8 i_s1s2 = 4 decomp_cascade_con%cascade_step_name(i_s1s2) = 'S1S2' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = rf_s1s2 cascade_donor_pool(i_s1s2) = i_soil1 cascade_receiver_pool(i_s1s2) = i_soil2 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = 1.0_r8 i_s2s3 = 5 decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 cascade_donor_pool(i_s2s3) = i_soil2 cascade_receiver_pool(i_s2s3) = i_soil3 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = 1.0_r8 i_s3s4 = 6 decomp_cascade_con%cascade_step_name(i_s3s4) = 'S3S4' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s4) = rf_s3s4 cascade_donor_pool(i_s3s4) = i_soil3 cascade_receiver_pool(i_s3s4) = i_soil4 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s4) = 1.0_r8 i_s4atm = 7 decomp_cascade_con%cascade_step_name(i_s4atm) = 'S4' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s4atm) = 1. cascade_donor_pool(i_s4atm) = i_soil4 cascade_receiver_pool(i_s4atm) = i_atm - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s4atm) = 1.0_r8 if (.not. use_fates) then i_cwdl2 = 8 @@ -505,14 +497,12 @@ subroutine init_decompcascade_cn(bounds, soilbiogeochem_state_inst) rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = 0._r8 cascade_donor_pool(i_cwdl2) = i_cwd cascade_receiver_pool(i_cwdl2) = i_litr2 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fcel i_cwdl3 = 9 decomp_cascade_con%cascade_step_name(i_cwdl3) = 'CWDL3' rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = 0._r8 cascade_donor_pool(i_cwdl3) = i_cwd cascade_receiver_pool(i_cwdl3) = i_litr3 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = cwd_flig end if end associate @@ -579,6 +569,8 @@ subroutine decomp_rate_constants_cn(bounds, & o2stress_unsat => ch4_inst%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area (excluding dedicated wetland columns) + pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] how much C from the donor pool passes through a given transition (frac) + t_scalar => soilbiogeochem_carbonflux_inst%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia @@ -847,6 +839,17 @@ subroutine decomp_rate_constants_cn(bounds, & end if end do end do + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s2) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s3) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s4) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s4atm) = 1.0_r8 + if (.not. use_fates) then + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fcel + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = cwd_flig + end if end associate diff --git a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 index 43b817c65b..d3009ba32e 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 @@ -110,7 +110,6 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, fpi_vr => soilbiogeochem_state_inst%fpi_vr_col , & ! Input: [real(r8) (:,:) ] fraction of potential immobilization (no units) rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) - pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) decomp_npools_vr => soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) N pools decomp_cpools_vr => soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index d7d6ed727f..1e9d75b732 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -110,7 +110,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & initial_cn_ratio => decomp_cascade_con%initial_cn_ratio , & ! Input: [real(r8) (:) ] c:n ratio for initialization of pools rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) - pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) + pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] how much C from the donor pool passes through a given transition (frac) decomp_npools_vr => soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) N pools diff --git a/src/soilbiogeochem/SoilBiogeochemStateType.F90 b/src/soilbiogeochem/SoilBiogeochemStateType.F90 index 118c42d3a9..da896af6bf 100644 --- a/src/soilbiogeochem/SoilBiogeochemStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemStateType.F90 @@ -34,7 +34,6 @@ module SoilBiogeochemStateType real(r8) , pointer :: fpi_col (:) ! (no units) fraction of potential immobilization real(r8), pointer :: fpg_col (:) ! (no units) fraction of potential gpp real(r8) , pointer :: rf_decomp_cascade_col (:,:,:) ! (frac) respired fraction in decomposition step - real(r8) , pointer :: pathfrac_decomp_cascade_col (:,:,:) ! (frac) what fraction of C leaving a given pool passes through a given transition real(r8) , pointer :: nfixation_prof_col (:,:) ! (1/m) profile for N fixation additions real(r8) , pointer :: ndep_prof_col (:,:) ! (1/m) profile for N fixation additions real(r8) , pointer :: som_adv_coef_col (:,:) ! (m2/s) SOM advective flux @@ -105,9 +104,6 @@ subroutine InitAllocate(this, bounds) allocate(this%rf_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)); this%rf_decomp_cascade_col(:,:,:) = nan - allocate(this%pathfrac_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)); - this%pathfrac_decomp_cascade_col(:,:,:) = nan - end subroutine InitAllocate !------------------------------------------------------------------------ From 724cb82b860b28cffe2079a3a7d08366948403b1 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 11 Aug 2021 16:41:29 -0600 Subject: [PATCH 32/69] Change to variable description as per code review suggestion --- src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 | 2 +- src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 | 2 +- src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 | 2 +- src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 index 1ae2afe6b2..072d13d54b 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 @@ -29,7 +29,7 @@ module SoilBiogeochemCarbonFluxType real(r8), pointer :: decomp_cascade_hr_col (:,:) ! vertically-integrated (diagnostic) het. resp. from decomposing C pools (gC/m2/s) real(r8), pointer :: decomp_cascade_ctransfer_vr_col (:,:,:) ! vertically-resolved C transferred along deomposition cascade (gC/m3/s) real(r8), pointer :: decomp_cascade_ctransfer_col (:,:) ! vertically-integrated (diagnostic) C transferred along decomposition cascade (gC/m2/s) - real(r8), pointer :: pathfrac_decomp_cascade_col (:,:,:) ! (frac) how much C from the donor pool passes through a given transition + real(r8), pointer :: pathfrac_decomp_cascade_col (:,:,:) ! (frac) what fraction of C passes from donor to receiver pool through a given transition real(r8), pointer :: decomp_k_col (:,:,:) ! rate coefficient for decomposition (1./sec) real(r8), pointer :: hr_vr_col (:,:) ! (gC/m3/s) total vertically-resolved het. resp. from decomposing C pools real(r8), pointer :: o_scalar_col (:,:) ! fraction by which decomposition is limited by anoxia diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index 2e60bca9df..d24a6d34ec 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -626,7 +626,7 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & o2stress_unsat => ch4_inst%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area - pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] how much C from the donor pool passes through a given transition (frac) + pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C passes from donor to receiver pool through a given transition (frac) t_scalar => soilbiogeochem_carbonflux_inst%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 index 336ed24d58..c3eb1fe2e1 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 @@ -569,7 +569,7 @@ subroutine decomp_rate_constants_cn(bounds, & o2stress_unsat => ch4_inst%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area (excluding dedicated wetland columns) - pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] how much C from the donor pool passes through a given transition (frac) + pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C passes from donor to receiver pool through a given transition (frac) t_scalar => soilbiogeochem_carbonflux_inst%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index 1e9d75b732..89e4329fb9 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -110,7 +110,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & initial_cn_ratio => decomp_cascade_con%initial_cn_ratio , & ! Input: [real(r8) (:) ] c:n ratio for initialization of pools rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) - pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] how much C from the donor pool passes through a given transition (frac) + pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C passes from donor to receiver pool through a given transition (frac) decomp_npools_vr => soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) N pools From 1f13e6576a2befcc0c2bd2f8ac8d3e62ce8fbca2 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 11 Aug 2021 18:18:44 -0600 Subject: [PATCH 33/69] Code corrections from attempting to build (part 2) --- src/main/clm_varcon.F90 | 2 ++ src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 | 4 ++++ .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 7 +++---- src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 | 2 +- src/soilbiogeochem/SoilBiogeochemStateType.F90 | 3 --- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/clm_varcon.F90 b/src/main/clm_varcon.F90 index 558f87521e..21341bcaa7 100644 --- a/src/main/clm_varcon.F90 +++ b/src/main/clm_varcon.F90 @@ -124,6 +124,8 @@ module clm_varcon real(r8), public, parameter :: aquifer_water_baseline = 5000._r8 ! baseline value for water in the unconfined aquifer [mm] real(r8), public, parameter :: c_to_b = 2.0_r8 ! conversion between mass carbon and total biomass (g biomass /g C) + real(r8), public, parameter :: g_to_mg = 1.0e3_r8 ! coefficient to convert g to mg + real(r8), public, parameter :: cm3_to_m3 = 1.0e-6_r8 ! coefficient to convert cm3 to m3 !!! C13 real(r8), public, parameter :: preind_atm_del13c = -6.0_r8 ! preindustrial value for atmospheric del13C diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 index fc3f337a6e..52cbc5ff29 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 @@ -30,6 +30,7 @@ module SoilBiogeochemCarbonFluxType real(r8), pointer :: decomp_cascade_hr_col (:,:) ! vertically-integrated (diagnostic) het. resp. from decomposing C pools (gC/m2/s) real(r8), pointer :: decomp_cascade_ctransfer_vr_col (:,:,:) ! vertically-resolved C transferred along deomposition cascade (gC/m3/s) real(r8), pointer :: decomp_cascade_ctransfer_col (:,:) ! vertically-integrated (diagnostic) C transferred along decomposition cascade (gC/m2/s) + real(r8), pointer :: cn_col (:,:) ! (gC/gN) C:N ratio by pool real(r8), pointer :: decomp_k_col (:,:,:) ! rate constant for decomposition (1./sec) real(r8), pointer :: hr_vr_col (:,:) ! (gC/m3/s) total vertically-resolved het. resp. from decomposing C pools real(r8), pointer :: o_scalar_col (:,:) ! fraction by which decomposition is limited by anoxia @@ -125,6 +126,8 @@ subroutine InitAllocate(this, bounds) allocate(this%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions)) this%decomp_cascade_ctransfer_col(:,:)= nan + allocate(this%cn_col(begc:endc,1:ndecomp_pools)) + this%cn_col(:,:)= spval allocate(this%decomp_k_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)) this%decomp_k_col(:,:,:)= spval @@ -707,6 +710,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) do fi = 1,num_column i = filter_column(fi) this%decomp_cpools_leached_col(i,k) = value_column + this%cn_col(i,k) = value_column end do do j = 1, nlevdecomp_full do fi = 1,num_column diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 6068967cdc..bc11199020 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -108,7 +108,7 @@ subroutine readParams ( ncid ) ! TODO Add new params here and in the params file. ! TODO Some may need _bgc or _mimics added/removed here and in the params ! file. Nicer to add as prefix instead of as suffix because params will - ! then appear grouped in the file. Need approval from Bill/Erik. + ! then appear grouped in the file. Requested approval from Erik. ! TODO Read MIMICS-specific params here & shared ones (eg *_bgc) as: ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding ! TODO When ready for all final params values, talk to @wwieder and, @@ -641,6 +641,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! !USES: use clm_time_manager , only : get_days_per_year use clm_varcon , only : secspday, secsphr, tfrz + use clm_varcon , only : g_to_mg, cm3_to_m3 ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -702,7 +703,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia - cn_col => soilbiogeochem_state_inst%cn_col , & ! Output: [real(r8) (:,:) ] C:N ratio + cn_col => soilbiogeochem_carbonflux_inst%cn_col , & ! Output: [real(r8) (:,:) ] C:N ratio decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate for decomposition (1./sec) spinup_factor => decomp_cascade_con%spinup_factor & ! Input: [real(r8) (:) ] factor for AD spinup associated with each pool ) @@ -1024,8 +1025,6 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Microbial concentration with necessary unit conversions ! mgC/cm3 = gC/m3 * (1e3 mg/g) / (1e6 cm3/m3) - g_to_mg = 1.0e3_r8 ! put unit conversions in clm_varcon? - cm3_to_m3 = 1.0e-6_r8 m1_conc = (decomp_cpools_vr(c,j,i_cop_mic) / col%dz(c,j)) * & g_to_mg * cm3_to_m3 m2_conc = (decomp_cpools_vr(c,j,i_oli_mic) / col%dz(c,j)) * & diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index ef3864bcaa..b02c422f00 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -131,7 +131,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & potential_immob_vr => soilbiogeochem_nitrogenflux_inst%potential_immob_vr_col , & ! Output: [real(r8) (:,:) ] gross_nmin_vr => soilbiogeochem_nitrogenflux_inst%gross_nmin_vr_col , & ! Output: [real(r8) (:,:) ] - cn_col => soilbiogeochem_state_inst%cn_col , & ! Input: [real(r8) (:,:) ] C:N ratio + cn_col => soilbiogeochem_carbonflux_inst%cn_col , & ! Input: [real(r8) (:,:) ] C:N ratio decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Input: [real(r8) (:,:,:) ] decomposition rate coefficient (1./sec) phr_vr => soilbiogeochem_carbonflux_inst%phr_vr_col & ! Output: [real(r8) (:,:) ] potential HR (gC/m3/s) ) diff --git a/src/soilbiogeochem/SoilBiogeochemStateType.F90 b/src/soilbiogeochem/SoilBiogeochemStateType.F90 index 776deb9bb1..aed85e93e2 100644 --- a/src/soilbiogeochem/SoilBiogeochemStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemStateType.F90 @@ -34,7 +34,6 @@ module SoilBiogeochemStateType real(r8) , pointer :: fpi_col (:) ! (no units) fraction of potential immobilization real(r8), pointer :: fpg_col (:) ! (no units) fraction of potential gpp real(r8) , pointer :: rf_decomp_cascade_col (:,:,:) ! (frac) respired fraction in decomposition step - real(r8) , pointer :: cn_col (:,:) ! (gC/gN) C:N ratio by pool real(r8) , pointer :: nue_decomp_cascade_col (:) ! (TODO) N use efficiency for a given transition real(r8) , pointer :: pathfrac_decomp_cascade_col (:,:,:) ! (frac) what fraction of C leaving a given pool passes through a given transition real(r8) , pointer :: nfixation_prof_col (:,:) ! (1/m) profile for N fixation additions @@ -106,8 +105,6 @@ subroutine InitAllocate(this, bounds) allocate(this%rf_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)); this%rf_decomp_cascade_col(:,:,:) = nan - allocate(this%cn_col(begc:endc,1:ndecomp_pools)); - this%cn_col(:,:) = nan allocate(this%nue_decomp_cascade_col(1:ndecomp_cascade_transitions)); this%nue_decomp_cascade_col(:) = nan From dcf7689c5ef1fc20cbb9990d2879168cdd852e7a Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 16 Aug 2021 16:44:14 -0600 Subject: [PATCH 34/69] Code corrections from attempting to build (part 3) There are more of these in store; however, I need to merge my work from #1457 while #1457 is pending, in order to make progress here --- src/biogeochem/CNDriverMod.F90 | 3 +- src/biogeochem/CNSharedParamsMod.F90 | 18 +- src/biogeochem/CNVegCarbonFluxType.F90 | 1 - src/biogeochem/EDBGCDynMod.F90 | 3 +- .../SoilBiogeochemDecompCascadeBGCMod.F90 | 77 +-- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 625 ++++++++++++------ 6 files changed, 476 insertions(+), 251 deletions(-) diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index 81485a75f4..e2323118cc 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -317,7 +317,8 @@ subroutine CNDriverNoLeaching(bounds, soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) else if (use_mimics_decomp) then call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & - soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, soilbiogeochem_carbonflux_inst) + soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & + soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) else ! deprecated call decomp_rate_constants_cn(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) diff --git a/src/biogeochem/CNSharedParamsMod.F90 b/src/biogeochem/CNSharedParamsMod.F90 index f38a7debb5..3b88c9be84 100644 --- a/src/biogeochem/CNSharedParamsMod.F90 +++ b/src/biogeochem/CNSharedParamsMod.F90 @@ -15,7 +15,9 @@ module CNSharedParamsMod type, public :: CNParamsShareType real(r8) :: Q10 ! temperature dependence real(r8) :: minpsi ! minimum soil water potential for heterotrophic resp - real(r8) :: cwd_fcel ! cellulose fraction of coarse woody debris + real(r8) :: maxpsi ! maximum soil water potential for heterotrophic resp + real(r8) :: rf_cwdl2 ! respiration fraction in CWD to litter2 transition (frac) + real(r8) :: tau_cwd ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) real(r8) :: cwd_flig ! lignin fraction of coarse woody debris real(r8) :: froz_q10 ! separate q10 for frozen soil respiration rates real(r8) :: decomp_depth_efolding ! e-folding depth for reduction in decomposition (m) @@ -96,10 +98,20 @@ subroutine CNParamsReadShared_netcdf(ncid) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) CNParamsShareInst%minpsi=tempr - tString='cwd_fcel' + tString='maxpsi_hr' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - CNParamsShareInst%cwd_fcel=tempr + CNParamsShareInst%maxpsi=tempr + + tString='rf_cwdl2' ! TODO slevis: rm suffix in params file(s) + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + CNParamsShareInst%rf_cwdl2=tempr + + tString='tau_cwd' ! TODO slevis: rm suffix in params file(s) + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + CNParamsShareInst%tau_cwd=tempr tString='cwd_flig' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index 6adf004c7f..b31578e543 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -4484,7 +4484,6 @@ subroutine Summary_carbonflux(this, & ! Calculate ligninNratioAve do fc = 1,num_soilc c = filter_soilc(fc) - ! TODO Use cwd_flig in *CascadeBGC the same way for consistency? ligninNratio_cwd = CNParamsShareInst%cwd_flig * & (soilbiogeochem_cwdc_col(c) / soilbiogeochem_cwdn_col(c)) * & soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2) diff --git a/src/biogeochem/EDBGCDynMod.F90 b/src/biogeochem/EDBGCDynMod.F90 index 06cd1e8974..1866ea8893 100644 --- a/src/biogeochem/EDBGCDynMod.F90 +++ b/src/biogeochem/EDBGCDynMod.F90 @@ -184,7 +184,8 @@ subroutine EDBGCDyn(bounds, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) else if (use_mimics_decomp) then call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & - soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, soilbiogeochem_carbonflux_inst) + soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & + soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) else ! deprecated call decomp_rate_constants_cn(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index f6a2b50bfd..ea73a1ca07 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -61,7 +61,6 @@ module SoilBiogeochemDecompCascadeBGCMod real(r8):: rf_s2s3_bgc real(r8):: rf_s3s1_bgc - real(r8):: rf_cwdl2_bgc real(r8):: rf_cwdl3_bgc real(r8):: tau_l1_bgc ! 1/turnover time of litter 1 from Century (l/18.5) (1/yr) @@ -69,13 +68,8 @@ module SoilBiogeochemDecompCascadeBGCMod real(r8):: tau_s1_bgc ! 1/turnover time of SOM 1 from Century (1/7.3) (1/yr) real(r8):: tau_s2_bgc ! 1/turnover time of SOM 2 from Century (1/0.2) (1/yr) real(r8):: tau_s3_bgc ! 1/turnover time of SOM 3 from Century (1/0.0045) (1/yr) - real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) real(r8) :: cwd_fcel_bgc !cellulose fraction for CWD - real(r8) :: cwd_flig - - real(r8) :: minpsi_bgc !minimum soil water potential for heterotrophic resp - real(r8) :: maxpsi_bgc !maximum soil water potential for heterotrophic resp real(r8), allocatable :: initial_Cstocks(:) ! Initial Carbon stocks for a cold-start real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start @@ -111,111 +105,86 @@ subroutine readParams ( ncid ) !----------------------------------------------------------------------- ! Read off of netcdf file - tString='tau_l1' + tString='bgc_tau_l1' ! TODO slevis: rename in params file(s) and code... call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_l1_bgc=tempr - tString='tau_l2_l3' + tString='bgc_tau_l2_l3' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_l2_l3_bgc=tempr - tString='tau_s1' + tString='bgc_tau_s1' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_s1_bgc=tempr - tString='tau_s2' + tString='bgc_tau_s2' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_s2_bgc=tempr - tString='tau_s3' + tString='bgc_tau_s3' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_s3_bgc=tempr - tString='tau_cwd_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_cwd_bgc=tempr - - tString='cn_s1_bgc' + tString='bgc_cn_s1' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cn_s1_bgc=tempr - tString='cn_s2_bgc' + tString='bgc_cn_s2' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cn_s2_bgc=tempr - tString='cn_s3_bgc' + tString='bgc_cn_s3' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cn_s3_bgc=tempr - tString='rf_l1s1_bgc' + tString='bgc_rf_l1s1' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l1s1_bgc=tempr - tString='rf_l2s1_bgc' + tString='bgc_rf_l2s1' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l2s1_bgc=tempr - tString='rf_l3s2_bgc' + tString='bgc_rf_l3s2' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l3s2_bgc=tempr - tString='rf_s2s1_bgc' + tString='bgc_rf_s2s1' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_s2s1_bgc=tempr - tString='rf_s2s3_bgc' + tString='bgc_rf_s2s3' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_s2s3_bgc=tempr - tString='rf_s3s1_bgc' + tString='bgc_rf_s3s1' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_s3s1_bgc=tempr - tString='rf_cwdl2_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_cwdl2_bgc=tempr - - tString='rf_cwdl3_bgc' + tString='bgc_rf_cwdl3' ! TODO slevis: rename in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_cwdl3_bgc=tempr - tString='cwd_fcel' + tString='bgc_cwd_fcel' ! TODO slevis: rename in params file(s) & code... call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cwd_fcel_bgc=tempr - tString='minpsi_hr' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%minpsi_bgc=tempr - - tString='maxpsi_hr' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%maxpsi_bgc=tempr - - tString='cwd_flig' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%cwd_flig=tempr - allocate(params_inst%initial_Cstocks(ndecomp_pools_max)) tString='initial_Cstocks_bgc' call ncd_io(trim(tString), params_inst%initial_Cstocks(:), 'read', ncid, readvar=readv) @@ -254,10 +223,8 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i real(r8) :: rf_s2s1 real(r8) :: rf_s2s3 real(r8) :: rf_s3s1 - real(r8) :: rf_cwdl2 real(r8) :: rf_cwdl3 real(r8) :: cwd_fcel - real(r8) :: cwd_flig real(r8) :: cn_s1 real(r8) :: cn_s2 real(r8) :: cn_s3 @@ -285,6 +252,8 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i !----------------------------------------------------------------------- associate( & + cwd_flig => CNParamsShareInst%cwd_flig , & ! Input: [real(r8) ] lignin fraction of coarse woody debris (frac) + rf_cwdl2 => CNParamsShareInst%rf_cwdl2 , & ! Input: [real(r8) ] respiration fraction in CWD to litter2 transition (frac) rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) @@ -325,12 +294,10 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i rf_s2s3 = params_inst%rf_s2s3_bgc rf_s3s1 = params_inst%rf_s3s1_bgc - rf_cwdl2 = params_inst%rf_cwdl2_bgc rf_cwdl3 = params_inst%rf_cwdl3_bgc ! set the cellulose and lignin fractions for coarse woody debris cwd_fcel = params_inst%cwd_fcel_bgc - cwd_flig = params_inst%cwd_flig ! set path fractions f_s2s1 = 0.42_r8/(0.45_r8) @@ -477,7 +444,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i spinup_factor(i_lig_lit) = 1._r8 !CWD if (.not. use_fates) then - spinup_factor(i_cwd) = max(1._r8, (speedup_fac * params_inst%tau_cwd_bgc / 2._r8 )) + spinup_factor(i_cwd) = max(1._r8, (speedup_fac * CNParamsShareInst%tau_cwd / 2._r8 )) end if !som1 spinup_factor(i_act_som) = 1._r8 @@ -630,8 +597,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & catanf(t1) = 11.75_r8 +(29.7_r8 / SHR_CONST_PI) * atan( SHR_CONST_PI * 0.031_r8 * ( t1 - 15.4_r8 )) associate( & - minpsi => params_inst%minpsi_bgc , & ! Input: [real(r8) ] minimum soil suction (mm) - maxpsi => params_inst%maxpsi_bgc , & ! Input: [real(r8) ] maximum soil suction (mm) + minpsi => CNParamsShareInst%minpsi , & ! Input: [real(r8) ] minimum soil suction (mm) + maxpsi => CNParamsShareInst%maxpsi , & ! Input: [real(r8) ] maximum soil suction (mm) soilpsi => soilstate_inst%soilpsi_col , & ! Input: [real(r8) (:,:) ] soil water potential in each soil layer (MPa) t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) @@ -671,7 +638,7 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & k_s1 = 1._r8 / (secspday * days_per_year * params_inst%tau_s1_bgc) k_s2 = 1._r8 / (secspday * days_per_year * params_inst%tau_s2_bgc) k_s3 = 1._r8 / (secspday * days_per_year * params_inst%tau_s3_bgc) - k_frag = 1._r8 / (secspday * days_per_year * params_inst%tau_cwd_bgc) + k_frag = 1._r8 / (secspday * days_per_year * CNParamsShareInst%tau_cwd) ! calc ref rate catanf_30 = catanf(30._r8) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index bc11199020..6c35475d11 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -21,6 +21,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con use SoilBiogeochemStateType , only : soilbiogeochem_state_type use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type + use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type use SoilStateType , only : soilstate_type use TemperatureType , only : temperature_type use CNVegCarbonFluxType , only : cnveg_carbonflux_type @@ -41,6 +42,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! !PUBLIC DATA MEMBERS ! ! !PRIVATE DATA MEMBERS + real(r8), allocatable :: desorp(:,:) integer, private :: i_phys_som ! index of physically protected Soil Organic Matter (SOM) integer, private :: i_chem_som ! index of chemically protected SOM integer, private :: i_avl_som ! index of available (aka active) SOM @@ -57,23 +59,47 @@ module SoilBiogeochemDecompCascadeMIMICSMod integer, private :: i_m2s2 type, private :: params_type - ! Respiration fraction cwd --> structural litter (keep comment sep for dif) - real(r8):: rf_cwdl2_bgc - real(r8):: tau_cwd_bgc ! corrected fragmentation rate constant CWD, century leaves wood decomposition rates open, within range of 0 - 0.5 yr^-1 (1/0.3) (1/yr) - real(r8) :: minpsi_bgc !minimum soil water potential for heterotrophic resp - real(r8) :: maxpsi_bgc !maximum soil water potential for heterotrophic resp - - ! TODO Need for spin-ups? real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start real(r8), allocatable :: initial_Cstocks(:) ! Initial Carbon stocks for a cold-start - real(r8), allocatable :: mge(:) ! Microbial growth efficiency (mg/mg) - real(r8), allocatable :: vmod(:) ! - real(r8), allocatable :: vslope(:) ! - real(r8), allocatable :: vint(:) ! - real(r8), allocatable :: kmod(:) ! - real(r8), allocatable :: kslope(:) ! - real(r8), allocatable :: kint(:) ! - + real(r8), allocatable :: mimics_mge(:) ! Microbial growth efficiency (mg/mg) + real(r8), allocatable :: mimics_vmod(:) ! + real(r8), allocatable :: mimics_vint(:) ! + real(r8), allocatable :: mimics_vslope(:) ! + real(r8), allocatable :: mimics_kmod(:) ! + real(r8), allocatable :: mimics_kint(:) ! + real(r8), allocatable :: mimics_kslope(:) ! + real(r8) :: mimics_nue_into_mic + real(r8) :: mimics_p_scalar_p1 + real(r8) :: mimics_p_scalar_p2 + real(r8) :: mimics_fphys_r_p1 + real(r8) :: mimics_fphys_r_p2 + real(r8) :: mimics_fphys_k_p1 + real(r8) :: mimics_fphys_k_p2 + real(r8) :: mimics_fchem_r_p1 + real(r8) :: mimics_fchem_r_p2 + real(r8) :: mimics_fchem_k_p1 + real(r8) :: mimics_fchem_k_p2 + real(r8) :: mimics_desorp_p1 + real(r8) :: mimics_desorp_p2 + real(r8) :: mimics_desorpQ10 + real(r8) :: mimics_densdep + real(r8) :: mimics_fmet_p1 + real(r8) :: mimics_fmet_p2 + real(r8) :: mimics_fmet_p3 + real(r8) :: mimics_fmet_p4 + real(r8) :: mimics_tau_mod_factor + real(r8) :: mimics_tau_mod_min + real(r8) :: mimics_tau_mod_max + real(r8) :: mimics_tau_r_p1 + real(r8) :: mimics_tau_r_p2 + real(r8) :: mimics_tau_k_p1 + real(r8) :: mimics_tau_k_p2 + real(r8) :: mimics_ko_r + real(r8) :: mimics_ko_k + real(r8) :: mimics_cn_r + real(r8) :: mimics_cn_k + real(r8) :: mimics_cn_mod_num + real(r8) :: mimics_t_soi_ref end type params_type ! type(params_type), private :: params_inst @@ -105,78 +131,216 @@ subroutine readParams ( ncid ) !----------------------------------------------------------------------- ! Read off of netcdf file - ! TODO Add new params here and in the params file. - ! TODO Some may need _bgc or _mimics added/removed here and in the params - ! file. Nicer to add as prefix instead of as suffix because params will - ! then appear grouped in the file. Requested approval from Erik. - ! TODO Read MIMICS-specific params here & shared ones (eg *_bgc) as: - ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding - ! TODO When ready for all final params values, talk to @wwieder and, - ! if values differ from the BGC values, make separate _mimics params. - tString='tau_cwd_bgc' + ! TODO Add new mimics_ params here and in the params file(s) + ! TODO Add shared ones in CNParamsShareInst & in the file(s) + ! TODO When ready for final params values, talk to @wwieder + ! TODO Need next one for spin-ups? If so, then add prefixes + ! mimics here and bgc in BGCMod if these two will differ or + ! move reading the parameter to CNSharedParamsMod if they + ! will not differ. Similar for both initial_Cstocks params. + tString='initial_Cstocks_depth_bgc' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%tau_cwd_bgc=tempr + params_inst%initial_Cstocks_depth=tempr - ! MIMICS value = 0 (same as BGC value) - tString='rf_cwdl2_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + allocate(params_inst%initial_Cstocks(ndecomp_pools_max)) + tString='initial_Cstocks_bgc' + call ncd_io(trim(tString), params_inst%initial_Cstocks(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%rf_cwdl2_bgc=tempr - tString='minpsi_hr' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_mge(ndecomp_pools_max)) + tString='mimics_mge' ! TODO rename in params file(s) + call ncd_io(trim(tString), params_inst%mimics_mge(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%minpsi_bgc=tempr - tString='maxpsi_hr' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_vmod(ndecomp_pools_max)) + tString='mimics_vmod' ! TODO rename in params file(s) + call ncd_io(trim(tString), params_inst%mimics_vmod(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%maxpsi_bgc=tempr - tString='initial_Cstocks_depth_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_vslope(ndecomp_pools_max)) + tString='mimics_vslope' ! TODO rename in params file(s) + call ncd_io(trim(tString), params_inst%mimics_vslope(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%initial_Cstocks_depth=tempr - allocate(params_inst%initial_Cstocks(ndecomp_pools_max)) - tString='initial_Cstocks_bgc' - call ncd_io(trim(tString), params_inst%initial_Cstocks(:), 'read', ncid, readvar=readv) + allocate(params_inst%mimics_vint(ndecomp_pools_max)) + tString='mimics_vint' ! TODO rename in params file(s) + call ncd_io(trim(tString), params_inst%mimics_vint(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_kmod(ndecomp_pools_max)) + tString='mimics_kmod' ! TODO rename in params file(s) + call ncd_io(trim(tString), params_inst%mimics_kmod(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_kslope(ndecomp_pools_max)) + tString='mimics_kslope' ! TODO rename in params file(s) + call ncd_io(trim(tString), params_inst%mimics_kslope(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_kint(ndecomp_pools_max)) + tString='mimics_kint' ! TODO rename in params file(s) + call ncd_io(trim(tString), params_inst%mimics_kint(:), 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_p_scalar_p1) + tString='mimics_p_scalar_p1' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_p_scalar_p1, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_p_scalar_p2) + tString='mimics_p_scalar_p2' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_p_scalar_p2, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_desorp_p1) + tString='mimics_desorp_p1' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_desorp_p1, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_desorp_p2) + tString='mimics_desorp_p2' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_desorp_p2, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_fphys_r_p1) + tString='mimics_fphys_r_p1' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fphys_r_p1, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_fphys_r_p2) + tString='mimics_fphys_r_p2' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fphys_r_p2, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_fphys_k_p1) + tString='mimics_fphys_k_p1' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fphys_k_p1, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_fphys_k_p2) + tString='mimics_fphys_k_p2' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fphys_k_p2, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_nue_into_mic) + tString='mimics_nue_into_mic' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_nue_into_mic, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mge(ndecomp_pools_max)) - tString='mge_mimics' - call ncd_io(trim(tString), params_inst%mge(:), 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fmet_p1) + tString='mimics_fmet_p1' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fmet_p1, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%vmod(ndecomp_pools_max)) - tString='vmod_mimics' - call ncd_io(trim(tString), params_inst%vmod(:), 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fmet_p2) + tString='mimics_fmet_p2' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fmet_p2, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%vslope(ndecomp_pools_max)) - tString='vslope_mimics' - call ncd_io(trim(tString), params_inst%vslope(:), 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fmet_p3) + tString='mimics_fmet_p3' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fmet_p3, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%vint(ndecomp_pools_max)) - tString='vint_mimics' - call ncd_io(trim(tString), params_inst%vint(:), 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fmet_p4) + tString='mimics_fmet_p4' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fmet_p4, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%kmod(ndecomp_pools_max)) - tString='kmod_mimics' - call ncd_io(trim(tString), params_inst%kmod(:), 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fchem_r_p1) + tString='mimics_fchem_r_p1' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fchem_r_p1, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%kslope(ndecomp_pools_max)) - tString='kslope_mimics' - call ncd_io(trim(tString), params_inst%kslope(:), 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fchem_r_p2) + tString='mimics_fchem_r_p2' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fchem_r_p2, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%kint(ndecomp_pools_max)) - tString='kint_mimics' - call ncd_io(trim(tString), params_inst%kint(:), 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fchem_k_p1) + tString='mimics_fchem_k_p1' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fchem_k_p1, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_fchem_k_p2) + tString='mimics_fchem_k_p2' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_fchem_k_p2, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_tau_mod_factor) + tString='mimics_tau_mod_factor' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_tau_mod_factor, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_tau_mod_min) + tString='mimics_tau_mod_min' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_tau_mod_min, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_tau_mod_max) + tString='mimics_tau_mod_max' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_tau_mod_max, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_tau_r_p1) + tString='mimics_tau_r_p1' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_tau_r_p1, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_tau_r_p2) + tString='mimics_tau_r_p2' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_tau_r_p2, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_tau_k_p1) + tString='mimics_tau_k_p1' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_tau_k_p1, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_tau_k_p2) + tString='mimics_tau_k_p2' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_tau_k_p2, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_ko_r) + tString='mimics_ko_r' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_ko_r, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_ko_k) + tString='mimics_ko_k' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_ko_k, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_densdep) + tString='mimics_densdep' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_densdep, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_desorpQ10) + tString='mimics_desorpQ10' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_desorpQ10, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_t_soi_ref) + tString='mimics_t_soi_ref' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_t_soi_ref, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_cn_mod_num) + tString='mimics_cn_mod_num' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_cn_mod_num, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_cn_r) + tString='mimics_cn_r' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_cn_r, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + allocate(params_inst%mimics_cn_k) + tString='mimics_cn_k' ! TODO add to params file(s) + call ncd_io(trim(tString), params_inst%mimics_cn_k, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) end subroutine readParams @@ -197,14 +361,21 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat ! ! !LOCAL VARIABLES !-- properties of each decomposing pool + real(r8) :: mimics_nue_into_mic + real(r8) :: mimics_p_scalar_p1 + real(r8) :: mimics_p_scalar_p2 + real(r8) :: mimics_fphys_r_p1 + real(r8) :: mimics_fphys_r_p2 + real(r8) :: mimics_fphys_k_p1 + real(r8) :: mimics_fphys_k_p2 + real(r8) :: mimics_desorp_p1 + real(r8) :: mimics_desorp_p2 real(r8) :: rf_l1m1 real(r8) :: rf_l1m2 real(r8) :: rf_l2m1 real(r8) :: rf_l2m2 real(r8) :: rf_s1m1 real(r8) :: rf_s1m2 - real(r8) :: rf_cwdl2 - real(r8), allocatable :: desorp(:,:) real(r8), allocatable :: fphys_m1(:,:) real(r8), allocatable :: fphys_m2(:,:) real(r8), allocatable :: p_scalar(:,:) @@ -219,6 +390,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat !----------------------------------------------------------------------- associate( & + rf_cwdl2 => CNParamsShareInst%rf_cwdl2 , & ! Input: [real(r8) ] respiration fraction in CWD to litter2 transition (frac) rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) nue_decomp_cascade => soilbiogeochem_state_inst%nue_decomp_cascade_col , & ! Output: [real(r8) (:) ] N use efficiency for a given transition (TODO) pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) @@ -247,68 +419,64 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat allocate(fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) allocate(p_scalar(bounds%begc:bounds%endc,1:nlevdecomp)) - ! TODO Prefix these parameters w params_inst% to move to params file(s). - ! First read TODOs in subr. readParams above. - p_scalar_p1 = 0.8_r8 - p_scalar_p2 = -3.0_r8 - desorp_p1 = 1.5e-5_r8 - desorp_p2 = -1.5_r8 - fphys_r_p1 = 0.3_r8 - fphys_r_p2 = 1.3_r8 - fphys_k_p1 = 0.2_r8 - fphys_k_p2 = 0.8_r8 - nue_into_mic = 0.85_r8 - !------- time-constant coefficients ---------- ! - ! set respiration fractions for fluxes between compartments - rf_l1m1 = 1.0_r8 - params_inst%mge(1) - rf_l2m1 = 1.0_r8 - params_inst%mge(2) - rf_s1m1 = 1.0_r8 - params_inst%mge(3) - rf_l1m2 = 1.0_r8 - params_inst%mge(4) - rf_l2m2 = 1.0_r8 - params_inst%mge(5) - rf_s1m2 = 1.0_r8 - params_inst%mge(6) + mimics_nue_into_mic = params_inst%mimics_nue_into_mic ! = 0.85_r8 + mimics_p_scalar_p1 = params_inst%mimics_p_scalar_p1 ! = 0.8_r8 + mimics_p_scalar_p2 = params_inst%mimics_p_scalar_p2 ! = -3.0_r8 + mimics_fphys_r_p1 = params_inst%mimics_fphys_r_p1 ! = 0.3_r8 + mimics_fphys_r_p2 = params_inst%mimics_fphys_r_p2 ! = 1.3_r8 + mimics_fphys_k_p1 = params_inst%mimics_fphys_k_p1 ! = 0.2_r8 + mimics_fphys_k_p2 = params_inst%mimics_fphys_k_p2 ! = 0.8_r8 + mimics_desorp_p1 = params_inst%mimics_desorp_p1 ! = 1.5e-5_r8 + mimics_desorp_p2 = params_inst%mimics_desorp_p2 ! = -1.5_r8 - rf_cwdl2 = params_inst%rf_cwdl2_bgc + ! set respiration fractions for fluxes between compartments + rf_l1m1 = 1.0_r8 - params_inst%mimics_mge(1) + rf_l2m1 = 1.0_r8 - params_inst%mimics_mge(2) + rf_s1m1 = 1.0_r8 - params_inst%mimics_mge(3) + rf_l1m2 = 1.0_r8 - params_inst%mimics_mge(4) + rf_l2m2 = 1.0_r8 - params_inst%mimics_mge(5) + rf_s1m2 = 1.0_r8 - params_inst%mimics_mge(6) ! vmod = "old" vmod * av AND kmod = ak / "old" kmod ! Table B1 Wieder et al. (2015) and MIMICS params file give diff ! ak and av values. I used the params file values. - vmod_l1_m1 = params_inst%vmod(1) - vmod_l2_m1 = params_inst%vmod(2) - vmod_s1_m1 = params_inst%vmod(3) - vmod_l1_m2 = params_inst%vmod(4) - vmod_l2_m2 = params_inst%vmod(5) - vmod_s1_m2 = params_inst%vmod(6) - kmod_l1_m1 = params_inst%kmod(1) - kmod_l2_m1 = params_inst%kmod(2) - kmod_s1_m1 = params_inst%kmod(3) - kmod_l1_m2 = params_inst%kmod(4) - kmod_l2_m2 = params_inst%kmod(5) - kmod_s1_m2 = params_inst%kmod(6) - vslope_l1_m1 = params_inst%vslope(1) - vslope_l2_m1 = params_inst%vslope(2) - vslope_s1_m1 = params_inst%vslope(3) - vslope_l1_m2 = params_inst%vslope(4) - vslope_l2_m2 = params_inst%vslope(5) - vslope_s1_m2 = params_inst%vslope(6) - kslope_l1_m1 = params_inst%kslope(1) - kslope_l2_m1 = params_inst%kslope(2) - kslope_s1_m1 = params_inst%kslope(3) - kslope_l1_m2 = params_inst%kslope(4) - kslope_l2_m2 = params_inst%kslope(5) - kslope_s1_m2 = params_inst%kslope(6) - vint_l1_m1 = params_inst%vint(1) - vint_l2_m1 = params_inst%vint(2) - vint_s1_m1 = params_inst%vint(3) - vint_l1_m2 = params_inst%vint(4) - vint_l2_m2 = params_inst%vint(5) - vint_s1_m2 = params_inst%vint(6) - kint_l1_m1 = params_inst%kint(1) - kint_l2_m1 = params_inst%kint(2) - kint_s1_m1 = params_inst%kint(3) - kint_l1_m2 = params_inst%kint(4) - kint_l2_m2 = params_inst%kint(5) - kint_s1_m2 = params_inst%kint(6) + vmod_l1_m1 = params_inst%mimics_vmod(1) + vmod_l2_m1 = params_inst%mimics_vmod(2) + vmod_s1_m1 = params_inst%mimics_vmod(3) + vmod_l1_m2 = params_inst%mimics_vmod(4) + vmod_l2_m2 = params_inst%mimics_vmod(5) + vmod_s1_m2 = params_inst%mimics_vmod(6) + kmod_l1_m1 = params_inst%mimics_kmod(1) + kmod_l2_m1 = params_inst%mimics_kmod(2) + kmod_s1_m1 = params_inst%mimics_kmod(3) + kmod_l1_m2 = params_inst%mimics_kmod(4) + kmod_l2_m2 = params_inst%mimics_kmod(5) + kmod_s1_m2 = params_inst%mimics_kmod(6) + vslope_l1_m1 = params_inst%mimics_vslope(1) + vslope_l2_m1 = params_inst%mimics_vslope(2) + vslope_s1_m1 = params_inst%mimics_vslope(3) + vslope_l1_m2 = params_inst%mimics_vslope(4) + vslope_l2_m2 = params_inst%mimics_vslope(5) + vslope_s1_m2 = params_inst%mimics_vslope(6) + kslope_l1_m1 = params_inst%mimics_kslope(1) + kslope_l2_m1 = params_inst%mimics_kslope(2) + kslope_s1_m1 = params_inst%mimics_kslope(3) + kslope_l1_m2 = params_inst%mimics_kslope(4) + kslope_l2_m2 = params_inst%mimics_kslope(5) + kslope_s1_m2 = params_inst%mimics_kslope(6) + vint_l1_m1 = params_inst%mimics_vint(1) + vint_l2_m1 = params_inst%mimics_vint(2) + vint_s1_m1 = params_inst%mimics_vint(3) + vint_l1_m2 = params_inst%mimics_vint(4) + vint_l2_m2 = params_inst%mimics_vint(5) + vint_s1_m2 = params_inst%mimics_vint(6) + kint_l1_m1 = params_inst%mimics_kint(1) + kint_l2_m1 = params_inst%mimics_kint(2) + kint_s1_m1 = params_inst%mimics_kint(3) + kint_l1_m2 = params_inst%mimics_kint(4) + kint_l2_m2 = params_inst%mimics_kint(5) + kint_s1_m2 = params_inst%mimics_kint(6) ! some of these are dependent on the soil texture properties ! One-time initializations here. @@ -316,13 +484,15 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat do c = bounds%begc, bounds%endc do j = 1, nlevdecomp - desorp(c,j) = desorp_p1 * exp(desorp_p2 * cellclay(c,j)) - fphys_m1(c,j) = min(1.0_r8, max(0.0_r8, fphys_r_p1 * & - exp(fphys_r_p2 * cellclay(c,j)))) - fphys_m2(c,j) = min(1.0_r8, max(0.0_r8, fphys_k_p1 * & - exp(fphys_k_p2 * cellclay(c,j)))) - p_scalar(c,j) = 1.0_r8 / (p_scalar_p1 * & - exp(p_scalar_p2 * & + desorp(c,j) = mimics_desorp_p1 * & + exp(mimics_desorp_p2 * cellclay(c,j)) + fphys_m1(c,j) = min(1.0_r8, max(0.0_r8, mimics_fphys_r_p1 * & + exp(mimics_fphys_r_p2 * cellclay(c,j)))) + fphys_m2(c,j) = min(1.0_r8, max(0.0_r8, mimics_fphys_k_p1 * & + exp(mimics_fphys_k_p2 * cellclay(c,j)))) + ! TODO slevis: Oups, where was p_scalar supposed to be used? + p_scalar(c,j) = 1.0_r8 / (mimics_p_scalar_p1 * & + exp(mimics_p_scalar_p2 * & sqrt(cellclay(c,j)))) end do end do @@ -478,7 +648,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat spinup_factor(i_str_lit) = 1._r8 !CWD if (.not. use_fates) then - spinup_factor(i_cwd) = max(1._r8, (speedup_fac * params_inst%tau_cwd_bgc / 2._r8 )) + spinup_factor(i_cwd) = max(1._r8, (speedup_fac * CNParamsShareInst%tau_cwd * 0.5_r8 )) end if !som1,2,3 spinup_factor(i_avl_som) = 1._r8 @@ -499,7 +669,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = rf_l1m1 cascade_donor_pool(i_l1m1) = i_met_lit cascade_receiver_pool(i_l1m1) = i_cop_mic - nue_decomp_cascade(i_l1m1) = nue_into_mic + nue_decomp_cascade(i_l1m1) = mimics_nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = 0.5_r8 i_l1m2 = 2 @@ -507,7 +677,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = rf_l1m2 cascade_donor_pool(i_l1m2) = i_met_lit cascade_receiver_pool(i_l1m2) = i_oli_mic - nue_decomp_cascade(i_l1m2) = nue_into_mic + nue_decomp_cascade(i_l1m2) = mimics_nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = 0.5_r8 i_l2m1 = 3 @@ -515,7 +685,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1) = rf_l2m1 cascade_donor_pool(i_l2m1) = i_str_lit cascade_receiver_pool(i_l2m1) = i_cop_mic - nue_decomp_cascade(i_l2m1) = nue_into_mic + nue_decomp_cascade(i_l2m1) = mimics_nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1)= 0.5_r8 i_l2m2 = 4 @@ -523,7 +693,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2) = rf_l2m2 cascade_donor_pool(i_l2m2) = i_str_lit cascade_receiver_pool(i_l2m2) = i_oli_mic - nue_decomp_cascade(i_l2m2) = nue_into_mic + nue_decomp_cascade(i_l2m2) = mimics_nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2)= 0.5_r8 i_s1m1 = 5 @@ -531,7 +701,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = rf_s1m1 cascade_donor_pool(i_s1m1) = i_avl_som cascade_receiver_pool(i_s1m1) = i_cop_mic - nue_decomp_cascade(i_s1m1) = nue_into_mic + nue_decomp_cascade(i_s1m1) = mimics_nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = 0.5_r8 i_s1m2 = 6 @@ -539,7 +709,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m2) = rf_s1m2 cascade_donor_pool(i_s1m2) = i_avl_som cascade_receiver_pool(i_s1m2) = i_oli_mic - nue_decomp_cascade(i_s1m2) = nue_into_mic + nue_decomp_cascade(i_s1m2) = mimics_nue_into_mic pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m2) = 0.5_r8 i_s2s1 = 7 @@ -616,13 +786,13 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = 1.0_r8 end if - deallocate(params_inst%mge) - deallocate(params_inst%vmod) - deallocate(params_inst%vslope) - deallocate(params_inst%vint) - deallocate(params_inst%kmod) - deallocate(params_inst%kslope) - deallocate(params_inst%kint) + deallocate(params_inst%mimics_mge) + deallocate(params_inst%mimics_vmod) + deallocate(params_inst%mimics_vint) + deallocate(params_inst%mimics_vslope) + deallocate(params_inst%mimics_kmod) + deallocate(params_inst%mimics_kint) + deallocate(params_inst%mimics_kslope) deallocate(params_inst%initial_Cstocks) end associate @@ -632,7 +802,7 @@ end subroutine init_decompcascade_mimics !----------------------------------------------------------------------- subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, cnveg_carbonflux_inst, & - ch4_inst, soilbiogeochem_carbonflux_inst) + ch4_inst, soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) ! ! !DESCRIPTION: ! Calculate rates and decomposition pathways for the MIMICS @@ -652,32 +822,104 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst type(ch4_type) , intent(in) :: ch4_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst + type(soilbiogeochem_carbonstate_type), intent(in) :: soilbiogeochem_carbonstate_inst ! ! !LOCAL VARIABLES: real(r8):: frw(bounds%begc:bounds%endc) ! rooting fraction weight real(r8), allocatable:: fr(:,:) ! column-level rooting fraction by soil depth real(r8):: psi ! temporary soilpsi for water scalar real(r8):: k_frag ! fragmentation rate constant CWD (1/sec) + real(r8):: fmet + real(r8):: favl + real(r8):: fchem_m1 + real(r8):: fchem_m2 + real(r8):: desorption real(r8):: vmax_l1_m1 ! real(r8):: vmax_l2_m1 ! real(r8):: vmax_s1_m1 ! real(r8):: vmax_l1_m2 ! real(r8):: vmax_l2_m2 ! real(r8):: vmax_s1_m2 ! + real(r8):: vmod_l1_m1 ! + real(r8):: vmod_l2_m1 ! + real(r8):: vmod_s1_m1 ! + real(r8):: vmod_l1_m2 ! + real(r8):: vmod_l2_m2 ! + real(r8):: vmod_s1_m2 ! + real(r8):: vint_l1_m1 ! + real(r8):: vint_l2_m1 ! + real(r8):: vint_s1_m1 ! + real(r8):: vint_l1_m2 ! + real(r8):: vint_l2_m2 ! + real(r8):: vint_s1_m2 ! + real(r8):: vslope_l1_m1 ! + real(r8):: vslope_l2_m1 ! + real(r8):: vslope_s1_m1 ! + real(r8):: vslope_l1_m2 ! + real(r8):: vslope_l2_m2 ! + real(r8):: vslope_s1_m2 ! real(r8):: km_l1_m1 ! real(r8):: km_l2_m1 ! real(r8):: km_s1_m1 ! real(r8):: km_l1_m2 ! real(r8):: km_l2_m2 ! real(r8):: km_s1_m2 ! + real(r8):: kmod_l1_m1 ! + real(r8):: kmod_l2_m1 ! + real(r8):: kmod_s1_m1 ! + real(r8):: kmod_l1_m2 ! + real(r8):: kmod_l2_m2 ! + real(r8):: kmod_s1_m2 ! + real(r8):: kint_l1_m1 ! + real(r8):: kint_l2_m1 ! + real(r8):: kint_s1_m1 ! + real(r8):: kint_l1_m2 ! + real(r8):: kint_l2_m2 ! + real(r8):: kint_s1_m2 ! + real(r8):: kslope_l1_m1 ! + real(r8):: kslope_l2_m1 ! + real(r8):: kslope_s1_m1 ! + real(r8):: kslope_l1_m2 ! + real(r8):: kslope_l2_m2 ! + real(r8):: kslope_s1_m2 ! real(r8):: tau_m1 ! real(r8):: tau_m2 ! - real(r8):: decomp_depth_efolding ! (meters) e-folding depth for reduction in decomposition [ + real(r8):: tau_mod + real(r8):: m1_conc ! + real(r8):: m2_conc ! + real(r8):: term_1 ! + real(r8):: term_2 ! + real(r8):: t_soi_degC +! real(r8):: decomp_depth_efolding ! (meters) e-folding depth for reduction in decomposition [ integer :: c, fc, j, k, l real(r8):: days_per_year ! days per year real(r8):: depth_scalar(bounds%begc:bounds%endc,1:nlevdecomp) real(r8):: w_d_o_scalars ! product of w_scalar * depth_scalar * o_scalar real(r8):: mino2lim !minimum anaerobic decomposition rate + real(r8):: mimics_fmet_p1 + real(r8):: mimics_fmet_p2 + real(r8):: mimics_fmet_p3 + real(r8):: mimics_fmet_p4 + real(r8):: mimics_fchem_r_p1 + real(r8):: mimics_fchem_r_p2 + real(r8):: mimics_fchem_k_p1 + real(r8):: mimics_fchem_k_p2 + real(r8):: mimics_tau_mod_min + real(r8):: mimics_tau_mod_max + real(r8):: mimics_tau_mod_factor + real(r8):: mimics_tau_r_p1 + real(r8):: mimics_tau_r_p2 + real(r8):: mimics_tau_k_p1 + real(r8):: mimics_tau_k_p2 + real(r8):: mimics_ko_r + real(r8):: mimics_ko_k + real(r8):: mimics_densdep + real(r8):: mimics_desorpQ10 + real(r8):: mimics_t_soi_ref + real(r8):: mimics_cn_mod_num + real(r8):: mimics_cn_r + real(r8):: mimics_cn_k + real(r8):: spinup_geogterm_l1(bounds%begc:bounds%endc) ! geographically-varying spinup term for l1 real(r8):: spinup_geogterm_l2(bounds%begc:bounds%endc) ! geographically-varying spinup term for l2 real(r8):: spinup_geogterm_cwd(bounds%begc:bounds%endc) ! geographically-varying spinup term for cwd @@ -690,17 +932,18 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & !----------------------------------------------------------------------- associate( & - annsum_npp_col => cnveg_carbonflux_inst%annsum_npp_col , & ! Input: [real(r8) (:) ] annual sum of NPP at the column level (gC/m2/yr) ligninNratioAvg => cnveg_carbonflux_inst%ligninNratioAvg_col , & ! Input: [real(r8) (:) ] column-level lignin to nitrogen ratio + annsum_npp_col => cnveg_carbonflux_inst%annsum_npp_col , & ! Input: [real(r8) (:) ] annual sum of NPP at the column level (gC/m2/yr) - minpsi => params_inst%minpsi_bgc , & ! Input: [real(r8) ] minimum soil suction (mm) - maxpsi => params_inst%maxpsi_bgc , & ! Input: [real(r8) ] maximum soil suction (mm) + minpsi => CNParamsShareInst%minpsi , & ! Input: [real(r8) ] minimum soil suction (mm) + maxpsi => CNParamsShareInst%maxpsi , & ! Input: [real(r8) ] maximum soil suction (mm) soilpsi => soilstate_inst%soilpsi_col , & ! Input: [real(r8) (:,:) ] soil water potential in each soil layer (MPa) t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) o2stress_sat => ch4_inst%o2stress_sat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) o2stress_unsat => ch4_inst%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area + decomp_cpools_vr => soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) C pools w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia cn_col => soilbiogeochem_carbonflux_inst%cn_col , & ! Output: [real(r8) (:,:) ] C:N ratio @@ -712,11 +955,11 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & days_per_year = get_days_per_year() - ! Set "decomp_depth_efolding" parameter - decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding +! ! Set "decomp_depth_efolding" parameter +! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding ! translate to per-second time constant - k_frag = 1._r8 / (secspday * days_per_year * params_inst%tau_cwd_bgc) + k_frag = 1._r8 / (secspday * days_per_year * CNParamsShareInst%tau_cwd) ! calc ref rate if ( spinup_state >= 1 ) then @@ -920,31 +1163,29 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do - ! TODO Move to the params files after - ! ... reading TODOs in subr. readParams (above) - fmet_p1 = 0.85_r8 - fmet_p2 = 0.85_r8 - fmet_p3 = 0.013_r8 - fmet_p4 = 40.0_r8 - fchem_r_p1 = 0.1_r8 - fchem_r_p2 = -3.0_r8 - fchem_k_p1 = 0.3_r8 - fchem_k_p2 = -3.0_r8 - tau_mod_factor = 0.01_r8 ! was tau_mod_denom = 100 - tau_mod_min = 0.8_r8 - tau_mod_max = 1.2_r8 - tau_r_p1 = 5.2e-4_r8 - tau_r_p2 = 0.3_r8 ! or 0.4? - tau_k_p1 = 2.4e-4_r8 - tau_k_p2 = 0.1_r8 - ko_r = 4.0_r8 - ko_k = 4.0_r8 - densdep = 1.0_r8 - desorpQ10 = 1.0_r8 - t_soi_ref = 25.0_r8 ! deg C - cn_mod_num = 1.0_r8 ! TODO slevis: I don't see values in the testbed - cn_r = 1.0_r8 ! ... or in the testbed's params file - cn_k = 1.0_r8 ! ... for these three + mimics_fmet_p1 = params_inst%mimics_fmet_p1 ! = 0.85_r8 + mimics_fmet_p2 = params_inst%mimics_fmet_p2 ! = 0.85_r8 + mimics_fmet_p3 = params_inst%mimics_fmet_p3 ! = 0.013_r8 + mimics_fmet_p4 = params_inst%mimics_fmet_p4 ! = 40.0_r8 + mimics_fchem_r_p1 = params_inst%mimics_fchem_r_p1 ! = 0.1_r8 + mimics_fchem_r_p2 = params_inst%mimics_fchem_r_p2 ! = -3.0_r8 + mimics_fchem_k_p1 = params_inst%mimics_fchem_k_p1 ! = 0.3_r8 + mimics_fchem_k_p2 = params_inst%mimics_fchem_k_p2 ! = -3.0_r8 + mimics_tau_mod_min = params_inst%mimics_tau_mod_min ! = 0.8_r8 + mimics_tau_mod_max = params_inst%mimics_tau_mod_max ! = 1.2_r8 + mimics_tau_mod_factor = params_inst%mimics_tau_mod_factor ! = 0.01_r8 ! was tau_mod_denom = 100 + mimics_tau_r_p1 = params_inst%mimics_tau_r_p1 ! = 5.2e-4_r8 + mimics_tau_r_p2 = params_inst%mimics_tau_r_p2 ! = 0.3_r8 ! or 0.4? + mimics_tau_k_p1 = params_inst%mimics_tau_k_p1 ! = 2.4e-4_r8 + mimics_tau_k_p2 = params_inst%mimics_tau_k_p2 ! = 0.1_r8 + mimics_ko_r = params_inst%mimics_ko_r ! = 4.0_r8 + mimics_ko_k = params_inst%mimics_ko_k ! = 4.0_r8 + mimics_densdep = params_inst%mimics_densdep ! = 1.0_r8 + mimics_desorpQ10 = params_inst%mimics_desorpQ10 ! = 1.0_r8 + mimics_t_soi_ref = params_inst%mimics_t_soi_ref ! = 25.0_r8 ! deg C + mimics_cn_mod_num = params_inst%mimics_cn_mod_num ! = 1.0_r8 ! TODO slevis: I don't see values in the testbed or + mimics_cn_r = params_inst%mimics_cn_r ! = 1.0_r8 ! ... in the testbed's + mimics_cn_k = params_inst%mimics_cn_k ! = 1.0_r8 ! ... params file for these 3 ! calculate rates for all litter and som pools ! TODO Ok that I reversed order of do-loops? @@ -958,29 +1199,33 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! TODO Check for high-freq variations in ligninNratioAvg. To avoid, ! replace pool_to_litter terms with ann or other long term mean ! in CNVegCarbonFluxType. - fmet = fmet_p1 * (fmet_p2 - fmet_p3 * min(fmet_p4, ligninNratioAvg(c))) - tau_mod = min(tau_mod_max, max(tau_mod_min, & - sqrt(tau_mod_factor * & - annsum_npp_col(c)))) + fmet = mimics_fmet_p1 * (mimics_fmet_p2 - mimics_fmet_p3 * min(mimics_fmet_p4, ligninNratioAvg(c))) + tau_mod = min(mimics_tau_mod_max, max(mimics_tau_mod_min, & + sqrt(mimics_tau_mod_factor * & + annsum_npp_col(c)))) ! tau_m1 is tauR and tau_m2 is tauK in Wieder et al. 2015 ! tau ends up in units of per hour but is expected ! in units of per second, so convert here; alternatively ! place the conversion once in w_d_o_scalars - tau_m1 = tau_r_p1 * exp(tau_r_p2 * fmet) * tau_mod * secsphr - tau_m2 = tau_k_p1 * exp(tau_k_p2 * fmet) * tau_mod * secsphr + tau_m1 = mimics_tau_r_p1 * exp(mimics_tau_r_p2 * fmet) * tau_mod * & + secsphr + tau_m2 = mimics_tau_k_p1 * exp(mimics_tau_k_p2 * fmet) * tau_mod * & + secsphr ! These two get used in SoilBiogeochemPotentialMod.F90 ! cn(c,i_cop_mic), cn(c,i_oli_mic) are CN_r, CN_k in the testbed code ! cn_r, cn_k are CNr, CNk in the testbed code ! https://github.com/wwieder/biogeochem_testbed_1.1/blob/Testbed_CN/SOURCE_CODE/mimics_cycle_CN.f90#L1613 - cn_col(c,i_cop_mic) = cn_r * sqrt(cn_mod_num / fmet) - cn_col(c,i_oli_mic) = cn_k * sqrt(cn_mod_num / fmet) + cn_col(c,i_cop_mic) = mimics_cn_r * sqrt(mimics_cn_mod_num / fmet) + cn_col(c,i_oli_mic) = mimics_cn_k * sqrt(mimics_cn_mod_num / fmet) ! Used in the update of certain pathfrac terms that vary with time ! in the next loop - fchem_m1 = min(1.0_r8, max(0.0_r8, fchem_r_p1 * exp(fchem_r_p2 * fmet))) - fchem_m2 = min(1.0_r8, max(0.0_r8, fchem_k_p1 * exp(fchem_k_p2 * fmet))) + fchem_m1 = min(1.0_r8, max(0.0_r8, mimics_fchem_r_p1 * & + exp(mimics_fchem_r_p2 * fmet))) + fchem_m2 = min(1.0_r8, max(0.0_r8, mimics_fchem_k_p1 * & + exp(mimics_fchem_k_p2 * fmet))) do j = 1,nlevdecomp ! vmax ends up in units of per hour but is expected @@ -1020,8 +1265,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Q10 = 1.1 w/ reference temperature of 25C. ! Expected in units of per second, so convert; alternatively ! place the conversion once in w_d_o_scalars - desorption = desorp(c,j) * desorpQ10 * secsphr * & - exp((t_soi_degC - t_soi_ref) / 10.0_r8) + desorption = desorp(c,j) * mimics_desorpQ10 * secsphr * & + exp((t_soi_degC - mimics_t_soi_ref) / 10.0_r8) ! Microbial concentration with necessary unit conversions ! mgC/cm3 = gC/m3 * (1e3 mg/g) / (1e6 cm3/m3) @@ -1056,19 +1301,19 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & decomp_k(c,j,i_phys_som) = desorption * depth_scalar(c,j) - term_1 = vmax_l2_m1 * m1_conc / (ko_r * km_l2_m1 + m1_conc) - term_2 = vmax_l2_m2 * m2_conc / (ko_k * km_l2_m2 + m2_conc) + term_1 = vmax_l2_m1 * m1_conc / (mimics_ko_r * km_l2_m1 + m1_conc) + term_2 = vmax_l2_m2 * m2_conc / (mimics_ko_k * km_l2_m2 + m2_conc) ! The right hand side is OXIDAT in the testbed (line 1145) decomp_k(c,j,i_chem_som) = (term_1 + term_2) * w_d_o_scalars decomp_k(c,j,i_cop_mic) = tau_m1 * & - m1_conc**(densdep - 1.0_r8) * w_d_o_scalars + m1_conc**(mimics_densdep - 1.0_r8) * w_d_o_scalars favl = min(1.0_r8, max(0.0_r8, 1.0_r8 - fphys_m1(c,j) - fchem_m1)) pathfrac_decomp_cascade(c,j,i_m1s1) = favl pathfrac_decomp_cascade(c,j,i_m1s2) = fchem_m1 decomp_k(c,j,i_oli_mic) = tau_m2 * & - m2_conc**(densdep - 1.0_r8) * w_d_o_scalars + m2_conc**(mimics_densdep - 1.0_r8) * w_d_o_scalars favl = min(1.0_r8, max(0.0_r8, 1.0_r8 - fphys_m2(c,j) - fchem_m2)) pathfrac_decomp_cascade(c,j,i_m2s1) = favl pathfrac_decomp_cascade(c,j,i_m2s2) = fchem_m2 From fefccc9c6bcb01307dda499afd55fa5d5fcf1201 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 17 Aug 2021 18:48:34 -0600 Subject: [PATCH 35/69] Code corrections from attempting to build (part 4) Not done, though I think I see light at the end of the tunnel :-) --- src/biogeochem/EDBGCDynMod.F90 | 3 +- .../SoilBiogeochemDecompCascadeBGCMod.F90 | 2 +- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 176 +++++++++--------- 3 files changed, 88 insertions(+), 93 deletions(-) diff --git a/src/biogeochem/EDBGCDynMod.F90 b/src/biogeochem/EDBGCDynMod.F90 index 1866ea8893..93b8d50cc4 100644 --- a/src/biogeochem/EDBGCDynMod.F90 +++ b/src/biogeochem/EDBGCDynMod.F90 @@ -74,7 +74,6 @@ subroutine EDBGCDyn(bounds, & use CNGapMortalityMod , only: CNGapMortality use SoilBiogeochemDecompCascadeBGCMod , only: decomp_rate_constants_bgc use SoilBiogeochemDecompCascadeCNMod , only: decomp_rate_constants_cn - use SoilBiogeochemCompetitionMod , only: SoilBiogeochemCompetition use SoilBiogeochemDecompMod , only: SoilBiogeochemDecomp use SoilBiogeochemLittVertTranspMod , only: SoilBiogeochemLittVertTransp use SoilBiogeochemPotentialMod , only: SoilBiogeochemPotential @@ -115,6 +114,7 @@ subroutine EDBGCDyn(bounds, & real(r8):: cn_decomp_pools(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) real(r8):: p_decomp_cpool_loss(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential C loss from one pool to another real(r8):: pmnf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential mineral N flux, from one pool to another + real(r8):: p_decomp_cn_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! C:N ratio of the flux gained by the receiver pool real(r8):: arepr(bounds%begp:bounds%endp) ! reproduction allocation coefficient (only used for crop_prog) real(r8):: aroot(bounds%begp:bounds%endp) ! root allocation coefficient (only used for crop_prog) integer :: begp,endp @@ -197,6 +197,7 @@ subroutine EDBGCDyn(bounds, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & + p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index 26e2ba15f0..844666026b 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -916,7 +916,7 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & end do end do pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = 1.0_r8 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1)= 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = f_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = f_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 6c35475d11..63193cbd60 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -43,11 +43,13 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! ! !PRIVATE DATA MEMBERS real(r8), allocatable :: desorp(:,:) + real(r8), allocatable :: fphys_m1(:,:) + real(r8), allocatable :: fphys_m2(:,:) integer, private :: i_phys_som ! index of physically protected Soil Organic Matter (SOM) integer, private :: i_chem_som ! index of chemically protected SOM integer, private :: i_avl_som ! index of available (aka active) SOM integer, private :: i_str_lit ! index of structural litter pool - integer, private :: i_l1m1 ! indices of pool transfers needed in whole module + integer, private :: i_l1m1 integer, private :: i_l1m2 integer, private :: i_l2m1 integer, private :: i_l2m2 @@ -57,6 +59,46 @@ module SoilBiogeochemDecompCascadeMIMICSMod integer, private :: i_m1s2 integer, private :: i_m2s1 integer, private :: i_m2s2 + integer, private :: i_s2s1 + integer, private :: i_s3s1 + integer, private :: i_m1s3 + integer, private :: i_m2s3 + real(r8) :: vint_l1_m1 ! + real(r8) :: vint_l2_m1 ! + real(r8) :: vint_s1_m1 ! + real(r8) :: vint_l1_m2 ! + real(r8) :: vint_l2_m2 ! + real(r8) :: vint_s1_m2 ! + real(r8) :: kint_l1_m1 ! + real(r8) :: kint_l2_m1 ! + real(r8) :: kint_s1_m1 ! + real(r8) :: kint_l1_m2 ! + real(r8) :: kint_l2_m2 ! + real(r8) :: kint_s1_m2 ! + real(r8) :: vmod_l1_m1 ! + real(r8) :: vmod_l2_m1 ! + real(r8) :: vmod_s1_m1 ! + real(r8) :: vmod_l1_m2 ! + real(r8) :: vmod_l2_m2 ! + real(r8) :: vmod_s1_m2 ! + real(r8) :: kmod_l1_m1 ! + real(r8) :: kmod_l2_m1 ! + real(r8) :: kmod_s1_m1 ! + real(r8) :: kmod_l1_m2 ! + real(r8) :: kmod_l2_m2 ! + real(r8) :: kmod_s1_m2 ! + real(r8) :: vslope_l1_m1 ! + real(r8) :: vslope_l2_m1 ! + real(r8) :: vslope_s1_m1 ! + real(r8) :: vslope_l1_m2 ! + real(r8) :: vslope_l2_m2 ! + real(r8) :: vslope_s1_m2 ! + real(r8) :: kslope_l1_m1 ! + real(r8) :: kslope_l2_m1 ! + real(r8) :: kslope_s1_m1 ! + real(r8) :: kslope_l1_m2 ! + real(r8) :: kslope_l2_m2 ! + real(r8) :: kslope_s1_m2 ! type, private :: params_type real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start @@ -68,38 +110,38 @@ module SoilBiogeochemDecompCascadeMIMICSMod real(r8), allocatable :: mimics_kmod(:) ! real(r8), allocatable :: mimics_kint(:) ! real(r8), allocatable :: mimics_kslope(:) ! - real(r8) :: mimics_nue_into_mic - real(r8) :: mimics_p_scalar_p1 - real(r8) :: mimics_p_scalar_p2 - real(r8) :: mimics_fphys_r_p1 - real(r8) :: mimics_fphys_r_p2 - real(r8) :: mimics_fphys_k_p1 - real(r8) :: mimics_fphys_k_p2 - real(r8) :: mimics_fchem_r_p1 - real(r8) :: mimics_fchem_r_p2 - real(r8) :: mimics_fchem_k_p1 - real(r8) :: mimics_fchem_k_p2 - real(r8) :: mimics_desorp_p1 - real(r8) :: mimics_desorp_p2 - real(r8) :: mimics_desorpQ10 - real(r8) :: mimics_densdep - real(r8) :: mimics_fmet_p1 - real(r8) :: mimics_fmet_p2 - real(r8) :: mimics_fmet_p3 - real(r8) :: mimics_fmet_p4 - real(r8) :: mimics_tau_mod_factor - real(r8) :: mimics_tau_mod_min - real(r8) :: mimics_tau_mod_max - real(r8) :: mimics_tau_r_p1 - real(r8) :: mimics_tau_r_p2 - real(r8) :: mimics_tau_k_p1 - real(r8) :: mimics_tau_k_p2 - real(r8) :: mimics_ko_r - real(r8) :: mimics_ko_k - real(r8) :: mimics_cn_r - real(r8) :: mimics_cn_k - real(r8) :: mimics_cn_mod_num - real(r8) :: mimics_t_soi_ref + real(r8), allocatable :: mimics_nue_into_mic + real(r8), allocatable :: mimics_p_scalar_p1 + real(r8), allocatable :: mimics_p_scalar_p2 + real(r8), allocatable :: mimics_fphys_r_p1 + real(r8), allocatable :: mimics_fphys_r_p2 + real(r8), allocatable :: mimics_fphys_k_p1 + real(r8), allocatable :: mimics_fphys_k_p2 + real(r8), allocatable :: mimics_fchem_r_p1 + real(r8), allocatable :: mimics_fchem_r_p2 + real(r8), allocatable :: mimics_fchem_k_p1 + real(r8), allocatable :: mimics_fchem_k_p2 + real(r8), allocatable :: mimics_desorp_p1 + real(r8), allocatable :: mimics_desorp_p2 + real(r8), allocatable :: mimics_desorpQ10 + real(r8), allocatable :: mimics_densdep + real(r8), allocatable :: mimics_fmet_p1 + real(r8), allocatable :: mimics_fmet_p2 + real(r8), allocatable :: mimics_fmet_p3 + real(r8), allocatable :: mimics_fmet_p4 + real(r8), allocatable :: mimics_tau_mod_factor + real(r8), allocatable :: mimics_tau_mod_min + real(r8), allocatable :: mimics_tau_mod_max + real(r8), allocatable :: mimics_tau_r_p1 + real(r8), allocatable :: mimics_tau_r_p2 + real(r8), allocatable :: mimics_tau_k_p1 + real(r8), allocatable :: mimics_tau_k_p2 + real(r8), allocatable :: mimics_ko_r + real(r8), allocatable :: mimics_ko_k + real(r8), allocatable :: mimics_cn_r + real(r8), allocatable :: mimics_cn_k + real(r8), allocatable :: mimics_cn_mod_num + real(r8), allocatable :: mimics_t_soi_ref end type params_type ! type(params_type), private :: params_inst @@ -376,14 +418,8 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat real(r8) :: rf_l2m2 real(r8) :: rf_s1m1 real(r8) :: rf_s1m2 - real(r8), allocatable :: fphys_m1(:,:) - real(r8), allocatable :: fphys_m2(:,:) real(r8), allocatable :: p_scalar(:,:) - integer :: i_s2s1 ! indices of pool transfers needed in this subr. only - integer :: i_s3s1 - integer :: i_m1s3 - integer :: i_m2s3 real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. integer :: c, j ! indices @@ -393,7 +429,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat rf_cwdl2 => CNParamsShareInst%rf_cwdl2 , & ! Input: [real(r8) ] respiration fraction in CWD to litter2 transition (frac) rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) nue_decomp_cascade => soilbiogeochem_state_inst%nue_decomp_cascade_col , & ! Output: [real(r8) (:) ] N use efficiency for a given transition (TODO) - pathfrac_decomp_cascade => soilbiogeochem_state_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) cellclay => soilstate_inst%cellclay_col , & ! Input: [real(r8) (:,:) ] column 3D clay @@ -670,7 +705,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_l1m1) = i_met_lit cascade_receiver_pool(i_l1m1) = i_cop_mic nue_decomp_cascade(i_l1m1) = mimics_nue_into_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m1) = 0.5_r8 i_l1m2 = 2 decomp_cascade_con%cascade_step_name(i_l1m2) = 'L1M2' @@ -678,7 +712,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_l1m2) = i_met_lit cascade_receiver_pool(i_l1m2) = i_oli_mic nue_decomp_cascade(i_l1m2) = mimics_nue_into_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1m2) = 0.5_r8 i_l2m1 = 3 decomp_cascade_con%cascade_step_name(i_l2m1) = 'L2M1' @@ -686,7 +719,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_l2m1) = i_str_lit cascade_receiver_pool(i_l2m1) = i_cop_mic nue_decomp_cascade(i_l2m1) = mimics_nue_into_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m1)= 0.5_r8 i_l2m2 = 4 decomp_cascade_con%cascade_step_name(i_l2m2) = 'L2M2' @@ -694,7 +726,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_l2m2) = i_str_lit cascade_receiver_pool(i_l2m2) = i_oli_mic nue_decomp_cascade(i_l2m2) = mimics_nue_into_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2m2)= 0.5_r8 i_s1m1 = 5 decomp_cascade_con%cascade_step_name(i_s1m1) = 'S1M1' @@ -702,7 +733,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_s1m1) = i_avl_som cascade_receiver_pool(i_s1m1) = i_cop_mic nue_decomp_cascade(i_s1m1) = mimics_nue_into_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m1) = 0.5_r8 i_s1m2 = 6 decomp_cascade_con%cascade_step_name(i_s1m2) = 'S1M2' @@ -710,7 +740,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_s1m2) = i_avl_som cascade_receiver_pool(i_s1m2) = i_oli_mic nue_decomp_cascade(i_s1m2) = mimics_nue_into_mic - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1m2) = 0.5_r8 i_s2s1 = 7 decomp_cascade_con%cascade_step_name(i_s2s1) = 'S2S1' @@ -718,7 +747,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_s2s1) = i_chem_som cascade_receiver_pool(i_s2s1) = i_avl_som nue_decomp_cascade(i_s2s1) = 1.0_r8 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = 1.0_r8 i_s3s1 = 8 decomp_cascade_con%cascade_step_name(i_s3s1) = 'S3S1' @@ -726,7 +754,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_s3s1) = i_phys_som cascade_receiver_pool(i_s3s1) = i_avl_som nue_decomp_cascade(i_s3s1) = 1.0_r8 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 i_m1s1 = 9 decomp_cascade_con%cascade_step_name(i_m1s1) = 'M1S1' @@ -734,7 +761,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_m1s1) = i_cop_mic cascade_receiver_pool(i_m1s1) = i_avl_som nue_decomp_cascade(i_m1s1) = 1.0_r8 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s1) = 0.5_r8 * (1.0_r8 - fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp)) i_m1s2 = 10 decomp_cascade_con%cascade_step_name(i_m1s2) = 'M1S2' @@ -742,7 +768,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_m1s2) = i_cop_mic cascade_receiver_pool(i_m1s2) = i_chem_som nue_decomp_cascade(i_m1s2) = 1.0_r8 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s2) = 0.5_r8 * (1.0_r8 - fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp)) i_m1s3 = 11 decomp_cascade_con%cascade_step_name(i_m1s3) = 'M1S3' @@ -750,7 +775,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_m1s3) = i_cop_mic cascade_receiver_pool(i_m1s3) = i_phys_som nue_decomp_cascade(i_m1s3) = 1.0_r8 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp) i_m2s1 = 12 decomp_cascade_con%cascade_step_name(i_m2s1) = 'M2S1' @@ -758,7 +782,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_m2s1) = i_oli_mic cascade_receiver_pool(i_m2s1) = i_avl_som nue_decomp_cascade(i_m2s1) = 1.0_r8 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s1) = 0.5_r8 * (1.0_r8 - fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) i_m2s2 = 13 decomp_cascade_con%cascade_step_name(i_m2s2) = 'M2S2' @@ -766,7 +789,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_m2s2) = i_oli_mic cascade_receiver_pool(i_m2s2) = i_chem_som nue_decomp_cascade(i_m2s2) = 1.0_r8 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s2) = 0.5_r8 * (1.0_r8 - fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp)) i_m2s3 = 14 decomp_cascade_con%cascade_step_name(i_m2s3) = 'M2S3' @@ -774,7 +796,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_m2s3) = i_oli_mic cascade_receiver_pool(i_m2s3) = i_phys_som nue_decomp_cascade(i_m2s3) = 1.0_r8 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp) if (.not. use_fates) then i_cwdl2 = 15 @@ -783,7 +804,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat cascade_donor_pool(i_cwdl2) = i_cwd cascade_receiver_pool(i_cwdl2) = i_str_lit nue_decomp_cascade(i_cwdl2) = 1.0_r8 - pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = 1.0_r8 end if deallocate(params_inst%mimics_mge) @@ -840,48 +860,12 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & real(r8):: vmax_l1_m2 ! real(r8):: vmax_l2_m2 ! real(r8):: vmax_s1_m2 ! - real(r8):: vmod_l1_m1 ! - real(r8):: vmod_l2_m1 ! - real(r8):: vmod_s1_m1 ! - real(r8):: vmod_l1_m2 ! - real(r8):: vmod_l2_m2 ! - real(r8):: vmod_s1_m2 ! - real(r8):: vint_l1_m1 ! - real(r8):: vint_l2_m1 ! - real(r8):: vint_s1_m1 ! - real(r8):: vint_l1_m2 ! - real(r8):: vint_l2_m2 ! - real(r8):: vint_s1_m2 ! - real(r8):: vslope_l1_m1 ! - real(r8):: vslope_l2_m1 ! - real(r8):: vslope_s1_m1 ! - real(r8):: vslope_l1_m2 ! - real(r8):: vslope_l2_m2 ! - real(r8):: vslope_s1_m2 ! real(r8):: km_l1_m1 ! real(r8):: km_l2_m1 ! real(r8):: km_s1_m1 ! real(r8):: km_l1_m2 ! real(r8):: km_l2_m2 ! real(r8):: km_s1_m2 ! - real(r8):: kmod_l1_m1 ! - real(r8):: kmod_l2_m1 ! - real(r8):: kmod_s1_m1 ! - real(r8):: kmod_l1_m2 ! - real(r8):: kmod_l2_m2 ! - real(r8):: kmod_s1_m2 ! - real(r8):: kint_l1_m1 ! - real(r8):: kint_l2_m1 ! - real(r8):: kint_s1_m1 ! - real(r8):: kint_l1_m2 ! - real(r8):: kint_l2_m2 ! - real(r8):: kint_s1_m2 ! - real(r8):: kslope_l1_m1 ! - real(r8):: kslope_l2_m1 ! - real(r8):: kslope_s1_m1 ! - real(r8):: kslope_l1_m2 ! - real(r8):: kslope_l2_m2 ! - real(r8):: kslope_s1_m2 ! real(r8):: tau_m1 ! real(r8):: tau_m2 ! real(r8):: tau_mod @@ -944,6 +928,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area decomp_cpools_vr => soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) C pools + pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C leaving a given pool passes through a given transition (frac) w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia cn_col => soilbiogeochem_carbonflux_inst%cn_col , & ! Output: [real(r8) (:,:) ] C:N ratio @@ -1327,6 +1312,15 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do + ! pathfrac terms not calculated in the previous loop + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = 1.0_r8 + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m1s3) = fphys_m1(bounds%begc:bounds%endc,1:nlevdecomp) + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_m2s3) = fphys_m2(bounds%begc:bounds%endc,1:nlevdecomp) + if (.not. use_fates) then + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = 1.0_r8 + end if + end associate end subroutine decomp_rates_mimics From dfe0688f9b8e434dac691ecfc8dd0293be28a2c7 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 18 Aug 2021 18:09:24 -0600 Subject: [PATCH 36/69] Code corrections from attempting to build (part 5) Successful build! Run fails because I need to introduce a whole bunch of parameters to the params file. --- src/biogeochem/CNDriverMod.F90 | 9 +++++++++ src/biogeochem/CNVegetationFacade.F90 | 4 ++++ src/biogeochem/EDBGCDynMod.F90 | 1 + src/main/clm_instMod.F90 | 1 + 4 files changed, 15 insertions(+) diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index e2323118cc..936f240d91 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -128,6 +128,7 @@ subroutine CNDriverNoLeaching(bounds, use CNGapMortalityMod , only: CNGapMortality use CNSharedParamsMod , only: use_fun use dynHarvestMod , only: CNHarvest + use SoilBiogeochemDecompCascadeMIMICSMod, only: decomp_rates_mimics use SoilBiogeochemDecompCascadeBGCMod , only: decomp_rate_constants_bgc use SoilBiogeochemDecompCascadeCNMod , only: decomp_rate_constants_cn use SoilBiogeochemCompetitionMod , only: SoilBiogeochemCompetition @@ -985,6 +986,10 @@ subroutine CNDriverSummarizeFluxes(bounds, & soilbiogeochem_carbonflux_inst, & c13_soilbiogeochem_carbonflux_inst, & c14_soilbiogeochem_carbonflux_inst, & + soilbiogeochem_carbonstate_inst, & + c13_soilbiogeochem_carbonstate_inst, & + c14_soilbiogeochem_carbonstate_inst, & + soilbiogeochem_nitrogenstate_inst, & soilbiogeochem_nitrogenflux_inst) ! ! !DESCRIPTION: @@ -1009,6 +1014,10 @@ subroutine CNDriverSummarizeFluxes(bounds, & type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: c13_soilbiogeochem_carbonflux_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: c14_soilbiogeochem_carbonflux_inst + type(soilbiogeochem_carbonstate_type) , intent(in) :: soilbiogeochem_carbonstate_inst + type(soilbiogeochem_carbonstate_type) , intent(in) :: c13_soilbiogeochem_carbonstate_inst + type(soilbiogeochem_carbonstate_type) , intent(in) :: c14_soilbiogeochem_carbonstate_inst + type(soilbiogeochem_nitrogenstate_type) , intent(in) :: soilbiogeochem_nitrogenstate_inst type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst ! ! !LOCAL VARIABLES: diff --git a/src/biogeochem/CNVegetationFacade.F90 b/src/biogeochem/CNVegetationFacade.F90 index 98995626b0..457f5818ec 100644 --- a/src/biogeochem/CNVegetationFacade.F90 +++ b/src/biogeochem/CNVegetationFacade.F90 @@ -1083,6 +1083,10 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & soilbiogeochem_carbonflux_inst, & c13_soilbiogeochem_carbonflux_inst, & c14_soilbiogeochem_carbonflux_inst, & + soilbiogeochem_carbonstate_inst, & + c13_soilbiogeochem_carbonstate_inst, & + c14_soilbiogeochem_carbonstate_inst, & + soilbiogeochem_nitrogenstate_inst, & soilbiogeochem_nitrogenflux_inst) ! On the radiation time step, use C state variables to calculate diff --git a/src/biogeochem/EDBGCDynMod.F90 b/src/biogeochem/EDBGCDynMod.F90 index 93b8d50cc4..5e006719bd 100644 --- a/src/biogeochem/EDBGCDynMod.F90 +++ b/src/biogeochem/EDBGCDynMod.F90 @@ -72,6 +72,7 @@ subroutine EDBGCDyn(bounds, & use CNNStateUpdate1Mod , only: NStateUpdate1 use CNNStateUpdate2Mod , only: NStateUpdate2, NStateUpdate2h use CNGapMortalityMod , only: CNGapMortality + use SoilBiogeochemDecompCascadeMIMICSMod, only: decomp_rates_mimics use SoilBiogeochemDecompCascadeBGCMod , only: decomp_rate_constants_bgc use SoilBiogeochemDecompCascadeCNMod , only: decomp_rate_constants_cn use SoilBiogeochemDecompMod , only: SoilBiogeochemDecomp diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90 index e8786cef53..73d35a09b0 100644 --- a/src/main/clm_instMod.F90 +++ b/src/main/clm_instMod.F90 @@ -188,6 +188,7 @@ subroutine clm_instInit(bounds) use clm_varpar , only : nlevsno use controlMod , only : nlfilename, fsurdat use domainMod , only : ldomain + use SoilBiogeochemDecompCascadeMIMICSMod, only : init_decompcascade_mimics use SoilBiogeochemDecompCascadeBGCMod , only : init_decompcascade_bgc use SoilBiogeochemDecompCascadeCNMod , only : init_decompcascade_cn use SoilBiogeochemDecompCascadeContype , only : init_decomp_cascade_constants From 4e22c9145c521b601003e2247f8bce49c903b2a2 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 19 Aug 2021 13:31:14 -0600 Subject: [PATCH 37/69] Adding rf_decomp_cascade to history --- doc/ChangeLog | 20 ++++---- doc/ChangeSum | 2 +- .../SoilBiogeochemCarbonFluxType.F90 | 22 +++++++- .../SoilBiogeochemDecompCascadeBGCMod.F90 | 50 ++++++++----------- .../SoilBiogeochemDecompCascadeCNMod.F90 | 34 ++++++------- .../SoilBiogeochemDecompMod.F90 | 2 +- .../SoilBiogeochemPotentialMod.F90 | 2 +- .../SoilBiogeochemStateType.F90 | 4 -- 8 files changed, 72 insertions(+), 64 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index fe17e5d69c..f613deb652 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,18 +1,18 @@ =============================================================== -Tag name: ctsm5.1.dev053 +Tag name: ctsm5.1.dev054 Originator(s): slevis (Samuel Levis,SLevis Consulting,303-665-1310) -Date: Tue Aug 10 16:22:24 MDT 2021 +Date: Thu Aug 19 13:15:24 MDT 2021 One-line Summary: Adding history variables for use with Newton-Krylov Purpose and description of changes ---------------------------------- - Considering @klindsay28's Newton-Krylov spin-up method for BGC and MIMICS. - Newton-Krylov needs decomp_k and pathfrac_decomp_cascade on ctsm history - files. + Considering @klindsay28's Newton-Krylov spin-up method for BGC & MIMICS. + Newton-Krylov needs decomp_k and pathfrac_decomp_cascade and may need + fpi and rf_decomp_cascade on ctsm history files. - decomp_k was already in place. - I have now also added pathfrac_decomp_cascade. + decomp_k and fpi were already in place as inactive history fields. + I have now also added pathfrac_decomp_cascade and rf_decomp_cascade. Significant changes to scientifically-supported configurations -------------------------------------------------------------- @@ -38,7 +38,7 @@ Issues fixed (include CTSM Issue #): #1455 Known bugs found since the previous tag (include issue #): I did not open an issue for this: decomp_k was dimensioned wrong, and I corrected it in this PR without affecting answers. In particular I changed the - size of the third dimension from ndecomp_pools to ndecomp_cascade_transitions. + size of the third dimension from ndecomp_cascade_transitions to ndecomp_pools. Notes of particular relevance for users --------------------------------------- @@ -48,8 +48,8 @@ Substantial timing or memory changes: Notes of particular relevance for developers: --------------------------------------------- Caveats for developers (e.g., code that is duplicated that requires double maintenance): - This PR adds a variable to ctsm's history files; however, I have not updated - the corresponding master list in the documentation, yet. + This PR adds 2 variables to ctsm's history files; however, I have not + updated the corresponding master list in the documentation, yet. Testing summary: ---------------- diff --git a/doc/ChangeSum b/doc/ChangeSum index 0175bc53a0..aaf9b06161 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,6 +1,6 @@ Tag Who Date Summary ============================================================================================================================ - ctsm5.1.dev053 slevis 08/10/2021 Adding history variables for use with Newton-Krylov + ctsm5.1.dev054 slevis 08/19/2021 Adding history variables for use with Newton-Krylov ctsm5.1.dev051 multiple 08/06/2021 New LUNA-specific ozone stress option ctsm5.1.dev050 sacks 08/02/2021 Improve and document method for getting diagnostics on a problem point ctsm5.1.dev049 jedwards 07/26/2021 Update externals, NEON updates, fix stop_option=date, move neon niwo test to match user_mods, local time option diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 index 072d13d54b..3901c99989 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 @@ -29,6 +29,7 @@ module SoilBiogeochemCarbonFluxType real(r8), pointer :: decomp_cascade_hr_col (:,:) ! vertically-integrated (diagnostic) het. resp. from decomposing C pools (gC/m2/s) real(r8), pointer :: decomp_cascade_ctransfer_vr_col (:,:,:) ! vertically-resolved C transferred along deomposition cascade (gC/m3/s) real(r8), pointer :: decomp_cascade_ctransfer_col (:,:) ! vertically-integrated (diagnostic) C transferred along decomposition cascade (gC/m2/s) + real(r8), pointer :: rf_decomp_cascade_col (:,:,:) ! (frac) respired fraction in decomposition step real(r8), pointer :: pathfrac_decomp_cascade_col (:,:,:) ! (frac) what fraction of C passes from donor to receiver pool through a given transition real(r8), pointer :: decomp_k_col (:,:,:) ! rate coefficient for decomposition (1./sec) real(r8), pointer :: hr_vr_col (:,:) ! (gC/m3/s) total vertically-resolved het. resp. from decomposing C pools @@ -122,6 +123,9 @@ subroutine InitAllocate(this, bounds) allocate(this%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions)) this%decomp_cascade_ctransfer_col(:,:)= nan + allocate(this%rf_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)) + this%rf_decomp_cascade_col(:,:,:) = nan + allocate(this%pathfrac_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)) this%pathfrac_decomp_cascade_col(:,:,:) = nan @@ -252,6 +256,7 @@ subroutine InitHistory(this, bounds, carbon_type) this%decomp_cascade_ctransfer_col(begc:endc,:) = spval this%decomp_cascade_ctransfer_vr_col(begc:endc,:,:) = spval this%pathfrac_decomp_cascade_col(begc:endc,:,:) = spval + this%rf_decomp_cascade_col(begc:endc,:,:) = spval do l = 1, ndecomp_cascade_transitions ! output the vertically integrated fluxes only as default @@ -329,8 +334,20 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name=longname, & ptr_col=data2dptr, default='inactive') - ! pathfrac_decomp_cascade_col needed when using - ! Newton-Krylov to spin up the decomposition + ! pathfrac_decomp_cascade_col and rf_decomp_cascade_col needed + ! when using Newton-Krylov to spin up the decomposition + data2dptr => this%rf_decomp_cascade_col(:,:,l) + fieldname = & + trim(decomp_cascade_con%decomp_pool_name_short(decomp_cascade_con%cascade_donor_pool(l)))//'_RESP_FRAC_'//& + trim(decomp_cascade_con%decomp_pool_name_short(decomp_cascade_con%cascade_receiver_pool(l)))& + //trim(vr_suffix) + longname = 'respired from '//& + trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_donor_pool(l)))//' to '// & + trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_receiver_pool(l))) + call hist_addfld_decomp (fname=fieldname, units='fraction', type2d='levdcmp', & + avgflag='A', long_name=longname, & + ptr_col=data2dptr, default='inactive') + data2dptr => this%pathfrac_decomp_cascade_col(:,:,l) fieldname = & trim(decomp_cascade_con%decomp_pool_name_short(decomp_cascade_con%cascade_donor_pool(l)))//'_PATHFRAC_'//& @@ -713,6 +730,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) this%decomp_cascade_ctransfer_col(i,l) = value_column this%decomp_cascade_ctransfer_vr_col(i,j,l) = value_column this%pathfrac_decomp_cascade_col(i,j,l) = value_column + this%rf_decomp_cascade_col(i,j,l) = value_column end do end do end do diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index d24a6d34ec..42d4ddfee3 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -50,6 +50,16 @@ module SoilBiogeochemDecompCascadeBGCMod real(r8), private :: cwd_fcel real(r8), private :: cwd_flig + real(r8), private :: rf_l1s1 + real(r8), private :: rf_l2s1 + real(r8), private :: rf_l3s2 + real(r8), private :: rf_s2s1 + real(r8), private :: rf_s2s3 + real(r8), private :: rf_s3s1 + real(r8), private :: rf_cwdl2 + real(r8), private :: rf_cwdl3 + real(r8), private, allocatable :: rf_s1s2(:,:) + real(r8), private, allocatable :: rf_s1s3(:,:) real(r8), private, allocatable :: f_s1s2(:,:) real(r8), private, allocatable :: f_s1s3(:,:) real(r8), private :: f_s2s1 @@ -262,18 +272,6 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i ! ! !LOCAL VARIABLES !-- properties of each decomposing pool - real(r8) :: rf_l1s1 - real(r8) :: rf_l2s1 - real(r8) :: rf_l3s2 - !real(r8) :: rf_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) - !real(r8) :: rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) - real(r8), allocatable :: rf_s1s2(:,:) - real(r8), allocatable :: rf_s1s3(:,:) - real(r8) :: rf_s2s1 - real(r8) :: rf_s2s3 - real(r8) :: rf_s3s1 - real(r8) :: rf_cwdl2 - real(r8) :: rf_cwdl3 real(r8) :: cn_s1 real(r8) :: cn_s2 real(r8) :: cn_s3 @@ -284,8 +282,6 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i !----------------------------------------------------------------------- associate( & - rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) - cellsand => soilstate_inst%cellsand_col , & ! Input: [real(r8) (:,:) ] column 3D sand cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Output: [integer (:) ] which pool is C taken from for a given decomposition step @@ -491,68 +487,56 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i !---------------- list of transitions and their time-independent coefficients ---------------! i_l1s1 = 1 decomp_cascade_con%cascade_step_name(i_l1s1) = 'L1S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = rf_l1s1 cascade_donor_pool(i_l1s1) = i_met_lit cascade_receiver_pool(i_l1s1) = i_act_som i_l2s1 = 2 decomp_cascade_con%cascade_step_name(i_l2s1) = 'L2S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1) = rf_l2s1 cascade_donor_pool(i_l2s1) = i_cel_lit cascade_receiver_pool(i_l2s1) = i_act_som i_l3s2 = 3 decomp_cascade_con%cascade_step_name(i_l3s2) = 'L3S2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = rf_l3s2 cascade_donor_pool(i_l3s2) = i_lig_lit cascade_receiver_pool(i_l3s2) = i_slo_som i_s1s2 = 4 decomp_cascade_con%cascade_step_name(i_s1s2) = 'S1S2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = rf_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) cascade_donor_pool(i_s1s2) = i_act_som cascade_receiver_pool(i_s1s2) = i_slo_som i_s1s3 = 5 decomp_cascade_con%cascade_step_name(i_s1s3) = 'S1S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) cascade_donor_pool(i_s1s3) = i_act_som cascade_receiver_pool(i_s1s3) = i_pas_som i_s2s1 = 6 decomp_cascade_con%cascade_step_name(i_s2s1) = 'S2S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = rf_s2s1 cascade_donor_pool(i_s2s1) = i_slo_som cascade_receiver_pool(i_s2s1) = i_act_som i_s2s3 = 7 decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 cascade_donor_pool(i_s2s3) = i_slo_som cascade_receiver_pool(i_s2s3) = i_pas_som i_s3s1 = 8 decomp_cascade_con%cascade_step_name(i_s3s1) = 'S3S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = rf_s3s1 cascade_donor_pool(i_s3s1) = i_pas_som cascade_receiver_pool(i_s3s1) = i_act_som if (.not. use_fates) then i_cwdl2 = 9 decomp_cascade_con%cascade_step_name(i_cwdl2) = 'CWDL2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 cascade_donor_pool(i_cwdl2) = i_cwd cascade_receiver_pool(i_cwdl2) = i_cel_lit i_cwdl3 = 10 decomp_cascade_con%cascade_step_name(i_cwdl3) = 'CWDL3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = rf_cwdl3 cascade_donor_pool(i_cwdl3) = i_cwd cascade_receiver_pool(i_cwdl3) = i_lig_lit end if - deallocate(rf_s1s2) - deallocate(rf_s1s3) deallocate(params_inst%initial_Cstocks) end associate @@ -625,8 +609,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & o2stress_sat => ch4_inst%o2stress_sat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) o2stress_unsat => ch4_inst%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area - - pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C passes from donor to receiver pool through a given transition (frac) + rf_decomp_cascade => soilbiogeochem_carbonflux_inst%rf_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) + pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C passes from donor to receiver pool through a given transition (frac) t_scalar => soilbiogeochem_carbonflux_inst%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia @@ -957,7 +941,17 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & if (.not. use_fates) then pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fcel pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = cwd_flig + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = rf_cwdl2 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = rf_cwdl3 end if + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = rf_l1s1 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1) = rf_l2s1 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = rf_l3s2 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = rf_s1s2(bounds%begc:bounds%endc,1:nlevdecomp) + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s3) = rf_s1s3(bounds%begc:bounds%endc,1:nlevdecomp) + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s1) = rf_s2s1 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s1) = rf_s3s1 end associate diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 index c3eb1fe2e1..dac35aff31 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeCNMod.F90 @@ -41,6 +41,12 @@ module SoilBiogeochemDecompCascadeCNMod real(r8), private :: cwd_fcel real(r8), private :: cwd_flig + real(r8), private :: rf_l1s1 !respiration fraction litter 1 -> SOM 1 + real(r8), private :: rf_l2s2 !respiration fraction litter 2 -> SOM 2 + real(r8), private :: rf_l3s3 !respiration fraction litter 3 -> SOM 3 + real(r8), private :: rf_s1s2 !respiration fraction SOM 1 -> SOM 2 + real(r8), private :: rf_s2s3 !respiration fraction SOM 2 -> SOM 3 + real(r8), private :: rf_s3s4 !respiration fraction SOM 3 -> SOM 4 integer, private :: i_l1s1 integer, private :: i_l2s2 integer, private :: i_l3s3 @@ -249,12 +255,6 @@ subroutine init_decompcascade_cn(bounds, soilbiogeochem_state_inst) ! !-- properties of each pathway along decomposition cascade !-- properties of each decomposing pool - real(r8) :: rf_l1s1 !respiration fraction litter 1 -> SOM 1 - real(r8) :: rf_l2s2 !respiration fraction litter 2 -> SOM 2 - real(r8) :: rf_l3s3 !respiration fraction litter 3 -> SOM 3 - real(r8) :: rf_s1s2 !respiration fraction SOM 1 -> SOM 2 - real(r8) :: rf_s2s3 !respiration fraction SOM 2 -> SOM 3 - real(r8) :: rf_s3s4 !respiration fraction SOM 3 -> SOM 4 real(r8) :: cn_s1 real(r8) :: cn_s2 real(r8) :: cn_s3 @@ -263,7 +263,6 @@ subroutine init_decompcascade_cn(bounds, soilbiogeochem_state_inst) !----------------------------------------------------------------------- associate( & - rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Output: [integer (:) ] which pool is C taken from for a given decomposition step cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & ! Output: [integer (:) ] which pool is C added to for a given decomposition step floating_cn_ratio_decomp_pools => decomp_cascade_con%floating_cn_ratio_decomp_pools , & ! Output: [logical (:) ] TRUE => pool has fixed C:N ratio @@ -451,56 +450,47 @@ subroutine init_decompcascade_cn(bounds, soilbiogeochem_state_inst) !---------------- list of transitions and their time-independent coefficients ---------------! i_l1s1 = 1 decomp_cascade_con%cascade_step_name(i_l1s1) = 'L1S1' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = rf_l1s1 cascade_donor_pool(i_l1s1) = i_litr1 cascade_receiver_pool(i_l1s1) = i_soil1 i_l2s2 = 2 decomp_cascade_con%cascade_step_name(i_l2s2) = 'L2S2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s2) = rf_l2s2 cascade_donor_pool(i_l2s2) = i_litr2 cascade_receiver_pool(i_l2s2) = i_soil2 i_l3s3 = 3 decomp_cascade_con%cascade_step_name(i_l3s3) = 'L3S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s3) = rf_l3s3 cascade_donor_pool(i_l3s3) = i_litr3 cascade_receiver_pool(i_l3s3) = i_soil3 i_s1s2 = 4 decomp_cascade_con%cascade_step_name(i_s1s2) = 'S1S2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = rf_s1s2 cascade_donor_pool(i_s1s2) = i_soil1 cascade_receiver_pool(i_s1s2) = i_soil2 i_s2s3 = 5 decomp_cascade_con%cascade_step_name(i_s2s3) = 'S2S3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 cascade_donor_pool(i_s2s3) = i_soil2 cascade_receiver_pool(i_s2s3) = i_soil3 i_s3s4 = 6 decomp_cascade_con%cascade_step_name(i_s3s4) = 'S3S4' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s4) = rf_s3s4 cascade_donor_pool(i_s3s4) = i_soil3 cascade_receiver_pool(i_s3s4) = i_soil4 i_s4atm = 7 decomp_cascade_con%cascade_step_name(i_s4atm) = 'S4' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s4atm) = 1. cascade_donor_pool(i_s4atm) = i_soil4 cascade_receiver_pool(i_s4atm) = i_atm if (.not. use_fates) then i_cwdl2 = 8 decomp_cascade_con%cascade_step_name(i_cwdl2) = 'CWDL2' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = 0._r8 cascade_donor_pool(i_cwdl2) = i_cwd cascade_receiver_pool(i_cwdl2) = i_litr2 i_cwdl3 = 9 decomp_cascade_con%cascade_step_name(i_cwdl3) = 'CWDL3' - rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = 0._r8 cascade_donor_pool(i_cwdl3) = i_cwd cascade_receiver_pool(i_cwdl3) = i_litr3 end if @@ -569,7 +559,8 @@ subroutine decomp_rate_constants_cn(bounds, & o2stress_unsat => ch4_inst%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) finundated => ch4_inst%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area (excluding dedicated wetland columns) - pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C passes from donor to receiver pool through a given transition (frac) + rf_decomp_cascade => soilbiogeochem_carbonflux_inst%rf_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) + pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Output: [real(r8) (:,:,:) ] what fraction of C passes from donor to receiver pool through a given transition (frac) t_scalar => soilbiogeochem_carbonflux_inst%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp @@ -849,7 +840,16 @@ subroutine decomp_rate_constants_cn(bounds, & if (.not. use_fates) then pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = cwd_fcel pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = cwd_flig + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl2) = 0._r8 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_cwdl3) = 0._r8 end if + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = rf_l1s1 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s2) = rf_l2s2 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s3) = rf_l3s3 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s1s2) = rf_s1s2 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s2s3) = rf_s2s3 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s3s4) = rf_s3s4 + rf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_s4atm) = 1. end associate diff --git a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 index d3009ba32e..7aa3eb2bd6 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 @@ -109,7 +109,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, initial_cn_ratio => decomp_cascade_con%initial_cn_ratio , & ! Input: [real(r8) (:) ] c:n ratio for initialization of pools fpi_vr => soilbiogeochem_state_inst%fpi_vr_col , & ! Input: [real(r8) (:,:) ] fraction of potential immobilization (no units) - rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) + rf_decomp_cascade => soilbiogeochem_carbonflux_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) decomp_npools_vr => soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) N pools decomp_cpools_vr => soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index 89e4329fb9..97f1a7c6c7 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -109,7 +109,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & floating_cn_ratio_decomp_pools => decomp_cascade_con%floating_cn_ratio_decomp_pools , & ! Input: [logical (:) ] TRUE => pool has fixed C:N ratio initial_cn_ratio => decomp_cascade_con%initial_cn_ratio , & ! Input: [real(r8) (:) ] c:n ratio for initialization of pools - rf_decomp_cascade => soilbiogeochem_state_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) + rf_decomp_cascade => soilbiogeochem_carbonflux_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C passes from donor to receiver pool through a given transition (frac) decomp_npools_vr => soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) N pools diff --git a/src/soilbiogeochem/SoilBiogeochemStateType.F90 b/src/soilbiogeochem/SoilBiogeochemStateType.F90 index da896af6bf..dc9f073410 100644 --- a/src/soilbiogeochem/SoilBiogeochemStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemStateType.F90 @@ -33,7 +33,6 @@ module SoilBiogeochemStateType real(r8) , pointer :: fpi_vr_col (:,:) ! (no units) fraction of potential immobilization real(r8) , pointer :: fpi_col (:) ! (no units) fraction of potential immobilization real(r8), pointer :: fpg_col (:) ! (no units) fraction of potential gpp - real(r8) , pointer :: rf_decomp_cascade_col (:,:,:) ! (frac) respired fraction in decomposition step real(r8) , pointer :: nfixation_prof_col (:,:) ! (1/m) profile for N fixation additions real(r8) , pointer :: ndep_prof_col (:,:) ! (1/m) profile for N fixation additions real(r8) , pointer :: som_adv_coef_col (:,:) ! (m2/s) SOM advective flux @@ -101,9 +100,6 @@ subroutine InitAllocate(this, bounds) allocate(this%som_diffus_coef_col (begc:endc,1:nlevdecomp_full)) ; this%som_diffus_coef_col (:,:) = spval allocate(this%plant_ndemand_col (begc:endc)) ; this%plant_ndemand_col (:) = nan - allocate(this%rf_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)); - this%rf_decomp_cascade_col(:,:,:) = nan - end subroutine InitAllocate !------------------------------------------------------------------------ From 07c641ba701c2afb99cbbd3169f94ca2dfc36fc3 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 21 Aug 2021 14:54:07 -0600 Subject: [PATCH 38/69] user_nl_clm and shell_commands files for Newton-Krylov testing --- .../newton_krylov_spinup/shell_commands | 3 +++ .../newton_krylov_spinup/user_nl_clm | 15 +++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 cime_config/usermods_dirs/newton_krylov_spinup/shell_commands create mode 100644 cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm diff --git a/cime_config/usermods_dirs/newton_krylov_spinup/shell_commands b/cime_config/usermods_dirs/newton_krylov_spinup/shell_commands new file mode 100644 index 0000000000..a66f52f6fd --- /dev/null +++ b/cime_config/usermods_dirs/newton_krylov_spinup/shell_commands @@ -0,0 +1,3 @@ +#!/bin/bash +./xmlchange CLM_FORCE_COLDSTART="on" + diff --git a/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm b/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm new file mode 100644 index 0000000000..b28ffd3d9a --- /dev/null +++ b/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm @@ -0,0 +1,15 @@ +hist_dov2xy = .true.,.false. +hist_nhtfrq = 0,-175200 +hist_mfilt = 1,1 +hist_fincl2 = 'FPI_vr', 'K_PAS_SOM', 'K_SLO_SOM', 'K_ACT_SOM', + 'K_CWD', 'K_CEL_LIT', 'K_LIG_LIT', 'K_MET_LIT', + 'CWD_PATHFRAC_L2_vr', 'CWD_RESP_FRAC_L2_vr', + 'CWD_PATHFRAC_L3_VR', 'CWD_RESP_FRAC_L3_vr', + 'L1_PATHFRAC_S1_vr', 'L1_RESP_FRAC_S1_vr', + 'L2_PATHFRAC_S1_vr', 'L2_RESP_FRAC_S1_vr', + 'L3_PATHFRAC_S2_vr', 'L3_RESP_FRAC_S2_vr', + 'S1_PATHFRAC_S2_vr', 'S1_RESP_FRAC_S2_vr' + 'S1_PATHFRAC_S3_vr', 'S1_RESP_FRAC_S3_vr' + 'S2_PATHFRAC_S1_vr', 'S2_RESP_FRAC_S1_vr' + 'S2_PATHFRAC_S3_vr', 'S2_RESP_FRAC_S3_vr' + 'S3_PATHFRAC_S1_vr', 'S3_RESP_FRAC_S1_vr' From 2687cf1225570f475e79f0e8efb187d3016d2502 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 21 Aug 2021 15:30:35 -0600 Subject: [PATCH 39/69] Typo correction... --- cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm b/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm index b28ffd3d9a..318105a043 100644 --- a/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm +++ b/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm @@ -4,7 +4,7 @@ hist_mfilt = 1,1 hist_fincl2 = 'FPI_vr', 'K_PAS_SOM', 'K_SLO_SOM', 'K_ACT_SOM', 'K_CWD', 'K_CEL_LIT', 'K_LIG_LIT', 'K_MET_LIT', 'CWD_PATHFRAC_L2_vr', 'CWD_RESP_FRAC_L2_vr', - 'CWD_PATHFRAC_L3_VR', 'CWD_RESP_FRAC_L3_vr', + 'CWD_PATHFRAC_L3_vr', 'CWD_RESP_FRAC_L3_vr', 'L1_PATHFRAC_S1_vr', 'L1_RESP_FRAC_S1_vr', 'L2_PATHFRAC_S1_vr', 'L2_RESP_FRAC_S1_vr', 'L3_PATHFRAC_S2_vr', 'L3_RESP_FRAC_S2_vr', From 1c1a94511dad218cba102a5e24d9fe13ecf63cde Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 25 Aug 2021 12:21:24 -0600 Subject: [PATCH 40/69] Made params consistent w current params file ctsm51_params.c210528.nc PASS: ./create_test ERP_P36x2_D_Ld3.f10_f10_mg37.I1850Clm50BgcCrop.cheyenne_gnu.clm-extra_outputs -c /glade/p/cgd/tss/ctsm_baselines/ctsm5.1.dev053 I will submit the test-suites to catch more errors before attempting to run MIMICS itself. --- src/biogeochem/CNSharedParamsMod.F90 | 4 +- .../SoilBiogeochemDecompCascadeBGCMod.F90 | 32 +-- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 242 +++++++----------- 3 files changed, 105 insertions(+), 173 deletions(-) diff --git a/src/biogeochem/CNSharedParamsMod.F90 b/src/biogeochem/CNSharedParamsMod.F90 index 3b88c9be84..08eaa3443e 100644 --- a/src/biogeochem/CNSharedParamsMod.F90 +++ b/src/biogeochem/CNSharedParamsMod.F90 @@ -103,12 +103,12 @@ subroutine CNParamsReadShared_netcdf(ncid) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) CNParamsShareInst%maxpsi=tempr - tString='rf_cwdl2' ! TODO slevis: rm suffix in params file(s) + tString='rf_cwdl2_bgc' ! TODO slevis: rm suffix in params file(s) call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) CNParamsShareInst%rf_cwdl2=tempr - tString='tau_cwd' ! TODO slevis: rm suffix in params file(s) + tString='tau_cwd_bgc' ! TODO slevis: rm suffix in params file(s) call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) CNParamsShareInst%tau_cwd=tempr diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index 2c53532818..891625ec40 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -131,82 +131,82 @@ subroutine readParams ( ncid ) !----------------------------------------------------------------------- ! Read off of netcdf file - tString='bgc_tau_l1' ! TODO slevis: rename in params file(s) and code... + tString='tau_l1' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_l1_bgc=tempr - tString='bgc_tau_l2_l3' ! TODO slevis: rename in params file(s) and code + tString='tau_l2_l3' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_l2_l3_bgc=tempr - tString='bgc_tau_s1' ! TODO slevis: rename in params file(s) and code + tString='tau_s1' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_s1_bgc=tempr - tString='bgc_tau_s2' ! TODO slevis: rename in params file(s) and code + tString='tau_s2' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_s2_bgc=tempr - tString='bgc_tau_s3' ! TODO slevis: rename in params file(s) and code + tString='tau_s3' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_s3_bgc=tempr - tString='bgc_cn_s1' ! TODO slevis: rename in params file(s) and code + tString='cn_s1_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cn_s1_bgc=tempr - tString='bgc_cn_s2' ! TODO slevis: rename in params file(s) and code + tString='cn_s2_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cn_s2_bgc=tempr - tString='bgc_cn_s3' ! TODO slevis: rename in params file(s) and code + tString='cn_s3_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cn_s3_bgc=tempr - tString='bgc_rf_l1s1' ! TODO slevis: rename in params file(s) and code + tString='rf_l1s1_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l1s1_bgc=tempr - tString='bgc_rf_l2s1' ! TODO slevis: rename in params file(s) and code + tString='rf_l2s1_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l2s1_bgc=tempr - tString='bgc_rf_l3s2' ! TODO slevis: rename in params file(s) and code + tString='rf_l3s2_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l3s2_bgc=tempr - tString='bgc_rf_s2s1' ! TODO slevis: rename in params file(s) and code + tString='rf_s2s1_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_s2s1_bgc=tempr - tString='bgc_rf_s2s3' ! TODO slevis: rename in params file(s) and code + tString='rf_s2s3_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_s2s3_bgc=tempr - tString='bgc_rf_s3s1' ! TODO slevis: rename in params file(s) and code + tString='rf_s3s1_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_s3s1_bgc=tempr - tString='bgc_rf_cwdl3' ! TODO slevis: rename in params file(s) and code + tString='rf_cwdl3_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_cwdl3_bgc=tempr - tString='bgc_cwd_fcel' ! TODO slevis: rename in params file(s) & code... + tString='cwd_fcel' ! TODO slevis: bgc_ prefix in params file(s) and code call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cwd_fcel_bgc=tempr diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index dd122ecb29..03628f6d6b 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -117,31 +117,20 @@ module SoilBiogeochemDecompCascadeMIMICSMod real(r8), allocatable :: mimics_kint(:) ! real(r8), allocatable :: mimics_kslope(:) ! real(r8), allocatable :: mimics_nue_into_mic - real(r8), allocatable :: mimics_p_scalar_p1 - real(r8), allocatable :: mimics_p_scalar_p2 - real(r8), allocatable :: mimics_fphys_r_p1 - real(r8), allocatable :: mimics_fphys_r_p2 - real(r8), allocatable :: mimics_fphys_k_p1 - real(r8), allocatable :: mimics_fphys_k_p2 - real(r8), allocatable :: mimics_fchem_r_p1 - real(r8), allocatable :: mimics_fchem_r_p2 - real(r8), allocatable :: mimics_fchem_k_p1 - real(r8), allocatable :: mimics_fchem_k_p2 - real(r8), allocatable :: mimics_desorp_p1 - real(r8), allocatable :: mimics_desorp_p2 + real(r8), allocatable :: mimics_p_scalar(:) + real(r8), allocatable :: mimics_fphys_r(:) + real(r8), allocatable :: mimics_fphys_k(:) + real(r8), allocatable :: mimics_fchem_r(:) + real(r8), allocatable :: mimics_fchem_k(:) + real(r8), allocatable :: mimics_desorp(:) real(r8), allocatable :: mimics_desorpQ10 real(r8), allocatable :: mimics_densdep - real(r8), allocatable :: mimics_fmet_p1 - real(r8), allocatable :: mimics_fmet_p2 - real(r8), allocatable :: mimics_fmet_p3 - real(r8), allocatable :: mimics_fmet_p4 + real(r8), allocatable :: mimics_fmet(:) real(r8), allocatable :: mimics_tau_mod_factor real(r8), allocatable :: mimics_tau_mod_min real(r8), allocatable :: mimics_tau_mod_max - real(r8), allocatable :: mimics_tau_r_p1 - real(r8), allocatable :: mimics_tau_r_p2 - real(r8), allocatable :: mimics_tau_k_p1 - real(r8), allocatable :: mimics_tau_k_p2 + real(r8), allocatable :: mimics_tau_r(:) + real(r8), allocatable :: mimics_tau_k(:) real(r8), allocatable :: mimics_ko_r real(r8), allocatable :: mimics_ko_k real(r8), allocatable :: mimics_cn_r @@ -179,8 +168,6 @@ subroutine readParams ( ncid ) !----------------------------------------------------------------------- ! Read off of netcdf file - ! TODO Add new mimics_ params here and in the params file(s) - ! TODO Add shared ones in CNParamsShareInst & in the file(s) ! TODO When ready for final params values, talk to @wwieder ! TODO Need next one for spin-ups? If so, then add prefixes ! mimics here and bgc in BGCMod if these two will differ or @@ -197,197 +184,142 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_mge(ndecomp_pools_max)) - tString='mimics_mge' ! TODO rename in params file(s) + tString='mimics_mge' call ncd_io(trim(tString), params_inst%mimics_mge(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_vmod(ndecomp_pools_max)) - tString='mimics_vmod' ! TODO rename in params file(s) + tString='mimics_vmod' call ncd_io(trim(tString), params_inst%mimics_vmod(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_vslope(ndecomp_pools_max)) - tString='mimics_vslope' ! TODO rename in params file(s) + tString='mimics_vslope' call ncd_io(trim(tString), params_inst%mimics_vslope(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_vint(ndecomp_pools_max)) - tString='mimics_vint' ! TODO rename in params file(s) + tString='mimics_vint' call ncd_io(trim(tString), params_inst%mimics_vint(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_kmod(ndecomp_pools_max)) - tString='mimics_kmod' ! TODO rename in params file(s) + tString='mimics_kmod' call ncd_io(trim(tString), params_inst%mimics_kmod(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_kslope(ndecomp_pools_max)) - tString='mimics_kslope' ! TODO rename in params file(s) + tString='mimics_kslope' call ncd_io(trim(tString), params_inst%mimics_kslope(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_kint(ndecomp_pools_max)) - tString='mimics_kint' ! TODO rename in params file(s) + tString='mimics_kint' call ncd_io(trim(tString), params_inst%mimics_kint(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_p_scalar_p1) - tString='mimics_p_scalar_p1' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_p_scalar_p1, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_p_scalar(2)) + tString='mimics_p_scalar' + call ncd_io(trim(tString), params_inst%mimics_p_scalar, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_p_scalar_p2) - tString='mimics_p_scalar_p2' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_p_scalar_p2, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_desorp(2)) + tString='mimics_desorp' + call ncd_io(trim(tString), params_inst%mimics_desorp, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_desorp_p1) - tString='mimics_desorp_p1' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_desorp_p1, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fphys_r(2)) + tString='mimics_fphys_r' + call ncd_io(trim(tString), params_inst%mimics_fphys_r, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_desorp_p2) - tString='mimics_desorp_p2' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_desorp_p2, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_fphys_r_p1) - tString='mimics_fphys_r_p1' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fphys_r_p1, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_fphys_r_p2) - tString='mimics_fphys_r_p2' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fphys_r_p2, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_fphys_k_p1) - tString='mimics_fphys_k_p1' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fphys_k_p1, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_fphys_k_p2) - tString='mimics_fphys_k_p2' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fphys_k_p2, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fphys_k(2)) + tString='mimics_fphys_k' + call ncd_io(trim(tString), params_inst%mimics_fphys_k, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_nue_into_mic) - tString='mimics_nue_into_mic' ! TODO add to params file(s) + tString='mimics_nue_into_mic' call ncd_io(trim(tString), params_inst%mimics_nue_into_mic, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_fmet_p1) - tString='mimics_fmet_p1' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fmet_p1, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_fmet_p2) - tString='mimics_fmet_p2' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fmet_p2, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_fmet_p3) - tString='mimics_fmet_p3' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fmet_p3, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_fmet_p4) - tString='mimics_fmet_p4' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fmet_p4, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fmet(4)) + tString='mimics_fmet' + call ncd_io(trim(tString), params_inst%mimics_fmet, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_fchem_r_p1) - tString='mimics_fchem_r_p1' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fchem_r_p1, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fchem_r(2)) + tString='mimics_fchem_r' + call ncd_io(trim(tString), params_inst%mimics_fchem_r, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_fchem_r_p2) - tString='mimics_fchem_r_p2' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fchem_r_p2, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_fchem_k_p1) - tString='mimics_fchem_k_p1' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fchem_k_p1, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_fchem_k_p2) - tString='mimics_fchem_k_p2' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_fchem_k_p2, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_fchem_k(2)) + tString='mimics_fchem_k' + call ncd_io(trim(tString), params_inst%mimics_fchem_k, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_tau_mod_factor) - tString='mimics_tau_mod_factor' ! TODO add to params file(s) + tString='mimics_tau_mod_factor' call ncd_io(trim(tString), params_inst%mimics_tau_mod_factor, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_tau_mod_min) - tString='mimics_tau_mod_min' ! TODO add to params file(s) + tString='mimics_tau_mod_min' call ncd_io(trim(tString), params_inst%mimics_tau_mod_min, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_tau_mod_max) - tString='mimics_tau_mod_max' ! TODO add to params file(s) + tString='mimics_tau_mod_max' call ncd_io(trim(tString), params_inst%mimics_tau_mod_max, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_tau_r_p1) - tString='mimics_tau_r_p1' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_tau_r_p1, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_tau_r_p2) - tString='mimics_tau_r_p2' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_tau_r_p2, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_tau_k_p1) - tString='mimics_tau_k_p1' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_tau_k_p1, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_tau_r(2)) + tString='mimics_tau_r' + call ncd_io(trim(tString), params_inst%mimics_tau_r, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_tau_k_p2) - tString='mimics_tau_k_p2' ! TODO add to params file(s) - call ncd_io(trim(tString), params_inst%mimics_tau_k_p2, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_tau_k(2)) + tString='mimics_tau_k' + call ncd_io(trim(tString), params_inst%mimics_tau_k, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_ko_r) - tString='mimics_ko_r' ! TODO add to params file(s) + tString='mimics_ko_r' call ncd_io(trim(tString), params_inst%mimics_ko_r, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_ko_k) - tString='mimics_ko_k' ! TODO add to params file(s) + tString='mimics_ko_k' call ncd_io(trim(tString), params_inst%mimics_ko_k, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_densdep) - tString='mimics_densdep' ! TODO add to params file(s) + tString='mimics_densdep' call ncd_io(trim(tString), params_inst%mimics_densdep, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_desorpQ10) - tString='mimics_desorpQ10' ! TODO add to params file(s) + tString='mimics_desorpQ10' call ncd_io(trim(tString), params_inst%mimics_desorpQ10, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_t_soi_ref) - tString='mimics_t_soi_ref' ! TODO add to params file(s) + tString='mimics_t_soi_ref' call ncd_io(trim(tString), params_inst%mimics_t_soi_ref, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_cn_mod_num) - tString='mimics_cn_mod_num' ! TODO add to params file(s) + tString='mimics_cn_mod_num' call ncd_io(trim(tString), params_inst%mimics_cn_mod_num, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_cn_r) - tString='mimics_cn_r' ! TODO add to params file(s) + tString='mimics_cn_r' call ncd_io(trim(tString), params_inst%mimics_cn_r, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_cn_k) - tString='mimics_cn_k' ! TODO add to params file(s) + tString='mimics_cn_k' call ncd_io(trim(tString), params_inst%mimics_cn_k, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -453,15 +385,15 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat allocate(p_scalar(bounds%begc:bounds%endc,1:nlevdecomp)) !------- time-constant coefficients ---------- ! - mimics_nue_into_mic = params_inst%mimics_nue_into_mic ! = 0.85_r8 - mimics_p_scalar_p1 = params_inst%mimics_p_scalar_p1 ! = 0.8_r8 - mimics_p_scalar_p2 = params_inst%mimics_p_scalar_p2 ! = -3.0_r8 - mimics_fphys_r_p1 = params_inst%mimics_fphys_r_p1 ! = 0.3_r8 - mimics_fphys_r_p2 = params_inst%mimics_fphys_r_p2 ! = 1.3_r8 - mimics_fphys_k_p1 = params_inst%mimics_fphys_k_p1 ! = 0.2_r8 - mimics_fphys_k_p2 = params_inst%mimics_fphys_k_p2 ! = 0.8_r8 - mimics_desorp_p1 = params_inst%mimics_desorp_p1 ! = 1.5e-5_r8 - mimics_desorp_p2 = params_inst%mimics_desorp_p2 ! = -1.5_r8 + mimics_nue_into_mic = params_inst%mimics_nue_into_mic + mimics_p_scalar_p1 = params_inst%mimics_p_scalar(1) + mimics_p_scalar_p2 = params_inst%mimics_p_scalar(2) + mimics_fphys_r_p1 = params_inst%mimics_fphys_r(1) + mimics_fphys_r_p2 = params_inst%mimics_fphys_r(2) + mimics_fphys_k_p1 = params_inst%mimics_fphys_k(1) + mimics_fphys_k_p2 = params_inst%mimics_fphys_k(2) + mimics_desorp_p1 = params_inst%mimics_desorp(1) + mimics_desorp_p2 = params_inst%mimics_desorp(2) ! set respiration fractions for fluxes between compartments rf_l1m1 = 1.0_r8 - params_inst%mimics_mge(1) @@ -1132,29 +1064,29 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do - mimics_fmet_p1 = params_inst%mimics_fmet_p1 ! = 0.85_r8 - mimics_fmet_p2 = params_inst%mimics_fmet_p2 ! = 0.85_r8 - mimics_fmet_p3 = params_inst%mimics_fmet_p3 ! = 0.013_r8 - mimics_fmet_p4 = params_inst%mimics_fmet_p4 ! = 40.0_r8 - mimics_fchem_r_p1 = params_inst%mimics_fchem_r_p1 ! = 0.1_r8 - mimics_fchem_r_p2 = params_inst%mimics_fchem_r_p2 ! = -3.0_r8 - mimics_fchem_k_p1 = params_inst%mimics_fchem_k_p1 ! = 0.3_r8 - mimics_fchem_k_p2 = params_inst%mimics_fchem_k_p2 ! = -3.0_r8 - mimics_tau_mod_min = params_inst%mimics_tau_mod_min ! = 0.8_r8 - mimics_tau_mod_max = params_inst%mimics_tau_mod_max ! = 1.2_r8 - mimics_tau_mod_factor = params_inst%mimics_tau_mod_factor ! = 0.01_r8 ! was tau_mod_denom = 100 - mimics_tau_r_p1 = params_inst%mimics_tau_r_p1 ! = 5.2e-4_r8 - mimics_tau_r_p2 = params_inst%mimics_tau_r_p2 ! = 0.3_r8 ! or 0.4? - mimics_tau_k_p1 = params_inst%mimics_tau_k_p1 ! = 2.4e-4_r8 - mimics_tau_k_p2 = params_inst%mimics_tau_k_p2 ! = 0.1_r8 - mimics_ko_r = params_inst%mimics_ko_r ! = 4.0_r8 - mimics_ko_k = params_inst%mimics_ko_k ! = 4.0_r8 - mimics_densdep = params_inst%mimics_densdep ! = 1.0_r8 - mimics_desorpQ10 = params_inst%mimics_desorpQ10 ! = 1.0_r8 - mimics_t_soi_ref = params_inst%mimics_t_soi_ref ! = 25.0_r8 ! deg C - mimics_cn_mod_num = params_inst%mimics_cn_mod_num ! = 1.0_r8 ! TODO slevis: I don't see values in the testbed or - mimics_cn_r = params_inst%mimics_cn_r ! = 1.0_r8 ! ... in the testbed's - mimics_cn_k = params_inst%mimics_cn_k ! = 1.0_r8 ! ... params file for these 3 + mimics_fmet_p1 = params_inst%mimics_fmet(1) + mimics_fmet_p2 = params_inst%mimics_fmet(2) + mimics_fmet_p3 = params_inst%mimics_fmet(3) + mimics_fmet_p4 = params_inst%mimics_fmet(4) + mimics_fchem_r_p1 = params_inst%mimics_fchem_r(1) + mimics_fchem_r_p2 = params_inst%mimics_fchem_r(2) + mimics_fchem_k_p1 = params_inst%mimics_fchem_k(1) + mimics_fchem_k_p2 = params_inst%mimics_fchem_k(2) + mimics_tau_mod_min = params_inst%mimics_tau_mod_min + mimics_tau_mod_max = params_inst%mimics_tau_mod_max + mimics_tau_mod_factor = params_inst%mimics_tau_mod_factor + mimics_tau_r_p1 = params_inst%mimics_tau_r(1) + mimics_tau_r_p2 = params_inst%mimics_tau_r(2) + mimics_tau_k_p1 = params_inst%mimics_tau_k(1) + mimics_tau_k_p2 = params_inst%mimics_tau_k(2) + mimics_ko_r = params_inst%mimics_ko_r + mimics_ko_k = params_inst%mimics_ko_k + mimics_densdep = params_inst%mimics_densdep + mimics_desorpQ10 = params_inst%mimics_desorpQ10 + mimics_t_soi_ref = params_inst%mimics_t_soi_ref + mimics_cn_mod_num = params_inst%mimics_cn_mod_num ! TODO slevis: I don't see values in the testbed or + mimics_cn_r = params_inst%mimics_cn_r ! ... in the testbed's + mimics_cn_k = params_inst%mimics_cn_k ! ... params file for these 3 ! calculate rates for all litter and som pools ! TODO Ok that I reversed order of do-loops? From ecadf73cca21475d595f591e31032a922f82cb76 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 30 Aug 2021 15:30:08 -0600 Subject: [PATCH 41/69] Added use_mimics_decomp to the namelist Modified the handling of use_century_decomp in the /bld scripts to make it an alternative to use_mimics_decomp. Removed decomp_depth_efolding from the namelist, which I will repeat in a separate PR for tracking purposes. --- bld/CLMBuildNamelist.pm | 62 ++++++++++++++----- bld/namelist_files/namelist_defaults_ctsm.xml | 20 +++--- .../namelist_definition_ctsm.xml | 19 ++++-- src/biogeochem/CNSharedParamsMod.F90 | 10 +-- .../SoilBiogeochemCompetitionMod.F90 | 2 +- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 1 + 6 files changed, 79 insertions(+), 35 deletions(-) diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 126683a5c8..8f0d6feeca 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -84,6 +84,9 @@ REQUIRED OPTIONS -structure "structure" The overall structure being used [ standard | fast ] OPTIONS -driver "value" mct or nuopc + -decomp "value" Build with below-ground decomposition package [ century | mimics ] + (default is NONE). + Below-ground decomposition modes other than NONE require -bgc set to bgc/fates. -bgc "value" Build CLM with BGC package [ sp | cn | bgc | fates ] (default is sp). CLM Biogeochemistry mode @@ -92,12 +95,12 @@ OPTIONS cn = Carbon Nitrogen model (CN) This toggles on the namelist variable: use_cn bgc = Carbon Nitrogen with methane, nitrification, vertical soil C, - CENTURY decomposition + CENTURY or MIMICS decomposition This toggles on the namelist variables: - use_cn, use_lch4, use_nitrif_denitrif, use_vertsoilc, use_century_decomp + use_cn, use_lch4, use_nitrif_denitrif, use_vertsoilc, and (use_century_decomp or use_mimics_decomp) fates = FATES/Ecosystem Demography with below ground BGC This toggles on the namelist variables: - use_fates, use_vertsoilc, use_century_decomp + use_fates, use_vertsoilc, and (use_century_decomp or use_mimics_decomp) (Only for CLM4.5/CLM5.0) -[no-]chk_res Also check [do NOT check] to make sure the resolution and land-mask is valid. @@ -756,7 +759,7 @@ sub setup_cmdl_fates_mode { # The following variables may be set by the user and are compatible with use_fates # no need to set defaults, covered in a different routine - my @list = ( "use_vertsoilc", "use_century_decomp", "use_lch4" ); + my @list = ( "use_vertsoilc", "use_lch4" ); foreach my $var ( @list ) { if ( defined($nl->get_value($var)) ) { $nl_flags->{$var} = $nl->get_value($var); @@ -836,15 +839,47 @@ sub setup_cmdl_bgc { if ($nl_flags->{$var} eq "cn" ) { $nl_flags->{'use_cn'} = ".true."; $nl_flags->{'use_fates'} = ".false."; + $nl_flags->{'use_century_decomp'} = ".false."; + $nl_flags->{'use_mimics_decomp'} = ".false."; + $log->warning("Ignoring decomp_mode and overwriting any values of use_century_decomp and use_mimics_decomp to .false. because bgc_mode = cn."); } elsif ($nl_flags->{$var} eq "bgc" ) { $nl_flags->{'use_cn'} = ".true."; $nl_flags->{'use_fates'} = ".false."; + $nl_flags->{'use_century_decomp'} = ".true."; +# Previous line to be replaced by this if-block +# if ($nl_flags->{'decomp_mode'} eq "century" ) { +# $nl_flags->{'use_century_decomp'} = ".true."; +# $nl_flags->{'use_mimics_decomp'} = ".false."; +# $log->warning("Overwriting any values of use_century_decomp to .true. and of use_mimics_decomp to .false. because decomp_mode = century."); +# } elsif ($nl_flags->{'decomp_mode'} eq "mimics" ) { +# $nl_flags->{'use_century_decomp'} = ".false."; +# $nl_flags->{'use_mimics_decomp'} = ".true."; +# $log->warning("Overwriting any values of use_century_decomp to .false. and of use_mimics_decomp to .true. because decomp_mode = mimics."); +# } else { +# $log->fatal_error("The namelist variable decomp_mode should equal either 'century' or 'mimics' and currently it's neither"); +# } } elsif ($nl_flags->{$var} eq "fates" ) { $nl_flags->{'use_cn'} = ".false."; $nl_flags->{'use_fates'} = ".true."; + $nl_flags->{'use_century_decomp'} = ".true."; +# Previous line to be replaced by this if-block +# if ($nl_flags->{'decomp_mode'} eq "century" ) { +# $nl_flags->{'use_century_decomp'} = ".true."; +# $nl_flags->{'use_mimics_decomp'} = ".false."; +# $log->warning("Overwriting any values of use_century_decomp to .true. and of use_mimics_decomp to .false. because decomp_mode = century."); +# } elsif ($nl_flags->{'decomp_mode'} eq "mimics" ) { +# $nl_flags->{'use_century_decomp'} = ".false."; +# $nl_flags->{'use_mimics_decomp'} = ".true."; +# $log->warning("Overwriting any values of use_century_decomp to .false. and of use_mimics_decomp to .true. because decomp_mode = mimics."); +# } else { +# $log->fatal_error("The namelist variable decomp_mode should equal either 'century' or 'mimics' and currently it's neither"); +# } } else { $nl_flags->{'use_cn'} = ".false."; $nl_flags->{'use_fates'} = ".false."; + $nl_flags->{'use_century_decomp'} = ".false."; + $nl_flags->{'use_mimics_decomp'} = ".false."; + $log->warning("Ignoring decomp_mode and overwriting any values of use_century_decomp and use_mimics_decomp to .false. because bgc_mode not equal to bgc nor fates."); } if ( defined($nl->get_value("use_cn")) && ($nl_flags->{'use_cn'} ne $nl->get_value("use_cn")) ) { $log->fatal_error("The namelist variable use_cn is inconsistent with the -bgc option"); @@ -855,7 +890,7 @@ sub setup_cmdl_bgc { { # If the variable has already been set use it, if not set to the value defined by the bgc_mode - my @list = ( "use_lch4", "use_nitrif_denitrif", "use_vertsoilc", "use_century_decomp" ); + my @list = ( "use_lch4", "use_nitrif_denitrif", "use_vertsoilc" ); my $ndiff = 0; my %settings = ( 'bgc_mode'=>$nl_flags->{'bgc_mode'} ); foreach my $var ( @list ) { @@ -882,8 +917,8 @@ sub setup_cmdl_bgc { } } - # Now set use_cn and use_fates - foreach $var ( "use_cn", "use_fates" ) { + # Now set use_cn, use_fates, use_century_decomp, use_mimics_decomp + foreach $var ( "use_cn", "use_fates", "use_century_decomp", "use_mimics_decomp" ) { $val = $nl_flags->{$var}; $group = $definition->get_group_name($var); $nl->set_variable_value($group, $var, $val); @@ -2142,6 +2177,7 @@ sub setup_logic_demand { $settings{'use_nitrif_denitrif'} = $nl_flags->{'use_nitrif_denitrif'}; $settings{'use_vertsoilc'} = $nl_flags->{'use_vertsoilc'}; $settings{'use_century_decomp'} = $nl_flags->{'use_century_decomp'}; + $settings{'use_mimics_decomp'} = $nl_flags->{'use_mimics_decomp'}; $settings{'use_crop'} = $nl_flags->{'use_crop'}; my $demand = $nl->get_value('clm_demand'); @@ -2258,8 +2294,8 @@ sub setup_logic_initial_conditions { $settings{'sim_year'} = $st_year; } foreach my $item ( "mask", "maxpft", "irrigate", "glc_nec", "use_crop", "use_cn", "use_cndv", - "use_nitrif_denitrif", "use_vertsoilc", "use_century_decomp", "use_fates", - "lnd_tuning_mode", + "use_nitrif_denitrif", "use_vertsoilc", "use_century_decomp", "use_mimics_decomp", + "use_fates", "lnd_tuning_mode", ) { $settings{$item} = $nl_flags->{$item}; } @@ -2689,12 +2725,6 @@ sub setup_logic_bgc_shared { if ( $nl_flags->{'bgc_mode'} ne "sp" ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'constrain_stress_deciduous_onset', 'phys'=>$physv->as_string() ); } - # FIXME(bja, 201606) the logic around fates / bgc_mode / - # use_century_decomp is confusing and messed up. This is a hack - # workaround. - if ( &value_is_true($nl_flags->{'use_century_decomp'}) ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'decomp_depth_efolding', 'phys'=>$physv->as_string() ); - } } #------------------------------------------------------------------------------- @@ -4007,7 +4037,7 @@ sub write_output_files { soil_moisture_streams lai_streams atm2lnd_inparm lnd2atm_inparm clm_canopyhydrology_inparm cnphenology clm_soilhydrology_inparm dynamic_subgrid cnvegcarbonstate finidat_consistency_checks dynpft_consistency_checks - clm_initinterp_inparm century_soilbgcdecompcascade + clm_initinterp_inparm soilbgcdecompcascade soilhydrology_inparm luna friction_velocity mineral_nitrogen_dynamics soilwater_movement_inparm rooting_profile_inparm soil_resis_inparm bgc_shared canopyfluxes_inparm aerosol diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index ab8b291076..b54bb8f15b 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -31,8 +31,9 @@ attributes from the config_cache.xml file (with keys converted to upper-case). constant - + sp +NONE clm4_5_CRUv7 clm5_0_cam6.0 @@ -568,11 +569,6 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .false. .false. - -0.5 -10.0 -10.0 - .false. .true. @@ -2569,26 +2565,36 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts >lnd/clm2/paramdata/finundated_inversiondata_0.9x1_ESMFmesh_cdf5_130621.nc - + .false. .false. +.false. .false. .false. .false. .false. +.false. .false. .false. .true. .true. + .true. .true. .true. .true. + .false. .false. diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index e18426b8ca..4d2ec9de96 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -1032,6 +1032,13 @@ Requires the CN or FATES model to work (either CN or CNDV). group="clm_inparm" valid_values="" value=".false."> Use parameters for decomposition from the CENTURY Carbon model Requires the CN or FATES model to work (either CN or CNDV). +Requires bgc_mode set to bgc or fates and decomp_mode set to century. + + + +Use MIMICS below-ground decomposition. +Requires bgc_mode set to bgc or fates and decomp_mode set to mimics. + +Command line arguement for below-ground decomposition mode available when +bgc_mode is set to bgc or fates. + + @@ -2125,12 +2138,6 @@ Base advective flux (downwards) for SOM. Maximum depth to mix soils to by croturbation, in permafrost soils. - - -E-folding depth over which decomposition is slowed with depth in all soils. - - If TRUE, reduce heterotrophic respiration according to available oxygen predicted by CH4 submodel. diff --git a/src/biogeochem/CNSharedParamsMod.F90 b/src/biogeochem/CNSharedParamsMod.F90 index 08eaa3443e..bc4ce6bb94 100644 --- a/src/biogeochem/CNSharedParamsMod.F90 +++ b/src/biogeochem/CNSharedParamsMod.F90 @@ -118,6 +118,11 @@ subroutine CNParamsReadShared_netcdf(ncid) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) CNParamsShareInst%cwd_flig=tempr + tString='decomp_depth_efolding' + call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + CNParamsShareInst%decomp_depth_efolding=tempr + tString='froz_q10' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -161,7 +166,6 @@ subroutine CNParamsReadShared_namelist(namelist_file) integer :: ierr ! error code integer :: unitn ! unit for namelist file - real(r8) :: decomp_depth_efolding = 0.0_r8 logical :: constrain_stress_deciduous_onset = .false. character(len=32) :: subroutine_name = 'CNParamsReadNamelist' @@ -174,7 +178,6 @@ subroutine CNParamsReadShared_namelist(namelist_file) ! ---------------------------------------------------------------------- namelist /bgc_shared/ & - decomp_depth_efolding, & constrain_stress_deciduous_onset @@ -201,18 +204,15 @@ subroutine CNParamsReadShared_namelist(namelist_file) end if ! masterproc ! Broadcast the parameters from master - call shr_mpi_bcast ( decomp_depth_efolding, mpicom ) call shr_mpi_bcast ( constrain_stress_deciduous_onset, mpicom ) ! Save the parameter to the instance - CNParamsShareInst%decomp_depth_efolding = decomp_depth_efolding CNParamsShareInst%constrain_stress_deciduous_onset = constrain_stress_deciduous_onset ! Output read parameters to the lnd.log if (masterproc) then write(iulog,*) 'CN/BGC shared namelist parameters:' write(iulog,*)' ' - write(iulog,*)' decomp_depth_efolding = ', decomp_depth_efolding write(iulog,*)' constrain_stress_deciduous_onset = ',constrain_stress_deciduous_onset write(iulog,*) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index da11047618..ce720ac637 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -383,7 +383,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, fpi_vr(c,j) = 0.0_r8 do k = 1, ndecomp_cascade_transitions - ! TODO slevis: correct to identify as receiver pools? + ! TODO slevis: ok to identify as receiver pools? if (cascade_receiver_pool(k) == i_cop_mic .or. & cascade_receiver_pool(k) == i_oli_mic) then if (pmnf_decomp_cascade(c,j,k) > 0.0_r8 .and. & diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 03628f6d6b..d2bfecebee 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -721,6 +721,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat nue_decomp_cascade(i_cwdl2) = 1.0_r8 end if + ! TODO Add rest of new params here unless used after init. deallocate(params_inst%mimics_mge) deallocate(params_inst%mimics_vmod) deallocate(params_inst%mimics_vint) From 66d7b921a8421548479d457738c3d19e6e00badd Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 31 Aug 2021 16:42:26 -0600 Subject: [PATCH 42/69] Introduced MIMICS test mod directory New test ERP_P36x2_D_Ld3.f10_f10_mg37.I1850Clm51BgcCrop.cheyenne_gnu.clm-mimics points to the new test mod directory and to a new params file containing a long list of new parameters needed by MIMICS. When I'm done debugging MIMICS, I will add this test to the test-suite. --- bld/CLMBuildNamelist.pm | 71 +++++++++++-------- bld/listDefaultNamelist.pl | 7 ++ bld/namelist_files/namelist_defaults_ctsm.xml | 10 ++- .../testdefs/testmods_dirs/clm/mimics/README | 2 + .../clm/mimics/include_user_mods | 1 + .../testmods_dirs/clm/mimics/user_nl_clm | 2 + 6 files changed, 59 insertions(+), 34 deletions(-) create mode 100644 cime_config/testdefs/testmods_dirs/clm/mimics/README create mode 100644 cime_config/testdefs/testmods_dirs/clm/mimics/include_user_mods create mode 100644 cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 8f0d6feeca..757754b65c 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -835,51 +835,66 @@ sub setup_cmdl_bgc { } $log->verbose_message("Using $nl_flags->{$var} for bgc."); + my $var1 = "decomp_mode"; + my $val1 = $nl->get_value($var1); + # now set the actual name list variables based on the bgc alias if ($nl_flags->{$var} eq "cn" ) { $nl_flags->{'use_cn'} = ".true."; $nl_flags->{'use_fates'} = ".false."; $nl_flags->{'use_century_decomp'} = ".false."; $nl_flags->{'use_mimics_decomp'} = ".false."; - $log->warning("Ignoring decomp_mode and overwriting any values of use_century_decomp and use_mimics_decomp to .false. because bgc_mode = cn."); + if ($val1 eq "'century'" || $val1 eq "'mimics'") { + $log->warning("Ignoring decomp_mode and overwriting any values of use_century_decomp and use_mimics_decomp to .false. because bgc_mode = cn. To get past this warning, use -ignore_warnings or set decomp_mode to NONE."); + } } elsif ($nl_flags->{$var} eq "bgc" ) { $nl_flags->{'use_cn'} = ".true."; $nl_flags->{'use_fates'} = ".false."; - $nl_flags->{'use_century_decomp'} = ".true."; -# Previous line to be replaced by this if-block -# if ($nl_flags->{'decomp_mode'} eq "century" ) { -# $nl_flags->{'use_century_decomp'} = ".true."; -# $nl_flags->{'use_mimics_decomp'} = ".false."; -# $log->warning("Overwriting any values of use_century_decomp to .true. and of use_mimics_decomp to .false. because decomp_mode = century."); -# } elsif ($nl_flags->{'decomp_mode'} eq "mimics" ) { -# $nl_flags->{'use_century_decomp'} = ".false."; -# $nl_flags->{'use_mimics_decomp'} = ".true."; -# $log->warning("Overwriting any values of use_century_decomp to .false. and of use_mimics_decomp to .true. because decomp_mode = mimics."); -# } else { -# $log->fatal_error("The namelist variable decomp_mode should equal either 'century' or 'mimics' and currently it's neither"); -# } + if ($val1 eq "'century'" ) { + if (! &value_is_true($nl_flags->{'use_century_decomp'}) || + &value_is_true($nl_flags->{'use_mimics_decomp'}) ) { + $log->verbose_message("Overwriting any values of use_century_decomp to .true. and of use_mimics_decomp to .false. because decomp_mode = century."); + } + $nl_flags->{'use_century_decomp'} = ".true."; + $nl_flags->{'use_mimics_decomp'} = ".false."; + } elsif ($val1 eq "'mimics'" ) { + if (&value_is_true($nl_flags->{'use_century_decomp'}) || + ! &value_is_true($nl_flags->{'use_mimics_decomp'}) ) { + $log->verbose_message("Overwriting any values of use_century_decomp to .false. and of use_mimics_decomp to .true. because decomp_mode = mimics."); + } + $nl_flags->{'use_century_decomp'} = ".false."; + $nl_flags->{'use_mimics_decomp'} = ".true."; + } else { + $log->fatal_error("The namelist variable decomp_mode should equal either 'century' or 'mimics' and currently it's neither"); + } } elsif ($nl_flags->{$var} eq "fates" ) { $nl_flags->{'use_cn'} = ".false."; $nl_flags->{'use_fates'} = ".true."; - $nl_flags->{'use_century_decomp'} = ".true."; -# Previous line to be replaced by this if-block -# if ($nl_flags->{'decomp_mode'} eq "century" ) { -# $nl_flags->{'use_century_decomp'} = ".true."; -# $nl_flags->{'use_mimics_decomp'} = ".false."; -# $log->warning("Overwriting any values of use_century_decomp to .true. and of use_mimics_decomp to .false. because decomp_mode = century."); -# } elsif ($nl_flags->{'decomp_mode'} eq "mimics" ) { -# $nl_flags->{'use_century_decomp'} = ".false."; -# $nl_flags->{'use_mimics_decomp'} = ".true."; -# $log->warning("Overwriting any values of use_century_decomp to .false. and of use_mimics_decomp to .true. because decomp_mode = mimics."); -# } else { -# $log->fatal_error("The namelist variable decomp_mode should equal either 'century' or 'mimics' and currently it's neither"); -# } + if ($val1 eq "'century'" ) { + if (! &value_is_true($nl_flags->{'use_century_decomp'}) || + &value_is_true($nl_flags->{'use_mimics_decomp'}) ) { + $log->verbose_message("Overwriting any values of use_century_decomp to .true. and of use_mimics_decomp to .false. because decomp_mode = century."); + } + $nl_flags->{'use_century_decomp'} = ".true."; + $nl_flags->{'use_mimics_decomp'} = ".false."; + } elsif ($val1 eq "'mimics'" ) { + if (&value_is_true($nl_flags->{'use_century_decomp'}) || + ! &value_is_true($nl_flags->{'use_mimics_decomp'}) ) { + $log->verbose_message("Overwriting any values of use_century_decomp to .false. and of use_mimics_decomp to .true. because decomp_mode = mimics."); + } + $nl_flags->{'use_century_decomp'} = ".false."; + $nl_flags->{'use_mimics_decomp'} = ".true."; + } else { + $log->fatal_error("The namelist variable decomp_mode should equal either 'century' or 'mimics' and currently it's neither"); + } } else { $nl_flags->{'use_cn'} = ".false."; $nl_flags->{'use_fates'} = ".false."; $nl_flags->{'use_century_decomp'} = ".false."; $nl_flags->{'use_mimics_decomp'} = ".false."; - $log->warning("Ignoring decomp_mode and overwriting any values of use_century_decomp and use_mimics_decomp to .false. because bgc_mode not equal to bgc nor fates."); + if ($val1 eq "'century'" || $val1 eq "'mimics'") { + $log->warning("Ignoring decomp_mode and overwriting any values of use_century_decomp and use_mimics_decomp to .false. because bgc_mode /= bgc and /= fates. To get past this warning, use -ignore_warnings or set decomp_mode to NONE."); + } } if ( defined($nl->get_value("use_cn")) && ($nl_flags->{'use_cn'} ne $nl->get_value("use_cn")) ) { $log->fatal_error("The namelist variable use_cn is inconsistent with the -bgc option"); diff --git a/bld/listDefaultNamelist.pl b/bld/listDefaultNamelist.pl index 938ee7f5b1..6053767608 100755 --- a/bld/listDefaultNamelist.pl +++ b/bld/listDefaultNamelist.pl @@ -269,12 +269,19 @@ sub GetListofNeededFiles { if ( $sim_year ne 1850 && $sim_year ne 2000 && $sim_year > 1800 ) { next YEAR; } my @bgcsettings = $definition->get_valid_values( "bgc_mode", 'noquotes'=>1 ); + my @decompsettings = $definition->get_valid_values( "decomp_mode", 'noquotes'=>1 ); print "bgc=@bgcsettings\n" if $printing; + print "decomp=@decompsettings\n" if $printing; # # Loop over all possible BGC settings # foreach my $bgc ( @bgcsettings ) { $settings{'bgc'} = $bgc; + if ( $bgc eq "bgc" || $bgc eq "fates" ) { + foreach my $decomp ( @decompsettings ) { + $settings{'decomp'} = $decomp; + } + } my @crop_vals; if ( $bgc =~ /^cn/ ) { @crop_vals = ( "on", "off" ); diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index b54bb8f15b..e8e72105e0 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -2581,20 +2581,18 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts .false. .true. -.true. - +.false. .true. .true. .true. -.true. - +.false. .false. .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics/README b/cime_config/testdefs/testmods_dirs/clm/mimics/README new file mode 100644 index 0000000000..b138ba628f --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/mimics/README @@ -0,0 +1,2 @@ +This test mod turns on the MIMICS instead of the CENTURY below-ground +biogeochemistry. diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/mimics/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/mimics/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm new file mode 100644 index 0000000000..54fe09c6c6 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm @@ -0,0 +1,2 @@ +decomp_mode = 'mimics' +paramfile = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/paramdata/ctsm51_params.c210825.nc' From 3ff27f32c0d9d5fcfda497f92d2eab0df3403c85 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 4 Sep 2021 16:27:50 -0600 Subject: [PATCH 43/69] Debugging while running with use_mimics_decomp = .true. Next error to resolve: CH4 Conservation Error in CH4Mod during diffusion --- bld/CLMBuildNamelist.pm | 10 +- src/main/readParamsMod.F90 | 11 +- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 162 ++++++++++-------- 3 files changed, 105 insertions(+), 78 deletions(-) diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 757754b65c..d91ea25cb4 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -850,7 +850,10 @@ sub setup_cmdl_bgc { } elsif ($nl_flags->{$var} eq "bgc" ) { $nl_flags->{'use_cn'} = ".true."; $nl_flags->{'use_fates'} = ".false."; - if ($val1 eq "'century'" ) { + # TODO Remove when not needed anymore: + # The .or. part of this if-statment satisfies backwards compatibility + # while decomp_mode is not, yet, set in baseline tests (slevis 2021/9/1) + if ($val1 eq "'century'" || $val1 eq "" ) { if (! &value_is_true($nl_flags->{'use_century_decomp'}) || &value_is_true($nl_flags->{'use_mimics_decomp'}) ) { $log->verbose_message("Overwriting any values of use_century_decomp to .true. and of use_mimics_decomp to .false. because decomp_mode = century."); @@ -870,7 +873,10 @@ sub setup_cmdl_bgc { } elsif ($nl_flags->{$var} eq "fates" ) { $nl_flags->{'use_cn'} = ".false."; $nl_flags->{'use_fates'} = ".true."; - if ($val1 eq "'century'" ) { + # TODO Remove when not needed anymore: + # The .or. part of this if-statment satisfies backwards compatibility + # while decomp_mode is not, yet, set in baseline tests (slevis 2021/9/1) + if ($val1 eq "'century'" || $val1 eq "" ) { if (! &value_is_true($nl_flags->{'use_century_decomp'}) || &value_is_true($nl_flags->{'use_mimics_decomp'}) ) { $log->verbose_message("Overwriting any values of use_century_decomp to .true. and of use_mimics_decomp to .false. because decomp_mode = century."); diff --git a/src/main/readParamsMod.F90 b/src/main/readParamsMod.F90 index 38d412414e..54f26588da 100644 --- a/src/main/readParamsMod.F90 +++ b/src/main/readParamsMod.F90 @@ -8,6 +8,7 @@ module readParamsMod ! ! ! USES: use clm_varctl , only : paramfile, iulog, use_fates, use_cn + use clm_varctl , only : use_century_decomp, use_mimics_decomp use spmdMod , only : masterproc use fileutils , only : getfil use ncdio_pio , only : ncd_pio_closefile, ncd_pio_openfile @@ -37,6 +38,7 @@ subroutine readParameters (nutrient_competition_method, photosyns_inst) use SoilBiogeochemLittVertTranspMod , only : readSoilBiogeochemLittVertTranspParams => readParams use SoilBiogeochemPotentialMod , only : readSoilBiogeochemPotentialParams => readParams use SoilBiogeochemDecompMod , only : readSoilBiogeochemDecompParams => readParams + use SoilBiogeochemDecompCascadeMIMICSMod, only : readSoilBiogeochemDecompMimicsParams => readParams use SoilBiogeochemDecompCascadeBGCMod , only : readSoilBiogeochemDecompBgcParams => readParams use SoilBiogeochemDecompCascadeCNMod , only : readSoilBiogeochemDecompCnParams => readParams use ch4Mod , only : readCH4Params => readParams @@ -95,8 +97,13 @@ subroutine readParameters (nutrient_competition_method, photosyns_inst) ! if (use_cn .or. use_fates) then call readSoilBiogeochemCompetitionParams(ncid) - call readSoilBiogeochemDecompBgcParams(ncid) - call readSoilBiogeochemDecompCnParams(ncid) + if (use_mimics_decomp) then + call readSoilBiogeochemDecompMimicsParams(ncid) + else if (use_century_decomp) then + call readSoilBiogeochemDecompBgcParams(ncid) + else ! *DecompCN is deprecated + call readSoilBiogeochemDecompCnParams(ncid) + end if call readSoilBiogeochemDecompParams(ncid) call readSoilBiogeochemLittVertTranspParams(ncid) call readSoilBiogeochemNitrifDenitrifParams(ncid) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index d2bfecebee..2cc127f6db 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -42,9 +42,10 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! !PUBLIC DATA MEMBERS ! ! !PRIVATE DATA MEMBERS - real(r8), allocatable :: desorp(:,:) - real(r8), allocatable :: fphys_m1(:,:) - real(r8), allocatable :: fphys_m2(:,:) + real(r8), private, allocatable :: desorp(:,:) + real(r8), private, allocatable :: fphys_m1(:,:) + real(r8), private, allocatable :: fphys_m2(:,:) + real(r8), private, allocatable :: p_scalar(:,:) integer, private :: i_phys_som ! index of physically protected Soil Organic Matter (SOM) integer, private :: i_chem_som ! index of chemically protected SOM integer, private :: i_avl_som ! index of available (aka active) SOM @@ -107,8 +108,23 @@ module SoilBiogeochemDecompCascadeMIMICSMod real(r8), private :: kslope_s1_m2 ! type, private :: params_type + real(r8) :: mimics_nue_into_mic + real(r8) :: mimics_desorpQ10 + real(r8) :: mimics_densdep + real(r8) :: mimics_tau_mod_factor + real(r8) :: mimics_tau_mod_min + real(r8) :: mimics_tau_mod_max + real(r8) :: mimics_ko_r + real(r8) :: mimics_ko_k + real(r8) :: mimics_cn_r + real(r8) :: mimics_cn_k + real(r8) :: mimics_cn_mod_num + real(r8) :: mimics_t_soi_ref real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start real(r8), allocatable :: initial_Cstocks(:) ! Initial Carbon stocks for a cold-start + ! The next few vectors are dimensioned by the number of decomposition + ! transitions making use of the corresponding parameters. The transitions + ! are represented in this order: l1m1 l2m1 s1m1 l1m2 l2m2 s1m2 real(r8), allocatable :: mimics_mge(:) ! Microbial growth efficiency (mg/mg) real(r8), allocatable :: mimics_vmod(:) ! real(r8), allocatable :: mimics_vint(:) ! @@ -116,27 +132,19 @@ module SoilBiogeochemDecompCascadeMIMICSMod real(r8), allocatable :: mimics_kmod(:) ! real(r8), allocatable :: mimics_kint(:) ! real(r8), allocatable :: mimics_kslope(:) ! - real(r8), allocatable :: mimics_nue_into_mic + ! The next few vectors are dimensioned by the number of + ! parameters with the same name used in the same formula. + ! In the formulas themselves, we use scalar copies of each parameter + ! with suffixes _p1, p2, p3, ... to distinguish among them. + real(r8), allocatable :: mimics_fmet(:) real(r8), allocatable :: mimics_p_scalar(:) real(r8), allocatable :: mimics_fphys_r(:) real(r8), allocatable :: mimics_fphys_k(:) real(r8), allocatable :: mimics_fchem_r(:) real(r8), allocatable :: mimics_fchem_k(:) real(r8), allocatable :: mimics_desorp(:) - real(r8), allocatable :: mimics_desorpQ10 - real(r8), allocatable :: mimics_densdep - real(r8), allocatable :: mimics_fmet(:) - real(r8), allocatable :: mimics_tau_mod_factor - real(r8), allocatable :: mimics_tau_mod_min - real(r8), allocatable :: mimics_tau_mod_max real(r8), allocatable :: mimics_tau_r(:) real(r8), allocatable :: mimics_tau_k(:) - real(r8), allocatable :: mimics_ko_r - real(r8), allocatable :: mimics_ko_k - real(r8), allocatable :: mimics_cn_r - real(r8), allocatable :: mimics_cn_k - real(r8), allocatable :: mimics_cn_mod_num - real(r8), allocatable :: mimics_t_soi_ref end type params_type ! type(params_type), private :: params_inst @@ -160,7 +168,7 @@ subroutine readParams ( ncid ) type(file_desc_t),intent(inout) :: ncid ! pio netCDF file id ! ! !LOCAL VARIABLES: - character(len=32) :: subname = 'readParams' + character(len=32) :: subname = 'readMimicsParams' character(len=100) :: errCode = 'Error reading MIMICS params ' logical :: readv ! has variable been read in or not real(r8) :: tempr ! temporary to read in constant @@ -174,7 +182,7 @@ subroutine readParams ( ncid ) ! move reading the parameter to CNSharedParamsMod if they ! will not differ. Similar for both initial_Cstocks params. tString='initial_Cstocks_depth_bgc' - call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%initial_Cstocks_depth=tempr @@ -220,108 +228,108 @@ subroutine readParams ( ncid ) allocate(params_inst%mimics_p_scalar(2)) tString='mimics_p_scalar' - call ncd_io(trim(tString), params_inst%mimics_p_scalar, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), params_inst%mimics_p_scalar(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_desorp(2)) tString='mimics_desorp' - call ncd_io(trim(tString), params_inst%mimics_desorp, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), params_inst%mimics_desorp(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_fphys_r(2)) tString='mimics_fphys_r' - call ncd_io(trim(tString), params_inst%mimics_fphys_r, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), params_inst%mimics_fphys_r(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_fphys_k(2)) tString='mimics_fphys_k' - call ncd_io(trim(tString), params_inst%mimics_fphys_k, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - - allocate(params_inst%mimics_nue_into_mic) - tString='mimics_nue_into_mic' - call ncd_io(trim(tString), params_inst%mimics_nue_into_mic, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), params_inst%mimics_fphys_k(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_fmet(4)) tString='mimics_fmet' - call ncd_io(trim(tString), params_inst%mimics_fmet, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), params_inst%mimics_fmet(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_fchem_r(2)) tString='mimics_fchem_r' - call ncd_io(trim(tString), params_inst%mimics_fchem_r, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), params_inst%mimics_fchem_r(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_fchem_k(2)) tString='mimics_fchem_k' - call ncd_io(trim(tString), params_inst%mimics_fchem_k, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), params_inst%mimics_fchem_k(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_tau_mod_factor) - tString='mimics_tau_mod_factor' - call ncd_io(trim(tString), params_inst%mimics_tau_mod_factor, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_tau_r(2)) + tString='mimics_tau_r' + call ncd_io(trim(tString), params_inst%mimics_tau_r(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_tau_mod_min) - tString='mimics_tau_mod_min' - call ncd_io(trim(tString), params_inst%mimics_tau_mod_min, 'read', ncid, readvar=readv) + allocate(params_inst%mimics_tau_k(2)) + tString='mimics_tau_k' + call ncd_io(trim(tString), params_inst%mimics_tau_k(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_tau_mod_max) - tString='mimics_tau_mod_max' - call ncd_io(trim(tString), params_inst%mimics_tau_mod_max, 'read', ncid, readvar=readv) + tString='mimics_nue_into_mic' + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_nue_into_mic = tempr - allocate(params_inst%mimics_tau_r(2)) - tString='mimics_tau_r' - call ncd_io(trim(tString), params_inst%mimics_tau_r, 'read', ncid, readvar=readv) + tString='mimics_tau_mod_factor' + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_tau_mod_factor = tempr - allocate(params_inst%mimics_tau_k(2)) - tString='mimics_tau_k' - call ncd_io(trim(tString), params_inst%mimics_tau_k, 'read', ncid, readvar=readv) + tString='mimics_tau_mod_min' + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_tau_mod_min = tempr + + tString='mimics_tau_mod_max' + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_tau_mod_max = tempr - allocate(params_inst%mimics_ko_r) tString='mimics_ko_r' - call ncd_io(trim(tString), params_inst%mimics_ko_r, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_ko_r = tempr - allocate(params_inst%mimics_ko_k) tString='mimics_ko_k' - call ncd_io(trim(tString), params_inst%mimics_ko_k, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_ko_k = tempr - allocate(params_inst%mimics_densdep) tString='mimics_densdep' - call ncd_io(trim(tString), params_inst%mimics_densdep, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_densdep = tempr - allocate(params_inst%mimics_desorpQ10) tString='mimics_desorpQ10' - call ncd_io(trim(tString), params_inst%mimics_desorpQ10, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_desorpQ10 = tempr - allocate(params_inst%mimics_t_soi_ref) tString='mimics_t_soi_ref' - call ncd_io(trim(tString), params_inst%mimics_t_soi_ref, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_t_soi_ref = tempr - allocate(params_inst%mimics_cn_mod_num) tString='mimics_cn_mod_num' - call ncd_io(trim(tString), params_inst%mimics_cn_mod_num, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_cn_mod_num = tempr - allocate(params_inst%mimics_cn_r) tString='mimics_cn_r' - call ncd_io(trim(tString), params_inst%mimics_cn_r, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_cn_r = tempr - allocate(params_inst%mimics_cn_k) tString='mimics_cn_k' - call ncd_io(trim(tString), params_inst%mimics_cn_k, 'read', ncid, readvar=readv) + call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%mimics_cn_k = tempr end subroutine readParams @@ -350,10 +358,10 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat real(r8) :: mimics_fphys_k_p2 real(r8) :: mimics_desorp_p1 real(r8) :: mimics_desorp_p2 - real(r8), allocatable :: p_scalar(:,:) real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. + real(r8) :: clay ! local copy of cellclay integer :: c, j ! indices !----------------------------------------------------------------------- @@ -449,16 +457,19 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat do c = bounds%begc, bounds%endc do j = 1, nlevdecomp - desorp(c,j) = mimics_desorp_p1 * & - exp(mimics_desorp_p2 * cellclay(c,j)) - fphys_m1(c,j) = min(1.0_r8, max(0.0_r8, mimics_fphys_r_p1 * & - exp(mimics_fphys_r_p2 * cellclay(c,j)))) - fphys_m2(c,j) = min(1.0_r8, max(0.0_r8, mimics_fphys_k_p1 * & - exp(mimics_fphys_k_p2 * cellclay(c,j)))) - ! TODO slevis: Oups, where was p_scalar supposed to be used? + ! The parameter values currently in the params files always lead to + ! positive values for the expressions below, so we do not + ! need to use the max function to limit these expressions. + ! We apply the min function on cellclay because we are looping over + ! some non-soil columns here that contain cellclay = 1e36. + clay = dmin1(100.0_r8, cellclay(c,j)) + desorp(c,j) = mimics_desorp_p1 * dexp(mimics_desorp_p2 * clay) + fphys_m1(c,j) = dmin1(1.0_r8, mimics_fphys_r_p1 * & + dexp(mimics_fphys_r_p2 * clay)) + fphys_m2(c,j) = dmin1(1.0_r8, mimics_fphys_k_p1 * & + dexp(mimics_fphys_k_p2 * clay)) p_scalar(c,j) = 1.0_r8 / (mimics_p_scalar_p1 * & - exp(mimics_p_scalar_p2 * & - sqrt(cellclay(c,j)))) + dexp(mimics_p_scalar_p2 * dsqrt(clay))) end do end do initial_stock_soildepth = params_inst%initial_Cstocks_depth @@ -721,7 +732,6 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat nue_decomp_cascade(i_cwdl2) = 1.0_r8 end if - ! TODO Add rest of new params here unless used after init. deallocate(params_inst%mimics_mge) deallocate(params_inst%mimics_vmod) deallocate(params_inst%mimics_vint) @@ -729,6 +739,10 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat deallocate(params_inst%mimics_kmod) deallocate(params_inst%mimics_kint) deallocate(params_inst%mimics_kslope) + deallocate(params_inst%mimics_p_scalar) + deallocate(params_inst%mimics_desorp) + deallocate(params_inst%mimics_fphys_r) + deallocate(params_inst%mimics_fphys_k) deallocate(params_inst%initial_Cstocks) end associate @@ -1159,9 +1173,9 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & km_l2_m2 = exp(kslope_l2_m2 * t_soi_degC + kint_l2_m2) * & kmod_l2_m2 km_s1_m1 = exp(kslope_s1_m1 * t_soi_degC + kint_s1_m1) * & - kmod_s1_m1 + kmod_s1_m1 * p_scalar(c,j) km_s1_m2 = exp(kslope_s1_m2 * t_soi_degC + kint_s1_m2) * & - kmod_s1_m2 + kmod_s1_m2 * p_scalar(c,j) ! Desorption a function of soil temperature and ! Q10 = 1.1 w/ reference temperature of 25C. From ee6c4014059c88031704b29e182deea655ba5fd4 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 13 Sep 2021 12:25:13 -0600 Subject: [PATCH 44/69] Corrections to unit conversions based on meeting with @wwieder These corrections fixed the CH4 conservation error and now I get a column Cbalance error --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 74 +++++++++---------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 2cc127f6db..1f69bafc5e 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -996,23 +996,20 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do ! TODO May need a hook from MIMICS to ch4 code for this to work - if (use_lch4) then - ! Calculate ANOXIA - if (anoxia) then - ! Check for anoxia w/o LCH4 now done in controlMod. + ! Calculate ANOXIA + ! anoxia = .true. when (use_lch4 .and. use_vertsoilc) - do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + if (anoxia) then - if (j==1) o_scalar(c,:) = 0._r8 + do j = 1,nlev_soildecomp_standard + do fc = 1,num_soilc + c = filter_soilc(fc) - o_scalar(c,1) = o_scalar(c,1) + fr(c,j) * max(o2stress_unsat(c,j), mino2lim) - end do + if (j==1) o_scalar(c,:) = 0._r8 + + o_scalar(c,1) = o_scalar(c,1) + fr(c,j) * max(o2stress_unsat(c,j), mino2lim) end do - else - o_scalar(bounds%begc:bounds%endc,1:nlevdecomp) = 1._r8 - end if + end do else o_scalar(bounds%begc:bounds%endc,1:nlevdecomp) = 1._r8 end if @@ -1042,21 +1039,17 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do - if (use_lch4) then - ! Calculate ANOXIA - ! Check for anoxia w/o LCH4 now done in controlMod. + ! Calculate ANOXIA + ! anoxia = .true. when (use_lch4 .and. use_vertsoilc) - if (anoxia) then - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + if (anoxia) then + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) - o_scalar(c,j) = max(o2stress_unsat(c,j), mino2lim) - end do + o_scalar(c,j) = max(o2stress_unsat(c,j), mino2lim) end do - else - o_scalar(bounds%begc:bounds%endc,1:nlevdecomp) = 1._r8 - end if + end do else o_scalar(bounds%begc:bounds%endc,1:nlevdecomp) = 1._r8 end if @@ -1068,14 +1061,13 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & do j = 1, nlevdecomp do fc = 1, num_soilc c = filter_soilc(fc) - if (use_vertsoilc) then - ! Using fixed e-folding depth as in - ! SoilBiogeochemDecompCascadeBGCMod.F90 +! if (use_vertsoilc) then +! ! Using fixed e-folding depth as in +! ! SoilBiogeochemDecompCascadeBGCMod.F90 ! depth_scalar(c,j) = exp(-zsoi(j) / decomp_depth_efolding) +! else depth_scalar(c,j) = 1.0_r8 - else - depth_scalar(c,j) = 1.0_r8 - end if +! end if end do end do @@ -1124,9 +1116,9 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! tau ends up in units of per hour but is expected ! in units of per second, so convert here; alternatively ! place the conversion once in w_d_o_scalars - tau_m1 = mimics_tau_r_p1 * exp(mimics_tau_r_p2 * fmet) * tau_mod * & + tau_m1 = mimics_tau_r_p1 * exp(mimics_tau_r_p2 * fmet) * tau_mod / & secsphr - tau_m2 = mimics_tau_k_p1 * exp(mimics_tau_k_p2 * fmet) * tau_mod * & + tau_m2 = mimics_tau_k_p1 * exp(mimics_tau_k_p2 * fmet) * tau_mod / & secsphr ! These two get used in SoilBiogeochemPotentialMod.F90 @@ -1149,20 +1141,20 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! place the conversion once in w_d_o_scalars ! Table B1 Wieder et al. 2015 & MIMICS params file give diff ! kslope. I used the params file value(s). - t_soi_degC = t_soisno(c,j) + tfrz + t_soi_degC = t_soisno(c,j) - tfrz vmax_l1_m1 = exp(vslope_l1_m1 * t_soi_degC + vint_l1_m1) * & - vmod_l1_m1 * secsphr + vmod_l1_m1 / secsphr vmax_l1_m2 = exp(vslope_l1_m2 * t_soi_degC + vint_l1_m2) * & - vmod_l1_m2 * secsphr + vmod_l1_m2 / secsphr vmax_l2_m1 = exp(vslope_l2_m1 * t_soi_degC + vint_l2_m1) * & - vmod_l2_m1 * secsphr + vmod_l2_m1 / secsphr vmax_l2_m2 = exp(vslope_l2_m2 * t_soi_degC + vint_l2_m2) * & - vmod_l2_m2 * secsphr + vmod_l2_m2 / secsphr vmax_s1_m1 = exp(vslope_s1_m1 * t_soi_degC + vint_s1_m1) * & - vmod_s1_m1 * secsphr + vmod_s1_m1 / secsphr vmax_s1_m2 = exp(vslope_s1_m2 * t_soi_degC + vint_s1_m2) * & - vmod_s1_m2 * secsphr + vmod_s1_m2 / secsphr km_l1_m1 = exp(kslope_l1_m1 * t_soi_degC + kint_l1_m1) * & kmod_l1_m1 @@ -1181,7 +1173,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Q10 = 1.1 w/ reference temperature of 25C. ! Expected in units of per second, so convert; alternatively ! place the conversion once in w_d_o_scalars - desorption = desorp(c,j) * mimics_desorpQ10 * secsphr * & + desorption = (desorp(c,j) / secsphr) * mimics_desorpQ10 * & exp((t_soi_degC - mimics_t_soi_ref) / 10.0_r8) ! Microbial concentration with necessary unit conversions From 680512ecfe18421047e2e574c5910af049a19394 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 23 Sep 2021 12:44:26 -0600 Subject: [PATCH 45/69] C balance error seems resolved and replaced with N balance error --- src/biogeochem/CNBalanceCheckMod.F90 | 2 +- src/biogeochem/CNDriverMod.F90 | 3 + src/biogeochem/CNVegCarbonFluxType.F90 | 9 +- src/biogeochem/CNVegCarbonStateType.F90 | 7 +- src/main/pftconMod.F90 | 16 +++- .../SoilBiogeochemCarbonFluxType.F90 | 31 +++++++ .../SoilBiogeochemCarbonStateType.F90 | 33 ++++++++ .../SoilBiogeochemPotentialMod.F90 | 84 +++++++++++-------- 8 files changed, 142 insertions(+), 43 deletions(-) diff --git a/src/biogeochem/CNBalanceCheckMod.F90 b/src/biogeochem/CNBalanceCheckMod.F90 index 67e83713c3..c5288c809e 100644 --- a/src/biogeochem/CNBalanceCheckMod.F90 +++ b/src/biogeochem/CNBalanceCheckMod.F90 @@ -325,7 +325,7 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & do g = bounds%begg, bounds%endg ! calculate gridcell-level carbon storage for mass conservation check ! Notes: - ! totgrcc = totcolc = totc_p2c_col(c) + soilbiogeochem_cwdc_col(c) + soilbiogeochem_totlitc_col(c) + soilbiogeochem_totsomc_col(c) + soilbiogeochem_ctrunc_col(c) + ! totgrcc = totcolc = totc_p2c_col(c) + soilbiogeochem_cwdc_col(c) + soilbiogeochem_totlitc_col(c) + soilbiogeochem_totmicc_col(c) + soilbiogeochem_totsomc_col(c) + soilbiogeochem_ctrunc_col(c) ! totc_p2c_col = totc_patch = totvegc_patch(p) + xsmrpool_patch(p) + ctrunc_patch(p) + cropseedc_deficit_patch(p) ! Not including seedc_grc in grc_begcb and grc_endcb because ! seedc_grc forms out of thin air, for now, and equals diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index 936f240d91..091c39c47f 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -948,6 +948,7 @@ subroutine CNDriverSummarizeStates(bounds, num_allc, filter_allc, & num_soilc, filter_soilc, num_soilp, filter_soilp, & soilbiogeochem_cwdc_col=soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & soilbiogeochem_totlitc_col=soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & + soilbiogeochem_totmicc_col=soilbiogeochem_carbonstate_inst%totmicc_col(begc:endc), & soilbiogeochem_totsomc_col=soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & soilbiogeochem_ctrunc_col=soilbiogeochem_carbonstate_inst%ctrunc_col(begc:endc)) @@ -956,6 +957,7 @@ subroutine CNDriverSummarizeStates(bounds, num_allc, filter_allc, & num_soilc, filter_soilc, num_soilp, filter_soilp, & soilbiogeochem_cwdc_col=c13_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & soilbiogeochem_totlitc_col=c13_soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & + soilbiogeochem_totmicc_col=c13_soilbiogeochem_carbonstate_inst%totmicc_col(begc:endc), & soilbiogeochem_totsomc_col=c13_soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & soilbiogeochem_ctrunc_col=c13_soilbiogeochem_carbonstate_inst%ctrunc_col(begc:endc)) end if @@ -965,6 +967,7 @@ subroutine CNDriverSummarizeStates(bounds, num_allc, filter_allc, & num_soilc, filter_soilc, num_soilp, filter_soilp, & soilbiogeochem_cwdc_col=c14_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & soilbiogeochem_totlitc_col=c14_soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & + soilbiogeochem_totmicc_col=c14_soilbiogeochem_carbonstate_inst%totmicc_col(begc:endc), & soilbiogeochem_totsomc_col=c14_soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & soilbiogeochem_ctrunc_col=c14_soilbiogeochem_carbonstate_inst%ctrunc_col(begc:endc)) end if diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index b31578e543..54a6b5f302 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -3416,12 +3416,12 @@ subroutine InitCold(this, bounds) if (lun%ifspecial(l)) then this%annsum_npp_col(c) = spval + this%ligninNratioAvg_col(c) = spval end if - ! also initialize dynamic landcover fluxes so that they have - ! real values on first timestep, prior to calling pftdyn_cnbal if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then this%annsum_npp_col(c) = 0._r8 + this%ligninNratioAvg_col(c) = 0._r8 end if end do @@ -3589,6 +3589,11 @@ subroutine RestartBulkOnly ( this, bounds, ncid, flag ) long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%annsum_npp_col) + call restartvar(ncid=ncid, flag=flag, varname='ligninNratioAvg', xtype=ncd_double, & + dim1name='column', & + long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%ligninNratioAvg_col) + call restartvar(ncid=ncid, flag=flag, varname='tempsum_litfall', xtype=ncd_double, & dim1name='pft', & long_name='', units='', & diff --git a/src/biogeochem/CNVegCarbonStateType.F90 b/src/biogeochem/CNVegCarbonStateType.F90 index b4e69cc089..318f00eac2 100644 --- a/src/biogeochem/CNVegCarbonStateType.F90 +++ b/src/biogeochem/CNVegCarbonStateType.F90 @@ -2392,7 +2392,8 @@ end subroutine ZeroDwt !----------------------------------------------------------------------- subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_cwdc_col, soilbiogeochem_totlitc_col, soilbiogeochem_totsomc_col, & + soilbiogeochem_cwdc_col, soilbiogeochem_totlitc_col, & + soilbiogeochem_totmicc_col, soilbiogeochem_totsomc_col, & soilbiogeochem_ctrunc_col) ! ! !USES: @@ -2413,6 +2414,7 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches real(r8) , intent(in) :: soilbiogeochem_cwdc_col(bounds%begc:) + real(r8) , intent(in) :: soilbiogeochem_totmicc_col(bounds%begc:) real(r8) , intent(in) :: soilbiogeochem_totlitc_col(bounds%begc:) real(r8) , intent(in) :: soilbiogeochem_totsomc_col(bounds%begc:) real(r8) , intent(in) :: soilbiogeochem_ctrunc_col(bounds%begc:) @@ -2423,6 +2425,7 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & !----------------------------------------------------------------------- SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_cwdc_col) == (/bounds%endc/)), sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_totmicc_col) == (/bounds%endc/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_totlitc_col) == (/bounds%endc/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_totsomc_col) == (/bounds%endc/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_ctrunc_col) == (/bounds%endc/)), sourcefile, __LINE__) @@ -2513,6 +2516,7 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & ! total ecosystem carbon, including veg but excluding cpool (TOTECOSYSC) this%totecosysc_col(c) = & soilbiogeochem_cwdc_col(c) + & + soilbiogeochem_totmicc_col(c) + & soilbiogeochem_totlitc_col(c) + & soilbiogeochem_totsomc_col(c) + & this%totvegc_col(c) @@ -2520,6 +2524,7 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & ! total column carbon, including veg and cpool (TOTCOLC) this%totc_col(c) = this%totc_p2c_col(c) + & soilbiogeochem_cwdc_col(c) + & + soilbiogeochem_totmicc_col(c) + & soilbiogeochem_totlitc_col(c) + & soilbiogeochem_totsomc_col(c) + & soilbiogeochem_ctrunc_col(c) diff --git a/src/main/pftconMod.F90 b/src/main/pftconMod.F90 index 27c6375344..9f67500662 100644 --- a/src/main/pftconMod.F90 +++ b/src/main/pftconMod.F90 @@ -506,6 +506,7 @@ subroutine InitRead(this) use ncdio_pio , only : ncd_io, ncd_pio_closefile, ncd_pio_openfile, file_desc_t use ncdio_pio , only : ncd_inqdid, ncd_inqdlen use clm_varctl , only : paramfile, use_fates, use_flexibleCN, use_dynroot, use_biomass_heat_storage + use clm_varctl , only : use_mimics_decomp use spmdMod , only : masterproc use CLMFatesParamInterfaceMod, only : FatesReadPFTs ! @@ -765,11 +766,18 @@ subroutine InitRead(this) ! in do-loops. While executing the next few lines, we do not yet have access ! to i_litr_min, i_litr_max. this%fr_f(:,1) = this%fr_flab - this%fr_f(:,2) = this%fr_fcel - this%fr_f(:,3) = this%fr_flig this%lf_f(:,1) = this%lf_flab - this%lf_f(:,2) = this%lf_fcel - this%lf_f(:,3) = this%lf_flig + if (use_mimics_decomp) then + this%fr_f(:,2) = this%fr_fcel + this%fr_flig + this%fr_f(:,3) = 0.0_r8 + this%lf_f(:,2) = this%lf_fcel + this%lf_flig + this%lf_f(:,3) = 0.0_r8 + else + this%fr_f(:,2) = this%fr_fcel + this%fr_f(:,3) = this%fr_flig + this%lf_f(:,2) = this%lf_fcel + this%lf_f(:,3) = this%lf_flig + end if call ncd_io('leaf_long', this%leaf_long, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 index cf03f853a0..b689c55784 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 @@ -47,6 +47,7 @@ module SoilBiogeochemCarbonFluxType real(r8), pointer :: fphr_col (:,:) ! fraction of potential heterotrophic respiration real(r8), pointer :: hr_col (:) ! (gC/m2/s) total heterotrophic respiration + real(r8), pointer :: michr_col (:) ! (gC/m2/s) microbial heterotrophic respiration real(r8), pointer :: cwdhr_col (:) ! (gC/m2/s) coarse woody debris heterotrophic respiration real(r8), pointer :: lithr_col (:) ! (gC/m2/s) litter heterotrophic respiration real(r8), pointer :: somhr_col (:) ! (gC/m2/s) soil organic matter heterotrophic res @@ -147,6 +148,7 @@ subroutine InitAllocate(this, bounds) this%decomp_cpools_transport_tendency_col(:,:,:)= nan allocate(this%hr_col (begc:endc)) ; this%hr_col (:) = nan + allocate(this%michr_col (begc:endc)) ; this%michr_col (:) = nan allocate(this%cwdhr_col (begc:endc)) ; this%cwdhr_col (:) = nan allocate(this%lithr_col (begc:endc)) ; this%lithr_col (:) = nan allocate(this%somhr_col (begc:endc)) ; this%somhr_col (:) = nan @@ -222,6 +224,11 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='total heterotrophic respiration', & ptr_col=this%hr_col) + this%michr_col(begc:endc) = spval + call hist_addfld1d (fname='MICC_HR', units='gC/m^2/s', & + avgflag='A', long_name='microbial C heterotrophic respiration', & + ptr_col=this%michr_col) + this%cwdhr_col(begc:endc) = spval call hist_addfld1d (fname='CWDC_HR', units='gC/m^2/s', & avgflag='A', long_name='cwd C heterotrophic respiration', & @@ -434,6 +441,11 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 total heterotrophic respiration', & ptr_col=this%hr_col) + this%michr_col(begc:endc) = spval + call hist_addfld1d (fname='C13_MICC_HR', units='gC13/m^2/s', & + avgflag='A', long_name='C13 microbial heterotrophic respiration', & + ptr_col=this%michr_col, default='inactive') + this%cwdhr_col(begc:endc) = spval call hist_addfld1d (fname='C13_CWDC_HR', units='gC/m^2/s', & avgflag='A', long_name='C13 cwd C heterotrophic respiration', & @@ -508,6 +520,11 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C14 total heterotrophic respiration', & ptr_col=this%hr_col) + this%michr_col(begc:endc) = spval + call hist_addfld1d (fname='C14_MICC_HR', units='gC13/m^2/s', & + avgflag='A', long_name='C14 microbial heterotrophic respiration', & + ptr_col=this%michr_col, default='inactive') + this%cwdhr_col(begc:endc) = spval call hist_addfld1d (fname='C14_CWDC_HR', units='gC/m^2/s', & avgflag='A', long_name='C14 cwd C heterotrophic respiration', & @@ -775,6 +792,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) this%somhr_col(i) = value_column this%lithr_col(i) = value_column this%cwdhr_col(i) = value_column + this%michr_col(i) = value_column this%soilc_change_col(i) = value_column end do @@ -894,11 +912,24 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) end do end associate + ! microbial heterotrophic respiration (MICHR) + associate(is_microbe => decomp_cascade_con%is_microbe) ! TRUE => pool is a microbial pool + do k = 1, ndecomp_cascade_transitions + if ( is_microbe(decomp_cascade_con%cascade_donor_pool(k)) ) then + do fc = 1,num_soilc + c = filter_soilc(fc) + this%michr_col(c) = this%michr_col(c) + this%decomp_cascade_hr_col(c,k) + end do + end if + end do + end associate + ! total heterotrophic respiration (HR) do fc = 1,num_soilc c = filter_soilc(fc) this%hr_col(c) = & + this%michr_col(c) + & this%cwdhr_col(c) + & this%lithr_col(c) + & this%somhr_col(c) diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 index dcf36fb537..589668a6cc 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 @@ -30,6 +30,7 @@ module SoilBiogeochemCarbonStateType ! summary (diagnostic) state variables, not involved in mass balance real(r8), pointer :: ctrunc_col (:) ! (gC/m2) column-level sink for C truncation + real(r8), pointer :: totmicc_col (:) ! (gC/m2) total microbial carbon real(r8), pointer :: totlitc_col (:) ! (gC/m2) total litter carbon real(r8), pointer :: totlitc_1m_col (:) ! (gC/m2) total litter carbon to 1 meter real(r8), pointer :: totsomc_col (:) ! (gC/m2) total soil organic matter carbon @@ -110,6 +111,7 @@ subroutine InitAllocate(this, bounds) if ( .not. use_fates ) then allocate(this%cwdc_col (begc :endc)) ; this%cwdc_col (:) = nan endif + allocate(this%totmicc_col (begc :endc)) ; this%totmicc_col (:) = nan allocate(this%totlitc_col (begc :endc)) ; this%totlitc_col (:) = nan allocate(this%totsomc_col (begc :endc)) ; this%totsomc_col (:) = nan allocate(this%totlitc_1m_col (begc :endc)) ; this%totlitc_1m_col (:) = nan @@ -183,6 +185,11 @@ subroutine InitHistory(this, bounds, carbon_type) endif end do + this%totmicc_col(begc:endc) = spval + call hist_addfld1d (fname='TOTMICC', units='gC/m^2', & + avgflag='A', long_name='total microbial carbon', & + ptr_col=this%totmicc_col) + this%totlitc_col(begc:endc) = spval call hist_addfld1d (fname='TOTLITC', units='gC/m^2', & avgflag='A', long_name='total litter carbon', & @@ -253,6 +260,11 @@ subroutine InitHistory(this, bounds, carbon_type) ptr_col=data1dptr, default='inactive') end do + this%totmicc_col(begc:endc) = spval + call hist_addfld1d (fname='C13_TOTMICC', units='gC/m^2', & + avgflag='A', long_name='C13 total microbial carbon', & + ptr_col=this%totmicc_col) + this%totlitc_col(begc:endc) = spval call hist_addfld1d (fname='C13_TOTLITC', units='gC13/m^2', & avgflag='A', long_name='C13 total litter carbon', & @@ -328,6 +340,11 @@ subroutine InitHistory(this, bounds, carbon_type) endif end do + this%totmicc_col(begc:endc) = spval + call hist_addfld1d (fname='C14_TOTMICC', units='gC/m^2', & + avgflag='A', long_name='C14 total microbial carbon', & + ptr_col=this%totmicc_col) + this%totlitc_col(begc:endc) = spval call hist_addfld1d (fname='C14_TOTLITC', units='gC14/m^2', & avgflag='A', long_name='C14 total litter carbon', & @@ -447,6 +464,7 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) this%cwdc_col(c) = 0._r8 end if this%ctrunc_col(c) = 0._r8 + this%totmicc_col(c) = 0._r8 this%totlitc_col(c) = 0._r8 this%totsomc_col(c) = 0._r8 this%totlitc_1m_col(c) = 0._r8 @@ -760,6 +778,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) this%cwdc_col(i) = value_column end if this%ctrunc_col(i) = value_column + this%totmicc_col(i) = value_column this%totlitc_col(i) = value_column this%totlitc_1m_col(i) = value_column this%totsomc_col(i) = value_column @@ -928,6 +947,20 @@ subroutine Summary(this, bounds, num_allc, filter_allc) end do end if + ! total microbial carbon (TOTMICC) + do fc = 1,num_allc + c = filter_allc(fc) + this%totmicc_col(c) = 0._r8 + end do + do l = 1, ndecomp_pools + if ( decomp_cascade_con%is_microbe(l) ) then + do fc = 1,num_allc + c = filter_allc(fc) + this%totmicc_col(c) = this%totmicc_col(c) + this%decomp_cpools_col(c,l) + end do + endif + end do + ! total litter carbon (TOTLITC) do fc = 1,num_allc c = filter_allc(fc) diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index a39a88f3cd..7eb4328001 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -215,13 +215,13 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & p_decomp_npool_loss * nue_decomp_cascade(k) p_decomp_npool_to_din(c,j,k) = & p_decomp_npool_loss - p_decomp_npool_gain(c,j,k) - end if - end if - end if - end do + end if ! using mimics + end if ! floating_cn_ratio_decomp_pools = .true. + end if ! donors donating (decomp_cpools_vr and decomp_k > 0) + end do ! column loop - end do - end do + end do ! soil level loop + end do ! transitions loop ! Determine immobilization vs. mineralization by comparing the ! cn_gain into microbial biomass compared with the target C:N @@ -233,41 +233,53 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! Sum C & N fluxes from all transitions into m1 & m2 pools. ! Had to form a new loop for the summation due to the order ! necessary, ie do k as the innermost loop. + p_decomp_cpool_gain_sum(:) = 0.0_r8 + p_decomp_npool_gain_sum(:) = 0.0_r8 do k = 1, ndecomp_cascade_transitions if (cascade_receiver_pool(k) == i_cop_mic .or. & cascade_receiver_pool(k) == i_oli_mic) then - p_decomp_cpool_gain_sum(cascade_receiver_pool(k)) = & - p_decomp_cpool_gain_sum(cascade_receiver_pool(k)) + & - p_decomp_cpool_gain(c,j,k) - p_decomp_npool_gain_sum(cascade_receiver_pool(k)) = & - p_decomp_npool_gain_sum(cascade_receiver_pool(k)) + & - p_decomp_npool_gain(c,j,k) - ! Once k-loop completes, the left hand side should end up - ! with the correct cn ratio - if (p_decomp_npool_gain_sum(cascade_receiver_pool(k)) > 0.0_r8) then - p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) = & - p_decomp_cpool_gain_sum(cascade_receiver_pool(k)) / & - p_decomp_npool_gain_sum(cascade_receiver_pool(k)) - end if - end if - end do + if (decomp_cpools_vr(c,j,cascade_donor_pool(k)) > 0._r8 .and. & + decomp_k(c,j,cascade_donor_pool(k)) > 0._r8 ) then + p_decomp_cpool_gain_sum(cascade_receiver_pool(k)) = & + p_decomp_cpool_gain_sum(cascade_receiver_pool(k)) + & + p_decomp_cpool_gain(c,j,k) + p_decomp_npool_gain_sum(cascade_receiver_pool(k)) = & + p_decomp_npool_gain_sum(cascade_receiver_pool(k)) + & + p_decomp_npool_gain(c,j,k) + ! Once k-loop completes, the left hand side should end + ! up with the correct cn ratio + if (p_decomp_npool_gain_sum(cascade_receiver_pool(k)) > 0.0_r8) then + p_decomp_cn_gain(c,j,k) = & + p_decomp_cpool_gain_sum(cascade_receiver_pool(k)) / & + p_decomp_npool_gain_sum(cascade_receiver_pool(k)) + else + p_decomp_cn_gain(c,j,k) = 0.0_r8 + end if ! denominator check + end if ! donors donating (decomp_cpools_vr & decomp_k > 0) + end if ! microbes receiving + end do ! transitions loop do k = 1, ndecomp_cascade_transitions if (cascade_receiver_pool(k) == i_cop_mic .or. & cascade_receiver_pool(k) == i_oli_mic) then - ! if p_decomp_cn_diff < 0 N mineralization - ! > 0 immobilization - p_decomp_cn_diff_ratio = & - (p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) - & - cn_col(c,cascade_receiver_pool(k))) / cn_col(c,cascade_receiver_pool(k)) - ! Actual amount of N that's mineralized or that would need to be immobilized - ! negative=mineralization: add to the DIN pool - ! positive=immobilizaiton: compete for N with plants to see how much we get - pmnf_decomp_cascade(c,j,k) = p_decomp_cn_diff_ratio * p_decomp_npool_gain(c,j,k) - end if - end do - end do - end do - end if + if (decomp_cpools_vr(c,j,cascade_donor_pool(k)) > 0._r8 .and. & + decomp_k(c,j,cascade_donor_pool(k)) > 0._r8 ) then + ! if p_decomp_cn_diff < 0 N mineralization + ! > 0 immobilization + p_decomp_cn_diff_ratio = max(0.0_r8, & + (p_decomp_cn_gain(c,j,k) - & + cn_col(c,cascade_receiver_pool(k))) / cn_col(c,cascade_receiver_pool(k))) + ! Actual amount of N that's mineralized or that would + ! need to be immobilized + ! negative=mineralization: add to the DIN pool + ! positive=immobilizaiton: compete for N with plants to + ! see how much we get + pmnf_decomp_cascade(c,j,k) = p_decomp_cn_diff_ratio * p_decomp_npool_gain(c,j,k) + end if ! donors donating (decomp_cpools_vr & decomp_k > 0) + end if ! microbes receiving + end do ! transitions loop + end do ! column loop + end do ! soil levels loop + end if ! using mimics ! Sum up all the potential immobilization fluxes (positive pmnf flux) ! and all the mineralization fluxes (negative pmnf flux) @@ -288,6 +300,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & end if if (use_mimics_decomp) then gross_nmin_vr(c,j) = gross_nmin_vr(c,j) + p_decomp_npool_to_din(c,j,k) + if (c == 1) write(iulog,*) 'gross_nmin_vr, p_decomp_npool_to_din, c,j' ! slevis diag + if (c == 1) write(iulog,*) gross_nmin_vr(c,j), p_decomp_npool_to_din(c,j,k), c,j,k ! slevis diag end if end do end do From c5229161ada0eb783375d2c91c6379e105000c52 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 23 Sep 2021 15:17:20 -0600 Subject: [PATCH 46/69] Now past the big N balance error but still getting small one --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 5 ++++- src/soilbiogeochem/SoilBiogeochemDecompMod.F90 | 2 ++ src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 | 8 +++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 1f69bafc5e..8b56289ae3 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -180,12 +180,13 @@ subroutine readParams ( ncid ) ! TODO Need next one for spin-ups? If so, then add prefixes ! mimics here and bgc in BGCMod if these two will differ or ! move reading the parameter to CNSharedParamsMod if they - ! will not differ. Similar for both initial_Cstocks params. + ! will not differ. tString='initial_Cstocks_depth_bgc' call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%initial_Cstocks_depth=tempr + ! TODO initial_Cstocks definitely needs to differ: mimics_ vs. bgc_ allocate(params_inst%initial_Cstocks(ndecomp_pools_max)) tString='initial_Cstocks_bgc' call ncd_io(trim(tString), params_inst%initial_Cstocks(:), 'read', ncid, readvar=readv) @@ -1192,6 +1193,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & term_1 = vmax_l1_m1 * m1_conc / (km_l1_m1 + m1_conc) term_2 = vmax_l1_m2 * m2_conc / (km_l1_m2 + m2_conc) decomp_k(c,j,i_met_lit) = (term_1 + term_2) * w_d_o_scalars + ! TODO May need if-statment for all cases that term_1 +/ term_2 + ! are zero bc biomass would never flow into such pools in that case pathfrac_decomp_cascade(c,j,i_l1m1) = term_1 / (term_1 + term_2) pathfrac_decomp_cascade(c,j,i_l1m2) = term_2 / (term_1 + term_2) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 index c6feb26bfb..3d1bd5a8ab 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 @@ -183,6 +183,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, end if end if decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) + c_overflow_vr(c,j,k) + ! TODO slevis: Should the next line also account for + ! c_overflow_vr? If so, repeat for fates below decomp_cascade_ctransfer_vr(c,j,k) = (1._r8 - rf_decomp_cascade(c,j,k)) * p_decomp_cpool_loss(c,j,k) if (decomp_npools_vr(c,j,cascade_donor_pool(k)) > 0._r8 .and. cascade_receiver_pool(k) /= i_atm) then decomp_cascade_ntransfer_vr(c,j,k) = p_decomp_cpool_loss(c,j,k) / cn_decomp_pools(c,j,cascade_donor_pool(k)) diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index 7eb4328001..2bedbff802 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -217,7 +217,11 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & p_decomp_npool_loss - p_decomp_npool_gain(c,j,k) end if ! using mimics end if ! floating_cn_ratio_decomp_pools = .true. - end if ! donors donating (decomp_cpools_vr and decomp_k > 0) + else ! donors not donating + p_decomp_cpool_gain(c,j,k) = 0.0_r8 + p_decomp_npool_gain(c,j,k) = 0.0_r8 + p_decomp_npool_to_din(c,j,k) = 0.0_r8 + end if ! donors donating? (ie decomp_cpools_vr & decomp_k > 0) end do ! column loop end do ! soil level loop @@ -300,8 +304,6 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & end if if (use_mimics_decomp) then gross_nmin_vr(c,j) = gross_nmin_vr(c,j) + p_decomp_npool_to_din(c,j,k) - if (c == 1) write(iulog,*) 'gross_nmin_vr, p_decomp_npool_to_din, c,j' ! slevis diag - if (c == 1) write(iulog,*) gross_nmin_vr(c,j), p_decomp_npool_to_din(c,j,k), c,j,k ! slevis diag end if end do end do From 3ce2163d52d223927b4c408625f716a715627c4d Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 12 Oct 2021 19:17:39 -0600 Subject: [PATCH 47/69] Small changes that seem necessary for N balance though still looking... --- .../clm/mimics/include_user_mods | 2 +- src/biogeochem/CNDriverMod.F90 | 7 ++-- src/biogeochem/EDBGCDynMod.F90 | 7 ++-- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 8 +++++ .../SoilBiogeochemDecompMod.F90 | 32 +++++++++++++++---- .../SoilBiogeochemPotentialMod.F90 | 6 ++-- 6 files changed, 48 insertions(+), 14 deletions(-) diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/mimics/include_user_mods index fe0e18cf88..3dbc936366 100644 --- a/cime_config/testdefs/testmods_dirs/clm/mimics/include_user_mods +++ b/cime_config/testdefs/testmods_dirs/clm/mimics/include_user_mods @@ -1 +1 @@ -../default +../coldStart diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index 091c39c47f..48092ed8a4 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -201,6 +201,7 @@ subroutine CNDriverNoLeaching(bounds, real(r8):: cn_decomp_pools(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) real(r8):: p_decomp_cpool_loss(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential C loss from one pool to another real(r8):: pmnf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential mineral N flux, from one pool to another + real(r8):: p_decomp_npool_to_din(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential flux to dissolved inorganic N real(r8):: p_decomp_cn_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! C:N ratio of the flux gained by the receiver pool real(r8):: arepr(bounds%begp:bounds%endp) ! reproduction allocation coefficient (only used for use_crop) real(r8):: aroot(bounds%begp:bounds%endp) ! root allocation coefficient (only used for use_crop) @@ -332,7 +333,8 @@ subroutine CNDriverNoLeaching(bounds, cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) + pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & + p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) ! calculate vertical profiles for distributing soil and litter C and N (previously subroutine decomp_vertprofiles called from CNDecompAlloc) call SoilBiogeochemVerticalProfile(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & @@ -447,7 +449,8 @@ subroutine CNDriverNoLeaching(bounds, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) + pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & + p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) call t_stopf('SoilBiogeochemDecomp') diff --git a/src/biogeochem/EDBGCDynMod.F90 b/src/biogeochem/EDBGCDynMod.F90 index 5e006719bd..c74c024b14 100644 --- a/src/biogeochem/EDBGCDynMod.F90 +++ b/src/biogeochem/EDBGCDynMod.F90 @@ -115,6 +115,7 @@ subroutine EDBGCDyn(bounds, & real(r8):: cn_decomp_pools(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) real(r8):: p_decomp_cpool_loss(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential C loss from one pool to another real(r8):: pmnf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential mineral N flux, from one pool to another + real(r8):: p_decomp_npool_to_din(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential flux to dissolved inorganic N real(r8):: p_decomp_cn_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! C:N ratio of the flux gained by the receiver pool real(r8):: arepr(bounds%begp:bounds%endp) ! reproduction allocation coefficient (only used for crop_prog) real(r8):: aroot(bounds%begp:bounds%endp) ! root allocation coefficient (only used for crop_prog) @@ -199,7 +200,8 @@ subroutine EDBGCDyn(bounds, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) + pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & + p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) !-------------------------------------------- @@ -223,7 +225,8 @@ subroutine EDBGCDyn(bounds, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) + pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & + p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) call t_stopf('SoilBiogeochemDecomp') diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 8b56289ae3..ecdb3cd897 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -489,6 +489,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_met_lit) = .false. initial_cn_ratio(i_met_lit) = 10._r8 ! 90 in BGC; not used in MIMICS initial_stock(i_met_lit) = params_inst%initial_Cstocks(i_met_lit) + initial_stock(i_met_lit) = 1._r8 ! slevis diag is_metabolic(i_met_lit) = .true. is_cellulose(i_met_lit) = .false. is_lignin(i_met_lit) = .false. @@ -505,6 +506,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_str_lit) = .false. initial_cn_ratio(i_str_lit) = 10._r8 ! 90 in BGC; not used in MIMICS initial_stock(i_str_lit) = params_inst%initial_Cstocks(i_str_lit) + initial_stock(i_str_lit) = 1._r8 ! slevis diag is_metabolic(i_str_lit) = .false. is_cellulose(i_str_lit) = .true. is_lignin(i_str_lit) = .true. @@ -531,6 +533,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_avl_som) = .false. initial_cn_ratio(i_avl_som) = 10._r8 ! cn_s1 in BGC; not used in MIMICS initial_stock(i_avl_som) = params_inst%initial_Cstocks(i_avl_som) + initial_stock(i_avl_som) = 200._r8 ! slevis diag is_metabolic(i_avl_som) = .false. is_cellulose(i_avl_som) = .false. is_lignin(i_avl_som) = .false. @@ -547,6 +550,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_chem_som) = .false. initial_cn_ratio(i_chem_som) = 10._r8 ! cn_s2 in BGC; not used in MIMICS initial_stock(i_chem_som) = params_inst%initial_Cstocks(i_chem_som) + initial_stock(i_chem_som) = 200._r8 ! slevis diag is_metabolic(i_chem_som) = .false. is_cellulose(i_chem_som) = .false. is_lignin(i_chem_som) = .false. @@ -563,6 +567,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_phys_som) = .false. initial_cn_ratio(i_phys_som) = 10._r8 ! cn_s3 in BGC; not used in MIMICS initial_stock(i_phys_som) = params_inst%initial_Cstocks(i_phys_som) + initial_stock(i_phys_som) = 200._r8 ! slevis diag is_metabolic(i_phys_som) = .false. is_cellulose(i_phys_som) = .false. is_lignin(i_phys_som) = .false. @@ -579,6 +584,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_cop_mic) = .false. initial_cn_ratio(i_cop_mic) = 10._r8 ! MIMICS may use this initial_stock(i_cop_mic) = params_inst%initial_Cstocks(i_cop_mic) + initial_stock(i_cop_mic) = 1._r8 ! slevis diag is_metabolic(i_cop_mic) = .false. is_cellulose(i_cop_mic) = .false. is_lignin(i_cop_mic) = .false. @@ -595,6 +601,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_oli_mic) = .false. initial_cn_ratio(i_oli_mic) = 10._r8 ! MIMICS may use this initial_stock(i_oli_mic) = params_inst%initial_Cstocks(i_oli_mic) + initial_stock(i_oli_mic) = 1._r8 ! slevis diag is_metabolic(i_oli_mic) = .false. is_cellulose(i_oli_mic) = .false. is_lignin(i_oli_mic) = .false. @@ -613,6 +620,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_cwd) = .true. initial_cn_ratio(i_cwd) = 10._r8 ! 90 in BGC; not used in MIMICS initial_stock(i_cwd) = params_inst%initial_Cstocks(i_cwd) + initial_stock(i_cwd) = 1._r8 ! slevis diag is_metabolic(i_cwd) = .false. is_cellulose(i_cwd) = .false. is_lignin(i_cwd) = .false. diff --git a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 index 3d1bd5a8ab..431389e3f7 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 @@ -11,7 +11,7 @@ module SoilBiogeochemDecompMod use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type use clm_varpar , only : nlevdecomp, ndecomp_cascade_transitions, ndecomp_pools - use clm_varctl , only : use_nitrif_denitrif, use_lch4, use_fates + use clm_varctl , only : use_nitrif_denitrif, use_lch4, use_fates, use_mimics_decomp, iulog use clm_varcon , only : dzsoi_decomp use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con use SoilBiogeochemStateType , only : soilbiogeochem_state_type @@ -70,7 +70,8 @@ end subroutine readParams subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & - cn_decomp_pools, p_decomp_cpool_loss, pmnf_decomp_cascade) + cn_decomp_pools, p_decomp_cpool_loss, pmnf_decomp_cascade, & + p_decomp_npool_to_din) ! ! !USES: use SoilBiogeochemDecompCascadeConType, only : i_atm @@ -87,6 +88,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, real(r8) , intent(inout) :: cn_decomp_pools(bounds%begc:,1:,1:) ! c:n ratios of applicable pools real(r8) , intent(inout) :: p_decomp_cpool_loss(bounds%begc:,1:,1:) ! potential C loss from one pool to another real(r8) , intent(inout) :: pmnf_decomp_cascade(bounds%begc:,1:,1:) ! potential mineral N flux from one pool to another + real(r8) , intent(inout) :: p_decomp_npool_to_din(bounds%begc:,1:,1:) ! potential flux to dissolved inorganic N ! ! !LOCAL VARIABLES: integer :: c,j,k,l,m ! indices @@ -101,6 +103,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, SHR_ASSERT_ALL_FL((ubound(cn_decomp_pools) == (/endc,nlevdecomp,ndecomp_pools/)) , sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(p_decomp_cpool_loss) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(pmnf_decomp_cascade) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(p_decomp_npool_to_din) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) associate( & cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Input: [integer (:) ] which pool is C taken from for a given decomposition step @@ -182,10 +185,14 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, sminn_to_denit_decomp_cascade_vr(c,j,k) = -params_inst%dnp * pmnf_decomp_cascade(c,j,k) end if end if - decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) + c_overflow_vr(c,j,k) - ! TODO slevis: Should the next line also account for - ! c_overflow_vr? If so, repeat for fates below + decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) decomp_cascade_ctransfer_vr(c,j,k) = (1._r8 - rf_decomp_cascade(c,j,k)) * p_decomp_cpool_loss(c,j,k) + if (use_mimics_decomp) then + decomp_cascade_hr_vr(c,j,k) = min( & + p_decomp_cpool_loss(c,j,k), & + decomp_cascade_hr_vr(c,j,k) + c_overflow_vr(c,j,k)) + decomp_cascade_ctransfer_vr(c,j,k) = max(0.0_r8, p_decomp_cpool_loss(c,j,k) - decomp_cascade_hr_vr(c,j,k)) + end if if (decomp_npools_vr(c,j,cascade_donor_pool(k)) > 0._r8 .and. cascade_receiver_pool(k) /= i_atm) then decomp_cascade_ntransfer_vr(c,j,k) = p_decomp_cpool_loss(c,j,k) / cn_decomp_pools(c,j,cascade_donor_pool(k)) else @@ -197,6 +204,12 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, decomp_cascade_sminn_flux_vr(c,j,k) = - pmnf_decomp_cascade(c,j,k) endif net_nmin_vr(c,j) = net_nmin_vr(c,j) - pmnf_decomp_cascade(c,j,k) +! TODO slevis: NEED THIS if-block? If so, need anything additional that +! is done to pmnf_decomp_cascade or other? + if (use_mimics_decomp) then + decomp_cascade_sminn_flux_vr(c,j,k) = decomp_cascade_sminn_flux_vr(c,j,k) + p_decomp_npool_to_din(c,j,k) + net_nmin_vr(c,j) = net_nmin_vr(c,j) + p_decomp_npool_to_din(c,j,k) + end if else decomp_cascade_ntransfer_vr(c,j,k) = 0._r8 if (.not. use_nitrif_denitrif) then @@ -214,9 +227,14 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, do fc = 1,num_soilc c = filter_soilc(fc) ! - decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) + c_overflow_vr(c,j,k) - ! + decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) decomp_cascade_ctransfer_vr(c,j,k) = (1._r8 - rf_decomp_cascade(c,j,k)) * p_decomp_cpool_loss(c,j,k) + if (use_mimics_decomp) then + decomp_cascade_hr_vr(c,j,k) = min( & + p_decomp_cpool_loss(c,j,k), & + decomp_cascade_hr_vr(c,j,k) + c_overflow_vr(c,j,k)) + decomp_cascade_ctransfer_vr(c,j,k) = max(0.0_r8, p_decomp_cpool_loss(c,j,k) - decomp_cascade_hr_vr(c,j,k)) + end if ! end do end do diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index 2bedbff802..7bb26ae922 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -71,7 +71,8 @@ end subroutine readParams subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & - cn_decomp_pools, p_decomp_cpool_loss, p_decomp_cn_gain, pmnf_decomp_cascade) + cn_decomp_pools, p_decomp_cpool_loss, p_decomp_cn_gain, & + pmnf_decomp_cascade, p_decomp_npool_to_din) ! ! !USES: use shr_log_mod , only : errMsg => shr_log_errMsg @@ -89,6 +90,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & real(r8) , intent(out) :: cn_decomp_pools(bounds%begc:,1:,1:) ! c:n ratios of applicable pools real(r8) , intent(out) :: p_decomp_cpool_loss(bounds%begc:,1:,1:) ! potential C loss from one pool to another real(r8) , intent(out) :: pmnf_decomp_cascade(bounds%begc:,1:,1:) ! potential mineral N flux, from one pool to another + real(r8) , intent(out) :: p_decomp_npool_to_din(bounds%begc:,1:,1:) ! potential flux to dissolved inorganic N real(r8) , intent(out) :: p_decomp_cn_gain(bounds%begc:,1:,1:) ! C:N ratio of the flux gained by the receiver pool ! ! !LOCAL VARIABLES: @@ -98,7 +100,6 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & real(r8):: immob(bounds%begc:bounds%endc,1:nlevdecomp) !potential N immobilization real(r8):: p_decomp_cpool_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential C gain by receiver pool real(r8):: p_decomp_npool_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential N gain by receiver pool - real(r8):: p_decomp_npool_to_din(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential flux to dissolved inorganic N real(r8):: p_decomp_cpool_gain_sum(1:ndecomp_pools) ! total potential C gain by receiver pool (only microbial pools) real(r8):: p_decomp_npool_gain_sum(1:ndecomp_pools) ! total potential N gain by receiver pool (only microbial pools) real(r8):: decomp_nc_loss_donor ! N:C ratio of donor pool @@ -113,6 +114,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & SHR_ASSERT_ALL_FL((ubound(p_decomp_cn_gain) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(p_decomp_cpool_loss) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(pmnf_decomp_cascade) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(p_decomp_npool_to_din) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) associate( & cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Input: [integer (:) ] which pool is C taken from for a given decomposition step From e037adf491ecc044740ec19600fea4a6ec737098 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 19 Oct 2021 13:08:32 -0600 Subject: [PATCH 48/69] Adding totmicn to the N balance; still not fixed though --- src/biogeochem/CNBalanceCheckMod.F90 | 2 +- src/biogeochem/CNVegNitrogenStateType.F90 | 2 ++ .../SoilBiogeochemNitrogenStateType.F90 | 25 +++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/biogeochem/CNBalanceCheckMod.F90 b/src/biogeochem/CNBalanceCheckMod.F90 index c5288c809e..925c3479d0 100644 --- a/src/biogeochem/CNBalanceCheckMod.F90 +++ b/src/biogeochem/CNBalanceCheckMod.F90 @@ -540,7 +540,7 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & write(iulog,*)'output mass = ',col_noutputs(c)*dt write(iulog,*)'net flux = ',(col_ninputs(c)-col_noutputs(c))*dt write(iulog,*)'inputs,ffix,nfix,ndep = ',ffix_to_sminn(c)*dt,nfix_to_sminn(c)*dt,ndep_to_sminn(c)*dt - write(iulog,*)'outputs,ffix,nfix,ndep = ',smin_no3_leached(c)*dt, smin_no3_runoff(c)*dt,f_n2o_nit(c)*dt + write(iulog,*)'outputs,lch,roff,dnit = ',smin_no3_leached(c)*dt, smin_no3_runoff(c)*dt,f_n2o_nit(c)*dt call endrun(subgrid_index=c, subgrid_level=subgrid_level_column, msg=errMsg(sourcefile, __LINE__)) end if diff --git a/src/biogeochem/CNVegNitrogenStateType.F90 b/src/biogeochem/CNVegNitrogenStateType.F90 index 1a74c6c7f1..f8d491faf4 100644 --- a/src/biogeochem/CNVegNitrogenStateType.F90 +++ b/src/biogeochem/CNVegNitrogenStateType.F90 @@ -1038,6 +1038,7 @@ subroutine Summary_nitrogenstate(this, bounds, num_allc, filter_allc, & this%totecosysn_col(c) = & soilbiogeochem_nitrogenstate_inst%cwdn_col(c) + & soilbiogeochem_nitrogenstate_inst%totlitn_col(c) + & + soilbiogeochem_nitrogenstate_inst%totmicn_col(c) + & soilbiogeochem_nitrogenstate_inst%totsomn_col(c) + & soilbiogeochem_nitrogenstate_inst%sminn_col(c) + & this%totvegn_col(c) @@ -1047,6 +1048,7 @@ subroutine Summary_nitrogenstate(this, bounds, num_allc, filter_allc, & this%totn_col(c) = this%totn_p2c_col(c) + & soilbiogeochem_nitrogenstate_inst%cwdn_col(c) + & soilbiogeochem_nitrogenstate_inst%totlitn_col(c) + & + soilbiogeochem_nitrogenstate_inst%totmicn_col(c) + & soilbiogeochem_nitrogenstate_inst%totsomn_col(c) + & soilbiogeochem_nitrogenstate_inst%sminn_col(c) + & soilbiogeochem_nitrogenstate_inst%ntrunc_col(c) diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 index 23781a8782..3a676505d0 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 @@ -46,6 +46,7 @@ module SoilBiogeochemNitrogenStateType real(r8), pointer :: ntrunc_col (:) ! col (gN/m2) column-level sink for N truncation real(r8), pointer :: cwdn_col (:) ! col (gN/m2) Diagnostic: coarse woody debris N real(r8), pointer :: totlitn_col (:) ! col (gN/m2) total litter nitrogen + real(r8), pointer :: totmicn_col (:) ! col (gN/m2) total microbial nitrogen real(r8), pointer :: totsomn_col (:) ! col (gN/m2) total soil organic matter nitrogen real(r8), pointer :: totlitn_1m_col (:) ! col (gN/m2) total litter nitrogen to 1 meter real(r8), pointer :: totsomn_1m_col (:) ! col (gN/m2) total soil organic matter nitrogen to 1 meter @@ -120,6 +121,7 @@ subroutine InitAllocate(this, bounds) allocate(this%sminn_col (begc:endc)) ; this%sminn_col (:) = nan allocate(this%ntrunc_col (begc:endc)) ; this%ntrunc_col (:) = nan allocate(this%totlitn_col (begc:endc)) ; this%totlitn_col (:) = nan + allocate(this%totmicn_col (begc:endc)) ; this%totmicn_col (:) = nan allocate(this%totsomn_col (begc:endc)) ; this%totsomn_col (:) = nan allocate(this%totlitn_1m_col (begc:endc)) ; this%totlitn_1m_col (:) = nan allocate(this%totsomn_1m_col (begc:endc)) ; this%totsomn_1m_col (:) = nan @@ -277,6 +279,11 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='total litter N', & ptr_col=this%totlitn_col) + this%totmicn_col(begc:endc) = spval + call hist_addfld1d (fname='TOTMICN', units='gN/m^2', & + avgflag='A', long_name='total microbial N', & + ptr_col=this%totmicn_col) + this%totsomn_col(begc:endc) = spval call hist_addfld1d (fname='TOTSOMN', units='gN/m^2', & avgflag='A', long_name='total soil organic matter N', & @@ -368,6 +375,7 @@ subroutine InitCold(this, bounds, & this%smin_no3_col(c) = 0._r8 end if this%totlitn_col(c) = 0._r8 + this%totmicn_col(c) = 0._r8 this%totsomn_col(c) = 0._r8 this%totlitn_1m_col(c) = 0._r8 this%totsomn_1m_col(c) = 0._r8 @@ -696,6 +704,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column ) this%smin_nh4_col(i) = value_column end if this%totlitn_col(i) = value_column + this%totmicn_col(i) = value_column this%totsomn_col(i) = value_column this%totsomn_1m_col(i) = value_column this%totlitn_1m_col(i) = value_column @@ -889,6 +898,22 @@ subroutine Summary(this, bounds, num_allc, filter_allc) end if end do + ! total microbial nitrogen (TOTMICN) + do fc = 1,num_allc + c = filter_allc(fc) + this%totmicn_col(c) = 0._r8 + end do + do l = 1, ndecomp_pools + if ( decomp_cascade_con%is_microbe(l) ) then + do fc = 1,num_allc + c = filter_allc(fc) + this%totmicn_col(c) = & + this%totmicn_col(c) + & + this%decomp_npools_col(c,l) + end do + end if + end do + ! total soil organic matter nitrogen (TOTSOMN) do fc = 1,num_allc c = filter_allc(fc) From e6d365cbf6d81b14c9d72dcd7feeacfb77745f12 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 22 Oct 2021 16:23:29 -0600 Subject: [PATCH 49/69] Dimension p_decomp_cn_gain by pools instead of transitions N-bal error same --- src/biogeochem/CNDriverMod.F90 | 4 ++-- src/biogeochem/EDBGCDynMod.F90 | 4 ++-- src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index 48092ed8a4..389910bf91 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -202,7 +202,7 @@ subroutine CNDriverNoLeaching(bounds, real(r8):: p_decomp_cpool_loss(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential C loss from one pool to another real(r8):: pmnf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential mineral N flux, from one pool to another real(r8):: p_decomp_npool_to_din(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential flux to dissolved inorganic N - real(r8):: p_decomp_cn_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! C:N ratio of the flux gained by the receiver pool + real(r8):: p_decomp_cn_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) ! C:N ratio of the flux gained by the receiver pool real(r8):: arepr(bounds%begp:bounds%endp) ! reproduction allocation coefficient (only used for use_crop) real(r8):: aroot(bounds%begp:bounds%endp) ! root allocation coefficient (only used for use_crop) integer :: begp,endp @@ -332,7 +332,7 @@ subroutine CNDriverNoLeaching(bounds, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & + p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_pools), & pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) diff --git a/src/biogeochem/EDBGCDynMod.F90 b/src/biogeochem/EDBGCDynMod.F90 index c74c024b14..46e466648f 100644 --- a/src/biogeochem/EDBGCDynMod.F90 +++ b/src/biogeochem/EDBGCDynMod.F90 @@ -116,7 +116,7 @@ subroutine EDBGCDyn(bounds, & real(r8):: p_decomp_cpool_loss(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential C loss from one pool to another real(r8):: pmnf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential mineral N flux, from one pool to another real(r8):: p_decomp_npool_to_din(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential flux to dissolved inorganic N - real(r8):: p_decomp_cn_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! C:N ratio of the flux gained by the receiver pool + real(r8):: p_decomp_cn_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) ! C:N ratio of the flux gained by the receiver pool real(r8):: arepr(bounds%begp:bounds%endp) ! reproduction allocation coefficient (only used for crop_prog) real(r8):: aroot(bounds%begp:bounds%endp) ! root allocation coefficient (only used for crop_prog) integer :: begp,endp @@ -199,7 +199,7 @@ subroutine EDBGCDyn(bounds, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & + p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_pools), & pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index 7bb26ae922..c6d1022d0f 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -111,7 +111,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & begc = bounds%begc; endc = bounds%endc SHR_ASSERT_ALL_FL((ubound(cn_decomp_pools) == (/endc,nlevdecomp,ndecomp_pools/)) , sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(p_decomp_cn_gain) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(p_decomp_cn_gain) == (/endc,nlevdecomp,ndecomp_pools/)) , sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(p_decomp_cpool_loss) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(pmnf_decomp_cascade) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(p_decomp_npool_to_din) == (/endc,nlevdecomp,ndecomp_cascade_transitions/)) , sourcefile, __LINE__) @@ -255,11 +255,11 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! Once k-loop completes, the left hand side should end ! up with the correct cn ratio if (p_decomp_npool_gain_sum(cascade_receiver_pool(k)) > 0.0_r8) then - p_decomp_cn_gain(c,j,k) = & + p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) = & p_decomp_cpool_gain_sum(cascade_receiver_pool(k)) / & p_decomp_npool_gain_sum(cascade_receiver_pool(k)) else - p_decomp_cn_gain(c,j,k) = 0.0_r8 + p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) = 0.0_r8 end if ! denominator check end if ! donors donating (decomp_cpools_vr & decomp_k > 0) end if ! microbes receiving @@ -272,7 +272,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! if p_decomp_cn_diff < 0 N mineralization ! > 0 immobilization p_decomp_cn_diff_ratio = max(0.0_r8, & - (p_decomp_cn_gain(c,j,k) - & + (p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) - & cn_col(c,cascade_receiver_pool(k))) / cn_col(c,cascade_receiver_pool(k))) ! Actual amount of N that's mineralized or that would ! need to be immobilized From f3f7d0ac046e322324d3169a803a2276c1c14a31 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 25 Oct 2021 14:39:03 -0600 Subject: [PATCH 50/69] Eliminate max from a line and correct NaNs that resulted --- src/biogeochem/CNVegCarbonFluxType.F90 | 10 +++++++--- src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 | 12 +++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index 54a6b5f302..aa1066d54d 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -4489,9 +4489,13 @@ subroutine Summary_carbonflux(this, & ! Calculate ligninNratioAve do fc = 1,num_soilc c = filter_soilc(fc) - ligninNratio_cwd = CNParamsShareInst%cwd_flig * & - (soilbiogeochem_cwdc_col(c) / soilbiogeochem_cwdn_col(c)) * & - soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2) + if (soilbiogeochem_cwdn_col(c) > 0._r8) then + ligninNratio_cwd = CNParamsShareInst%cwd_flig * & + (soilbiogeochem_cwdc_col(c) / soilbiogeochem_cwdn_col(c)) * & + soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2) + else + ligninNratio_cwd = 0._r8 + end if this%ligninNratioAvg_col(c) = & (ligninNratio_leaf_col(c) + ligninNratio_froot_col(c) + & ligninNratio_cwd) / & diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index c6d1022d0f..651c247c69 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -229,9 +229,11 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & end do ! soil level loop end do ! transitions loop - ! Determine immobilization vs. mineralization by comparing the - ! cn_gain into microbial biomass compared with the target C:N - ! ratio of microbial biomass pools + ! Calculate cn_gain into microbial biomass (in first do k + ! transitions loop). + ! Compare cn_gain to target C:N ratio of microbial biomass pools + ! to determine immobilization vs. mineralization (in second do k + ! transitions loop). if (use_mimics_decomp) then do j = 1,nlevdecomp do fc = 1,num_soilc @@ -271,9 +273,9 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & decomp_k(c,j,cascade_donor_pool(k)) > 0._r8 ) then ! if p_decomp_cn_diff < 0 N mineralization ! > 0 immobilization - p_decomp_cn_diff_ratio = max(0.0_r8, & + p_decomp_cn_diff_ratio = & (p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) - & - cn_col(c,cascade_receiver_pool(k))) / cn_col(c,cascade_receiver_pool(k))) + cn_col(c,cascade_receiver_pool(k))) / cn_col(c,cascade_receiver_pool(k)) ! Actual amount of N that's mineralized or that would ! need to be immobilized ! negative=mineralization: add to the DIN pool From 80c0c2f1e506ee6cfd1b09da459d7137647479eb Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 25 Oct 2021 15:38:37 -0600 Subject: [PATCH 51/69] Updates discussed with @wwieder --- .../SoilBiogeochemCompetitionMod.F90 | 118 ++++++++++++------ 1 file changed, 83 insertions(+), 35 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index ce720ac637..751644deef 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -375,39 +375,6 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do end do - if (use_mimics_decomp) then - do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) - - fpi_vr(c,j) = 0.0_r8 - - do k = 1, ndecomp_cascade_transitions - ! TODO slevis: ok to identify as receiver pools? - if (cascade_receiver_pool(k) == i_cop_mic .or. & - cascade_receiver_pool(k) == i_oli_mic) then - if (pmnf_decomp_cascade(c,j,k) > 0.0_r8 .and. & - sum_ndemand_vr(c,j) > 0.0_r8) then - amnf_immob_vr = (sminn_vr(c,j) / dt) * & - (pmnf_decomp_cascade(c,j,k) / & - sum_ndemand_vr(c,j)) - n_deficit_vr = pmnf_decomp_cascade(c,j,k) - & - amnf_immob_vr - c_overflow_vr(c,j,k) = & - n_deficit_vr * p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) - else - c_overflow_vr(c,j,k) = 0.0_r8 - end if - else - c_overflow_vr(c,j,k) = 0.0_r8 - end if - end do - end do - end do - else ! not use_mimics_decomp - c_overflow_vr(:,:,:) = 0.0_r8 - end if - if ( local_use_fun ) then call t_startf( 'CNFUN' ) call CNFUN(bounds,num_soilc,filter_soilc,num_soilp,filter_soilp,waterstatebulk_inst, & @@ -590,7 +557,29 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, sum_nh4_demand_scaled(c,j) = plant_ndemand(c)* nuptake_prof(c,j) * compet_plant_nh4 + & potential_immob_vr(c,j)*compet_decomp_nh4 + pot_f_nit_vr(c,j)*compet_nit - if (sum_nh4_demand(c,j)*dt < smin_nh4_vr(c,j)) then + if (use_mimics_decomp) then + ! this turns off fpi for MIMICS and only lets plants + ! take up available mineral nitrogen. + ! TODO slevis: -ve or tiny sminn_vr could cause problems + nlimit_nh4(c,j) = 1 + fpi_nh4_vr(c,j) = 1.0_r8 + actual_immob_nh4_vr(c,j) = potential_immob_vr(c,j) + ! TODO slevis: check the logic here... + f_nit_vr(c,j) = pot_f_nit_vr(c,j) + if ( .not. local_use_fun ) then + smin_nh4_to_plant_vr(c,j) = min((smin_nh4_vr(c,j) / dt) * & + plant_ndemand(c) * & + nuptake_prof(c,j) * & + compet_plant_nh4 / & + sum_nh4_demand_scaled(c,j), & + plant_ndemand(c) * & + nuptake_prof(c,j)) + else + smin_nh4_to_plant_vr(c,j) = smin_nh4_vr(c,j) / dt - & + actual_immob_nh4_vr(c,j) - & + f_nit_vr(c,j) + end if + else if (sum_nh4_demand(c,j)*dt < smin_nh4_vr(c,j)) then ! NH4 availability is not limiting immobilization or plant ! uptake, and all can proceed at their potential rates @@ -661,7 +650,32 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, - if (sum_no3_demand(c,j)*dt < smin_no3_vr(c,j)) then + if (use_mimics_decomp) then + ! this turns off fpi for MIMICS and only lets plants + ! take up available mineral nitrogen. + ! TODO slevis: -ve or tiny sminn_vr could cause problems + nlimit_no3(c,j) = 1 + fpi_no3_vr(c,j) = 1.0_r8 - fpi_nh4_vr(c,j) ! currently 0 + actual_immob_no3_vr(c,j) = potential_immob_vr(c,j) - & + actual_immob_nh4_vr(c,j) ! currently 0 + ! TODO slevis: check the logic here... + f_denit_vr(c,j) = pot_f_denit_vr(c,j) + if ( .not. local_use_fun ) then + smin_no3_to_plant_vr(c,j) = min((smin_no3_vr(c,j) / dt) * & + (plant_ndemand(c) * & + nuptake_prof(c,j) - & + smin_nh4_to_plant_vr(c,j)) * & + compet_plant_no3 / & + sum_no3_demand_scaled(c,j), & + plant_ndemand(c) * & + nuptake_prof(c,j) - & + smin_nh4_to_plant_vr(c,j)) + else + smin_no3_to_plant_vr(c,j) = smin_no3_vr(c,j) / dt - & + actual_immob_no3_vr(c,j) - & + f_denit_vr(c,j) + end if + else if (sum_no3_demand(c,j)*dt < smin_no3_vr(c,j)) then ! NO3 availability is not limiting immobilization or plant ! uptake, and all can proceed at their potential rates @@ -835,6 +849,40 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if + ! TODO slevis: MIMICS block ok here? And + ! ok to check for microbes as receiver pools? + if (use_mimics_decomp) then + do j = 1, nlevdecomp + do fc=1,num_soilc + c = filter_soilc(fc) + + do k = 1, ndecomp_cascade_transitions + if (cascade_receiver_pool(k) == i_cop_mic .or. & + cascade_receiver_pool(k) == i_oli_mic) then + sum_ndemand_vr(c,j) = sum_no3_demand_scaled(c,j) + & + sum_nh4_demand_scaled(c,j) + if (pmnf_decomp_cascade(c,j,k) > 0.0_r8 .and. & + sum_ndemand_vr(c,j) > 0.0_r8) then + amnf_immob_vr = (sminn_vr(c,j) / dt) * & + (pmnf_decomp_cascade(c,j,k) / & + sum_ndemand_vr(c,j)) + n_deficit_vr = pmnf_decomp_cascade(c,j,k) - & + amnf_immob_vr + c_overflow_vr(c,j,k) = & + n_deficit_vr * p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) + else ! not pmnf and sum_ndemand > 0 + c_overflow_vr(c,j,k) = 0.0_r8 + end if + else ! not microbes receiving + c_overflow_vr(c,j,k) = 0.0_r8 + end if + end do + end do + end do + else ! not use_mimics_decomp + c_overflow_vr(:,:,:) = 0.0_r8 + end if + if(.not.local_use_fun)then ! give plants a second pass to see if there is any mineral N left over with which to satisfy residual N demand. ! first take frm nh4 pool; then take from no3 pool From 520f4f98d9c044dbffdb5c30ec99f4e30d22249f Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 26 Oct 2021 18:48:09 -0600 Subject: [PATCH 52/69] The model now runs without balance or other errors I have submitted a 100-yr point simulation and a 10-yr global one using the following tests hoping for no further unforseen problems: SMS_Ly100_Mmpi-serial.1x1_brazil.IHistClm50BgcQianRs.cheyenne_gnu.clm-mimics ERS_Ly10.f10_f10_mg37.I1850Clm51BgcCrop.cheyenne_gnu.clm-mimics --- .../SoilBiogeochemCompetitionMod.F90 | 104 +++++++++--------- .../SoilBiogeochemDecompMod.F90 | 8 +- .../SoilBiogeochemNitrogenStateType.F90 | 4 +- .../SoilBiogeochemPotentialMod.F90 | 5 +- 4 files changed, 64 insertions(+), 57 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 751644deef..9a220e566a 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -557,29 +557,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, sum_nh4_demand_scaled(c,j) = plant_ndemand(c)* nuptake_prof(c,j) * compet_plant_nh4 + & potential_immob_vr(c,j)*compet_decomp_nh4 + pot_f_nit_vr(c,j)*compet_nit - if (use_mimics_decomp) then - ! this turns off fpi for MIMICS and only lets plants - ! take up available mineral nitrogen. - ! TODO slevis: -ve or tiny sminn_vr could cause problems - nlimit_nh4(c,j) = 1 - fpi_nh4_vr(c,j) = 1.0_r8 - actual_immob_nh4_vr(c,j) = potential_immob_vr(c,j) - ! TODO slevis: check the logic here... - f_nit_vr(c,j) = pot_f_nit_vr(c,j) - if ( .not. local_use_fun ) then - smin_nh4_to_plant_vr(c,j) = min((smin_nh4_vr(c,j) / dt) * & - plant_ndemand(c) * & - nuptake_prof(c,j) * & - compet_plant_nh4 / & - sum_nh4_demand_scaled(c,j), & - plant_ndemand(c) * & - nuptake_prof(c,j)) - else - smin_nh4_to_plant_vr(c,j) = smin_nh4_vr(c,j) / dt - & - actual_immob_nh4_vr(c,j) - & - f_nit_vr(c,j) - end if - else if (sum_nh4_demand(c,j)*dt < smin_nh4_vr(c,j)) then + if (sum_nh4_demand(c,j)*dt < smin_nh4_vr(c,j)) then ! NH4 availability is not limiting immobilization or plant ! uptake, and all can proceed at their potential rates @@ -596,6 +574,31 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, smin_nh4_to_plant_vr(c,j) = smin_nh4_vr(c,j)/dt - actual_immob_nh4_vr(c,j) - f_nit_vr(c,j) end if + else if (use_mimics_decomp) then + ! this turns off fpi for MIMICS and only lets plants + ! take up available mineral nitrogen. + ! TODO slevis: -ve or tiny sminn_vr could cause problems + nlimit_nh4(c,j) = 1 + if (sum_nh4_demand(c,j) > 0.0_r8) then + fpi_nh4_vr(c,j) = 1.0_r8 + actual_immob_nh4_vr(c,j) = potential_immob_vr(c,j) + ! TODO slevis: consolidate repeating code if poss. + f_nit_vr(c,j) = min((smin_nh4_vr(c,j)/dt)*(pot_f_nit_vr(c,j)*compet_nit / & + sum_nh4_demand_scaled(c,j)), pot_f_nit_vr(c,j)) + if ( .not. local_use_fun ) then + smin_nh4_to_plant_vr(c,j) = min((smin_nh4_vr(c,j) / dt) * & + plant_ndemand(c) * & + nuptake_prof(c,j) * & + compet_plant_nh4 / & + sum_nh4_demand_scaled(c,j), & + plant_ndemand(c) * & + nuptake_prof(c,j)) + else + smin_nh4_to_plant_vr(c,j) = smin_nh4_vr(c,j) / dt - & + actual_immob_nh4_vr(c,j) - & + f_nit_vr(c,j) + end if + end if else ! NH4 availability can not satisfy the sum of immobilization, nitrification, and @@ -650,32 +653,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, - if (use_mimics_decomp) then - ! this turns off fpi for MIMICS and only lets plants - ! take up available mineral nitrogen. - ! TODO slevis: -ve or tiny sminn_vr could cause problems - nlimit_no3(c,j) = 1 - fpi_no3_vr(c,j) = 1.0_r8 - fpi_nh4_vr(c,j) ! currently 0 - actual_immob_no3_vr(c,j) = potential_immob_vr(c,j) - & - actual_immob_nh4_vr(c,j) ! currently 0 - ! TODO slevis: check the logic here... - f_denit_vr(c,j) = pot_f_denit_vr(c,j) - if ( .not. local_use_fun ) then - smin_no3_to_plant_vr(c,j) = min((smin_no3_vr(c,j) / dt) * & - (plant_ndemand(c) * & - nuptake_prof(c,j) - & - smin_nh4_to_plant_vr(c,j)) * & - compet_plant_no3 / & - sum_no3_demand_scaled(c,j), & - plant_ndemand(c) * & - nuptake_prof(c,j) - & - smin_nh4_to_plant_vr(c,j)) - else - smin_no3_to_plant_vr(c,j) = smin_no3_vr(c,j) / dt - & - actual_immob_no3_vr(c,j) - & - f_denit_vr(c,j) - end if - else if (sum_no3_demand(c,j)*dt < smin_no3_vr(c,j)) then + if (sum_no3_demand(c,j)*dt < smin_no3_vr(c,j)) then ! NO3 availability is not limiting immobilization or plant ! uptake, and all can proceed at their potential rates @@ -698,6 +676,34 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if endif + else if (use_mimics_decomp) then + ! this turns off fpi for MIMICS and only lets plants + ! take up available mineral nitrogen. + ! TODO slevis: -ve or tiny sminn_vr could cause problems + nlimit_no3(c,j) = 1 + if (sum_no3_demand(c,j) > 0.0_r8) then + fpi_no3_vr(c,j) = 1.0_r8 - fpi_nh4_vr(c,j) ! => 0 + actual_immob_no3_vr(c,j) = potential_immob_vr(c,j) - & + actual_immob_nh4_vr(c,j) ! => 0 + ! TODO slevis: consolidate repeating code if poss. + f_denit_vr(c,j) = min((smin_no3_vr(c,j)/dt)*(pot_f_denit_vr(c,j)*compet_denit / & + sum_no3_demand_scaled(c,j)), pot_f_denit_vr(c,j)) + if ( .not. local_use_fun ) then + smin_no3_to_plant_vr(c,j) = min((smin_no3_vr(c,j) / dt) * & + (plant_ndemand(c) * & + nuptake_prof(c,j) - & + smin_nh4_to_plant_vr(c,j)) * & + compet_plant_no3 / & + sum_no3_demand_scaled(c,j), & + plant_ndemand(c) * & + nuptake_prof(c,j) - & + smin_nh4_to_plant_vr(c,j)) + else + smin_no3_to_plant_vr(c,j) = smin_no3_vr(c,j) / dt - & + actual_immob_no3_vr(c,j) - & + f_denit_vr(c,j) + end if + end if else ! NO3 availability can not satisfy the sum of immobilization, denitrification, and diff --git a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 index 431389e3f7..71c71915c9 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 @@ -88,7 +88,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, real(r8) , intent(inout) :: cn_decomp_pools(bounds%begc:,1:,1:) ! c:n ratios of applicable pools real(r8) , intent(inout) :: p_decomp_cpool_loss(bounds%begc:,1:,1:) ! potential C loss from one pool to another real(r8) , intent(inout) :: pmnf_decomp_cascade(bounds%begc:,1:,1:) ! potential mineral N flux from one pool to another - real(r8) , intent(inout) :: p_decomp_npool_to_din(bounds%begc:,1:,1:) ! potential flux to dissolved inorganic N + real(r8) , intent(in) :: p_decomp_npool_to_din(bounds%begc:,1:,1:) ! potential flux to dissolved inorganic N ! ! !LOCAL VARIABLES: integer :: c,j,k,l,m ! indices @@ -121,7 +121,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, decomp_cascade_sminn_flux_vr => soilbiogeochem_nitrogenflux_inst%decomp_cascade_sminn_flux_vr_col , & ! Output: [real(r8) (:,:,:) ] vert-res mineral N flux for transition along decomposition cascade (gN/m3/s) potential_immob_vr => soilbiogeochem_nitrogenflux_inst%potential_immob_vr_col , & ! Output: [real(r8) (:,:) ] sminn_to_denit_decomp_cascade_vr => soilbiogeochem_nitrogenflux_inst%sminn_to_denit_decomp_cascade_vr_col , & ! Output: [real(r8) (:,:,:) ] - gross_nmin_vr => soilbiogeochem_nitrogenflux_inst%gross_nmin_vr_col , & ! Output: [real(r8) (:,:) ] + gross_nmin_vr => soilbiogeochem_nitrogenflux_inst%gross_nmin_vr_col , & ! Input: [real(r8) (:,:) ] net_nmin_vr => soilbiogeochem_nitrogenflux_inst%net_nmin_vr_col , & ! Output: [real(r8) (:,:) ] gross_nmin => soilbiogeochem_nitrogenflux_inst%gross_nmin_col , & ! Output: [real(r8) (:) ] gross rate of N mineralization (gN/m2/s) net_nmin => soilbiogeochem_nitrogenflux_inst%net_nmin_col , & ! Output: [real(r8) (:) ] net rate of N mineralization (gN/m2/s) @@ -204,10 +204,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, decomp_cascade_sminn_flux_vr(c,j,k) = - pmnf_decomp_cascade(c,j,k) endif net_nmin_vr(c,j) = net_nmin_vr(c,j) - pmnf_decomp_cascade(c,j,k) -! TODO slevis: NEED THIS if-block? If so, need anything additional that -! is done to pmnf_decomp_cascade or other? if (use_mimics_decomp) then - decomp_cascade_sminn_flux_vr(c,j,k) = decomp_cascade_sminn_flux_vr(c,j,k) + p_decomp_npool_to_din(c,j,k) + decomp_cascade_sminn_flux_vr(c,j,k) = decomp_cascade_sminn_flux_vr(c,j,k) - p_decomp_npool_to_din(c,j,k) net_nmin_vr(c,j) = net_nmin_vr(c,j) + p_decomp_npool_to_din(c,j,k) end if else diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 index 3a676505d0..e4c688acff 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 @@ -541,8 +541,10 @@ subroutine Restart ( this, bounds, ncid, flag, totvegc_col ) ! matches what the restart file was generated with. ! add info about the SOM decomposition cascade - if (use_century_decomp .or. use_mimics_decomp) then + if (use_century_decomp) then decomp_cascade_state = 1 + else if (use_mimics_decomp) then + decomp_cascade_state = 2 else decomp_cascade_state = 0 end if diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index 651c247c69..e4fc1c20eb 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -273,9 +273,10 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & decomp_k(c,j,cascade_donor_pool(k)) > 0._r8 ) then ! if p_decomp_cn_diff < 0 N mineralization ! > 0 immobilization - p_decomp_cn_diff_ratio = & + ! "min" in next line turns off immobilization flux + p_decomp_cn_diff_ratio = min(0.0_r8, & (p_decomp_cn_gain(c,j,cascade_receiver_pool(k)) - & - cn_col(c,cascade_receiver_pool(k))) / cn_col(c,cascade_receiver_pool(k)) + cn_col(c,cascade_receiver_pool(k))) / cn_col(c,cascade_receiver_pool(k))) ! Actual amount of N that's mineralized or that would ! need to be immobilized ! negative=mineralization: add to the DIN pool From 1faa67353fd1a54f912eedfa929eb254144cf256 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 27 Oct 2021 12:04:54 -0600 Subject: [PATCH 53/69] Code simplification for improved clarity --- .../SoilBiogeochemCompetitionMod.F90 | 73 ++++--------------- 1 file changed, 15 insertions(+), 58 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index 9a220e566a..e766e22fdc 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -574,31 +574,6 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, smin_nh4_to_plant_vr(c,j) = smin_nh4_vr(c,j)/dt - actual_immob_nh4_vr(c,j) - f_nit_vr(c,j) end if - else if (use_mimics_decomp) then - ! this turns off fpi for MIMICS and only lets plants - ! take up available mineral nitrogen. - ! TODO slevis: -ve or tiny sminn_vr could cause problems - nlimit_nh4(c,j) = 1 - if (sum_nh4_demand(c,j) > 0.0_r8) then - fpi_nh4_vr(c,j) = 1.0_r8 - actual_immob_nh4_vr(c,j) = potential_immob_vr(c,j) - ! TODO slevis: consolidate repeating code if poss. - f_nit_vr(c,j) = min((smin_nh4_vr(c,j)/dt)*(pot_f_nit_vr(c,j)*compet_nit / & - sum_nh4_demand_scaled(c,j)), pot_f_nit_vr(c,j)) - if ( .not. local_use_fun ) then - smin_nh4_to_plant_vr(c,j) = min((smin_nh4_vr(c,j) / dt) * & - plant_ndemand(c) * & - nuptake_prof(c,j) * & - compet_plant_nh4 / & - sum_nh4_demand_scaled(c,j), & - plant_ndemand(c) * & - nuptake_prof(c,j)) - else - smin_nh4_to_plant_vr(c,j) = smin_nh4_vr(c,j) / dt - & - actual_immob_nh4_vr(c,j) - & - f_nit_vr(c,j) - end if - end if else ! NH4 availability can not satisfy the sum of immobilization, nitrification, and @@ -636,7 +611,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if - + if (use_mimics_decomp) then + ! turn off fpi for MIMICS and only lets plants + ! take up available mineral nitrogen. + ! TODO slevis: -ve or tiny sminn_vr could cause problems + fpi_nh4_vr(c,j) = 1.0_r8 + actual_immob_nh4_vr(c,j) = potential_immob_vr(c,j) + end if if(.not.local_use_fun)then sum_no3_demand(c,j) = (plant_ndemand(c)*nuptake_prof(c,j)-smin_nh4_to_plant_vr(c,j)) + & @@ -676,34 +657,6 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if endif - else if (use_mimics_decomp) then - ! this turns off fpi for MIMICS and only lets plants - ! take up available mineral nitrogen. - ! TODO slevis: -ve or tiny sminn_vr could cause problems - nlimit_no3(c,j) = 1 - if (sum_no3_demand(c,j) > 0.0_r8) then - fpi_no3_vr(c,j) = 1.0_r8 - fpi_nh4_vr(c,j) ! => 0 - actual_immob_no3_vr(c,j) = potential_immob_vr(c,j) - & - actual_immob_nh4_vr(c,j) ! => 0 - ! TODO slevis: consolidate repeating code if poss. - f_denit_vr(c,j) = min((smin_no3_vr(c,j)/dt)*(pot_f_denit_vr(c,j)*compet_denit / & - sum_no3_demand_scaled(c,j)), pot_f_denit_vr(c,j)) - if ( .not. local_use_fun ) then - smin_no3_to_plant_vr(c,j) = min((smin_no3_vr(c,j) / dt) * & - (plant_ndemand(c) * & - nuptake_prof(c,j) - & - smin_nh4_to_plant_vr(c,j)) * & - compet_plant_no3 / & - sum_no3_demand_scaled(c,j), & - plant_ndemand(c) * & - nuptake_prof(c,j) - & - smin_nh4_to_plant_vr(c,j)) - else - smin_no3_to_plant_vr(c,j) = smin_no3_vr(c,j) / dt - & - actual_immob_no3_vr(c,j) - & - f_denit_vr(c,j) - end if - end if else ! NO3 availability can not satisfy the sum of immobilization, denitrification, and @@ -757,9 +710,15 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if end if - - + if (use_mimics_decomp) then + ! turn off fpi for MIMICS and only lets plants + ! take up available mineral nitrogen. + ! TODO slevis: -ve or tiny sminn_vr could cause problems + fpi_no3_vr(c,j) = 1.0_r8 - fpi_nh4_vr(c,j) ! => 0 + actual_immob_no3_vr(c,j) = potential_immob_vr(c,j) - & + actual_immob_nh4_vr(c,j) ! => 0 + end if ! n2o emissions: n2o from nitr is const fraction, n2o from denitr is calculated in nitrif_denitrif f_n2o_nit_vr(c,j) = f_nit_vr(c,j) * nitrif_n2o_loss_frac @@ -855,8 +814,6 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if - ! TODO slevis: MIMICS block ok here? And - ! ok to check for microbes as receiver pools? if (use_mimics_decomp) then do j = 1, nlevdecomp do fc=1,num_soilc From 3b2073bc358c2419501322376841f72a1536bd1f Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 4 Nov 2021 17:45:55 -0600 Subject: [PATCH 54/69] Minor corrections of mistakes that snuck through the dev061 merge --- bld/CLMBuildNamelist.pm | 1 - src/biogeochem/CNDriverMod.F90 | 2 +- src/main/clm_instMod.F90 | 2 +- src/main/readParamsMod.F90 | 5 +++-- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 17 +++++++---------- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index a4e3851399..da1ca25b5a 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -854,7 +854,6 @@ sub setup_cmdl_bgc { $nl_flags->{'use_cn'} = ".false."; $nl_flags->{'use_fates'} = ".false."; $nl_flags->{'use_mimics_decomp'} = ".false."; - } } if ( defined($nl->get_value("use_cn")) && ($nl_flags->{'use_cn'} ne $nl->get_value("use_cn")) ) { $log->fatal_error("The namelist variable use_cn is inconsistent with the -bgc option"); diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index a70915f78b..f79b5faa5f 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -11,7 +11,7 @@ module CNDriverMod use decompMod , only : bounds_type use perf_mod , only : t_startf, t_stopf use clm_varctl , only : use_nitrif_denitrif, use_nguardrail - use clm_varctl , only : use_mimics_decomp, use_crop + use clm_varctl , only : iulog, use_mimics_decomp, use_crop use SoilBiogeochemDecompCascadeConType, only : century_decomp, decomp_method use CNSharedParamsMod , only : use_fun use CNVegStateType , only : cnveg_state_type diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90 index c51868dce5..a50b90b044 100644 --- a/src/main/clm_instMod.F90 +++ b/src/main/clm_instMod.F90 @@ -9,7 +9,7 @@ module clm_instMod use decompMod , only : bounds_type use clm_varpar , only : ndecomp_pools, nlevdecomp_full use clm_varctl , only : use_cn, use_c13, use_c14, use_lch4, use_cndv, use_fates - use clm_varctl , only : use_mimics_decomp + use clm_varctl , only : iulog, use_mimics_decomp use clm_varctl , only : use_crop, snow_cover_fraction_method, paramfile use SoilBiogeochemDecompCascadeConType , only : century_decomp, decomp_method use clm_varcon , only : bdsno, c13ratio, c14ratio diff --git a/src/main/readParamsMod.F90 b/src/main/readParamsMod.F90 index 7562391cba..144d488fd6 100644 --- a/src/main/readParamsMod.F90 +++ b/src/main/readParamsMod.F90 @@ -8,7 +8,8 @@ module readParamsMod ! ! ! USES: use clm_varctl , only : paramfile, iulog, use_fates, use_cn - use clm_varctl , only : century_decomp, use_mimics_decomp + use clm_varctl , only : use_mimics_decomp + use SoilBiogeochemDecompCascadeConType, only : century_decomp, decomp_method use spmdMod , only : masterproc use fileutils , only : getfil use ncdio_pio , only : ncd_pio_closefile, ncd_pio_openfile @@ -102,7 +103,7 @@ subroutine readParameters (nutrient_competition_method, photosyns_inst) call readSoilBiogeochemCompetitionParams(ncid) if (use_mimics_decomp) then call readSoilBiogeochemDecompMimicsParams(ncid) - else if (century_decomp) then + else if (decomp_method == century_decomp) then call readSoilBiogeochemDecompBgcParams(ncid) else write(iulog,*) 'WARNING:' diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index ecdb3cd897..2dcdb7e221 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -12,7 +12,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod use clm_varpar , only : nlevdecomp, ndecomp_pools_max use clm_varpar , only : i_met_lit, i_cop_mic, i_oli_mic, i_cwd use clm_varpar , only : i_litr_min, i_litr_max, i_cwdl2 - use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_vertsoilc, use_fates + use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_fates use clm_varcon , only : zsoi use decompMod , only : bounds_type use spmdMod , only : masterproc @@ -1006,7 +1006,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! TODO May need a hook from MIMICS to ch4 code for this to work ! Calculate ANOXIA - ! anoxia = .true. when (use_lch4 .and. use_vertsoilc) + ! anoxia = .true. when (use_lch4) if (anoxia) then @@ -1049,7 +1049,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do ! Calculate ANOXIA - ! anoxia = .true. when (use_lch4 .and. use_vertsoilc) + ! anoxia = .true. when (use_lch4) if (anoxia) then do j = 1,nlevdecomp @@ -1070,13 +1070,10 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & do j = 1, nlevdecomp do fc = 1, num_soilc c = filter_soilc(fc) -! if (use_vertsoilc) then -! ! Using fixed e-folding depth as in -! ! SoilBiogeochemDecompCascadeBGCMod.F90 -! depth_scalar(c,j) = exp(-zsoi(j) / decomp_depth_efolding) -! else - depth_scalar(c,j) = 1.0_r8 -! end if + ! Using fixed e-folding depth as in + ! SoilBiogeochemDecompCascadeBGCMod.F90 +! depth_scalar(c,j) = exp(-zsoi(j) / decomp_depth_efolding) + depth_scalar(c,j) = 1.0_r8 end do end do From a399480b573695505621f237e8b33b7b850c9a7c Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 5 Nov 2021 16:27:42 -0600 Subject: [PATCH 55/69] Change use_mimics_decomp -> mimics_decomp and coordinate w decomp_method --- bld/CLMBuildNamelist.pm | 22 +++++-------------- bld/listDefaultNamelist.pl | 1 - bld/namelist_files/namelist_defaults_ctsm.xml | 11 +--------- .../namelist_definition_ctsm.xml | 15 ++----------- .../testmods_dirs/clm/mimics/user_nl_clm | 2 +- src/biogeochem/CNDriverMod.F90 | 6 ++--- src/biogeochem/CNVegCarbonFluxType.F90 | 8 +++---- src/biogeochem/EDBGCDynMod.F90 | 5 ++--- src/main/clm_instMod.F90 | 6 ++--- src/main/clm_varctl.F90 | 1 - src/main/clm_varpar.F90 | 2 +- src/main/controlMod.F90 | 4 +--- src/main/pftconMod.F90 | 4 ++-- src/main/readParamsMod.F90 | 5 ++--- .../SoilBiogeochemCompetitionMod.F90 | 11 +++++----- .../SoilBiogeochemDecompCascadeConType.F90 | 11 ++++++---- .../SoilBiogeochemDecompMod.F90 | 10 ++++----- .../SoilBiogeochemNitrogenStateType.F90 | 5 ++--- .../SoilBiogeochemPotentialMod.F90 | 12 +++++----- 19 files changed, 52 insertions(+), 89 deletions(-) diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index da1ca25b5a..4850c03d55 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -92,10 +92,10 @@ OPTIONS bgc = Carbon Nitrogen with methane, nitrification, vertical soil C, CENTURY or MIMICS decomposition This toggles on the namelist variables: - use_cn, use_lch4, use_nitrif_denitrif, and use_mimics_decomp + use_cn, use_lch4, use_nitrif_denitrif fates = FATES/Ecosystem Demography with below ground BGC This toggles on the namelist variables: - use_fates and use_mimics_decomp + use_fates (Only for CLM4.5/CLM5.0) -[no-]chk_res Also check [do NOT check] to make sure the resolution and land-mask is valid. @@ -834,26 +834,16 @@ sub setup_cmdl_bgc { } $log->verbose_message("Using $nl_flags->{$var} for bgc."); - my $var1 = "decomp_mode"; - my $val1 = $nl->get_value($var1); - # now set the actual name list variables based on the bgc alias if ($nl_flags->{$var} eq "bgc" ) { $nl_flags->{'use_cn'} = ".true."; $nl_flags->{'use_fates'} = ".false."; - if ($val1 eq "'mimics'" ) { - $nl_flags->{'use_mimics_decomp'} = ".true."; - } } elsif ($nl_flags->{$var} eq "fates" ) { $nl_flags->{'use_cn'} = ".false."; $nl_flags->{'use_fates'} = ".true."; - if ($val1 eq "'mimics'" ) { - $nl_flags->{'use_mimics_decomp'} = ".true."; - } } else { $nl_flags->{'use_cn'} = ".false."; $nl_flags->{'use_fates'} = ".false."; - $nl_flags->{'use_mimics_decomp'} = ".false."; } if ( defined($nl->get_value("use_cn")) && ($nl_flags->{'use_cn'} ne $nl->get_value("use_cn")) ) { $log->fatal_error("The namelist variable use_cn is inconsistent with the -bgc option"); @@ -862,8 +852,8 @@ sub setup_cmdl_bgc { $log->fatal_error("The namelist variable use_fates is inconsistent with the -bgc option"); } - # Now set use_cn, use_fates, use_mimics_decomp - foreach $var ( "use_cn", "use_fates", "use_mimics_decomp" ) { + # Now set use_cn and use_fates + foreach $var ( "use_cn", "use_fates" ) { $val = $nl_flags->{$var}; $group = $definition->get_group_name($var); $nl->set_variable_value($group, $var, $val); @@ -885,7 +875,7 @@ sub setup_cmdl_bgc { $log->fatal_error("$var must NOT be None if use_cn or use_fates are on"); } } elsif ( $soil_decomp_method ne "None" ) { - $log->fatal_error("$var must be None if use_cn or use_fates are not"); + $log->fatal_error("$var must be None if use_cn and use_fates are off"); } # # Soil decomposition control variables, methane and Nitrification-Denitrification @@ -2190,7 +2180,6 @@ sub setup_logic_demand { $settings{'use_cndv'} = $nl_flags->{'use_cndv'}; $settings{'use_lch4'} = $nl_flags->{'use_lch4'}; $settings{'use_nitrif_denitrif'} = $nl_flags->{'use_nitrif_denitrif'}; - $settings{'use_mimics_decomp'} = $nl_flags->{'use_mimics_decomp'}; $settings{'use_crop'} = $nl_flags->{'use_crop'}; my $demand = $nl->get_value('clm_demand'); @@ -2339,7 +2328,6 @@ sub setup_logic_initial_conditions { $settings{'sim_year'} = $st_year; } foreach my $item ( "mask", "maxpft", "irrigate", "glc_nec", "use_crop", "use_cn", "use_cndv", - "use_mimics_decomp", "use_fates", "lnd_tuning_mode", ) { diff --git a/bld/listDefaultNamelist.pl b/bld/listDefaultNamelist.pl index 6053767608..ee995145bd 100755 --- a/bld/listDefaultNamelist.pl +++ b/bld/listDefaultNamelist.pl @@ -269,7 +269,6 @@ sub GetListofNeededFiles { if ( $sim_year ne 1850 && $sim_year ne 2000 && $sim_year > 1800 ) { next YEAR; } my @bgcsettings = $definition->get_valid_values( "bgc_mode", 'noquotes'=>1 ); - my @decompsettings = $definition->get_valid_values( "decomp_mode", 'noquotes'=>1 ); print "bgc=@bgcsettings\n" if $printing; print "decomp=@decompsettings\n" if $printing; # diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index e32a6be2b4..e3e2b25bd9 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -31,9 +31,8 @@ attributes from the config_cache.xml file (with keys converted to upper-case). constant - + sp -NONE clm4_5_CRUv7 clm5_0_cam6.0 @@ -2533,18 +2532,10 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts -.false. -.false. - CENTURYKoven2013 CENTURYKoven2013 None -.true. -.false. -.true. -.false. - .false. .true. .false. diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index 137299929e..bb0245a7f5 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -1027,12 +1027,6 @@ Exponent power for heterotrophic respiration for max denitrification rates Maximum nitrification rate constant (1/s) - -Use MIMICS below-ground decomposition. -Requires bgc_mode set to bgc or fates and decomp_mode set to mimics. - - Toggle to use 25 lake layers instead of 10 @@ -2094,12 +2088,6 @@ Command line arguement for biogeochemistry mode for CLM4.5 fates = FATES/ED ecosystem demography model with below ground BGC: - -Command line arguement for below-ground decomposition mode available when -bgc_mode is set to bgc or fates. - - @@ -2166,10 +2154,11 @@ Number of days over which to use exponential relaxation of NPP in N fixation cal + group="soilbgc_decomp" valid_values="None,CENTURYKoven2013,MIMICSWieder2015" > Soil decomposition method None -- No soil decomposition is done CENTURYKoven2013 -- CENTURY model in CTSM from Koven et. al. 2013 + MIMICSWieder2015 -- MIMICS model in CTSM from Wieder et. al. 2015 An active soil decomposition method requires the BGC or FATES model to work And both BGC and FATES models require an active soil decomposition model diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm index 54fe09c6c6..bdc2933d85 100644 --- a/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm @@ -1,2 +1,2 @@ -decomp_mode = 'mimics' +soil_decomp_method = 'MIMICSWieder2015' paramfile = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/paramdata/ctsm51_params.c210825.nc' diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index f79b5faa5f..494295ad07 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -11,8 +11,8 @@ module CNDriverMod use decompMod , only : bounds_type use perf_mod , only : t_startf, t_stopf use clm_varctl , only : use_nitrif_denitrif, use_nguardrail - use clm_varctl , only : iulog, use_mimics_decomp, use_crop - use SoilBiogeochemDecompCascadeConType, only : century_decomp, decomp_method + use clm_varctl , only : iulog, use_crop + use SoilBiogeochemDecompCascadeConType, only : mimics_decomp, century_decomp, decomp_method use CNSharedParamsMod , only : use_fun use CNVegStateType , only : cnveg_state_type use CNVegCarbonStateType , only : cnveg_carbonstate_type @@ -317,7 +317,7 @@ subroutine CNDriverNoLeaching(bounds, if (decomp_method == century_decomp) then call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) - else if (use_mimics_decomp) then + else if (decomp_method == mimics_decomp) then call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index aa1066d54d..dfe571eb72 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -4012,9 +4012,9 @@ subroutine Summary_carbonflux(this, & ! !USES: use clm_time_manager , only: get_step_size_real use clm_varcon , only: secspday - use clm_varctl , only: nfix_timeconst, carbon_resp_opt, use_mimics_decomp + use clm_varctl , only: nfix_timeconst, carbon_resp_opt use subgridAveMod , only: p2c, c2g - use SoilBiogeochemDecompCascadeConType , only: decomp_cascade_con + use SoilBiogeochemDecompCascadeConType , only: decomp_cascade_con, mimics_decomp, decomp_method use CNSharedParamsMod , only: use_fun, CNParamsShareInst ! ! !ARGUMENTS: @@ -4416,7 +4416,7 @@ subroutine Summary_carbonflux(this, & this%hrv_gresp_storage_to_litter_patch(p) + & this%hrv_gresp_xfer_to_litter_patch(p) - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then ! Calculate ligninNratio for leaves and fine roots ! TODO init. ligninNratio vars if nec. for call p2c to work associate(ivt => patch%itype) ! Input: [integer (:)] patch plant type @@ -4472,7 +4472,7 @@ subroutine Summary_carbonflux(this, & this%gpp_patch(bounds%begp:bounds%endp), & this%gpp_col(bounds%begc:bounds%endc)) - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then call p2c(bounds, num_soilc, filter_soilc, & ligninNratio_leaf_patch(bounds%begp:bounds%endp), & ligninNratio_leaf_col(bounds%begc:bounds%endc)) diff --git a/src/biogeochem/EDBGCDynMod.F90 b/src/biogeochem/EDBGCDynMod.F90 index a83f263696..82e68be6c5 100644 --- a/src/biogeochem/EDBGCDynMod.F90 +++ b/src/biogeochem/EDBGCDynMod.F90 @@ -10,8 +10,7 @@ module EDBGCDynMod use perf_mod , only : t_startf, t_stopf use shr_log_mod , only : errMsg => shr_log_errMsg use abortutils , only : endrun - use clm_varctl , only : use_mimics_decomp - use SoilBiogeochemDecompCascadeConType , only : century_decomp, decomp_method + use SoilBiogeochemDecompCascadeConType , only : mimics_decomp, century_decomp, decomp_method use CNVegCarbonStateType , only : cnveg_carbonstate_type use CNVegCarbonFluxType , only : cnveg_carbonflux_type use SoilBiogeochemStateType , only : soilbiogeochem_state_type @@ -183,7 +182,7 @@ subroutine EDBGCDyn(bounds, & if (decomp_method == century_decomp) then call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) - else if (use_mimics_decomp) then + else if (decomp_method == mimics_decomp) then call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90 index a50b90b044..72c52fc4fe 100644 --- a/src/main/clm_instMod.F90 +++ b/src/main/clm_instMod.F90 @@ -9,9 +9,9 @@ module clm_instMod use decompMod , only : bounds_type use clm_varpar , only : ndecomp_pools, nlevdecomp_full use clm_varctl , only : use_cn, use_c13, use_c14, use_lch4, use_cndv, use_fates - use clm_varctl , only : iulog, use_mimics_decomp + use clm_varctl , only : iulog use clm_varctl , only : use_crop, snow_cover_fraction_method, paramfile - use SoilBiogeochemDecompCascadeConType , only : century_decomp, decomp_method + use SoilBiogeochemDecompCascadeConType , only : mimics_decomp, century_decomp, decomp_method use clm_varcon , only : bdsno, c13ratio, c14ratio use landunit_varcon , only : istice, istsoil use perf_mod , only : t_startf, t_stopf @@ -385,7 +385,7 @@ subroutine clm_instInit(bounds) if (decomp_method == century_decomp ) then call init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, & soilstate_inst ) - else if (use_mimics_decomp) then + else if (decomp_method == mimics_decomp ) then call init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, & soilstate_inst) else diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index d3c232cf3e..3ad4b14bef 100644 --- a/src/main/clm_varctl.F90 +++ b/src/main/clm_varctl.F90 @@ -378,7 +378,6 @@ module clm_varctl logical, public :: use_nitrif_denitrif = .true. logical, public :: use_extralakelayers = .false. logical, public :: use_vichydro = .false. - logical, public :: use_mimics_decomp = .false. logical, public :: use_cn = .false. logical, public :: use_cndv = .false. logical, public :: use_grainproduct = .false. diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index f81b556abb..b75806b226 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -8,7 +8,7 @@ module clm_varpar use shr_kind_mod , only: r8 => shr_kind_r8 use shr_sys_mod , only: shr_sys_abort use spmdMod , only: masterproc - use clm_varctl , only: use_extralakelayers, use_mimics_decomp + use clm_varctl , only: use_extralakelayers use clm_varctl , only: use_c13, use_c14 use clm_varctl , only: iulog, use_crop, create_crop_landunit, irrigate use clm_varctl , only: use_vichydro, rundef diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index 3c4acd30fe..082d68e8eb 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -278,7 +278,7 @@ subroutine control_init(dtime) use_lch4, use_nitrif_denitrif, use_extralakelayers, & use_vichydro, use_cn, use_cndv, use_crop, use_fertilizer, o3_veg_stress_method, & use_grainproduct, use_snicar_frc, use_vancouver, use_mexicocity, use_noio, & - use_nguardrail, use_mimics_decomp + use_nguardrail ! ---------------------------------------------------------------------- @@ -623,7 +623,6 @@ subroutine control_spmd() call mpi_bcast (use_nitrif_denitrif, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_extralakelayers, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_vichydro, 1, MPI_LOGICAL, 0, mpicom, ier) - call mpi_bcast (use_mimics_decomp, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_cn, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_cndv, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_nguardrail, 1, MPI_LOGICAL, 0, mpicom, ier) @@ -867,7 +866,6 @@ subroutine control_print () write(iulog,*) ' use_nitrif_denitrif = ', use_nitrif_denitrif write(iulog,*) ' use_extralakelayers = ', use_extralakelayers write(iulog,*) ' use_vichydro = ', use_vichydro - write(iulog,*) ' use_mimics_decomp = ', use_mimics_decomp write(iulog,*) ' use_cn = ', use_cn write(iulog,*) ' use_cndv = ', use_cndv write(iulog,*) ' use_crop = ', use_crop diff --git a/src/main/pftconMod.F90 b/src/main/pftconMod.F90 index 034f3daead..16dd97240c 100644 --- a/src/main/pftconMod.F90 +++ b/src/main/pftconMod.F90 @@ -506,9 +506,9 @@ subroutine InitRead(this) use ncdio_pio , only : ncd_io, ncd_pio_closefile, ncd_pio_openfile, file_desc_t use ncdio_pio , only : ncd_inqdid, ncd_inqdlen use clm_varctl , only : paramfile, use_fates, use_flexibleCN, use_dynroot, use_biomass_heat_storage - use clm_varctl , only : use_mimics_decomp use spmdMod , only : masterproc use CLMFatesParamInterfaceMod, only : FatesReadPFTs + use SoilBiogeochemDecompCascadeConType, only : mimics_decomp, decomp_method ! ! !ARGUMENTS: class(pftcon_type) :: this @@ -767,7 +767,7 @@ subroutine InitRead(this) ! to i_litr_min, i_litr_max. this%fr_f(:,1) = this%fr_flab this%lf_f(:,1) = this%lf_flab - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then this%fr_f(:,2) = this%fr_fcel + this%fr_flig this%fr_f(:,3) = 0.0_r8 this%lf_f(:,2) = this%lf_fcel + this%lf_flig diff --git a/src/main/readParamsMod.F90 b/src/main/readParamsMod.F90 index 144d488fd6..e1c2c9abc7 100644 --- a/src/main/readParamsMod.F90 +++ b/src/main/readParamsMod.F90 @@ -8,8 +8,7 @@ module readParamsMod ! ! ! USES: use clm_varctl , only : paramfile, iulog, use_fates, use_cn - use clm_varctl , only : use_mimics_decomp - use SoilBiogeochemDecompCascadeConType, only : century_decomp, decomp_method + use SoilBiogeochemDecompCascadeConType, only : mimics_decomp, century_decomp, decomp_method use spmdMod , only : masterproc use fileutils , only : getfil use ncdio_pio , only : ncd_pio_closefile, ncd_pio_openfile @@ -101,7 +100,7 @@ subroutine readParameters (nutrient_competition_method, photosyns_inst) ! if (use_cn .or. use_fates) then call readSoilBiogeochemCompetitionParams(ncid) - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then call readSoilBiogeochemDecompMimicsParams(ncid) else if (decomp_method == century_decomp) then call readSoilBiogeochemDecompBgcParams(ncid) diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index e766e22fdc..eec9e00f80 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -176,7 +176,6 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! ! !USES: use clm_varctl , only: cnallocate_carbon_only, iulog - use clm_varctl , only: use_mimics_decomp use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions use clm_varpar , only: i_cop_mic, i_oli_mic use clm_varcon , only: nitrif_n2o_loss_frac @@ -184,7 +183,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, use CNFUNMod , only: CNFUN use subgridAveMod , only: p2c use perf_mod , only : t_startf, t_stopf - use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, mimics_decomp, decomp_method ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -611,7 +610,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then ! turn off fpi for MIMICS and only lets plants ! take up available mineral nitrogen. ! TODO slevis: -ve or tiny sminn_vr could cause problems @@ -711,7 +710,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then ! turn off fpi for MIMICS and only lets plants ! take up available mineral nitrogen. ! TODO slevis: -ve or tiny sminn_vr could cause problems @@ -814,7 +813,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then do j = 1, nlevdecomp do fc=1,num_soilc c = filter_soilc(fc) @@ -842,7 +841,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do end do end do - else ! not use_mimics_decomp + else ! not mimics_decomp c_overflow_vr(:,:,:) = 0.0_r8 end if diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 index 9d2f040112..9f8357de37 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 @@ -46,6 +46,7 @@ module SoilBiogeochemDecompCascadeConType integer, public, parameter :: i_atm = 0 ! for terminal pools (i.e. 100% respiration) (only used for CN not for BGC) integer, public, parameter :: no_soil_decomp = 0 ! No soil decomposition is done integer, public, parameter :: century_decomp = 1 ! CENTURY decomposition method type + integer, public, parameter :: mimics_decomp = 2 ! MIMICS decomposition method type integer, public :: decomp_method = ispval ! Type of decomposition to use type(decomp_cascade_type), public :: decomp_cascade_con !------------------------------------------------------------------------ @@ -88,6 +89,8 @@ subroutine decomp_cascade_par_init( NLFilename ) decomp_method = no_soil_decomp case( 'CENTURYKoven2013' ) decomp_method = century_decomp + case( 'MIMICSWieder2015' ) + decomp_method = mimics_decomp case default call endrun('Bad soil_decomp_method = '//soil_decomp_method ) end select @@ -110,17 +113,17 @@ subroutine decomp_cascade_par_init( NLFilename ) if (decomp_method == century_decomp) then ndecomp_pools = 6 ndecomp_cascade_transitions = 8 - else ! TODO slevis: Currently for CN. MIMICS will get its own. + else if (decomp_method == mimics_decomp) then ndecomp_pools = 7 - ndecomp_cascade_transitions = 7 + ndecomp_cascade_transitions = 14 end if else if (decomp_method == century_decomp) then ndecomp_pools = 7 ndecomp_cascade_transitions = 10 - else ! TODO slevis: Currently for CN. MIMICS will get its own. + else if (decomp_method == mimics_decomp) then ndecomp_pools = 8 - ndecomp_cascade_transitions = 9 + ndecomp_cascade_transitions = 15 end if endif ! The next param also appears as a dimension in the params files dated diff --git a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 index 71c71915c9..b59db9c5ce 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 @@ -11,9 +11,9 @@ module SoilBiogeochemDecompMod use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type use clm_varpar , only : nlevdecomp, ndecomp_cascade_transitions, ndecomp_pools - use clm_varctl , only : use_nitrif_denitrif, use_lch4, use_fates, use_mimics_decomp, iulog + use clm_varctl , only : use_nitrif_denitrif, use_lch4, use_fates, iulog use clm_varcon , only : dzsoi_decomp - use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, mimics_decomp, decomp_method use SoilBiogeochemStateType , only : soilbiogeochem_state_type use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type @@ -187,7 +187,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, end if decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) decomp_cascade_ctransfer_vr(c,j,k) = (1._r8 - rf_decomp_cascade(c,j,k)) * p_decomp_cpool_loss(c,j,k) - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then decomp_cascade_hr_vr(c,j,k) = min( & p_decomp_cpool_loss(c,j,k), & decomp_cascade_hr_vr(c,j,k) + c_overflow_vr(c,j,k)) @@ -204,7 +204,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, decomp_cascade_sminn_flux_vr(c,j,k) = - pmnf_decomp_cascade(c,j,k) endif net_nmin_vr(c,j) = net_nmin_vr(c,j) - pmnf_decomp_cascade(c,j,k) - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then decomp_cascade_sminn_flux_vr(c,j,k) = decomp_cascade_sminn_flux_vr(c,j,k) - p_decomp_npool_to_din(c,j,k) net_nmin_vr(c,j) = net_nmin_vr(c,j) + p_decomp_npool_to_din(c,j,k) end if @@ -227,7 +227,7 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, ! decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) decomp_cascade_ctransfer_vr(c,j,k) = (1._r8 - rf_decomp_cascade(c,j,k)) * p_decomp_cpool_loss(c,j,k) - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then decomp_cascade_hr_vr(c,j,k) = min( & p_decomp_cpool_loss(c,j,k), & decomp_cascade_hr_vr(c,j,k) + c_overflow_vr(c,j,k)) diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 index 09e5278cd7..da5e2d4240 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 @@ -11,9 +11,8 @@ module SoilBiogeochemNitrogenStateType use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, nlevcan use clm_varpar , only : nlevdecomp_full, nlevdecomp, nlevsoi use clm_varcon , only : spval, dzsoi_decomp, zisoi - use clm_varctl , only : use_mimics_decomp use clm_varctl , only : use_nitrif_denitrif - use SoilBiogeochemDecompCascadeConType , only : century_decomp, decomp_method + use SoilBiogeochemDecompCascadeConType , only : mimics_decomp, century_decomp, decomp_method use clm_varctl , only : iulog, override_bgc_restart_mismatch_dump, spinup_state use landunit_varcon , only : istcrop, istsoil use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con @@ -504,7 +503,7 @@ subroutine Restart ( this, bounds, ncid, flag, totvegc_col ) if (decomp_method == century_decomp ) then decomp_cascade_state = 1 - else if (use_mimics_decomp) then + else if (decomp_method == mimics_decomp ) then decomp_cascade_state = 2 else decomp_cascade_state = 0 diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index e4fc1c20eb..ac066c8807 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -11,13 +11,13 @@ module SoilBiogeochemPotentialMod use decompMod , only : bounds_type use clm_varpar , only : nlevdecomp, ndecomp_cascade_transitions, ndecomp_pools use clm_varpar , only : i_cop_mic, i_oli_mic - use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, mimics_decomp, decomp_method use SoilBiogeochemStateType , only : soilbiogeochem_state_type use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type use SoilBiogeochemNitrogenFluxType , only : soilbiogeochem_nitrogenflux_type - use clm_varctl , only : use_mimics_decomp, use_fates, iulog + use clm_varctl , only : use_fates, iulog ! implicit none private @@ -196,10 +196,10 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & else ! 100% respiration pmnf_decomp_cascade(c,j,k) = - p_decomp_cpool_loss(c,j,k) / cn_decomp_pools(c,j,cascade_donor_pool(k)) endif - else ! CWD -> litter OR use_mimics_decomp is true + else ! CWD -> litter OR mimics_decomp is true pmnf_decomp_cascade(c,j,k) = 0._r8 - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then ! N:C ratio of donor pools (N:C instead of C:N because ! already checked that we're not dividing by zero) decomp_nc_loss_donor = & @@ -234,7 +234,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! Compare cn_gain to target C:N ratio of microbial biomass pools ! to determine immobilization vs. mineralization (in second do k ! transitions loop). - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then do j = 1,nlevdecomp do fc = 1,num_soilc c = filter_soilc(fc) @@ -307,7 +307,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & else gross_nmin_vr(c,j) = gross_nmin_vr(c,j) - pmnf_decomp_cascade(c,j,k) end if - if (use_mimics_decomp) then + if (decomp_method == mimics_decomp) then gross_nmin_vr(c,j) = gross_nmin_vr(c,j) + p_decomp_npool_to_din(c,j,k) end if end do From 8166fd069513df35002558188d2d7c23181cfb48 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 8 Nov 2021 10:46:57 -0700 Subject: [PATCH 56/69] Updated params files and respective code - to include the mimics parameters - to rename parameters that needed the bgc_ prefix - to remove obsolete parameters Copied parameter files to /glade/p/cesmdata/cseg/inputdata/lnd/clm2/paramdata ctsm51_params.c211106.nc clm50_params.c211106.nc clm45_params.c211106.nc ctsm51_ciso_cwd_hr_params.c211106.nc --- bld/namelist_files/namelist_defaults_ctsm.xml | 6 ++-- .../testmods_dirs/clm/ciso_cwd_hr/README | 2 +- .../testmods_dirs/clm/ciso_cwd_hr/user_nl_clm | 2 +- .../testmods_dirs/clm/mimics/user_nl_clm | 2 +- src/biogeochem/CNSharedParamsMod.F90 | 4 +-- .../SoilBiogeochemDecompCascadeBGCMod.F90 | 32 +++++++++---------- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index e3e2b25bd9..ccdaa02f31 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -481,9 +481,9 @@ attributes from the config_cache.xml file (with keys converted to upper-case). -lnd/clm2/paramdata/ctsm51_params.c210923.nc -lnd/clm2/paramdata/clm50_params.c210803.nc -lnd/clm2/paramdata/clm45_params.c210803.nc +lnd/clm2/paramdata/ctsm51_params.c211106.nc +lnd/clm2/paramdata/clm50_params.c211106.nc +lnd/clm2/paramdata/clm45_params.c211106.nc diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/README b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/README index e8eee75e53..39ac318b86 100644 --- a/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/README +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/README @@ -1,5 +1,5 @@ This points to an alternate params file with -rf_cwdl2_bgc = 0.5 +rf_cwdl2 = 0.5 rf_cwdl3_bgc = 0.5 while by default these parameters equal zero. diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm index b7672df8ca..250f23f3a6 100644 --- a/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm @@ -1,2 +1,2 @@ -paramfile = '/glade/p/cesm/cseg/inputdata/lnd/clm2/paramdata/ctsm51_params.c210827.nc' +paramfile = '/glade/p/cesm/cseg/inputdata/lnd/clm2/paramdata/ctsm51_ciso_cwd_hr_params.c211106.nc' hist_fincl1 = 'CWDC_HR','C13_CWDC_HR','C14_CWDC_HR','CWD_HR_L2','CWD_HR_L2_vr','CWD_HR_L3','CWD_HR_L3_vr' diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm index bdc2933d85..5ae1e7298e 100644 --- a/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm @@ -1,2 +1,2 @@ soil_decomp_method = 'MIMICSWieder2015' -paramfile = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/paramdata/ctsm51_params.c210825.nc' +paramfile = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/paramdata/ctsm51_params.c211106.nc' diff --git a/src/biogeochem/CNSharedParamsMod.F90 b/src/biogeochem/CNSharedParamsMod.F90 index bc4ce6bb94..93e464eda1 100644 --- a/src/biogeochem/CNSharedParamsMod.F90 +++ b/src/biogeochem/CNSharedParamsMod.F90 @@ -103,12 +103,12 @@ subroutine CNParamsReadShared_netcdf(ncid) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) CNParamsShareInst%maxpsi=tempr - tString='rf_cwdl2_bgc' ! TODO slevis: rm suffix in params file(s) + tString='rf_cwdl2' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) CNParamsShareInst%rf_cwdl2=tempr - tString='tau_cwd_bgc' ! TODO slevis: rm suffix in params file(s) + tString='tau_cwd' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) CNParamsShareInst%tau_cwd=tempr diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index de8806f338..55720252d2 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -131,82 +131,82 @@ subroutine readParams ( ncid ) !----------------------------------------------------------------------- ! Read off of netcdf file - tString='tau_l1' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_tau_l1' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_l1_bgc=tempr - tString='tau_l2_l3' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_tau_l2_l3' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_l2_l3_bgc=tempr - tString='tau_s1' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_tau_s1' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_s1_bgc=tempr - tString='tau_s2' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_tau_s2' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_s2_bgc=tempr - tString='tau_s3' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_tau_s3' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%tau_s3_bgc=tempr - tString='cn_s1_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_cn_s1' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cn_s1_bgc=tempr - tString='cn_s2_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_cn_s2' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cn_s2_bgc=tempr - tString='cn_s3_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_cn_s3' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cn_s3_bgc=tempr - tString='rf_l1s1_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_rf_l1s1' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l1s1_bgc=tempr - tString='rf_l2s1_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_rf_l2s1' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l2s1_bgc=tempr - tString='rf_l3s2_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_rf_l3s2' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_l3s2_bgc=tempr - tString='rf_s2s1_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_rf_s2s1' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_s2s1_bgc=tempr - tString='rf_s2s3_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_rf_s2s3' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_s2s3_bgc=tempr - tString='rf_s3s1_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_rf_s3s1' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_s3s1_bgc=tempr - tString='rf_cwdl3_bgc' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_rf_cwdl3' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%rf_cwdl3_bgc=tempr - tString='cwd_fcel' ! TODO slevis: bgc_ prefix in params file(s) and code + tString='bgc_cwd_fcel' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cwd_fcel_bgc=tempr From 4eb33728bda7eb9bfe142d6fae20601370fba0fa Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 8 Nov 2021 13:45:33 -0700 Subject: [PATCH 57/69] Add mimics tests, one to cheyenne and one to izumi test suites ERP_D_P36x2_Ld3.f10_f10_mg37.I2000Clm51BgcCrop.cheyenne_gnu.clm-mimics SMS_Ld5_Mmpi-serial.1x1_brazil.IHistClm50BgcQianRs.izumi_gnu.clm-mimics For the record the same cheyenne test using the intel compiler triggers this error: 25:MPT ERROR: Rank 25(g:25) received signal SIGFPE(8). 25: Process ID: 24080, Host: r14i4n18, Program: /glade/scratch/slevis/ERP_D_P36x2_Ld3.f10_f10_mg37.I2000Clm51BgcCrop.cheyenne_intel.clm-mimics.20211108_123526_stdha2/bld/cesm.exe 25: MPT Version: HPE MPT 2.22 03/31/20 15:59:10 25: 25:MPT: --------stack traceback------- 25:OMP: Warning #190: Forking a process while a parallel region is active is potentially unsafe. -1:MPT ERROR: MPI_COMM_WORLD rank 29 has terminated without calling MPI_Finalize() -1: aborting job MPT: Received signal 8 --- cime_config/testdefs/testlist_clm.xml | 18 ++++++++++++++++++ .../testmods_dirs/clm/mimics/user_nl_clm | 1 - .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 16 ++++++++-------- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index 5613e08100..99a0f8a069 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -538,6 +538,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm index 5ae1e7298e..152d91b21e 100644 --- a/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm @@ -1,2 +1 @@ soil_decomp_method = 'MIMICSWieder2015' -paramfile = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/paramdata/ctsm51_params.c211106.nc' diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 2dcdb7e221..c3c7da28dd 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -489,7 +489,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_met_lit) = .false. initial_cn_ratio(i_met_lit) = 10._r8 ! 90 in BGC; not used in MIMICS initial_stock(i_met_lit) = params_inst%initial_Cstocks(i_met_lit) - initial_stock(i_met_lit) = 1._r8 ! slevis diag + initial_stock(i_met_lit) = 1._r8 ! TODO slevis: finalize in params files is_metabolic(i_met_lit) = .true. is_cellulose(i_met_lit) = .false. is_lignin(i_met_lit) = .false. @@ -506,7 +506,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_str_lit) = .false. initial_cn_ratio(i_str_lit) = 10._r8 ! 90 in BGC; not used in MIMICS initial_stock(i_str_lit) = params_inst%initial_Cstocks(i_str_lit) - initial_stock(i_str_lit) = 1._r8 ! slevis diag + initial_stock(i_str_lit) = 1._r8 ! TODO slevis: finalize in params files is_metabolic(i_str_lit) = .false. is_cellulose(i_str_lit) = .true. is_lignin(i_str_lit) = .true. @@ -533,7 +533,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_avl_som) = .false. initial_cn_ratio(i_avl_som) = 10._r8 ! cn_s1 in BGC; not used in MIMICS initial_stock(i_avl_som) = params_inst%initial_Cstocks(i_avl_som) - initial_stock(i_avl_som) = 200._r8 ! slevis diag + initial_stock(i_avl_som) = 200._r8 ! TODO slevis: finalize in params files is_metabolic(i_avl_som) = .false. is_cellulose(i_avl_som) = .false. is_lignin(i_avl_som) = .false. @@ -550,7 +550,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_chem_som) = .false. initial_cn_ratio(i_chem_som) = 10._r8 ! cn_s2 in BGC; not used in MIMICS initial_stock(i_chem_som) = params_inst%initial_Cstocks(i_chem_som) - initial_stock(i_chem_som) = 200._r8 ! slevis diag + initial_stock(i_chem_som) = 200._r8 ! TODO slevis: finalize in params files is_metabolic(i_chem_som) = .false. is_cellulose(i_chem_som) = .false. is_lignin(i_chem_som) = .false. @@ -567,7 +567,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_phys_som) = .false. initial_cn_ratio(i_phys_som) = 10._r8 ! cn_s3 in BGC; not used in MIMICS initial_stock(i_phys_som) = params_inst%initial_Cstocks(i_phys_som) - initial_stock(i_phys_som) = 200._r8 ! slevis diag + initial_stock(i_phys_som) = 200._r8 ! TODO slevis: finalize in params files is_metabolic(i_phys_som) = .false. is_cellulose(i_phys_som) = .false. is_lignin(i_phys_som) = .false. @@ -584,7 +584,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_cop_mic) = .false. initial_cn_ratio(i_cop_mic) = 10._r8 ! MIMICS may use this initial_stock(i_cop_mic) = params_inst%initial_Cstocks(i_cop_mic) - initial_stock(i_cop_mic) = 1._r8 ! slevis diag + initial_stock(i_cop_mic) = 1._r8 ! TODO slevis: finalize in params files is_metabolic(i_cop_mic) = .false. is_cellulose(i_cop_mic) = .false. is_lignin(i_cop_mic) = .false. @@ -601,7 +601,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_oli_mic) = .false. initial_cn_ratio(i_oli_mic) = 10._r8 ! MIMICS may use this initial_stock(i_oli_mic) = params_inst%initial_Cstocks(i_oli_mic) - initial_stock(i_oli_mic) = 1._r8 ! slevis diag + initial_stock(i_oli_mic) = 1._r8 ! TODO slevis: finalize in params files is_metabolic(i_oli_mic) = .false. is_cellulose(i_oli_mic) = .false. is_lignin(i_oli_mic) = .false. @@ -620,7 +620,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_cwd(i_cwd) = .true. initial_cn_ratio(i_cwd) = 10._r8 ! 90 in BGC; not used in MIMICS initial_stock(i_cwd) = params_inst%initial_Cstocks(i_cwd) - initial_stock(i_cwd) = 1._r8 ! slevis diag + initial_stock(i_cwd) = 1._r8 ! TODO slevis: finalize in params files is_metabolic(i_cwd) = .false. is_cellulose(i_cwd) = .false. is_lignin(i_cwd) = .false. From 019fe5403b3588e02b89f9dede7d9dce18094f1f Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 15 Nov 2021 13:03:13 -0700 Subject: [PATCH 58/69] Update params files (var names/values), clean up various TODOs --- bld/namelist_files/namelist_defaults_ctsm.xml | 6 +- .../testmods_dirs/clm/ciso_cwd_hr/user_nl_clm | 2 +- src/biogeochem/CNVegCarbonFluxType.F90 | 1 - .../SoilBiogeochemDecompCascadeBGCMod.F90 | 32 ++--- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 122 +++++++++--------- .../SoilBiogeochemPotentialMod.F90 | 2 +- .../SoilBiogeochemStateType.F90 | 2 +- 7 files changed, 83 insertions(+), 84 deletions(-) diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index ccdaa02f31..3b17b91e13 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -481,9 +481,9 @@ attributes from the config_cache.xml file (with keys converted to upper-case). -lnd/clm2/paramdata/ctsm51_params.c211106.nc -lnd/clm2/paramdata/clm50_params.c211106.nc -lnd/clm2/paramdata/clm45_params.c211106.nc +lnd/clm2/paramdata/ctsm51_params.c211112.nc +lnd/clm2/paramdata/clm50_params.c211112.nc +lnd/clm2/paramdata/clm45_params.c211112.nc diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm index 250f23f3a6..7ae4a69aad 100644 --- a/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm @@ -1,2 +1,2 @@ -paramfile = '/glade/p/cesm/cseg/inputdata/lnd/clm2/paramdata/ctsm51_ciso_cwd_hr_params.c211106.nc' +paramfile = '/glade/p/cesm/cseg/inputdata/lnd/clm2/paramdata/ctsm51_ciso_cwd_hr_params.c211112.nc' hist_fincl1 = 'CWDC_HR','C13_CWDC_HR','C14_CWDC_HR','CWD_HR_L2','CWD_HR_L2_vr','CWD_HR_L3','CWD_HR_L3_vr' diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index dfe571eb72..718f7b0330 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -4418,7 +4418,6 @@ subroutine Summary_carbonflux(this, & if (decomp_method == mimics_decomp) then ! Calculate ligninNratio for leaves and fine roots - ! TODO init. ligninNratio vars if nec. for call p2c to work associate(ivt => patch%itype) ! Input: [integer (:)] patch plant type ligninNratio_leaf_patch(p) = pftcon%lf_flig(ivt(p)) * & pftcon%lflitcn(ivt(p)) * & diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index 55720252d2..500b41f175 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -97,8 +97,8 @@ module SoilBiogeochemDecompCascadeBGCMod real(r8) :: cwd_fcel_bgc !cellulose fraction for CWD - real(r8), allocatable :: initial_Cstocks(:) ! Initial Carbon stocks for a cold-start - real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start + real(r8), allocatable :: bgc_initial_Cstocks(:) ! Initial Carbon stocks for a cold-start + real(r8) :: bgc_initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start end type params_type ! @@ -211,15 +211,15 @@ subroutine readParams ( ncid ) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%cwd_fcel_bgc=tempr - allocate(params_inst%initial_Cstocks(ndecomp_pools_max)) - tString='initial_Cstocks_bgc' - call ncd_io(trim(tString), params_inst%initial_Cstocks(:), 'read', ncid, readvar=readv) + allocate(params_inst%bgc_initial_Cstocks(ndecomp_pools_max)) + tString='bgc_initial_Cstocks' + call ncd_io(trim(tString), params_inst%bgc_initial_Cstocks(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - tString='initial_Cstocks_depth_bgc' + tString='bgc_initial_Cstocks_depth' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%initial_Cstocks_depth=tempr + params_inst%bgc_initial_Cstocks_depth=tempr end subroutine readParams @@ -305,7 +305,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i rf_s1s3(c,j) = t end do end do - initial_stock_soildepth = params_inst%initial_Cstocks_depth + initial_stock_soildepth = params_inst%bgc_initial_Cstocks_depth !------------------- list of pools and their attributes ------------ i_litr_min = 1 @@ -319,7 +319,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i is_soil(i_met_lit) = .false. is_cwd(i_met_lit) = .false. initial_cn_ratio(i_met_lit) = 90._r8 - initial_stock(i_met_lit) = params_inst%initial_Cstocks(i_met_lit) + initial_stock(i_met_lit) = params_inst%bgc_initial_Cstocks(i_met_lit) is_metabolic(i_met_lit) = .true. is_cellulose(i_met_lit) = .false. is_lignin(i_met_lit) = .false. @@ -334,7 +334,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i is_soil(i_cel_lit) = .false. is_cwd(i_cel_lit) = .false. initial_cn_ratio(i_cel_lit) = 90._r8 - initial_stock(i_cel_lit) = params_inst%initial_Cstocks(i_cel_lit) + initial_stock(i_cel_lit) = params_inst%bgc_initial_Cstocks(i_cel_lit) is_metabolic(i_cel_lit) = .false. is_cellulose(i_cel_lit) = .true. is_lignin(i_cel_lit) = .false. @@ -349,7 +349,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i is_soil(i_lig_lit) = .false. is_cwd(i_lig_lit) = .false. initial_cn_ratio(i_lig_lit) = 90._r8 - initial_stock(i_lig_lit) = params_inst%initial_Cstocks(i_lig_lit) + initial_stock(i_lig_lit) = params_inst%bgc_initial_Cstocks(i_lig_lit) is_metabolic(i_lig_lit) = .false. is_cellulose(i_lig_lit) = .false. is_lignin(i_lig_lit) = .true. @@ -374,7 +374,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i is_soil(i_act_som) = .true. is_cwd(i_act_som) = .false. initial_cn_ratio(i_act_som) = cn_s1 - initial_stock(i_act_som) = params_inst%initial_Cstocks(i_act_som) + initial_stock(i_act_som) = params_inst%bgc_initial_Cstocks(i_act_som) is_metabolic(i_act_som) = .false. is_cellulose(i_act_som) = .false. is_lignin(i_act_som) = .false. @@ -389,7 +389,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i is_soil(i_slo_som) = .true. is_cwd(i_slo_som) = .false. initial_cn_ratio(i_slo_som) = cn_s2 - initial_stock(i_slo_som) = params_inst%initial_Cstocks(i_slo_som) + initial_stock(i_slo_som) = params_inst%bgc_initial_Cstocks(i_slo_som) is_metabolic(i_slo_som) = .false. is_cellulose(i_slo_som) = .false. is_lignin(i_slo_som) = .false. @@ -404,7 +404,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i is_soil(i_pas_som) = .true. is_cwd(i_pas_som) = .false. initial_cn_ratio(i_pas_som) = cn_s3 - initial_stock(i_pas_som) = params_inst%initial_Cstocks(i_pas_som) + initial_stock(i_pas_som) = params_inst%bgc_initial_Cstocks(i_pas_som) is_metabolic(i_pas_som) = .false. is_cellulose(i_pas_som) = .false. is_lignin(i_pas_som) = .false. @@ -421,7 +421,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i is_soil(i_cwd) = .false. is_cwd(i_cwd) = .true. initial_cn_ratio(i_cwd) = 90._r8 - initial_stock(i_cwd) = params_inst%initial_Cstocks(i_cwd) + initial_stock(i_cwd) = params_inst%bgc_initial_Cstocks(i_cwd) is_metabolic(i_cwd) = .false. is_cellulose(i_cwd) = .false. is_lignin(i_cwd) = .false. @@ -502,7 +502,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i cascade_receiver_pool(i_cwdl3) = i_lig_lit end if - deallocate(params_inst%initial_Cstocks) + deallocate(params_inst%bgc_initial_Cstocks) end associate diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index c3c7da28dd..efa2c33de1 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -108,29 +108,29 @@ module SoilBiogeochemDecompCascadeMIMICSMod real(r8), private :: kslope_s1_m2 ! type, private :: params_type - real(r8) :: mimics_nue_into_mic + real(r8) :: mimics_nue_into_mic ! microbial N use efficiency for N fluxes real(r8) :: mimics_desorpQ10 - real(r8) :: mimics_densdep - real(r8) :: mimics_tau_mod_factor + real(r8) :: mimics_densdep ! exponent controling the density dependence of microbial turnover + real(r8) :: mimics_tau_mod_factor ! (1 / tauModDenom) from testbed code real(r8) :: mimics_tau_mod_min real(r8) :: mimics_tau_mod_max real(r8) :: mimics_ko_r real(r8) :: mimics_ko_k - real(r8) :: mimics_cn_r - real(r8) :: mimics_cn_k - real(r8) :: mimics_cn_mod_num + real(r8) :: mimics_cn_r ! C:N of MICr + real(r8) :: mimics_cn_k ! C:N of MICk + real(r8) :: mimics_cn_mod_num ! adjusts microbial CN based on fmet real(r8) :: mimics_t_soi_ref - real(r8) :: initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start - real(r8), allocatable :: initial_Cstocks(:) ! Initial Carbon stocks for a cold-start + real(r8) :: mimics_initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start + real(r8), allocatable :: mimics_initial_Cstocks(:) ! Initial Carbon stocks for a cold-start ! The next few vectors are dimensioned by the number of decomposition ! transitions making use of the corresponding parameters. The transitions ! are represented in this order: l1m1 l2m1 s1m1 l1m2 l2m2 s1m2 real(r8), allocatable :: mimics_mge(:) ! Microbial growth efficiency (mg/mg) real(r8), allocatable :: mimics_vmod(:) ! - real(r8), allocatable :: mimics_vint(:) ! - real(r8), allocatable :: mimics_vslope(:) ! + real(r8), allocatable :: mimics_vint(:) ! regression intercept (5.47 ln(mg Cs (mg MIC)-1 h-1) ) + real(r8), allocatable :: mimics_vslope(:) ! transition regression coeffs (ln(mg Cs (mg MIC)-1 h-1) ¡C-1) real(r8), allocatable :: mimics_kmod(:) ! - real(r8), allocatable :: mimics_kint(:) ! + real(r8), allocatable :: mimics_kint(:) ! regression intercept real(r8), allocatable :: mimics_kslope(:) ! ! The next few vectors are dimensioned by the number of ! parameters with the same name used in the same formula. @@ -176,20 +176,14 @@ subroutine readParams ( ncid ) !----------------------------------------------------------------------- ! Read off of netcdf file - ! TODO When ready for final params values, talk to @wwieder - ! TODO Need next one for spin-ups? If so, then add prefixes - ! mimics here and bgc in BGCMod if these two will differ or - ! move reading the parameter to CNSharedParamsMod if they - ! will not differ. - tString='initial_Cstocks_depth_bgc' + tString='mimics_initial_Cstocks_depth' call ncd_io(trim(tString), tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%initial_Cstocks_depth=tempr + params_inst%mimics_initial_Cstocks_depth=tempr - ! TODO initial_Cstocks definitely needs to differ: mimics_ vs. bgc_ - allocate(params_inst%initial_Cstocks(ndecomp_pools_max)) - tString='initial_Cstocks_bgc' - call ncd_io(trim(tString), params_inst%initial_Cstocks(:), 'read', ncid, readvar=readv) + allocate(params_inst%mimics_initial_Cstocks(ndecomp_pools_max)) + tString='mimics_initial_Cstocks' + call ncd_io(trim(tString), params_inst%mimics_initial_Cstocks(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) allocate(params_inst%mimics_mge(ndecomp_pools_max)) @@ -252,12 +246,12 @@ subroutine readParams ( ncid ) call ncd_io(trim(tString), params_inst%mimics_fmet(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_fchem_r(2)) + allocate(params_inst%mimics_fchem_r(4)) tString='mimics_fchem_r' call ncd_io(trim(tString), params_inst%mimics_fchem_r(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_fchem_k(2)) + allocate(params_inst%mimics_fchem_k(4)) tString='mimics_fchem_k' call ncd_io(trim(tString), params_inst%mimics_fchem_k(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -367,7 +361,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat !----------------------------------------------------------------------- associate( & - nue_decomp_cascade => soilbiogeochem_state_inst%nue_decomp_cascade_col , & ! Output: [real(r8) (:) ] N use efficiency for a given transition (TODO) + nue_decomp_cascade => soilbiogeochem_state_inst%nue_decomp_cascade_col , & ! Output: [real(r8) (:) ] N use efficiency for a given transition (gN going into microbe / gN decomposed) cellclay => soilstate_inst%cellclay_col , & ! Input: [real(r8) (:,:) ] column 3D clay @@ -473,7 +467,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat dexp(mimics_p_scalar_p2 * dsqrt(clay))) end do end do - initial_stock_soildepth = params_inst%initial_Cstocks_depth + initial_stock_soildepth = params_inst%mimics_initial_Cstocks_depth !------------------- list of pools and their attributes ------------ i_litr_min = 1 @@ -488,8 +482,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_soil(i_met_lit) = .false. is_cwd(i_met_lit) = .false. initial_cn_ratio(i_met_lit) = 10._r8 ! 90 in BGC; not used in MIMICS - initial_stock(i_met_lit) = params_inst%initial_Cstocks(i_met_lit) - initial_stock(i_met_lit) = 1._r8 ! TODO slevis: finalize in params files + initial_stock(i_met_lit) = params_inst%mimics_initial_Cstocks(i_met_lit) is_metabolic(i_met_lit) = .true. is_cellulose(i_met_lit) = .false. is_lignin(i_met_lit) = .false. @@ -505,8 +498,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_soil(i_str_lit) = .false. is_cwd(i_str_lit) = .false. initial_cn_ratio(i_str_lit) = 10._r8 ! 90 in BGC; not used in MIMICS - initial_stock(i_str_lit) = params_inst%initial_Cstocks(i_str_lit) - initial_stock(i_str_lit) = 1._r8 ! TODO slevis: finalize in params files + initial_stock(i_str_lit) = params_inst%mimics_initial_Cstocks(i_str_lit) is_metabolic(i_str_lit) = .false. is_cellulose(i_str_lit) = .true. is_lignin(i_str_lit) = .true. @@ -532,8 +524,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_soil(i_avl_som) = .true. is_cwd(i_avl_som) = .false. initial_cn_ratio(i_avl_som) = 10._r8 ! cn_s1 in BGC; not used in MIMICS - initial_stock(i_avl_som) = params_inst%initial_Cstocks(i_avl_som) - initial_stock(i_avl_som) = 200._r8 ! TODO slevis: finalize in params files + initial_stock(i_avl_som) = params_inst%mimics_initial_Cstocks(i_avl_som) is_metabolic(i_avl_som) = .false. is_cellulose(i_avl_som) = .false. is_lignin(i_avl_som) = .false. @@ -549,8 +540,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_soil(i_chem_som) = .true. is_cwd(i_chem_som) = .false. initial_cn_ratio(i_chem_som) = 10._r8 ! cn_s2 in BGC; not used in MIMICS - initial_stock(i_chem_som) = params_inst%initial_Cstocks(i_chem_som) - initial_stock(i_chem_som) = 200._r8 ! TODO slevis: finalize in params files + initial_stock(i_chem_som) = params_inst%mimics_initial_Cstocks(i_chem_som) is_metabolic(i_chem_som) = .false. is_cellulose(i_chem_som) = .false. is_lignin(i_chem_som) = .false. @@ -566,8 +556,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_soil(i_phys_som) = .true. is_cwd(i_phys_som) = .false. initial_cn_ratio(i_phys_som) = 10._r8 ! cn_s3 in BGC; not used in MIMICS - initial_stock(i_phys_som) = params_inst%initial_Cstocks(i_phys_som) - initial_stock(i_phys_som) = 200._r8 ! TODO slevis: finalize in params files + initial_stock(i_phys_som) = params_inst%mimics_initial_Cstocks(i_phys_som) is_metabolic(i_phys_som) = .false. is_cellulose(i_phys_som) = .false. is_lignin(i_phys_som) = .false. @@ -583,8 +572,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_soil(i_cop_mic) = .false. is_cwd(i_cop_mic) = .false. initial_cn_ratio(i_cop_mic) = 10._r8 ! MIMICS may use this - initial_stock(i_cop_mic) = params_inst%initial_Cstocks(i_cop_mic) - initial_stock(i_cop_mic) = 1._r8 ! TODO slevis: finalize in params files + initial_stock(i_cop_mic) = params_inst%mimics_initial_Cstocks(i_cop_mic) is_metabolic(i_cop_mic) = .false. is_cellulose(i_cop_mic) = .false. is_lignin(i_cop_mic) = .false. @@ -600,8 +588,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_soil(i_oli_mic) = .false. is_cwd(i_oli_mic) = .false. initial_cn_ratio(i_oli_mic) = 10._r8 ! MIMICS may use this - initial_stock(i_oli_mic) = params_inst%initial_Cstocks(i_oli_mic) - initial_stock(i_oli_mic) = 1._r8 ! TODO slevis: finalize in params files + initial_stock(i_oli_mic) = params_inst%mimics_initial_Cstocks(i_oli_mic) is_metabolic(i_oli_mic) = .false. is_cellulose(i_oli_mic) = .false. is_lignin(i_oli_mic) = .false. @@ -619,8 +606,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat is_soil(i_cwd) = .false. is_cwd(i_cwd) = .true. initial_cn_ratio(i_cwd) = 10._r8 ! 90 in BGC; not used in MIMICS - initial_stock(i_cwd) = params_inst%initial_Cstocks(i_cwd) - initial_stock(i_cwd) = 1._r8 ! TODO slevis: finalize in params files + initial_stock(i_cwd) = params_inst%mimics_initial_Cstocks(i_cwd) is_metabolic(i_cwd) = .false. is_cellulose(i_cwd) = .false. is_lignin(i_cwd) = .false. @@ -752,7 +738,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat deallocate(params_inst%mimics_desorp) deallocate(params_inst%mimics_fphys_r) deallocate(params_inst%mimics_fphys_k) - deallocate(params_inst%initial_Cstocks) + deallocate(params_inst%mimics_initial_Cstocks) end associate @@ -825,8 +811,10 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & real(r8):: mimics_fmet_p4 real(r8):: mimics_fchem_r_p1 real(r8):: mimics_fchem_r_p2 + real(r8):: mimics_fchem_r_p3 real(r8):: mimics_fchem_k_p1 real(r8):: mimics_fchem_k_p2 + real(r8):: mimics_fchem_k_p3 real(r8):: mimics_tau_mod_min real(r8):: mimics_tau_mod_max real(r8):: mimics_tau_mod_factor @@ -1004,7 +992,6 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do - ! TODO May need a hook from MIMICS to ch4 code for this to work ! Calculate ANOXIA ! anoxia = .true. when (use_lch4) @@ -1083,8 +1070,10 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & mimics_fmet_p4 = params_inst%mimics_fmet(4) mimics_fchem_r_p1 = params_inst%mimics_fchem_r(1) mimics_fchem_r_p2 = params_inst%mimics_fchem_r(2) + mimics_fchem_r_p3 = params_inst%mimics_fchem_r(3) mimics_fchem_k_p1 = params_inst%mimics_fchem_k(1) mimics_fchem_k_p2 = params_inst%mimics_fchem_k(2) + mimics_fchem_k_p3 = params_inst%mimics_fchem_k(3) mimics_tau_mod_min = params_inst%mimics_tau_mod_min mimics_tau_mod_max = params_inst%mimics_tau_mod_max mimics_tau_mod_factor = params_inst%mimics_tau_mod_factor @@ -1097,12 +1086,11 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & mimics_densdep = params_inst%mimics_densdep mimics_desorpQ10 = params_inst%mimics_desorpQ10 mimics_t_soi_ref = params_inst%mimics_t_soi_ref - mimics_cn_mod_num = params_inst%mimics_cn_mod_num ! TODO slevis: I don't see values in the testbed or - mimics_cn_r = params_inst%mimics_cn_r ! ... in the testbed's - mimics_cn_k = params_inst%mimics_cn_k ! ... params file for these 3 + mimics_cn_mod_num = params_inst%mimics_cn_mod_num + mimics_cn_r = params_inst%mimics_cn_r + mimics_cn_k = params_inst%mimics_cn_k ! calculate rates for all litter and som pools - ! TODO Ok that I reversed order of do-loops? do fc = 1,num_soilc c = filter_soilc(fc) @@ -1136,10 +1124,10 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Used in the update of certain pathfrac terms that vary with time ! in the next loop - fchem_m1 = min(1.0_r8, max(0.0_r8, mimics_fchem_r_p1 * & - exp(mimics_fchem_r_p2 * fmet))) - fchem_m2 = min(1.0_r8, max(0.0_r8, mimics_fchem_k_p1 * & - exp(mimics_fchem_k_p2 * fmet))) + fchem_m1 = min(1._r8, max(0._r8, mimics_fchem_r_p1 * & + exp(mimics_fchem_r_p2 * fmet) * mimics_fchem_r_p3)) + fchem_m2 = min(1._r8, max(0._r8, mimics_fchem_k_p1 * & + exp(mimics_fchem_k_p2 * fmet) * mimics_fchem_k_p3)) do j = 1,nlevdecomp ! vmax ends up in units of per hour but is expected @@ -1194,26 +1182,38 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! decomp_k used in SoilBiogeochemPotentialMod.F90 ! also updating pathfrac terms that vary with time - ! TODO No spinup terms for now (see cwd below) term_1 = vmax_l1_m1 * m1_conc / (km_l1_m1 + m1_conc) term_2 = vmax_l1_m2 * m2_conc / (km_l1_m2 + m2_conc) decomp_k(c,j,i_met_lit) = (term_1 + term_2) * w_d_o_scalars - ! TODO May need if-statment for all cases that term_1 +/ term_2 - ! are zero bc biomass would never flow into such pools in that case - pathfrac_decomp_cascade(c,j,i_l1m1) = term_1 / (term_1 + term_2) - pathfrac_decomp_cascade(c,j,i_l1m2) = term_2 / (term_1 + term_2) + if (term_1 + term_2 /= 0._r8) then + pathfrac_decomp_cascade(c,j,i_l1m1) = term_1 / (term_1 + term_2) + pathfrac_decomp_cascade(c,j,i_l1m2) = term_2 / (term_1 + term_2) + else + pathfrac_decomp_cascade(c,j,i_l1m1) = 0._r8 + pathfrac_decomp_cascade(c,j,i_l1m2) = 0._r8 + end if term_1 = vmax_l2_m1 * m1_conc / (km_l2_m1 + m1_conc) term_2 = vmax_l2_m2 * m2_conc / (km_l2_m2 + m2_conc) decomp_k(c,j,i_str_lit) = (term_1 + term_2) * w_d_o_scalars - pathfrac_decomp_cascade(c,j,i_l2m1) = term_1 / (term_1 + term_2) - pathfrac_decomp_cascade(c,j,i_l2m2) = term_2 / (term_1 + term_2) + if (term_1 + term_2 /= 0._r8) then + pathfrac_decomp_cascade(c,j,i_l2m1) = term_1 / (term_1 + term_2) + pathfrac_decomp_cascade(c,j,i_l2m2) = term_2 / (term_1 + term_2) + else + pathfrac_decomp_cascade(c,j,i_l2m1) = 0._r8 + pathfrac_decomp_cascade(c,j,i_l2m2) = 0._r8 + end if term_1 = vmax_s1_m1 * m1_conc / (km_s1_m1 + m1_conc) term_2 = vmax_s1_m2 * m2_conc / (km_s1_m2 + m2_conc) decomp_k(c,j,i_avl_som) = (term_1 + term_2) * w_d_o_scalars - pathfrac_decomp_cascade(c,j,i_s1m1) = term_1 / (term_1 + term_2) - pathfrac_decomp_cascade(c,j,i_s1m2) = term_2 / (term_1 + term_2) + if (term_1 + term_2 /= 0._r8) then + pathfrac_decomp_cascade(c,j,i_s1m1) = term_1 / (term_1 + term_2) + pathfrac_decomp_cascade(c,j,i_s1m2) = term_2 / (term_1 + term_2) + else + pathfrac_decomp_cascade(c,j,i_s1m1) = 0._r8 + pathfrac_decomp_cascade(c,j,i_s1m2) = 0._r8 + end if decomp_k(c,j,i_phys_som) = desorption * depth_scalar(c,j) diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index ac066c8807..da46e178b7 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -122,7 +122,7 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & floating_cn_ratio_decomp_pools => decomp_cascade_con%floating_cn_ratio_decomp_pools , & ! Input: [logical (:) ] TRUE => pool has fixed C:N ratio initial_cn_ratio => decomp_cascade_con%initial_cn_ratio , & ! Input: [real(r8) (:) ] c:n ratio for initialization of pools - nue_decomp_cascade => soilbiogeochem_state_inst%nue_decomp_cascade_col , & ! Input: [real(r8) (:) ] N use efficiency for a given transition (TODO) + nue_decomp_cascade => soilbiogeochem_state_inst%nue_decomp_cascade_col , & ! Input: [real(r8) (:) ] N use efficiency for a given transition (gN going into microbe / gN decomposed) rf_decomp_cascade => soilbiogeochem_carbonflux_inst%rf_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] respired fraction in decomposition step (frac) pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col , & ! Input: [real(r8) (:,:,:) ] what fraction of C passes from donor to receiver pool through a given transition (frac) diff --git a/src/soilbiogeochem/SoilBiogeochemStateType.F90 b/src/soilbiogeochem/SoilBiogeochemStateType.F90 index 26e3626bf8..fcdced386d 100644 --- a/src/soilbiogeochem/SoilBiogeochemStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemStateType.F90 @@ -33,7 +33,7 @@ module SoilBiogeochemStateType real(r8) , pointer :: fpi_vr_col (:,:) ! (no units) fraction of potential immobilization real(r8) , pointer :: fpi_col (:) ! (no units) fraction of potential immobilization real(r8), pointer :: fpg_col (:) ! (no units) fraction of potential gpp - real(r8) , pointer :: nue_decomp_cascade_col (:) ! (TODO) N use efficiency for a given transition + real(r8) , pointer :: nue_decomp_cascade_col (:) ! (gN going into microbe / gN decomposed) N use efficiency for a given transition real(r8) , pointer :: nfixation_prof_col (:,:) ! (1/m) profile for N fixation additions real(r8) , pointer :: ndep_prof_col (:,:) ! (1/m) profile for N fixation additions real(r8) , pointer :: som_adv_coef_col (:,:) ! (m2/s) SOM advective flux From 3b945970028266a4913ecee827528651ab33b335 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 15 Nov 2021 17:06:42 -0700 Subject: [PATCH 59/69] Revisions in response to Erik's code review and 1 or 2 remaining TODOs --- .../testdefs/testmods_dirs/clm/mimics/README | 4 + src/biogeochem/CNDriverMod.F90 | 4 - src/biogeochem/EDBGCDynMod.F90 | 4 - src/main/clm_instMod.F90 | 4 - src/main/readParamsMod.F90 | 4 - .../SoilBiogeochemDecompCascadeBGCMod.F90 | 16 +-- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 127 +++++++++--------- 7 files changed, 78 insertions(+), 85 deletions(-) diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics/README b/cime_config/testdefs/testmods_dirs/clm/mimics/README index b138ba628f..082e324f4d 100644 --- a/cime_config/testdefs/testmods_dirs/clm/mimics/README +++ b/cime_config/testdefs/testmods_dirs/clm/mimics/README @@ -1,2 +1,6 @@ This test mod turns on the MIMICS instead of the CENTURY below-ground biogeochemistry. + +As of 2021/11/15 this test inherits mods from the ../coldStart directory; +however the plan is to change that to ../default when we have an acceptable +spun up finidat file to initialize MIMICS with. diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index 494295ad07..f2cad9782a 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -321,10 +321,6 @@ subroutine CNDriverNoLeaching(bounds, call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) - else - write(iulog,*) 'WARNING:' - write(iulog,*) 'Neither use_mimics_decomp nor century_decomp' - write(iulog,*) 'have been set. Is this intentional?' end if ! calculate potential decomp rates and total immobilization demand (previously inlined in CNDecompAlloc) diff --git a/src/biogeochem/EDBGCDynMod.F90 b/src/biogeochem/EDBGCDynMod.F90 index 82e68be6c5..754f7ff4a0 100644 --- a/src/biogeochem/EDBGCDynMod.F90 +++ b/src/biogeochem/EDBGCDynMod.F90 @@ -186,10 +186,6 @@ subroutine EDBGCDyn(bounds, & call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) - else - write(iulog,*) 'WARNING:' - write(iulog,*) 'Neither use_mimics_decomp nor century_decomp' - write(iulog,*) 'have been set. Is this intentional?' end if ! calculate potential decomp rates and total immobilization demand (previously inlined in CNDecompAlloc) diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90 index 72c52fc4fe..a593664217 100644 --- a/src/main/clm_instMod.F90 +++ b/src/main/clm_instMod.F90 @@ -388,10 +388,6 @@ subroutine clm_instInit(bounds) else if (decomp_method == mimics_decomp ) then call init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, & soilstate_inst) - else - write(iulog,*) 'WARNING:' - write(iulog,*) 'Neither use_mimics_decomp nor century_decomp' - write(iulog,*) 'have been set. Is this intentional?' end if ! Initalize soilbiogeochem carbon types diff --git a/src/main/readParamsMod.F90 b/src/main/readParamsMod.F90 index e1c2c9abc7..31a116ab28 100644 --- a/src/main/readParamsMod.F90 +++ b/src/main/readParamsMod.F90 @@ -104,10 +104,6 @@ subroutine readParameters (nutrient_competition_method, photosyns_inst) call readSoilBiogeochemDecompMimicsParams(ncid) else if (decomp_method == century_decomp) then call readSoilBiogeochemDecompBgcParams(ncid) - else - write(iulog,*) 'WARNING:' - write(iulog,*) 'Neither use_mimics_decomp nor century_decomp' - write(iulog,*) 'have been set. Is this intentional?' end if call readSoilBiogeochemDecompParams(ncid) call readSoilBiogeochemLittVertTranspParams(ncid) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index 500b41f175..0944d0eeca 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -10,7 +10,7 @@ module SoilBiogeochemDecompCascadeBGCMod use shr_const_mod , only : SHR_CONST_TKFRZ use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : nlevdecomp, ndecomp_pools_max - use clm_varpar , only : i_litr_min, i_litr_max, i_met_lit, i_cwd + use clm_varpar , only : i_litr_min, i_litr_max, i_met_lit, i_cwd, i_cwdl2 use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_fates use clm_varcon , only : zsoi use decompMod , only : bounds_type @@ -71,7 +71,6 @@ module SoilBiogeochemDecompCascadeBGCMod integer, private :: i_s2s1 integer, private :: i_s2s3 integer, private :: i_s3s1 - integer, private :: i_cwdl2 integer, private :: i_cwdl3 type, private :: params_type @@ -531,6 +530,7 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst ! ! !LOCAL VARIABLES: + real(r8), parameter :: eps = 1.e-6_r8 real(r8):: frw(bounds%begc:bounds%endc) ! rooting fraction weight real(r8), allocatable:: fr(:,:) ! column-level rooting fraction by soil depth real(r8):: psi ! temporary soilpsi for water scalar @@ -618,39 +618,39 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & do fc = 1,num_soilc c = filter_soilc(fc) ! - if ( abs(spinup_factor(i_met_lit) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_met_lit) - 1._r8) .gt. eps) then spinup_geogterm_l1(c) = spinup_factor(i_met_lit) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_l1(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_cel_lit) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_cel_lit) - 1._r8) .gt. eps) then spinup_geogterm_l23(c) = spinup_factor(i_cel_lit) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_l23(c) = 1._r8 endif ! if ( .not. use_fates ) then - if ( abs(spinup_factor(i_cwd) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_cwd) - 1._r8) .gt. eps) then spinup_geogterm_cwd(c) = spinup_factor(i_cwd) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_cwd(c) = 1._r8 endif endif ! - if ( abs(spinup_factor(i_act_som) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_act_som) - 1._r8) .gt. eps) then spinup_geogterm_s1(c) = spinup_factor(i_act_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s1(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_slo_som) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_slo_som) - 1._r8) .gt. eps) then spinup_geogterm_s2(c) = spinup_factor(i_slo_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s2(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_pas_som) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_pas_som) - 1._r8) .gt. eps) then spinup_geogterm_s3(c) = spinup_factor(i_pas_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s3(c) = 1._r8 diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index efa2c33de1..d4cf1522d9 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -42,6 +42,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod ! !PUBLIC DATA MEMBERS ! ! !PRIVATE DATA MEMBERS + ! next four 2d vars are dimensioned (columns,nlevdecomp) real(r8), private, allocatable :: desorp(:,:) real(r8), private, allocatable :: fphys_m1(:,:) real(r8), private, allocatable :: fphys_m2(:,:) @@ -50,7 +51,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod integer, private :: i_chem_som ! index of chemically protected SOM integer, private :: i_avl_som ! index of available (aka active) SOM integer, private :: i_str_lit ! index of structural litter pool - integer, private :: i_l1m1 + integer, private :: i_l1m1 ! indices of transitions, eg l1m1: litter 1 -> first microbial pool integer, private :: i_l1m2 integer, private :: i_l2m1 integer, private :: i_l2m2 @@ -64,48 +65,48 @@ module SoilBiogeochemDecompCascadeMIMICSMod integer, private :: i_s3s1 integer, private :: i_m1s3 integer, private :: i_m2s3 - real(r8), private :: rf_l1m1 + real(r8), private :: rf_l1m1 ! respiration fractions by transition real(r8), private :: rf_l1m2 real(r8), private :: rf_l2m1 real(r8), private :: rf_l2m2 real(r8), private :: rf_s1m1 real(r8), private :: rf_s1m2 - real(r8), private :: vint_l1_m1 ! - real(r8), private :: vint_l2_m1 ! - real(r8), private :: vint_s1_m1 ! - real(r8), private :: vint_l1_m2 ! - real(r8), private :: vint_l2_m2 ! - real(r8), private :: vint_s1_m2 ! - real(r8), private :: kint_l1_m1 ! - real(r8), private :: kint_l2_m1 ! - real(r8), private :: kint_s1_m1 ! - real(r8), private :: kint_l1_m2 ! - real(r8), private :: kint_l2_m2 ! - real(r8), private :: kint_s1_m2 ! - real(r8), private :: vmod_l1_m1 ! - real(r8), private :: vmod_l2_m1 ! - real(r8), private :: vmod_s1_m1 ! - real(r8), private :: vmod_l1_m2 ! - real(r8), private :: vmod_l2_m2 ! - real(r8), private :: vmod_s1_m2 ! - real(r8), private :: kmod_l1_m1 ! - real(r8), private :: kmod_l2_m1 ! - real(r8), private :: kmod_s1_m1 ! - real(r8), private :: kmod_l1_m2 ! - real(r8), private :: kmod_l2_m2 ! - real(r8), private :: kmod_s1_m2 ! - real(r8), private :: vslope_l1_m1 ! - real(r8), private :: vslope_l2_m1 ! - real(r8), private :: vslope_s1_m1 ! - real(r8), private :: vslope_l1_m2 ! - real(r8), private :: vslope_l2_m2 ! - real(r8), private :: vslope_s1_m2 ! - real(r8), private :: kslope_l1_m1 ! - real(r8), private :: kslope_l2_m1 ! - real(r8), private :: kslope_s1_m1 ! - real(r8), private :: kslope_l1_m2 ! - real(r8), private :: kslope_l2_m2 ! - real(r8), private :: kslope_s1_m2 ! + real(r8), private :: vint_l1_m1 ! regression intercepts by transition + real(r8), private :: vint_l2_m1 + real(r8), private :: vint_s1_m1 + real(r8), private :: vint_l1_m2 + real(r8), private :: vint_l2_m2 + real(r8), private :: vint_s1_m2 + real(r8), private :: kint_l1_m1 ! regression intercepts by transition + real(r8), private :: kint_l2_m1 + real(r8), private :: kint_s1_m1 + real(r8), private :: kint_l1_m2 + real(r8), private :: kint_l2_m2 + real(r8), private :: kint_s1_m2 + real(r8), private :: vmod_l1_m1 ! vmod = vmod * av from Wieder et al 2015 + real(r8), private :: vmod_l2_m1 + real(r8), private :: vmod_s1_m1 + real(r8), private :: vmod_l1_m2 + real(r8), private :: vmod_l2_m2 + real(r8), private :: vmod_s1_m2 + real(r8), private :: kmod_l1_m1 ! kmod = ak / kmod from Wieder et al 2015 + real(r8), private :: kmod_l2_m1 + real(r8), private :: kmod_s1_m1 + real(r8), private :: kmod_l1_m2 + real(r8), private :: kmod_l2_m2 + real(r8), private :: kmod_s1_m2 + real(r8), private :: vslope_l1_m1 ! regression coefficients by transition + real(r8), private :: vslope_l2_m1 + real(r8), private :: vslope_s1_m1 + real(r8), private :: vslope_l1_m2 + real(r8), private :: vslope_l2_m2 + real(r8), private :: vslope_s1_m2 + real(r8), private :: kslope_l1_m1 ! regression coefficients by transition + real(r8), private :: kslope_l2_m1 + real(r8), private :: kslope_s1_m1 + real(r8), private :: kslope_l1_m2 + real(r8), private :: kslope_l2_m2 + real(r8), private :: kslope_s1_m2 type, private :: params_type real(r8) :: mimics_nue_into_mic ! microbial N use efficiency for N fluxes @@ -119,23 +120,26 @@ module SoilBiogeochemDecompCascadeMIMICSMod real(r8) :: mimics_cn_r ! C:N of MICr real(r8) :: mimics_cn_k ! C:N of MICk real(r8) :: mimics_cn_mod_num ! adjusts microbial CN based on fmet - real(r8) :: mimics_t_soi_ref - real(r8) :: mimics_initial_Cstocks_depth ! Soil depth for initial Carbon stocks for a cold-start - real(r8), allocatable :: mimics_initial_Cstocks(:) ! Initial Carbon stocks for a cold-start + real(r8) :: mimics_t_soi_ref ! reference soil temperature (degC) + real(r8) :: mimics_initial_Cstocks_depth ! Soil depth for initial C stocks for a cold-start (m) + real(r8), allocatable :: mimics_initial_Cstocks(:) ! Initial C stocks for a cold-start (gC/m3) ! The next few vectors are dimensioned by the number of decomposition - ! transitions making use of the corresponding parameters. The transitions - ! are represented in this order: l1m1 l2m1 s1m1 l1m2 l2m2 s1m2 + ! transitions that make use of the corresponding parameters, currently + ! six. The transitions are represented in this order: + ! l1m1 l2m1 s1m1 l1m2 l2m2 s1m2 real(r8), allocatable :: mimics_mge(:) ! Microbial growth efficiency (mg/mg) - real(r8), allocatable :: mimics_vmod(:) ! - real(r8), allocatable :: mimics_vint(:) ! regression intercept (5.47 ln(mg Cs (mg MIC)-1 h-1) ) - real(r8), allocatable :: mimics_vslope(:) ! transition regression coeffs (ln(mg Cs (mg MIC)-1 h-1) ¡C-1) - real(r8), allocatable :: mimics_kmod(:) ! - real(r8), allocatable :: mimics_kint(:) ! regression intercept - real(r8), allocatable :: mimics_kslope(:) ! - ! The next few vectors are dimensioned by the number of - ! parameters with the same name used in the same formula. - ! In the formulas themselves, we use scalar copies of each parameter - ! with suffixes _p1, p2, p3, ... to distinguish among them. + real(r8), allocatable :: mimics_vmod(:) ! vmod = vmod * av from Wieder et al 2015 + real(r8), allocatable :: mimics_vint(:) ! regression intercepts (5.47 ln(mg Cs (mg MIC)-1 h-1) ) + real(r8), allocatable :: mimics_vslope(:) ! regression coeffs (ln(mg Cs (mg MIC)-1 h-1) ¡C-1) + real(r8), allocatable :: mimics_kmod(:) ! kmod = ak / kmod from Wieder et al 2015 + real(r8), allocatable :: mimics_kint(:) ! regression intercepts + real(r8), allocatable :: mimics_kslope(:) ! regression coeffs + ! The next few vectors are dimensioned by the number of parameters with + ! the same name (eg 2 for mimics_tau_r_p1, mimics_tau_r_p2) used in the + ! respective formula. In the formulas, we use scalar copies of each + ! parameter with suffixes _p1, p2, p3, ... to distinguish among them. + ! See allocate statements below for the size of each of the following + ! vectors. real(r8), allocatable :: mimics_fmet(:) real(r8), allocatable :: mimics_p_scalar(:) real(r8), allocatable :: mimics_fphys_r(:) @@ -770,6 +774,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & type(soilbiogeochem_carbonstate_type), intent(in) :: soilbiogeochem_carbonstate_inst ! ! !LOCAL VARIABLES: + real(r8), parameter :: eps = 1.e-6_r8 real(r8):: frw(bounds%begc:bounds%endc) ! rooting fraction weight real(r8), allocatable:: fr(:,:) ! column-level rooting fraction by soil depth real(r8):: psi ! temporary soilpsi for water scalar @@ -879,51 +884,51 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & do fc = 1,num_soilc c = filter_soilc(fc) ! - if ( abs(spinup_factor(i_met_lit) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_met_lit) - 1._r8) .gt. eps) then spinup_geogterm_l1(c) = spinup_factor(i_met_lit) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_l1(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_str_lit) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_str_lit) - 1._r8) .gt. eps) then spinup_geogterm_l2(c) = spinup_factor(i_str_lit) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_l2(c) = 1._r8 endif ! if ( .not. use_fates ) then - if ( abs(spinup_factor(i_cwd) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_cwd) - 1._r8) .gt. eps) then spinup_geogterm_cwd(c) = spinup_factor(i_cwd) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_cwd(c) = 1._r8 endif endif ! - if ( abs(spinup_factor(i_avl_som) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_avl_som) - 1._r8) .gt. eps) then spinup_geogterm_s1(c) = spinup_factor(i_avl_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s1(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_chem_som) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_chem_som) - 1._r8) .gt. eps) then spinup_geogterm_s2(c) = spinup_factor(i_chem_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s2(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_phys_som) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_phys_som) - 1._r8) .gt. eps) then spinup_geogterm_s3(c) = spinup_factor(i_phys_som) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_s3(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_cop_mic) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_cop_mic) - 1._r8) .gt. eps) then spinup_geogterm_m1(c) = spinup_factor(i_cop_mic) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_m1(c) = 1._r8 endif ! - if ( abs(spinup_factor(i_oli_mic) - 1._r8) .gt. .000001_r8) then + if ( abs(spinup_factor(i_oli_mic) - 1._r8) .gt. eps) then spinup_geogterm_m2(c) = spinup_factor(i_oli_mic) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) else spinup_geogterm_m2(c) = 1._r8 From 3211e8982e0f24dcd813473fb270b79973313f2e Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 15 Nov 2021 17:28:59 -0700 Subject: [PATCH 60/69] I should have removed this comment in the previous commit --- src/main/clm_varpar.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index b75806b226..6e73555af1 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -74,7 +74,6 @@ module clm_varpar integer, public :: i_cop_mic = -9 ! index of copiotrophic microbial pool; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_oli_mic = -9 ! index of oligotrophic microbial pool; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_cwd = -9 ! index of cwd pool; overwritten in SoilBiogeochemDecompCascade*Mod - ! TODO Not necessary but cleaner to use this copy of i_cwdl2 in *CascadeBGC? integer, public :: i_cwdl2 = -9 ! index of cwd to l2 transition; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: ndecomp_pools_max From e5f3ffdc1851a61fef642c89adebaa5db2d1273a Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 16 Nov 2021 14:56:44 -0700 Subject: [PATCH 61/69] Revert unnecessary changes in bld/listDefaultNamelist.pl --- bld/listDefaultNamelist.pl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bld/listDefaultNamelist.pl b/bld/listDefaultNamelist.pl index ee995145bd..938ee7f5b1 100755 --- a/bld/listDefaultNamelist.pl +++ b/bld/listDefaultNamelist.pl @@ -270,17 +270,11 @@ sub GetListofNeededFiles { my @bgcsettings = $definition->get_valid_values( "bgc_mode", 'noquotes'=>1 ); print "bgc=@bgcsettings\n" if $printing; - print "decomp=@decompsettings\n" if $printing; # # Loop over all possible BGC settings # foreach my $bgc ( @bgcsettings ) { $settings{'bgc'} = $bgc; - if ( $bgc eq "bgc" || $bgc eq "fates" ) { - foreach my $decomp ( @decompsettings ) { - $settings{'decomp'} = $decomp; - } - } my @crop_vals; if ( $bgc =~ /^cn/ ) { @crop_vals = ( "on", "off" ); From f6b3bf91eb143a6825bedb8ac5fd702f30950437 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 18 Nov 2021 11:13:42 -0700 Subject: [PATCH 62/69] Correct the clay units by converting from % to fraction in MIMICS --- src/main/clm_varcon.F90 | 2 ++ .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/clm_varcon.F90 b/src/main/clm_varcon.F90 index 79d301487b..340115fe90 100644 --- a/src/main/clm_varcon.F90 +++ b/src/main/clm_varcon.F90 @@ -122,8 +122,10 @@ module clm_varcon real(r8), public, parameter :: aquifer_water_baseline = 5000._r8 ! baseline value for water in the unconfined aquifer [mm] real(r8), public, parameter :: c_to_b = 2.0_r8 ! conversion between mass carbon and total biomass (g biomass /g C) + ! Some non-tunable conversions (may need to place elsewhere) real(r8), public, parameter :: g_to_mg = 1.0e3_r8 ! coefficient to convert g to mg real(r8), public, parameter :: cm3_to_m3 = 1.0e-6_r8 ! coefficient to convert cm3 to m3 + real(r8), public, parameter :: pct_to_frac = 1.0e-2_r8 ! coefficient to convert % to fraction !!! C13 real(r8), public, parameter :: preind_atm_del13c = -6.0_r8 ! preindustrial value for atmospheric del13C diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index d4cf1522d9..d0b36dee42 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -340,6 +340,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat ! decomposition cascade of the MIMICS model. ! ! !USES: + use clm_varcon, only: pct_to_frac ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -360,14 +361,14 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat real(r8):: speedup_fac ! acceleration factor, higher when vertsoilc = .true. - real(r8) :: clay ! local copy of cellclay - integer :: c, j ! indices + real(r8) :: clay_frac ! local copy of cellclay converted from % (fraction) + integer :: c, j ! indices !----------------------------------------------------------------------- associate( & nue_decomp_cascade => soilbiogeochem_state_inst%nue_decomp_cascade_col , & ! Output: [real(r8) (:) ] N use efficiency for a given transition (gN going into microbe / gN decomposed) - cellclay => soilstate_inst%cellclay_col , & ! Input: [real(r8) (:,:) ] column 3D clay + cellclay => soilstate_inst%cellclay_col , & ! Input: [real(r8) (:,:) ] column 3D clay (%) cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Output: [integer (:) ] which pool is C taken from for a given decomposition step cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & ! Output: [integer (:) ] which pool is C added to for a given decomposition step @@ -461,14 +462,15 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat ! need to use the max function to limit these expressions. ! We apply the min function on cellclay because we are looping over ! some non-soil columns here that contain cellclay = 1e36. - clay = dmin1(100.0_r8, cellclay(c,j)) - desorp(c,j) = mimics_desorp_p1 * dexp(mimics_desorp_p2 * clay) + clay_frac = pct_to_frac * & + dmin1(100.0_r8, cellclay(c,j)) ! conv. % to fraction + desorp(c,j) = mimics_desorp_p1 * dexp(mimics_desorp_p2 * clay_frac) fphys_m1(c,j) = dmin1(1.0_r8, mimics_fphys_r_p1 * & - dexp(mimics_fphys_r_p2 * clay)) + dexp(mimics_fphys_r_p2 * clay_frac)) fphys_m2(c,j) = dmin1(1.0_r8, mimics_fphys_k_p1 * & - dexp(mimics_fphys_k_p2 * clay)) + dexp(mimics_fphys_k_p2 * clay_frac)) p_scalar(c,j) = 1.0_r8 / (mimics_p_scalar_p1 * & - dexp(mimics_p_scalar_p2 * dsqrt(clay))) + dexp(mimics_p_scalar_p2 * dsqrt(clay_frac))) end do end do initial_stock_soildepth = params_inst%mimics_initial_Cstocks_depth From 6205b309f35adec042e1833b09e682dbf81bfc78 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 11 Dec 2021 13:03:49 -0700 Subject: [PATCH 63/69] First draft of updated ChangeLog --- doc/ChangeLog | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++ doc/ChangeSum | 1 + 2 files changed, 177 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 4a8050bfe1..a7abce0c94 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,180 @@ =============================================================== +Tag name: ctsm5.1.dev0?? +Originator(s): slevis (Samuel Levis,SLevis Consulting,303-665-1310) +Date: Sat Dec 11 12:28:45 MST 2021 +One-line Summary: Introduce vert. resolved MIMICS as new method to solve below ground decomp. + +Purpose and description of changes +---------------------------------- + + Introducing new option to solve below ground decomposition: MIMICSWieder2015. + The old option (CENTURYKoven2013) remains available. User will select one or + the other via the namelist variable soil_decomp_method. + + Elin's MIMICS+ github issue relates: #1260. + MIMICS spinup issues relate and are listed in caveats for users. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +Issues fixed (include CTSM Issue #): + #1356 : remove decompCN code and testing + +CIME Issues fixed (include issue #): + +Known bugs introduced in this tag (include issue #): + +Known bugs found since the previous tag (include issue #): + + +Notes of particular relevance for users +--------------------------------------- +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +Caveats for users (e.g., need to interpolate initial conditions): + MIMICS spinup method is in development: + #1451 + #1455 + #1457 + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + New option MIMICSWieder2015 for use with namelist variable soil_decomp_method + +Changes made to namelist defaults (e.g., changed parameter values): + +Changes to the datasets (e.g., parameter, surface or initial files): + CLM parameter files now include new MIMICS-related parameters prefixed with + mimics_. Existing CENTURYKoven-specific parameters were renamed to include the + prefix bgc_. Parameters used by both CENTURYKoven2013 and MIMICSWieder2015 have + neither prefix. + +Substantial timing or memory changes: + Timing comparison between CENTURYKoven (BGC for short) and MIMICSWieder: + In a 1x1_brazil test writing annual output and restarts every 10 yrs, + BGC took ~2.8 hrs/100 yrs, MIMICS took ~3.6 hrs/100 yrs. + +Notes of particular relevance for developers: +--------------------------------------------- +NOTE: Be sure to review the steps in README.CHECKLIST.master_tags as well as the coding style in the Developers Guide +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + +Changes to tests or testing: + New test-suite tests: + ERP_D_P36x2_Ld3.f10_f10_mg37.I1850Clm51BgcCrop.cheyenne_gnu.clm-mimics + SMS_Ld5_Mmpi-serial.1x1_brazil.IHistClm50BgcQianRs.izumi_gnu.clm-mimics + +Testing summary: +---------------- +[... Remove before making master tag. + +Nearly all CTSM tags should undergo 'regular' (aux_clm) testing. +However, it occasionally makes sense to do more or less system testing; +here is guidance on different available levels of system testing: + a) no system testing (for use when the only changes are ones that + have absolutely no impact on system runs; this + includes documentation-only tags, tags that + just change the tools or some python code that + does not impact system runs, etc.) + b) minimal (for use in rare cases where only a small change with + known behavior is added ... eg. a minor bug fix. This + might be to just run the "short" test list, or to run + a single test. Whatever makes sense for the particular case.) + c) regular (regular tests on normal machines if CTSM source is modified) + d) release (regular tests plus the fates, ctsm_sci, mosart and rtm test lists + and normally all of the ancillary tests (build-namelist, python, ptclm, etc.) + would be run as well) + +In addition, various other tests of the tools, python and perl +infrastructure should be run when appropriate, as described below. + +...] + +[Remove any lines that don't apply.] + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - + + tools-tests (test/tools) (if tools have been changed): + + cheyenne - + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + (any machine) - + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK most recent against dev061 + izumi ------- OK most recent against dev061 + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- + izumi ------- + + any other testing (give details below): + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: NO + + [ If a tag changes answers relative to baseline comparison the + following should be filled in (otherwise remove this section). + And always remove these three lines and parts that don't apply. ] + + Summarize any changes to answers, i.e., + - what code configurations: + - what platforms/compilers: + - nature of change (roundoff; larger than roundoff/same climate; new climate): + + If bitwise differences were observed, how did you show they were no worse + than roundoff? + + If this tag changes climate describe the run(s) done to evaluate the new + climate (put details of the simulations in the experiment database) + - casename: + + URL for LMWG diagnostics output used to validate new climate: + + +Other details +------------- +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/1318 + +=============================================================== +=============================================================== Tag name: ctsm5.1.dev066 Originator(s): rgknox (Ryan Knox,,,) Date: Sat Dec 4 01:58:42 MST 2021 diff --git a/doc/ChangeSum b/doc/ChangeSum index 73281e5a9c..134baa31a7 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.1.dev0?? slevis 12/??/2021 Introduce vert. resolved MIMICS as new method to solve below ground decomp. ctsm5.1.dev066 rgknox 12/04/2021 API change with FATES to enable running means inside fates, includes passing in of model timestep ctsm5.1.dev065 glemieux 12/02/2021 Refactor static fire data input by moving variables into fire_base_type from cnveg_state_type ctsm5.1.dev064 afoster 11/29/2021 Updates to facilitate FATES history variable overhaul From ab17157b4a81b1fb6bdafe50728ce3cf201e5e01 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 27 Jan 2022 15:51:27 -0700 Subject: [PATCH 64/69] Minor merge conflict caught by test-suite --- src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index d0b36dee42..d1210c7c96 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -760,7 +760,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! decomposition cascade model ! ! !USES: - use clm_time_manager , only : get_days_per_year + use clm_time_manager , only : get_curr_days_per_year use clm_varcon , only : secspday, secsphr, tfrz use clm_varcon , only : g_to_mg, cm3_to_m3 ! @@ -873,7 +873,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & mino2lim = CNParamsShareInst%mino2lim - days_per_year = get_days_per_year() + days_per_year = get_curr_days_per_year() ! ! Set "decomp_depth_efolding" parameter ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding From c2a21bf8f478e059178893154504077b28f46786 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 27 Jan 2022 17:58:33 -0700 Subject: [PATCH 65/69] Update ChangeLog + add comment in SoilBiogeochemDecompCascadeMIMICSMod --- doc/ChangeLog | 75 +++---------------- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 3 + 2 files changed, 14 insertions(+), 64 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 025c937d8a..b1ca83dfbe 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -34,22 +34,12 @@ Does this tag change answers significantly for any of the following physics conf Bugs fixed or introduced ------------------------ -[Remove any lines that don't apply. Remove entire section if nothing applies.] - Issues fixed (include CTSM Issue #): #1356 : remove decompCN code and testing -CIME Issues fixed (include issue #): - -Known bugs introduced in this tag (include issue #): - -Known bugs found since the previous tag (include issue #): - Notes of particular relevance for users --------------------------------------- -[Remove any lines that don't apply. Remove entire section if nothing applies.] - Caveats for users (e.g., need to interpolate initial conditions): MIMICS spinup method is in development: #1451 @@ -59,8 +49,6 @@ Caveats for users (e.g., need to interpolate initial conditions): Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): New option MIMICSWieder2015 for use with namelist variable soil_decomp_method -Changes made to namelist defaults (e.g., changed parameter values): - Changes to the datasets (e.g., parameter, surface or initial files): CLM parameter files now include new MIMICS-related parameters prefixed with mimics_. Existing CENTURYKoven-specific parameters were renamed to include the @@ -72,13 +60,11 @@ Substantial timing or memory changes: In a 1x1_brazil test writing annual output and restarts every 10 yrs, BGC took ~2.8 hrs/100 yrs, MIMICS took ~3.6 hrs/100 yrs. + More timing comparisons shown here: + https://github.com/ESCOMP/CTSM/pull/1318#issuecomment-1008211485 + Notes of particular relevance for developers: --------------------------------------------- -NOTE: Be sure to review the steps in README.CHECKLIST.master_tags as well as the coding style in the Developers Guide -[Remove any lines that don't apply. Remove entire section if nothing applies.] - -Caveats for developers (e.g., code that is duplicated that requires double maintenance): - Changes to tests or testing: New test-suite tests: ERP_D_P36x2_Ld3.f10_f10_mg37.I1850Clm51BgcCrop.cheyenne_gnu.clm-mimics @@ -86,31 +72,6 @@ Changes to tests or testing: Testing summary: ---------------- -[... Remove before making master tag. - -Nearly all CTSM tags should undergo 'regular' (aux_clm) testing. -However, it occasionally makes sense to do more or less system testing; -here is guidance on different available levels of system testing: - a) no system testing (for use when the only changes are ones that - have absolutely no impact on system runs; this - includes documentation-only tags, tags that - just change the tools or some python code that - does not impact system runs, etc.) - b) minimal (for use in rare cases where only a small change with - known behavior is added ... eg. a minor bug fix. This - might be to just run the "short" test list, or to run - a single test. Whatever makes sense for the particular case.) - c) regular (regular tests on normal machines if CTSM source is modified) - d) release (regular tests plus the fates, ctsm_sci, mosart and rtm test lists - and normally all of the ancillary tests (build-namelist, python, ptclm, etc.) - would be run as well) - -In addition, various other tests of the tools, python and perl -infrastructure should be run when appropriate, as described below. - -...] - -[Remove any lines that don't apply.] [PASS means all tests PASS; OK means tests PASS other than expected fails.] @@ -122,14 +83,10 @@ infrastructure should be run when appropriate, as described below. cheyenne - - python testing (if python code has changed; see instructions in python/README.md; document testing done): - - (any machine) - - regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): - cheyenne ---- OK most recent against dev061 - izumi ------- OK most recent against dev061 + cheyenne ---- PASS + izumi ------- OK (see answer changes below) fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) cheyenne ---- @@ -143,31 +100,21 @@ If the tag used for baseline comparisons was NOT the previous tag, note that her Answer changes -------------- -Changes answers relative to baseline: NO +Changes answers relative to baseline: NO (almost) [ If a tag changes answers relative to baseline comparison the following should be filled in (otherwise remove this section). And always remove these three lines and parts that don't apply. ] - Summarize any changes to answers, i.e., - - what code configurations: - - what platforms/compilers: - - nature of change (roundoff; larger than roundoff/same climate; new climate): - - If bitwise differences were observed, how did you show they were no worse - than roundoff? - - If this tag changes climate describe the run(s) done to evaluate the new - climate (put details of the simulations in the experiment database) - - casename: - - URL for LMWG diagnostics output used to validate new climate: + One test in the izumi test-suite fails + SMS_Vmct.f10_f10_mg37.I2000Clm50BgcCrop.izumi_pgi.clm-crop + and this is due to diffs from baseline (dev073). + cprnc.out shows diffs only in one variable: + RMS TOTECOSYSC 1.9853E-12 NORMALIZED 6.5087E-17 Other details ------------- -[Remove any lines that don't apply. Remove entire section if nothing applies.] - List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): Pull Requests that document the changes (include PR ids): diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index d1210c7c96..677aa4b04d 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -1071,6 +1071,9 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do end do + ! TODO @ekluzek suggested possibly making the Left Hand Sides into arrays + ! and I wonder in that case whether to skip these assignments altogether + ! and use the Right Hand Sides directly mimics_fmet_p1 = params_inst%mimics_fmet(1) mimics_fmet_p2 = params_inst%mimics_fmet(2) mimics_fmet_p3 = params_inst%mimics_fmet(3) From 99c3c308d82cb03c29a10060f3f8508a1972e112 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 27 Jan 2022 18:01:07 -0700 Subject: [PATCH 66/69] Committing the three new timing calls that I added to time MIMICS --- src/biogeochem/CNDriverMod.F90 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index f2cad9782a..45119a452a 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -314,6 +314,7 @@ subroutine CNDriverNoLeaching(bounds, !-------------------------------------------- call t_startf('SoilBiogeochem') + call t_startf('DecompRate') if (decomp_method == century_decomp) then call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) @@ -322,7 +323,9 @@ subroutine CNDriverNoLeaching(bounds, soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) end if + call t_stopf('DecompRate') + call t_startf('SoilBiogeochemPotential') ! calculate potential decomp rates and total immobilization demand (previously inlined in CNDecompAlloc) call SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & @@ -332,6 +335,7 @@ subroutine CNDriverNoLeaching(bounds, p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_pools), & pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) + call t_stopf('SoilBiogeochemPotential') ! calculate vertical profiles for distributing soil and litter C and N (previously subroutine decomp_vertprofiles called from CNDecompAlloc) call SoilBiogeochemVerticalProfile(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & @@ -1052,6 +1056,7 @@ subroutine CNDriverSummarizeFluxes(bounds, & ! cnveg carbon/nitrogen flux summary ! ---------------------------------------------- + call t_startf('CNvegCflux_summary') call cnveg_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & isotope='bulk', & soilbiogeochem_hr_col=soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & @@ -1088,6 +1093,7 @@ subroutine CNDriverSummarizeFluxes(bounds, & soilbiogeochem_cwdn_col=soilbiogeochem_nitrogenstate_inst%cwdn_col(begc:endc), & product_closs_grc=c14_products_inst%product_loss_grc(begg:endg)) end if + call t_stopf('CNvegCflux_summary') call cnveg_nitrogenflux_inst%Summary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp) From 545149302d94e3bda3c99dd18fbbb6fce6a8047a Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 28 Jan 2022 18:41:28 -0700 Subject: [PATCH 67/69] Updated ChangeLog/ChangeSum Remembered and added another issue that this PR resolves --- doc/ChangeLog | 4 +++- doc/ChangeSum | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index b1ca83dfbe..5074a05da5 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,7 +1,7 @@ =============================================================== Tag name: ctsm5.1.dev074 Originator(s): slevis (Samuel Levis,SLevis Consulting,303-665-1310) -Date: Thu Jan 27 12:55:45 MST 2022 +Date: Fri Jan 28 18:40:45 MST 2022 One-line Summary: Introduce vert. resolved MIMICS as new method to solve below ground decomp. Purpose and description of changes @@ -36,6 +36,8 @@ Bugs fixed or introduced ------------------------ Issues fixed (include CTSM Issue #): #1356 : remove decompCN code and testing + #1473 : decomp_depth_efolding appears (with the same value) in the namelist + and the params files; the model ends up using the one from the namelist Notes of particular relevance for users diff --git a/doc/ChangeSum b/doc/ChangeSum index 43b0b478aa..1454466b5a 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,6 +1,6 @@ Tag Who Date Summary ============================================================================================================================ - ctsm5.1.dev074 slevis 01/27/2022 Introduce vert. resolved MIMICS as new method to solve below ground decomp. + ctsm5.1.dev074 slevis 01/28/2022 Introduce vert. resolved MIMICS as new method to solve below ground decomp. ctsm5.1.dev073 sacks 01/25/2022 Some fixes for Gregorian calendar ctsm5.1.dev072 negins 01/17/2022 mksurfdat toolchain part 1: gen_mksurf_namelist ctsm5.1.dev071 glemieux 01/16/2022 Small changes to enable new fates dimension and update fates tag From eba82445d2c741f3d13497aea388f752738f2eda Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 1 Feb 2022 18:04:54 -0700 Subject: [PATCH 68/69] Added newton_krylov_spinup testmod and corresponding new test SMS_Ly5_Mmpi-serial.1x1_brazil.IHistClm50BgcQianRs.cheyenne_intel.clm-newton_krylov_spinup --- cime_config/testdefs/testlist_clm.xml | 9 +++++++++ .../clm/newton_krylov_spinup/README | 8 ++++++++ .../newton_krylov_spinup/include_user_mods | 2 ++ .../clm/newton_krylov_spinup/user_nl_clm | 1 + .../usermods_dirs/newton_krylov_spinup/README | 4 ++++ doc/ChangeLog | 19 ++----------------- doc/ChangeSum | 2 +- 7 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/README create mode 100644 cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/include_user_mods create mode 100644 cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/user_nl_clm create mode 100644 cime_config/usermods_dirs/newton_krylov_spinup/README diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index 808f9c2717..34b4c7363d 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -540,6 +540,15 @@ + + + + + + + + + diff --git a/cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/README b/cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/README new file mode 100644 index 0000000000..1363ea696b --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/README @@ -0,0 +1,8 @@ +slevis 2022/2/1: +This testmod tests the newton_krylov_spinup usermod found in +cime_config/usermods_dirs/newton_krylov_spinup +combined with the mimics testmod. + +By default this usermod runs for 20 yrs and writes a history file at that +time. To save time running the test-suite, we're changing +hist_nhtfrq = 0,-43800 (from 0,-175200) diff --git a/cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/include_user_mods new file mode 100644 index 0000000000..192aa023a8 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/include_user_mods @@ -0,0 +1,2 @@ +../mimics +../../../../usermods_dirs/newton_krylov_spinup diff --git a/cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/user_nl_clm new file mode 100644 index 0000000000..bce7009c36 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/newton_krylov_spinup/user_nl_clm @@ -0,0 +1 @@ +hist_nhtfrq = 0,-43800 diff --git a/cime_config/usermods_dirs/newton_krylov_spinup/README b/cime_config/usermods_dirs/newton_krylov_spinup/README new file mode 100644 index 0000000000..037709ee7d --- /dev/null +++ b/cime_config/usermods_dirs/newton_krylov_spinup/README @@ -0,0 +1,4 @@ +user_nl_clm contains this line: +hist_nhtfrq = 0,-175200 +0 means monthly history frequency and +-175200 means 20 years history frequency (indicated in hours) diff --git a/doc/ChangeLog b/doc/ChangeLog index 5074a05da5..59c751c77f 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,7 +1,7 @@ =============================================================== Tag name: ctsm5.1.dev074 Originator(s): slevis (Samuel Levis,SLevis Consulting,303-665-1310) -Date: Fri Jan 28 18:40:45 MST 2022 +Date: Tue Feb 1 18:02:39 MST 2022 One-line Summary: Introduce vert. resolved MIMICS as new method to solve below ground decomp. Purpose and description of changes @@ -71,33 +71,18 @@ Changes to tests or testing: New test-suite tests: ERP_D_P36x2_Ld3.f10_f10_mg37.I1850Clm51BgcCrop.cheyenne_gnu.clm-mimics SMS_Ld5_Mmpi-serial.1x1_brazil.IHistClm50BgcQianRs.izumi_gnu.clm-mimics + SMS_Ly5_Mmpi-serial.1x1_brazil.IHistClm50BgcQianRs.cheyenne_intel.clm-newton_krylov_spinup Testing summary: ---------------- [PASS means all tests PASS; OK means tests PASS other than expected fails.] - build-namelist tests (if CLMBuildNamelist.pm has changed): - - cheyenne - - - tools-tests (test/tools) (if tools have been changed): - - cheyenne - - regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): cheyenne ---- PASS izumi ------- OK (see answer changes below) - fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) - cheyenne ---- - izumi ------- - - any other testing (give details below): - -If the tag used for baseline comparisons was NOT the previous tag, note that here: - Answer changes -------------- diff --git a/doc/ChangeSum b/doc/ChangeSum index 1454466b5a..615e1ea077 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,6 +1,6 @@ Tag Who Date Summary ============================================================================================================================ - ctsm5.1.dev074 slevis 01/28/2022 Introduce vert. resolved MIMICS as new method to solve below ground decomp. + ctsm5.1.dev074 slevis 02/01/2022 Introduce vert. resolved MIMICS as new method to solve below ground decomp. ctsm5.1.dev073 sacks 01/25/2022 Some fixes for Gregorian calendar ctsm5.1.dev072 negins 01/17/2022 mksurfdat toolchain part 1: gen_mksurf_namelist ctsm5.1.dev071 glemieux 01/16/2022 Small changes to enable new fates dimension and update fates tag From be14cd192be733b229e695f7f3a8dc803c8e850f Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 2 Feb 2022 00:45:48 -0700 Subject: [PATCH 69/69] Update changelog, tweak a few things, make sure issues mentioned have some description on them --- doc/ChangeLog | 30 +++++++++++++++++------------- doc/ChangeSum | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 59c751c77f..a93c31092f 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,7 +1,7 @@ =============================================================== Tag name: ctsm5.1.dev074 Originator(s): slevis (Samuel Levis,SLevis Consulting,303-665-1310) -Date: Tue Feb 1 18:02:39 MST 2022 +Date: Wed Feb 2 00:44:27 MST 2022 One-line Summary: Introduce vert. resolved MIMICS as new method to solve below ground decomp. Purpose and description of changes @@ -35,7 +35,6 @@ Does this tag change answers significantly for any of the following physics conf Bugs fixed or introduced ------------------------ Issues fixed (include CTSM Issue #): - #1356 : remove decompCN code and testing #1473 : decomp_depth_efolding appears (with the same value) in the namelist and the params files; the model ends up using the one from the namelist @@ -43,13 +42,15 @@ Issues fixed (include CTSM Issue #): Notes of particular relevance for users --------------------------------------- Caveats for users (e.g., need to interpolate initial conditions): - MIMICS spinup method is in development: - #1451 - #1455 - #1457 + MIMICS spinup method is in development + Issues related to spinup + #1451 -- MIMICS spinup + #1455 -- Additional history output for Newton-Krylov spinup + #1457 -- Adding history variables for Newton-Krylov spinup Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): New option MIMICSWieder2015 for use with namelist variable soil_decomp_method + decomp_depth_efolding removed as values on param files was already being used Changes to the datasets (e.g., parameter, surface or initial files): CLM parameter files now include new MIMICS-related parameters prefixed with @@ -78,10 +79,18 @@ Testing summary: [PASS means all tests PASS; OK means tests PASS other than expected fails.] + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - PASS (831 tests are different from baseline because of new param files) + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + cheyenne ---- OK (black test fails) + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): cheyenne ---- PASS - izumi ------- OK (see answer changes below) + izumi ------- OK (see one answer change below) Answer changes @@ -89,10 +98,6 @@ Answer changes Changes answers relative to baseline: NO (almost) - [ If a tag changes answers relative to baseline comparison the - following should be filled in (otherwise remove this section). - And always remove these three lines and parts that don't apply. ] - One test in the izumi test-suite fails SMS_Vmct.f10_f10_mg37.I2000Clm50BgcCrop.izumi_pgi.clm-crop and this is due to diffs from baseline (dev073). @@ -102,10 +107,9 @@ Changes answers relative to baseline: NO (almost) Other details ------------- -List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): Pull Requests that document the changes (include PR ids): - https://github.com/ESCOMP/ctsm/pull/1318 + https://github.com/ESCOMP/ctsm/pull/1318 -- MIMICS into vertically resolved CTSM =============================================================== =============================================================== diff --git a/doc/ChangeSum b/doc/ChangeSum index 615e1ea077..93e87f9495 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,6 +1,6 @@ Tag Who Date Summary ============================================================================================================================ - ctsm5.1.dev074 slevis 02/01/2022 Introduce vert. resolved MIMICS as new method to solve below ground decomp. + ctsm5.1.dev074 slevis 02/02/2022 Introduce vert. resolved MIMICS as new method to solve below ground decomp. ctsm5.1.dev073 sacks 01/25/2022 Some fixes for Gregorian calendar ctsm5.1.dev072 negins 01/17/2022 mksurfdat toolchain part 1: gen_mksurf_namelist ctsm5.1.dev071 glemieux 01/16/2022 Small changes to enable new fates dimension and update fates tag