From 90be91bb198538caa2c6e351aca79047b44b7794 Mon Sep 17 00:00:00 2001 From: Kyle <kyle.c.klenk@gmail.com> Date: Tue, 27 Sep 2022 18:30:55 +0000 Subject: [PATCH] copied from non-actors summa --- .../source/engine/sundials/computHeatCap.f90 | 961 +++++++++--------- 1 file changed, 480 insertions(+), 481 deletions(-) diff --git a/build/source/engine/sundials/computHeatCap.f90 b/build/source/engine/sundials/computHeatCap.f90 index 53997c8..b1f242c 100644 --- a/build/source/engine/sundials/computHeatCap.f90 +++ b/build/source/engine/sundials/computHeatCap.f90 @@ -20,492 +20,491 @@ module computHeatCap_module - ! data types - USE nrtype - - ! derived types to define the data structures - USE data_types,only:& - var_d, & ! data vector (rkind) - var_ilength, & ! data vector with variable length dimension (i4b) - var_dlength ! data vector with variable length dimension (rkind) - - ! named variables defining elements in the data structures - USE var_lookup,only:iLookPARAM,iLookDIAG,iLookINDEX ! named variables for structure elements - - ! physical constants - USE multiconst,only:& - Tfreeze, & ! freezing point of water (K) - iden_air, & ! intrinsic density of air (kg m-3) - iden_ice, & ! intrinsic density of ice (kg m-3) - iden_water, & ! intrinsic density of water (kg m-3) - ! specific heat - Cp_air, & ! specific heat of air (J kg-1 K-1) - Cp_ice, & ! specific heat of ice (J kg-1 K-1) - Cp_soil, & ! specific heat of soil (J kg-1 K-1) - Cp_water ! specific heat of liquid water (J kg-1 K-1) - ! named variables to describe the state variable type - USE globalData,only:iname_nrgCanair ! named variable defining the energy of the canopy air space - USE globalData,only:iname_nrgCanopy ! named variable defining the energy of the vegetation canopy - USE globalData,only:iname_watCanopy ! named variable defining the mass of total water on the vegetation canopy - USE globalData,only:iname_liqCanopy ! named variable defining the mass of liquid water on the vegetation canopy - USE globalData,only:iname_nrgLayer ! named variable defining the energy state variable for snow+soil layers - USE globalData,only:iname_watLayer ! named variable defining the total water state variable for snow+soil layers - USE globalData,only:iname_liqLayer ! named variable defining the liquid water state variable for snow+soil layers - USE globalData,only:iname_matLayer ! named variable defining the matric head state variable for soil layers - USE globalData,only:iname_lmpLayer ! named variable defining the liquid matric potential state variable for soil layers - USE globalData,only:iname_watAquifer ! named variable defining the water storage in the aquifer - - ! missing values - USE globalData,only:integerMissing ! missing integer - - ! named variables that define the layer type - USE globalData,only:iname_snow ! snow - USE globalData,only:iname_soil ! soil - - - ! privacy - implicit none - private - public::computHeatCap - public::computStatMult - public::computHeatCapAnalytic - public::computCm - - contains - - - ! ********************************************************************************************************** - ! public subroutine computHeatCap: compute diagnostic energy variables (heat capacity) - ! ********************************************************************************************************** - subroutine computHeatCap(& - ! input: control variables - nLayers, & ! intent(in): number of layers (soil+snow) - computeVegFlux, & ! intent(in): flag to denote if computing the vegetation flux - canopyDepth, & ! intent(in): canopy depth (m) - ! input data structures - mpar_data, & ! intent(in): model parameters - indx_data, & ! intent(in): model layer indices - diag_data, & ! intent(in): model diagnostic variables for a local HRU - ! input: state variables - scalarCanopyIce, & ! intent(in) - scalarCanopyLiquid, & ! intent(in) - scalarCanopyTempTrial, & ! intent(in): trial value of canopy temperature (K) - scalarCanopyTempPrev, & ! intent(in): previous value of canopy temperature (K) - scalarCanopyEnthalpyTrial, & ! intent(in): trial enthalpy of the vegetation canopy (J m-3) - scalarCanopyEnthalpyPrev, & ! intent(in): previous enthalpy of the vegetation canopy (J m-3) - mLayerVolFracIce, & ! intent(in): volumetric fraction of ice at the start of the sub-step (-) - mLayerVolFracLiq, & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-) - mLayerTempTrial, & ! intent(in): trial temperature - mLayerTempPrev, & ! intent(in): previous temperature - mLayerEnthalpyTrial, & ! intent(in): trial enthalpy for snow and soil - mLayerEnthalpyPrev, & ! intent(in): previous enthalpy for snow and soil - ! output - heatCapVeg, & - mLayerHeatCap, & ! intent(out): heat capacity for snow and soil - ! output: error control - err,message) ! intent(out): error control - ! -------------------------------------------------------------------------------------------------------------------------------------- - ! input: control variables - logical(lgt),intent(in) :: computeVegFlux ! logical flag to denote if computing the vegetation flux - real(rkind),intent(in) :: canopyDepth ! depth of the vegetation canopy (m) - ! input/output: data structures - type(var_dlength),intent(in) :: mpar_data ! model parameters - type(var_ilength),intent(in) :: indx_data ! model layer indices - ! input: - integer(i4b),intent(in) :: nLayers - type(var_dlength),intent(in) :: diag_data ! diagnostic variables for a local HRU - real(rkind),intent(in) :: scalarCanopyIce ! trial value of canopy ice content (kg m-2) - real(rkind),intent(in) :: scalarCanopyLiquid - real(rkind),intent(in) :: scalarCanopyTempTrial ! trial value of canopy temperature - real(rkind),intent(in) :: scalarCanopyEnthalpyTrial ! trial enthalpy of the vegetation canopy (J m-3) - real(rkind),intent(in) :: scalarCanopyEnthalpyPrev ! intent(in): previous enthalpy of the vegetation canopy (J m-3) - real(rkind),intent(in) :: scalarCanopyTempPrev ! Previous value of canopy temperature - real(rkind),intent(in) :: mLayerVolFracLiq(:) ! trial vector of volumetric liquid water content (-) - real(rkind),intent(in) :: mLayerVolFracIce(:) ! trial vector of volumetric ice water content (-) - real(rkind),intent(in) :: mLayerTempTrial(:) - real(rkind),intent(in) :: mLayerTempPrev(:) - real(rkind),intent(in) :: mLayerEnthalpyTrial(:) - real(rkind),intent(in) :: mLayerEnthalpyPrev(:) - ! output: - real(qp),intent(out) :: heatCapVeg - real(qp),intent(out) :: mLayerHeatCap(:) - integer(i4b),intent(out) :: err ! error code - character(*),intent(out) :: message ! error message - ! -------------------------------------------------------------------------------------------------------------------------------- - ! local variables - integer(i4b) :: iLayer ! index of model layer - real(rkind) :: delT - real(rkind) :: delEnt - integer(i4b) :: iSoil ! index of soil layer - ! -------------------------------------------------------------------------------------------------------------------------------- - ! associate variables in data structure - associate(& - ! input: coordinate variables - nSnow => indx_data%var(iLookINDEX%nSnow)%dat(1), & ! intent(in): number of snow layers - layerType => indx_data%var(iLookINDEX%layerType)%dat, & ! intent(in): layer type (iname_soil or iname_snow) - ! input: heat capacity and thermal conductivity - specificHeatVeg => mpar_data%var(iLookPARAM%specificHeatVeg)%dat(1), & ! intent(in): specific heat of vegetation (J kg-1 K-1) - maxMassVegetation => mpar_data%var(iLookPARAM%maxMassVegetation)%dat(1), & ! intent(in): maximum mass of vegetation (kg m-2) - ! input: depth varying soil parameters - iden_soil => mpar_data%var(iLookPARAM%soil_dens_intr)%dat, & ! intent(in): intrinsic density of soil (kg m-3) - theta_sat => mpar_data%var(iLookPARAM%theta_sat)%dat & ! intent(in): soil porosity (-) - ) ! end associate statemen - ! initialize error control - err=0; message="computHeatCap/" - - ! initialize the soil layer - iSoil=integerMissing - - ! compute the bulk volumetric heat capacity of vegetation (J m-3 K-1) - if(computeVegFlux)then - delT = scalarCanopyTempTrial - scalarCanopyTempPrev - if(abs(delT) <= 1e-14_rkind)then - heatCapVeg = specificHeatVeg*maxMassVegetation/canopyDepth + & ! vegetation component +! data types +USE nrtype + +! derived types to define the data structures +USE data_types,only:& + var_d, & ! data vector (rkind) + var_ilength, & ! data vector with variable length dimension (i4b) + var_dlength ! data vector with variable length dimension (rkind) + +! named variables defining elements in the data structures +USE var_lookup,only:iLookPARAM,iLookDIAG,iLookINDEX ! named variables for structure elements + +! physical constants +USE multiconst,only:& + Tfreeze, & ! freezing point of water (K) + iden_air, & ! intrinsic density of air (kg m-3) + iden_ice, & ! intrinsic density of ice (kg m-3) + iden_water, & ! intrinsic density of water (kg m-3) + ! specific heat + Cp_air, & ! specific heat of air (J kg-1 K-1) + Cp_ice, & ! specific heat of ice (J kg-1 K-1) + Cp_soil, & ! specific heat of soil (J kg-1 K-1) + Cp_water ! specific heat of liquid water (J kg-1 K-1) +! named variables to describe the state variable type +USE globalData,only:iname_nrgCanair ! named variable defining the energy of the canopy air space +USE globalData,only:iname_nrgCanopy ! named variable defining the energy of the vegetation canopy +USE globalData,only:iname_watCanopy ! named variable defining the mass of total water on the vegetation canopy +USE globalData,only:iname_liqCanopy ! named variable defining the mass of liquid water on the vegetation canopy +USE globalData,only:iname_nrgLayer ! named variable defining the energy state variable for snow+soil layers +USE globalData,only:iname_watLayer ! named variable defining the total water state variable for snow+soil layers +USE globalData,only:iname_liqLayer ! named variable defining the liquid water state variable for snow+soil layers +USE globalData,only:iname_matLayer ! named variable defining the matric head state variable for soil layers +USE globalData,only:iname_lmpLayer ! named variable defining the liquid matric potential state variable for soil layers +USE globalData,only:iname_watAquifer ! named variable defining the water storage in the aquifer + +! missing values +USE globalData,only:integerMissing ! missing integer + +! named variables that define the layer type +USE globalData,only:iname_snow ! snow +USE globalData,only:iname_soil ! soil + + +! privacy +implicit none +private +public::computHeatCap +public::computStatMult +public::computHeatCapAnalytic +public::computCm + +contains + + +! ********************************************************************************************************** +! public subroutine computHeatCap: compute diagnostic energy variables (heat capacity) +! ********************************************************************************************************** +subroutine computHeatCap(& + ! input: control variables + nLayers, & ! intent(in): number of layers (soil+snow) + computeVegFlux, & ! intent(in): flag to denote if computing the vegetation flux + canopyDepth, & ! intent(in): canopy depth (m) + ! input data structures + mpar_data, & ! intent(in): model parameters + indx_data, & ! intent(in): model layer indices + diag_data, & ! intent(in): model diagnostic variables for a local HRU + ! input: state variables + scalarCanopyIce, & ! intent(in) + scalarCanopyLiquid, & ! intent(in) + scalarCanopyTempTrial, & ! intent(in): trial value of canopy temperature (K) + scalarCanopyTempPrev, & ! intent(in): previous value of canopy temperature (K) + scalarCanopyEnthalpyTrial, & ! intent(in): trial enthalpy of the vegetation canopy (J m-3) + scalarCanopyEnthalpyPrev, & ! intent(in): previous enthalpy of the vegetation canopy (J m-3) + mLayerVolFracIce, & ! intent(in): volumetric fraction of ice at the start of the sub-step (-) + mLayerVolFracLiq, & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-) + mLayerTempTrial, & ! intent(in): trial temperature + mLayerTempPrev, & ! intent(in): previous temperature + mLayerEnthalpyTrial, & ! intent(in): trial enthalpy for snow and soil + mLayerEnthalpyPrev, & ! intent(in): previous enthalpy for snow and soil + ! output + heatCapVeg, & + mLayerHeatCap, & ! intent(out): heat capacity for snow and soil + ! output: error control + err,message) ! intent(out): error control + ! -------------------------------------------------------------------------------------------------------------------------------------- + ! input: control variables + logical(lgt),intent(in) :: computeVegFlux ! logical flag to denote if computing the vegetation flux + real(rkind),intent(in) :: canopyDepth ! depth of the vegetation canopy (m) + ! input/output: data structures + type(var_dlength),intent(in) :: mpar_data ! model parameters + type(var_ilength),intent(in) :: indx_data ! model layer indices + ! input: + integer(i4b),intent(in) :: nLayers + type(var_dlength),intent(in) :: diag_data ! diagnostic variables for a local HRU + real(rkind),intent(in) :: scalarCanopyIce ! trial value of canopy ice content (kg m-2) + real(rkind),intent(in) :: scalarCanopyLiquid + real(rkind),intent(in) :: scalarCanopyTempTrial ! trial value of canopy temperature + real(rkind),intent(in) :: scalarCanopyEnthalpyTrial ! trial enthalpy of the vegetation canopy (J m-3) + real(rkind),intent(in) :: scalarCanopyEnthalpyPrev ! intent(in): previous enthalpy of the vegetation canopy (J m-3) + real(rkind),intent(in) :: scalarCanopyTempPrev ! Previous value of canopy temperature + real(rkind),intent(in) :: mLayerVolFracLiq(:) ! trial vector of volumetric liquid water content (-) + real(rkind),intent(in) :: mLayerVolFracIce(:) ! trial vector of volumetric ice water content (-) + real(rkind),intent(in) :: mLayerTempTrial(:) + real(rkind),intent(in) :: mLayerTempPrev(:) + real(rkind),intent(in) :: mLayerEnthalpyTrial(:) + real(rkind),intent(in) :: mLayerEnthalpyPrev(:) + ! output: + real(qp),intent(out) :: heatCapVeg + real(qp),intent(out) :: mLayerHeatCap(:) + integer(i4b),intent(out) :: err ! error code + character(*),intent(out) :: message ! error message + ! -------------------------------------------------------------------------------------------------------------------------------- + ! local variables + integer(i4b) :: iLayer ! index of model layer + real(rkind) :: delT + real(rkind) :: delEnt + integer(i4b) :: iSoil ! index of soil layer + ! -------------------------------------------------------------------------------------------------------------------------------- + ! associate variables in data structure + associate(& + ! input: coordinate variables + nSnow => indx_data%var(iLookINDEX%nSnow)%dat(1), & ! intent(in): number of snow layers + layerType => indx_data%var(iLookINDEX%layerType)%dat, & ! intent(in): layer type (iname_soil or iname_snow) + ! input: heat capacity and thermal conductivity + specificHeatVeg => mpar_data%var(iLookPARAM%specificHeatVeg)%dat(1), & ! intent(in): specific heat of vegetation (J kg-1 K-1) + maxMassVegetation => mpar_data%var(iLookPARAM%maxMassVegetation)%dat(1), & ! intent(in): maximum mass of vegetation (kg m-2) + ! input: depth varying soil parameters + iden_soil => mpar_data%var(iLookPARAM%soil_dens_intr)%dat, & ! intent(in): intrinsic density of soil (kg m-3) + theta_sat => mpar_data%var(iLookPARAM%theta_sat)%dat & ! intent(in): soil porosity (-) + ) ! end associate statemen + ! initialize error control + err=0; message="computHeatCap/" + + ! initialize the soil layer + iSoil=integerMissing + + ! compute the bulk volumetric heat capacity of vegetation (J m-3 K-1) + if(computeVegFlux)then + delT = scalarCanopyTempTrial - scalarCanopyTempPrev + if(abs(delT) <= 1e-14_rkind)then + heatCapVeg = specificHeatVeg*maxMassVegetation/canopyDepth + & ! vegetation component Cp_water*scalarCanopyLiquid/canopyDepth + & ! liquid water component Cp_ice*scalarCanopyIce/canopyDepth ! ice component - else - delEnt = scalarCanopyEnthalpyTrial - scalarCanopyEnthalpyPrev - heatCapVeg = delEnt / delT - end if - end if - - ! loop through layers - do iLayer=1,nLayers - delT = mLayerTempTrial(iLayer) - mLayerTempPrev(iLayer) - if(abs(delT) <= 1e-14_rkind)then + else + delEnt = scalarCanopyEnthalpyTrial - scalarCanopyEnthalpyPrev + heatCapVeg = delEnt / delT + end if + end if + + ! loop through layers + do iLayer=1,nLayers + delT = mLayerTempTrial(iLayer) - mLayerTempPrev(iLayer) + if(abs(delT) <= 1e-14_rkind)then ! get the soil layer if(iLayer>nSnow) iSoil = iLayer-nSnow - select case(layerType(iLayer)) - ! * soil - case(iname_soil) - mLayerHeatCap(iLayer) = iden_soil(iSoil) * Cp_soil * ( 1._rkind - theta_sat(iSoil) ) + & ! soil component - iden_ice * Cp_Ice * mLayerVolFracIce(iLayer) + & ! ice component - iden_water * Cp_water * mLayerVolFracLiq(iLayer) + & ! liquid water component - iden_air * Cp_air * ( theta_sat(iSoil) - (mLayerVolFracIce(iLayer) + mLayerVolFracLiq(iLayer)) )! air component - case(iname_snow) - mLayerHeatCap(iLayer) = iden_ice * Cp_ice * mLayerVolFracIce(iLayer) + & ! ice component - iden_water * Cp_water * mLayerVolFracLiq(iLayer) + & ! liquid water component - iden_air * Cp_air * ( 1._rkind - (mLayerVolFracIce(iLayer) + mLayerVolFracLiq(iLayer)) ) ! air component - case default; err=20; message=trim(message)//'unable to identify type of layer (snow or soil) to compute olumetric heat capacity'; return - end select - else + select case(layerType(iLayer)) + ! * soil + case(iname_soil) + mLayerHeatCap(iLayer) = iden_soil(iSoil) * Cp_soil * ( 1._rkind - theta_sat(iSoil) ) + & ! soil component + iden_ice * Cp_Ice * mLayerVolFracIce(iLayer) + & ! ice component + iden_water * Cp_water * mLayerVolFracLiq(iLayer) + & ! liquid water component + iden_air * Cp_air * ( theta_sat(iSoil) - (mLayerVolFracIce(iLayer) + mLayerVolFracLiq(iLayer)) )! air component + case(iname_snow) + mLayerHeatCap(iLayer) = iden_ice * Cp_ice * mLayerVolFracIce(iLayer) + & ! ice component + iden_water * Cp_water * mLayerVolFracLiq(iLayer) + & ! liquid water component + iden_air * Cp_air * ( 1._rkind - (mLayerVolFracIce(iLayer) + mLayerVolFracLiq(iLayer)) ) ! air component + case default; err=20; message=trim(message)//'unable to identify type of layer (snow or soil) to compute olumetric heat capacity'; return + end select + else delEnt = mLayerEnthalpyTrial(iLayer) - mLayerEnthalpyPrev(iLayer) mLayerHeatCap(iLayer) = delEnt / delT - endif - end do ! looping through layers - - end associate - - end subroutine computHeatCap - - ! ********************************************************************************************************** - ! public subroutine computStatMult: get scale factors - ! ********************************************************************************************************** - subroutine computStatMult(& - heatCapVeg, & - mLayerHeatCap, & - ! input: data structures - diag_data, & ! intent(in): model diagnostic variables for a local HRU - indx_data, & ! intent(in): indices defining model states and layers - ! output - sMul, & ! intent(out): multiplier for state vector (used in the residual calculations) - err,message) ! intent(out): error control - ! -------------------------------------------------------------------------------------------------------------------------------- - USE nr_utility_module,only:arth ! get a sequence of numbers arth(start, incr, count) - USE f2008funcs_module,only:findIndex ! finds the index of the first value within a vector - ! -------------------------------------------------------------------------------------------------------------------------------- - ! input: data structures - real(qp),intent(out) :: heatCapVeg - real(qp),intent(out) :: mLayerHeatCap(:) - type(var_dlength),intent(in) :: diag_data ! diagnostic variables for a local HRU - type(var_ilength),intent(in) :: indx_data ! indices defining model states and layers - ! output: state vectors - real(qp),intent(out) :: sMul(:) ! NOTE: qp ! multiplier for state vector (used in the residual calculations) - ! output: error control - integer(i4b),intent(out) :: err ! error code - character(*),intent(out) :: message ! error message - ! -------------------------------------------------------------------------------------------------------------------------------- - ! local variables - ! -------------------------------------------------------------------------------------------------------------------------------- - ! state subsets - integer(i4b) :: iLayer ! index of layer within the snow+soil domain - integer(i4b) :: ixStateSubset ! index within the state subset - ! -------------------------------------------------------------------------------------------------------------------------------- - ! -------------------------------------------------------------------------------------------------------------------------------- - ! make association with variables in the data structures - associate(& - ! model diagnostic variables - canopyDepth => diag_data%var(iLookDIAG%scalarCanopyDepth)%dat(1) ,& ! intent(in): [dp] canopy depth (m) - volHeatCapVeg => diag_data%var(iLookDIAG%scalarBulkVolHeatCapVeg)%dat(1),& ! intent(in) : [dp] bulk volumetric heat capacity of vegetation (J m-3 K-1) - ! indices defining specific model states - ixCasNrg => indx_data%var(iLookINDEX%ixCasNrg)%dat ,& ! intent(in) : [i4b(:)] [length=1] index of canopy air space energy state variable - ixVegNrg => indx_data%var(iLookINDEX%ixVegNrg)%dat ,& ! intent(in) : [i4b(:)] [length=1] index of canopy energy state variable - ixVegHyd => indx_data%var(iLookINDEX%ixVegHyd)%dat ,& ! intent(in) : [i4b(:)] [length=1] index of canopy hydrology state variable (mass) - ! vector of energy and hydrology indices for the snow and soil domains - ixSnowSoilNrg => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat ,& ! intent(in) : [i4b(:)] index in the state subset for energy state variables in the snow+soil domain - ixSnowSoilHyd => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat ,& ! intent(in) : [i4b(:)] index in the state subset for hydrology state variables in the snow+soil domain - nSnowSoilNrg => indx_data%var(iLookINDEX%nSnowSoilNrg )%dat(1) ,& ! intent(in) : [i4b] number of energy state variables in the snow+soil domain - nSnowSoilHyd => indx_data%var(iLookINDEX%nSnowSoilHyd )%dat(1) ,& ! intent(in) : [i4b] number of hydrology state variables in the snow+soil domain - ! type of model state variabless - ixStateType_subset => indx_data%var(iLookINDEX%ixStateType_subset)%dat ,& ! intent(in) : [i4b(:)] [state subset] type of desired model state variables - ! number of layers - nSnow => indx_data%var(iLookINDEX%nSnow)%dat(1) ,& ! intent(in) : [i4b] number of snow layers - nSoil => indx_data%var(iLookINDEX%nSoil)%dat(1) ,& ! intent(in) : [i4b] number of soil layers - nLayers => indx_data%var(iLookINDEX%nLayers)%dat(1) & ! intent(in) : [i4b] total number of layers - ) ! end association with variables in the data structures - ! -------------------------------------------------------------------------------------------------------------------------------- - ! initialize error control - err=0; message='computStatMult/' - - ! ----- - ! * define components of derivative matrices that are constant over a time step (substep)... - ! ------------------------------------------------------------------------------------------ - - ! define the multiplier for the state vector for residual calculations (vegetation canopy) - ! NOTE: Use the "where" statement to generalize to multiple canopy layers (currently one canopy layer) - - where(ixStateType_subset==iname_nrgCanair) sMul = Cp_air*iden_air ! volumetric heat capacity of air (J m-3 K-1) - where(ixStateType_subset==iname_nrgCanopy) sMul = heatCapVeg ! volumetric heat capacity of the vegetation (J m-3 K-1) - where(ixStateType_subset==iname_watCanopy) sMul = 1._rkind ! nothing else on the left hand side - where(ixStateType_subset==iname_liqCanopy) sMul = 1._rkind ! nothing else on the left hand side - - - ! define the energy multiplier for the state vector for residual calculations (snow-soil domain) - if(nSnowSoilNrg>0)then - do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing) ! (loop through non-missing energy state variables in the snow+soil domain) - ixStateSubset = ixSnowSoilNrg(iLayer) ! index within the state vector - sMul(ixStateSubset) = mLayerHeatCap(iLayer) ! transfer volumetric heat capacity to the state multiplier - end do ! looping through non-missing energy state variables in the snow+soil domain - endif - - ! define the hydrology multiplier and diagonal elements for the state vector for residual calculations (snow-soil domain) - if(nSnowSoilHyd>0)then - do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing) ! (loop through non-missing energy state variables in the snow+soil domain) - ixStateSubset = ixSnowSoilHyd(iLayer) ! index within the state vector - sMul(ixStateSubset) = 1._rkind ! state multiplier = 1 (nothing else on the left-hand-side) - end do ! looping through non-missing energy state variables in the snow+soil domain - endif - - ! define the scaling factor and diagonal elements for the aquifer - where(ixStateType_subset==iname_watAquifer) sMul = 1._rkind - - ! ------------------------------------------------------------------------------------------ - ! ------------------------------------------------------------------------------------------ - - end associate - ! end association to variables in the data structure where vector length does not change - end subroutine computStatMult - - ! ********************************************************************************************************** - ! public subroutine computHeatCapAnalytic: compute diagnostic energy variables (heat capacity) - ! ********************************************************************************************************** - subroutine computHeatCapAnalytic(& - ! input: control variables - computeVegFlux, & ! intent(in): flag to denote if computing the vegetation flux - canopyDepth, & ! intent(in): canopy depth (m) - ! input: state variables - scalarCanopyIce, & ! intent(in) - scalarCanopyLiquid, & ! intent(in) - mLayerVolFracIce, & ! intent(in): volumetric fraction of ice at the start of the sub-step (-) - mLayerVolFracLiq, & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-) - ! input data structures - mpar_data, & ! intent(in): model parameters - indx_data, & ! intent(in): model layer indices - ! output - heatCapVeg, & - mLayerHeatCap, & - ! output: error control - err,message) ! intent(out): error control - ! -------------------------------------------------------------------------------------------------------------------------------------- - ! -------------------------------------------------------------------------------------------------------------------------------------- - ! input: model control - logical(lgt),intent(in) :: computeVegFlux ! logical flag to denote if computing the vegetation flux - real(rkind),intent(in) :: canopyDepth ! depth of the vegetation canopy (m) - real(rkind),intent(in) :: scalarCanopyIce ! trial value of canopy ice content (kg m-2) - real(rkind),intent(in) :: scalarCanopyLiquid - real(rkind),intent(in) :: mLayerVolFracLiq(:) ! trial vector of volumetric liquid water content (-) - real(rkind),intent(in) :: mLayerVolFracIce(:) ! trial vector of volumetric ice water content (-) - ! input/output: data structures - type(var_dlength),intent(in) :: mpar_data ! model parameters - type(var_ilength),intent(in) :: indx_data ! model layer indices - ! output: error control - real(qp),intent(out) :: heatCapVeg - real(qp),intent(out) :: mLayerHeatCap(:) - integer(i4b),intent(out) :: err ! error code - character(*),intent(out) :: message ! error message - ! -------------------------------------------------------------------------------------------------------------------------------- - ! local variables - character(LEN=256) :: cmessage ! error message of downwind routine - integer(i4b) :: iLayer ! index of model layer - integer(i4b) :: iSoil ! index of soil layer - ! -------------------------------------------------------------------------------------------------------------------------------- - ! associate variables in data structure - associate(& - ! input: coordinate variables - nSnow => indx_data%var(iLookINDEX%nSnow)%dat(1), & ! intent(in): number of snow layers - nLayers => indx_data%var(iLookINDEX%nLayers)%dat(1), & ! intent(in): total number of layers - layerType => indx_data%var(iLookINDEX%layerType)%dat, & ! intent(in): layer type (iname_soil or iname_snow) - ! input: heat capacity and thermal conductivity - specificHeatVeg => mpar_data%var(iLookPARAM%specificHeatVeg)%dat(1), & ! intent(in): specific heat of vegetation (J kg-1 K-1) - maxMassVegetation => mpar_data%var(iLookPARAM%maxMassVegetation)%dat(1), & ! intent(in): maximum mass of vegetation (kg m-2) - ! input: depth varying soil parameters - iden_soil => mpar_data%var(iLookPARAM%soil_dens_intr)%dat, & ! intent(in): intrinsic density of soil (kg m-3) - theta_sat => mpar_data%var(iLookPARAM%theta_sat)%dat & ! intent(in): soil porosity (-) - ) ! end associate statement - ! -------------------------------------------------------------------------------------------------------------------------------- - ! initialize error control - err=0; message="computHeatCapAnalytic/" - - ! initialize the soil layer - iSoil=integerMissing - - ! compute the bulk volumetric heat capacity of vegetation (J m-3 K-1) - if(computeVegFlux)then - heatCapVeg = specificHeatVeg*maxMassVegetation/canopyDepth + & ! vegetation component - Cp_water*scalarCanopyLiquid/canopyDepth + & ! liquid water component - Cp_ice*scalarCanopyIce/canopyDepth ! ice component - end if - - ! loop through layers - do iLayer=1,nLayers - - ! get the soil layer - if(iLayer>nSnow) iSoil = iLayer-nSnow - - ! ***** - ! * compute the volumetric heat capacity of each layer (J m-3 K-1)... - ! ******************************************************************* - select case(layerType(iLayer)) - ! * soil - case(iname_soil) - mLayerHeatCap(iLayer) = iden_soil(iSoil) * Cp_soil * ( 1._rkind - theta_sat(iSoil) ) + & ! soil component - iden_ice * Cp_ice * mLayerVolFracIce(iLayer) + & ! ice component - iden_water * Cp_water * mLayerVolFracLiq(iLayer) + & ! liquid water component - iden_air * Cp_air * ( theta_sat(iSoil) - (mLayerVolFracIce(iLayer) + mLayerVolFracLiq(iLayer)) )! air component - case(iname_snow) - mLayerHeatCap(iLayer) = iden_ice * Cp_ice * mLayerVolFracIce(iLayer) + & ! ice component - iden_water * Cp_water * mLayerVolFracLiq(iLayer) + & ! liquid water component - iden_air * Cp_air * ( 1._rkind - (mLayerVolFracIce(iLayer) + mLayerVolFracLiq(iLayer)) ) ! air component - case default; err=20; message=trim(message)//'unable to identify type of layer (snow or soil) to compute olumetric heat capacity'; return - end select - - end do ! looping through layers - !pause - - ! end association to variables in the data structure - end associate - - end subroutine computHeatCapAnalytic - - ! ********************************************************************************************************** - ! public subroutine computCm - ! ********************************************************************************************************** - subroutine computCm(& - ! input: control variables - computeVegFlux, & ! intent(in): flag to denote if computing the vegetation flux - ! input: state variables - scalarCanopyTemp, & ! intent(in) - mLayerTemp, & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-) - mLayerMatricHead, & ! intent(in) - ! input data structures - mpar_data, & ! intent(in): model parameters - indx_data, & ! intent(in): model layer indices - ! output - scalarCanopyCm, & ! intent(out): Cm for vegetation - mLayerCm, & ! intent(out): Cm for soil and snow - ! output: error control - err,message) ! intent(out): error control - ! -------------------------------------------------------------------------------------------------------------------------------------- - ! provide access to external subroutines - USE soil_utils_module,only:crit_soilT ! compute critical temperature below which ice exists - ! -------------------------------------------------------------------------------------------------------------------------------------- - ! input: model control - logical(lgt),intent(in) :: computeVegFlux ! logical flag to denote if computing the vegetation flux - real(rkind),intent(in) :: scalarCanopyTemp ! value of canopy ice content (kg m-2) - real(rkind),intent(in) :: mLayerTemp(:) ! vector of volumetric liquid water content (-) - real(rkind),intent(in) :: mLayerMatricHead(:) ! vector of total water matric potential (m) - ! input/output: data structures - type(var_dlength),intent(in) :: mpar_data ! model parameters - type(var_ilength),intent(in) :: indx_data ! model layer indices - ! output: error control - real(qp),intent(out) :: scalarCanopyCm - real(qp),intent(out) :: mLayerCm(:) - integer(i4b),intent(out) :: err ! error code - character(*),intent(out) :: message ! error message - ! -------------------------------------------------------------------------------------------------------------------------------- - ! local variables - character(LEN=256) :: cmessage ! error message of downwind routine - integer(i4b) :: iLayer ! index of model layer - integer(i4b) :: iSoil ! index of soil layer - real(rkind) :: g1 - real(rkind) :: g2 - real(rkind) :: Tcrit ! temperature where all water is unfrozen (K) - - ! -------------------------------------------------------------------------------------------------------------------------------- - ! associate variables in data structure - associate(& - ! input: coordinate variables - nSnow => indx_data%var(iLookINDEX%nSnow)%dat(1), & ! intent(in): number of snow layers - nLayers => indx_data%var(iLookINDEX%nLayers)%dat(1), & ! intent(in): total number of layers - layerType => indx_data%var(iLookINDEX%layerType)%dat, & ! intent(in): layer type (iname_soil or iname_snow) - snowfrz_scale => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1) & ! intent(in): [dp] scaling parameter for the snow freezing curve (K-1) - ) ! end associate statement - ! -------------------------------------------------------------------------------------------------------------------------------- - ! initialize error control - err=0; message="computCm/" - - ! initialize the soil layer - iSoil=integerMissing - - ! compute Cm of vegetation - ! Note that scalarCanopyCm/iden_water is computed - if(computeVegFlux)then - g2 = scalarCanopyTemp - Tfreeze - g1 = (1._rkind/snowfrz_scale) * atan(snowfrz_scale * g2) - if(scalarCanopyTemp < Tfreeze)then - scalarCanopyCm = Cp_water * g1 + Cp_ice * (g2 - g1) - else - scalarCanopyCm = Cp_water * g2 - end if - end if - - ! loop through layers - do iLayer=1,nLayers - - ! get the soil layer - if(iLayer>nSnow) iSoil = iLayer-nSnow - - ! ***** - ! * compute Cm of of each layer - ! ******************************************************************* - select case(layerType(iLayer)) - ! * soil - case(iname_soil) - g2 = mLayerTemp(iLayer) - Tfreeze - Tcrit = crit_soilT( mLayerMatricHead(iSoil) ) - if( mLayerTemp(iLayer) < Tcrit)then - mLayerCm(iLayer) = (iden_ice * Cp_ice - iden_air * Cp_air) * g2 - else - mLayerCm(iLayer) = (iden_water * Cp_water - iden_air * Cp_air) * g2 - end if - - case(iname_snow) - g2 = mLayerTemp(iLayer) - Tfreeze + endif + end do ! looping through layers + + end associate + +end subroutine computHeatCap + +! ********************************************************************************************************** +! public subroutine computStatMult: get scale factors +! ********************************************************************************************************** +subroutine computStatMult(& + heatCapVeg, & + mLayerHeatCap, & + ! input: data structures + diag_data, & ! intent(in): model diagnostic variables for a local HRU + indx_data, & ! intent(in): indices defining model states and layers + ! output + sMul, & ! intent(out): multiplier for state vector (used in the residual calculations) + err,message) ! intent(out): error control +! -------------------------------------------------------------------------------------------------------------------------------- +USE nr_utility_module,only:arth ! get a sequence of numbers arth(start, incr, count) +USE f2008funcs_module,only:findIndex ! finds the index of the first value within a vector + ! -------------------------------------------------------------------------------------------------------------------------------- + ! input: data structures + real(qp),intent(out) :: heatCapVeg + real(qp),intent(out) :: mLayerHeatCap(:) + type(var_dlength),intent(in) :: diag_data ! diagnostic variables for a local HRU + type(var_ilength),intent(in) :: indx_data ! indices defining model states and layers + ! output: state vectors + real(qp),intent(out) :: sMul(:) ! NOTE: qp ! multiplier for state vector (used in the residual calculations) + ! output: error control + integer(i4b),intent(out) :: err ! error code + character(*),intent(out) :: message ! error message + ! -------------------------------------------------------------------------------------------------------------------------------- + ! local variables + ! -------------------------------------------------------------------------------------------------------------------------------- + ! state subsets + integer(i4b) :: iLayer ! index of layer within the snow+soil domain + integer(i4b) :: ixStateSubset ! index within the state subset + ! -------------------------------------------------------------------------------------------------------------------------------- + ! -------------------------------------------------------------------------------------------------------------------------------- + ! make association with variables in the data structures + associate(& + ! model diagnostic variables + canopyDepth => diag_data%var(iLookDIAG%scalarCanopyDepth)%dat(1) ,& ! intent(in): [dp] canopy depth (m) + volHeatCapVeg => diag_data%var(iLookDIAG%scalarBulkVolHeatCapVeg)%dat(1),& ! intent(in) : [dp] bulk volumetric heat capacity of vegetation (J m-3 K-1) + ! indices defining specific model states + ixCasNrg => indx_data%var(iLookINDEX%ixCasNrg)%dat ,& ! intent(in) : [i4b(:)] [length=1] index of canopy air space energy state variable + ixVegNrg => indx_data%var(iLookINDEX%ixVegNrg)%dat ,& ! intent(in) : [i4b(:)] [length=1] index of canopy energy state variable + ixVegHyd => indx_data%var(iLookINDEX%ixVegHyd)%dat ,& ! intent(in) : [i4b(:)] [length=1] index of canopy hydrology state variable (mass) + ! vector of energy and hydrology indices for the snow and soil domains + ixSnowSoilNrg => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat ,& ! intent(in) : [i4b(:)] index in the state subset for energy state variables in the snow+soil domain + ixSnowSoilHyd => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat ,& ! intent(in) : [i4b(:)] index in the state subset for hydrology state variables in the snow+soil domain + nSnowSoilNrg => indx_data%var(iLookINDEX%nSnowSoilNrg )%dat(1) ,& ! intent(in) : [i4b] number of energy state variables in the snow+soil domain + nSnowSoilHyd => indx_data%var(iLookINDEX%nSnowSoilHyd )%dat(1) ,& ! intent(in) : [i4b] number of hydrology state variables in the snow+soil domain + ! type of model state variabless + ixStateType_subset => indx_data%var(iLookINDEX%ixStateType_subset)%dat ,& ! intent(in) : [i4b(:)] [state subset] type of desired model state variables + ! number of layers + nSnow => indx_data%var(iLookINDEX%nSnow)%dat(1) ,& ! intent(in) : [i4b] number of snow layers + nSoil => indx_data%var(iLookINDEX%nSoil)%dat(1) ,& ! intent(in) : [i4b] number of soil layers + nLayers => indx_data%var(iLookINDEX%nLayers)%dat(1) & ! intent(in) : [i4b] total number of layers + ) ! end association with variables in the data structures + ! -------------------------------------------------------------------------------------------------------------------------------- + ! initialize error control + err=0; message='computStatMult/' + + ! ----- + ! * define components of derivative matrices that are constant over a time step (substep)... + ! ------------------------------------------------------------------------------------------ + + ! define the multiplier for the state vector for residual calculations (vegetation canopy) + ! NOTE: Use the "where" statement to generalize to multiple canopy layers (currently one canopy layer) + + where(ixStateType_subset==iname_nrgCanair) sMul = Cp_air*iden_air ! volumetric heat capacity of air (J m-3 K-1) + where(ixStateType_subset==iname_nrgCanopy) sMul = heatCapVeg ! volumetric heat capacity of the vegetation (J m-3 K-1) + where(ixStateType_subset==iname_watCanopy) sMul = 1._rkind ! nothing else on the left hand side + where(ixStateType_subset==iname_liqCanopy) sMul = 1._rkind ! nothing else on the left hand side + + + ! define the energy multiplier for the state vector for residual calculations (snow-soil domain) + if(nSnowSoilNrg>0)then + do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing) ! (loop through non-missing energy state variables in the snow+soil domain) + ixStateSubset = ixSnowSoilNrg(iLayer) ! index within the state vector + sMul(ixStateSubset) = mLayerHeatCap(iLayer) ! transfer volumetric heat capacity to the state multiplier + end do ! looping through non-missing energy state variables in the snow+soil domain + endif + + ! define the hydrology multiplier and diagonal elements for the state vector for residual calculations (snow-soil domain) + if(nSnowSoilHyd>0)then + do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing) ! (loop through non-missing energy state variables in the snow+soil domain) + ixStateSubset = ixSnowSoilHyd(iLayer) ! index within the state vector + sMul(ixStateSubset) = 1._rkind ! state multiplier = 1 (nothing else on the left-hand-side) + end do ! looping through non-missing energy state variables in the snow+soil domain + endif + + ! define the scaling factor and diagonal elements for the aquifer + where(ixStateType_subset==iname_watAquifer) sMul = 1._rkind + + ! ------------------------------------------------------------------------------------------ + ! ------------------------------------------------------------------------------------------ + + end associate +! end association to variables in the data structure where vector length does not change +end subroutine computStatMult + +! ********************************************************************************************************** +! public subroutine computHeatCapAnalytic: compute diagnostic energy variables (heat capacity) +! ********************************************************************************************************** +subroutine computHeatCapAnalytic(& + ! input: control variables + computeVegFlux, & ! intent(in): flag to denote if computing the vegetation flux + canopyDepth, & ! intent(in): canopy depth (m) + ! input: state variables + scalarCanopyIce, & ! intent(in) + scalarCanopyLiquid, & ! intent(in) + mLayerVolFracIce, & ! intent(in): volumetric fraction of ice at the start of the sub-step (-) + mLayerVolFracLiq, & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-) + ! input data structures + mpar_data, & ! intent(in): model parameters + indx_data, & ! intent(in): model layer indices + ! output + heatCapVeg, & + mLayerHeatCap, & + ! output: error control + err,message) ! intent(out): error control + ! -------------------------------------------------------------------------------------------------------------------------------------- + ! -------------------------------------------------------------------------------------------------------------------------------------- + ! input: model control + logical(lgt),intent(in) :: computeVegFlux ! logical flag to denote if computing the vegetation flux + real(rkind),intent(in) :: canopyDepth ! depth of the vegetation canopy (m) + real(rkind),intent(in) :: scalarCanopyIce ! trial value of canopy ice content (kg m-2) + real(rkind),intent(in) :: scalarCanopyLiquid + real(rkind),intent(in) :: mLayerVolFracLiq(:) ! trial vector of volumetric liquid water content (-) + real(rkind),intent(in) :: mLayerVolFracIce(:) ! trial vector of volumetric ice water content (-) + ! input/output: data structures + type(var_dlength),intent(in) :: mpar_data ! model parameters + type(var_ilength),intent(in) :: indx_data ! model layer indices + ! output: error control + real(qp),intent(out) :: heatCapVeg + real(qp),intent(out) :: mLayerHeatCap(:) + integer(i4b),intent(out) :: err ! error code + character(*),intent(out) :: message ! error message + ! -------------------------------------------------------------------------------------------------------------------------------- + ! local variables + character(LEN=256) :: cmessage ! error message of downwind routine + integer(i4b) :: iLayer ! index of model layer + integer(i4b) :: iSoil ! index of soil layer + ! -------------------------------------------------------------------------------------------------------------------------------- + ! associate variables in data structure + associate(& + ! input: coordinate variables + nSnow => indx_data%var(iLookINDEX%nSnow)%dat(1), & ! intent(in): number of snow layers + nLayers => indx_data%var(iLookINDEX%nLayers)%dat(1), & ! intent(in): total number of layers + layerType => indx_data%var(iLookINDEX%layerType)%dat, & ! intent(in): layer type (iname_soil or iname_snow) + ! input: heat capacity and thermal conductivity + specificHeatVeg => mpar_data%var(iLookPARAM%specificHeatVeg)%dat(1), & ! intent(in): specific heat of vegetation (J kg-1 K-1) + maxMassVegetation => mpar_data%var(iLookPARAM%maxMassVegetation)%dat(1), & ! intent(in): maximum mass of vegetation (kg m-2) + ! input: depth varying soil parameters + iden_soil => mpar_data%var(iLookPARAM%soil_dens_intr)%dat, & ! intent(in): intrinsic density of soil (kg m-3) + theta_sat => mpar_data%var(iLookPARAM%theta_sat)%dat & ! intent(in): soil porosity (-) + ) ! end associate statement + ! -------------------------------------------------------------------------------------------------------------------------------- + ! initialize error control + err=0; message="computHeatCapAnalytic/" + + ! initialize the soil layer + iSoil=integerMissing + + ! compute the bulk volumetric heat capacity of vegetation (J m-3 K-1) + if(computeVegFlux)then + heatCapVeg = specificHeatVeg*maxMassVegetation/canopyDepth + & ! vegetation component + Cp_water*scalarCanopyLiquid/canopyDepth + & ! liquid water component + Cp_ice*scalarCanopyIce/canopyDepth ! ice component + end if + + ! loop through layers + do iLayer=1,nLayers + + ! get the soil layer + if(iLayer>nSnow) iSoil = iLayer-nSnow + + ! ***** + ! * compute the volumetric heat capacity of each layer (J m-3 K-1)... + ! ******************************************************************* + select case(layerType(iLayer)) + ! * soil + case(iname_soil) + mLayerHeatCap(iLayer) = iden_soil(iSoil) * Cp_soil * ( 1._rkind - theta_sat(iSoil) ) + & ! soil component + iden_ice * Cp_ice * mLayerVolFracIce(iLayer) + & ! ice component + iden_water * Cp_water * mLayerVolFracLiq(iLayer) + & ! liquid water component + iden_air * Cp_air * ( theta_sat(iSoil) - (mLayerVolFracIce(iLayer) + mLayerVolFracLiq(iLayer)) )! air component + case(iname_snow) + mLayerHeatCap(iLayer) = iden_ice * Cp_ice * mLayerVolFracIce(iLayer) + & ! ice component + iden_water * Cp_water * mLayerVolFracLiq(iLayer) + & ! liquid water component + iden_air * Cp_air * ( 1._rkind - (mLayerVolFracIce(iLayer) + mLayerVolFracLiq(iLayer)) ) ! air component + case default; err=20; message=trim(message)//'unable to identify type of layer (snow or soil) to compute olumetric heat capacity'; return + end select + + end do ! looping through layers + !pause + + ! end association to variables in the data structure + end associate +end subroutine computHeatCapAnalytic + +! ********************************************************************************************************** +! public subroutine computCm +! ********************************************************************************************************** +subroutine computCm(& + ! input: control variables + computeVegFlux, & ! intent(in): flag to denote if computing the vegetation flux + ! input: state variables + scalarCanopyTemp, & ! intent(in) + mLayerTemp, & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-) + mLayerMatricHead, & ! intent(in) + ! input data structures + mpar_data, & ! intent(in): model parameters + indx_data, & ! intent(in): model layer indices + ! output + scalarCanopyCm, & ! intent(out): Cm for vegetation + mLayerCm, & ! intent(out): Cm for soil and snow + ! output: error control + err,message) ! intent(out): error control + ! -------------------------------------------------------------------------------------------------------------------------------------- + ! provide access to external subroutines + USE soil_utils_module,only:crit_soilT ! compute critical temperature below which ice exists + ! -------------------------------------------------------------------------------------------------------------------------------------- + ! input: model control + logical(lgt),intent(in) :: computeVegFlux ! logical flag to denote if computing the vegetation flux + real(rkind),intent(in) :: scalarCanopyTemp ! value of canopy ice content (kg m-2) + real(rkind),intent(in) :: mLayerTemp(:) ! vector of volumetric liquid water content (-) + real(rkind),intent(in) :: mLayerMatricHead(:) ! vector of total water matric potential (m) + ! input/output: data structures + type(var_dlength),intent(in) :: mpar_data ! model parameters + type(var_ilength),intent(in) :: indx_data ! model layer indices + ! output: error control + real(qp),intent(out) :: scalarCanopyCm + real(qp),intent(out) :: mLayerCm(:) + integer(i4b),intent(out) :: err ! error code + character(*),intent(out) :: message ! error message + ! -------------------------------------------------------------------------------------------------------------------------------- + ! local variables + character(LEN=256) :: cmessage ! error message of downwind routine + integer(i4b) :: iLayer ! index of model layer + integer(i4b) :: iSoil ! index of soil layer + real(rkind) :: g1 + real(rkind) :: g2 + real(rkind) :: Tcrit ! temperature where all water is unfrozen (K) + + ! -------------------------------------------------------------------------------------------------------------------------------- + ! associate variables in data structure + associate(& + ! input: coordinate variables + nSnow => indx_data%var(iLookINDEX%nSnow)%dat(1), & ! intent(in): number of snow layers + nLayers => indx_data%var(iLookINDEX%nLayers)%dat(1), & ! intent(in): total number of layers + layerType => indx_data%var(iLookINDEX%layerType)%dat, & ! intent(in): layer type (iname_soil or iname_snow) + snowfrz_scale => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1) & ! intent(in): [dp] scaling parameter for the snow freezing curve (K-1) + ) ! end associate statement + ! -------------------------------------------------------------------------------------------------------------------------------- + ! initialize error control + err=0; message="computCm/" + + ! initialize the soil layer + iSoil=integerMissing + + ! compute Cm of vegetation + ! Note that scalarCanopyCm/iden_water is computed + if(computeVegFlux)then + g2 = scalarCanopyTemp - Tfreeze g1 = (1._rkind/snowfrz_scale) * atan(snowfrz_scale * g2) - mLayerCm(iLayer) = (iden_ice * Cp_ice - iden_air * Cp_air * iden_water/iden_ice) * ( g2 - g1 ) & - + (iden_water * Cp_water - iden_air * Cp_air) * g1 - - case default; err=20; message=trim(message)//'unable to identify type of layer (snow or soil) to compute Cm'; return - end select - - end do ! looping through layers - !pause - - ! end association to variables in the data structure - end associate - - end subroutine computCm - - - end module computHeatCap_module + if(scalarCanopyTemp < Tfreeze)then + scalarCanopyCm = Cp_water * g1 + Cp_ice * (g2 - g1) + else + scalarCanopyCm = Cp_water * g2 + end if + end if + + ! loop through layers + do iLayer=1,nLayers + + ! get the soil layer + if(iLayer>nSnow) iSoil = iLayer-nSnow + + ! ***** + ! * compute Cm of of each layer + ! ******************************************************************* + select case(layerType(iLayer)) + ! * soil + case(iname_soil) + g2 = mLayerTemp(iLayer) - Tfreeze + Tcrit = crit_soilT( mLayerMatricHead(iSoil) ) + if( mLayerTemp(iLayer) < Tcrit)then + mLayerCm(iLayer) = (iden_ice * Cp_ice - iden_air * Cp_air) * g2 + else + mLayerCm(iLayer) = (iden_water * Cp_water - iden_air * Cp_air) * g2 + end if + + case(iname_snow) + g2 = mLayerTemp(iLayer) - Tfreeze + g1 = (1._rkind/snowfrz_scale) * atan(snowfrz_scale * g2) + mLayerCm(iLayer) = (iden_ice * Cp_ice - iden_air * Cp_air * iden_water/iden_ice) * ( g2 - g1 ) & + + (iden_water * Cp_water - iden_air * Cp_air) * g1 + + case default; err=20; message=trim(message)//'unable to identify type of layer (snow or soil) to compute Cm'; return + end select + + end do ! looping through layers + !pause + + ! end association to variables in the data structure + end associate + +end subroutine computCm + + +end module computHeatCap_module \ No newline at end of file -- GitLab