Newer
Older
use NUMERICS, only : PROGONKA, STEP

Victor Stepanenko
committed
use NUMERIC_PARAMS, only : vector_length, small_value

Victor Stepanenko
committed
use LAKE_DATATYPES, only : ireals, iintegers
use ARRAYS_GRID, only : gridsize_type
use ARRAYS_BATHYM, only : layers_type, bathym
use ARRAYS_GRID, only : gridspacing_type
use ARRAYS_SOIL, only : lsh_type
use DRIVING_PARAMS, only : carbon_model

Victor Stepanenko
committed
use UNITS, only : kg_to_g
use DIFFUSION_MOD, only : DIFFUSION
real(4), parameter :: k_PA = 1.7 ! n/d, coefficient in Poole&Atkins formula
real(4), parameter :: extwat1 = k_PA/2., extwat2 = k_PA/3.5 ! Extinction coefficients
! identifying eutrophic,
! mesotrophic and oligotrophic lakes,
! derived from Poole and Atkins (1929)
! formula and data from Stefan and Fang, 1994
real(4), parameter :: chla_aver_oligo = 2.E-3 !2.E-3 ! mg/l, Mean chlorophyll density in oligotrophic lake, Stefan and Fang, 1994
real(4), parameter :: chla_aver_meso = 6.E-3 !6.E-3 ! mg/l, Mean chlorophyll density in mesotrophic lake, Stefan and Fang, 1994
real(4), parameter :: chla_aver_eu = 15.E-3 !15.E-3 ! mg/l, Mean chlorophyll density in eutrophic lake, Stefan and Fang, 1994
!> Subroutine OXYGEN calculates vertical diffusion of dissolved oxygen and interaction with bubbles
& (gs, Twater, fbbleflx_o2_sum, fbbleflx_o2, lamoxyg, gsp, fracb0, pressure, wind10, &
& o2_pres_atm, ls, bathymwater, lso, dt, febul0, eps_surf, sodbot, oxyg, soilswitch, Flux_atm)
use PHYS_FUNC, only : &
& HENRY_CONST, &
& GAS_WATATM_FLUX
use PHYS_CONSTANTS, only : kappa, z0_bot

Victor Stepanenko
committed
use PHYS_CONSTANTS, only : &
& Kelvin0

Victor Stepanenko
committed
use T_SOLVER_MOD, only : &
& DIFF_COEF
!> Grid size group
type(gridsize_type), intent(in) :: gs
!> Grid spacing group
type(gridspacing_type), intent(in) :: gsp
!> Group containing depths of physical layers
type(layers_type), intent(in) :: ls
!> Bathymetry characteristics of a water body
type(bathym), intent(in) :: bathymwater(1:gs%M+1)
!> Oxygen flux at the water-sediments interface
type(lsh_type), intent(in) :: lso
!> Water temperature profile, Celsius
real(kind=ireals), intent(in) :: Twater(1:gs%M+1)
!> The bubble oxygen flux, horizontally integrated, normalized by bottom value, n/d
real(kind=ireals), intent(inout) :: fbbleflx_o2_sum(0:gs%M+1)
!> The bubble oxygen flux above the deepest soil column, normalized by bottom value, n/d
real(kind=ireals), intent(in) :: fbbleflx_o2(0:gs%M+1)
!> Vertical diffusivity for oxygen, m**2/s
real(kind=ireals), intent(in) :: lamoxyg(1:gs%M)
!> Molar fractions of gases in a bubble
real(kind=ireals), intent(in) :: fracb0(1:ngasb)
!> Bottom methane flux, mol/m**2/s
real(kind=ireals), intent(in) :: febul0
!> Atmospheric pressure, Pa
real(kind=ireals), intent(in) :: pressure
!> Wind speed at 10 m above the surface
real(kind=ireals), intent(in) :: wind10
!> Oxygen partial pressure in the atmosphere, Pa
real(kind=ireals), intent(in) :: o2_pres_atm
!> Time step, s

Victor Stepanenko
committed
real(kind=ireals), intent(in) :: dt
!> TKE dissipation rate at the water surface, m**2/s**3
real(kind=ireals), intent(in) :: eps_surf
!> Sedimentary oxygen demand (oxygen flux at the bottom), mol/(m**2*s)
real(kind=ireals), intent(in) :: sodbot
!> Oxygen concentration in water, mol/m**3
real(kind=ireals), intent(inout) :: oxyg(1:gs%M+1,1:2)
!> Switch for soil (sediments)

Victor Stepanenko
committed
integer(kind=iintegers), intent(in) :: soilswitch
!> Flux to the atmosphere, mol/m**2/s
real(kind=ireals), intent(out) :: Flux_atm

Victor Stepanenko
committed
integer(kind=iintegers), parameter :: water_oxygen_indic = 9

Victor Stepanenko
committed
real(kind=ireals), allocatable :: a(:), b(:), c(:), f(:), y(:)

Victor Stepanenko
committed
real(kind=ireals), save :: Foxyg1 = 0.d0 ! Bottom oxygen flux, mol/(m**2*s)
real(kind=ireals) :: x, xx
real(kind=ireals) :: bcs(1:2)

Victor Stepanenko
committed
real(kind=ireals), save :: botO2 = 0. ! Bottom oxygen concentration, mol/m**3

Victor Stepanenko
committed
integer(kind=iintegers) :: i
integer(kind=iintegers), parameter :: switchbotbc = 1 !1 - Neumann, 2 - Dirichlet
integer(kind=iintegers) :: bctype(1:2)
allocate (a(1:vector_length),b(1:vector_length),c(1:vector_length), &
& f(1:vector_length),y(1:vector_length))
a(:) = 0.; b(:) = 0.; c(:) = 0.; f(:) = 0.; y(:) = 0.
!Foxyg1 = kappa*oxyg(gs%M+1,1)/log(0.25*gsp%ddz(gs%M)*ls%h1/z0_bot) !note: explicit scheme for flux
! 1-st step of splitting-up scheme - diffusion, explicit scheme for flux
x = HENRY_CONST(Henry_const0_o2, Henry_temp_dep_o2, Henry_temp_ref, &
& Twater(1) + Kelvin0)
Flux_atm = - GAS_WATATM_FLUX &

Victor Stepanenko
committed
& (Twater(1),wind10,oxyg(1,1),o2_pres_atm,x,water_oxygen_indic,eps_surf)
bctype(1) = 2
bcs (1) = Flux_atm
! ! Switching bottom b.c.
select case (switchbotbc)
case(1)
bctype(2) = 2
bcs (2) = 0.
bctype(2) = 1
bcs (2) = botO2
! Switching bottom b.c.
select case (switchbotbc)
case(1)
bctype(2) = 2
bcs (2) = Foxyg1
bctype(2) = 1
bcs (2) = botO2
call DIFFUSION(gs%M+1,bctype,bcs,dt,ls%h1,ls%dhw,ls%dhw0, &
& gsp%ddz,gsp%ddz05,gsp%dzeta_int,oxyg(1,1),oxyg(1,2),lamoxyg,&
& lso%water,bathymwater)
if (gs%nsoilcols == 1) then
fbbleflx_o2_sum(0) = febul0*fracb0(3)/fracb0(1)*fbbleflx_o2(0) *bathymwater(1) %area_int
fbbleflx_o2_sum(1:gs%M) = febul0*fracb0(3)/fracb0(1)*fbbleflx_o2(1:gs%M)*bathymwater(1:gs%M)%area_half
fbbleflx_o2_sum(gs%M+1) = febul0*fracb0(3)/fracb0(1)*fbbleflx_o2(gs%M+1)*bathymwater(gs%M+1)%area_int
endif
if (soilswitch == 1) then
! 2-d step of splitting-up scheme - source due to bubble dissolution
!x = dt*febul0*fracb0(3)/fracb0(1)
oxyg(1,2) = oxyg(1,2) + 2.d0*dt/(ls%h1*gsp%ddz(1))*(fbbleflx_o2_sum(1) - fbbleflx_o2_sum(0)) / &
& bathymwater(1)%area_int
do i = 2, gs%M
oxyg(i,2) = oxyg(i,2) + dt/(ls%h1*gsp%ddz05(i-1))*(fbbleflx_o2_sum(i) - fbbleflx_o2_sum(i-1)) / &
& bathymwater(i)%area_int
oxyg(gs%M+1,2) = oxyg(gs%M+1,2) + 2.d0*dt/(ls%h1*gsp%ddz(gs%M)) * &
& (fbbleflx_o2_sum(gs%M+1) - fbbleflx_o2_sum(gs%M)) / &
& bathymwater(gs%M+1)%area_int
oxyg(gs%M+1,2) = max(oxyg(gs%M+1,2),small_value)
endif
! x = oxyg(1,2)*ddz(1)/2.
! x = x + oxyg(M+1,2)*ddz(M)/2.
! do i = 2, M
! x = x + oxyg(i,2)*(ddz(i-1)+ddz(i))/2.
! enddo
endif
deallocate (a, b, c, f, y)
END SUBROUTINE OXYGEN
!> Calculates the rate of oxygen sources and sinks in the water column,
!! generally following Stefan and Fang, Ecological Modelling, 71 (1994) 37-68
!! V.S., 06.2014
SUBROUTINE OXYGEN_PRODCONS(gs,gsp,wst,bathymsoil,gas,area_int,area_half,ddz05, &
& h,dt,Tsoil,Chl_a,dzs,por,oxygsoil, &
& itroph,prodox,resp,bod,sod,sodbot)
use DRIVING_PARAMS, only : soilcolconjtype
& Wm22Em2, short2PAR, z0_bot

Victor Stepanenko
committed
& molmass_o2, &
& k_O2_SOD, mubeta0, kc0, &

Victor Stepanenko
committed
& thetaC_SOD, thetamu_SOD, &
& tortuosity_coef, &
& T0, & ! Reference temperature, Celsius
& T00, & ! Another reference temperature, Celsius
& c1_pmax, c2_pmax, &! Constants for temperature dependence,
! (Stefan and Fang, 1994; Megard et al., 1984)
& k1_c1, k1_c2, & ! (Megard et al., 1984)
& k2_c1, k2_c2, &
& YCHO2, & ! mass ratio of chlorophyll-a to oxygen utilized in respiration
& k_r, & ! day**(-1), (Brown and Barnwell, QUAL2E, 1987; Riley, 1988)
& theta_r, & ! temperature dependence of respiration (Ambrose et al., 1988)
& k_b, & ! day**(-1), 1-st order decay coefficient, (Riley, 1988; Brown and Barnwell, 1987)
& theta_b1, theta_b2, & ! temperature-dependence coefficient for biochemical oxygen demand
& mO2C_dec, mCChla_dec, & ! Stoichiometry constants for organics decay in the water column,
! for BOD, basing on carbonaceous BOD and neglecting
! nitropgenous BOD, see details in Stefan and Fang, 1994
& Sb20, & ! estimates: 0.5E+3 for oligotrophic, 1.5E+3 for eutrophic lakes, Stefan and Fang, 1994,
! mg/(m**2*day), reference sedimentary oxygen demand (SOD)
& theta_s1, theta_s2, &! temperature dependence coefficients for SOD, Stefan and Fang, 1994
& T_md, & ! the temperature of maximal density

Victor Stepanenko
committed
& alpha_POCL, tau_DOC_auto, tau_DOC_allo, tau_POCD, & !constants of Hanson et al. 2004 model
& halfsat_DIP_photosynt !half-saturation constant for soluble reactive phosphorus
!(~dissolved inorganic phosphorus) limitation in photosynthesis rate
use ARRAYS_GRID, only : &
& gridsize_type, gridspacing_type
use ARRAYS_WATERSTATE, only : waterstate_type

Victor Stepanenko
committed
use RADIATION, only : RadWater
use ARRAYS_BATHYM, only : bathym

Victor Stepanenko
committed
use PHYS_FUNC, only : DIFF_WATER_OXYGEN, LOGFLUX
use RADIATION, only : nbands
!> Grid sizes
type(gridsize_type), intent(in) :: gs
!> Grid spacings
type(gridspacing_type), intent(in) :: gsp
!> Water state variables
type(waterstate_type), intent(in) :: wst

Victor Stepanenko
committed
type(bathym), intent(in) :: bathymsoil(1:gs%nsoilcols+1,1:gs%nx,1:gs%ny)
!> Carbon species in water and oxygen
type(gas_type), intent(in) :: gas
!> Lake cross-section area at cell interfaces
real(kind=ireals), intent(in) :: area_int(1:gs%M+1)
!> Lake cross-section area at cell centers
real(kind=ireals), intent(in) :: area_half(1:gs%M)
!> Spacing between cell centers, n/d
real(kind=ireals), intent(in) :: ddz05(0:gs%M)
!> Soil temperature, deg. Celsius
real(kind=ireals), intent(in) :: Tsoil(1:gs%ns,1:gs%nsoilcols)
!> Chlorophyll-a concentration, mg * l**(-1)
real(kind=ireals), intent(in) :: Chl_a(1:gs%M+1)
!> Soil grid spacing, m
real(kind=ireals), intent(in) :: dzs (1:gs%ns)
!> Soil porosity, n/d
real(kind=ireals), intent(in) :: por (1:gs%ns)
!> Mean oxygen concentration in top soil layer
real(kind=ireals), intent(inout) :: oxygsoil (1:gs%nsoilcols)
!> Lake depth, m
real(kind=ireals), intent(in) :: h
!> Timestep, s
real(kind=ireals), intent(in) :: dt
!> Trophic status (1 - oligotrophic, 2 - mesotrophic, 3 - eutrophic)
integer(kind=iintegers), intent(in) :: itroph
!> Production of O2 by photosynthesis
real(kind=ireals), intent(out) :: prodox(1:gs%M+1)
!> Sink due to respiration
real(kind=ireals), intent(out) :: resp(1:gs%M+1)
!> Biochemical oxygen demand
real(kind=ireals), intent(out) :: bod(1:gs%M+1)
!> Sediment oxygen demand (sink)
real(kind=ireals), intent(out) :: sod(1:gs%M+1)
!> Sediment oxygen demand at the bottom, positive downwards
real(kind=ireals), intent(out) :: sodbot

Victor Stepanenko
committed
integer(kind=iintegers), parameter :: nSOD = 2 ! The switch for SOD models
real(4) :: Pmax ! Maximum oxygen production by photosynthesis, h**(-1)
real(4) :: minL ! Light limiting factor for photosynthesis
real(4) :: minN ! Nutrient limiting factor for photosynthesis
real(4) :: PAR ! Photosynthetically active radiation, Einstein /(m*m*h)
real(4) :: BOD_ ! detritus as oxygen equivalent, mg/l

Victor Stepanenko
committed
real(4) :: k1_minL, k2_minL, kc, mubeta, oxysurf
real(kind=ireals) :: x, step10, step20, chla_aver, flux, diff
real(kind=ireals), allocatable :: PARz(:)

Victor Stepanenko
committed
integer(kind=iintegers) :: i, j, k
integer(kind=iintegers), allocatable :: kcompl(:)
if (nSOD == 3) then
allocate (kcompl(1:gs%nsoilcols))

Victor Stepanenko
committed
kcompl(:) = 0
endif
! Calculating mean chlorophyll-a density
if (itroph == 3) then
! Eutrophic lake
chla_aver = chla_aver_eu
elseif (itroph == 2) then
! Mesotrophic lake
chla_aver = chla_aver_meso
elseif (itroph == 1) then
! Oligotrophic lake
chla_aver = chla_aver_oligo
endif
allocate(PARz(0:gs%M+1))
if (nbands > 1) then
PARz(0:gs%M+1) = RadWater%flux(0:gs%M+1,2) !2-d band assumed to be PAR
else
PARz(0:gs%M+1) = RadWater%flux(0:gs%M+1,1)
endif
Pmax = c1_pmax*c2_pmax**(wst%Tw2(i) - T0)
k1_minL = k1_c1*k1_c2**(wst%Tw2(i) - T0)
step10 = STEP(wst%Tw2(i) - T00) ! step function around 10 Celsius
k2_minL = step10*k2_c2 + (1 - step10)*k2_c1
if (i > 1) then
PAR = 0.5*(PARz(i-1) + PARz(i))*Wm22Em2*hour_sec !*short2PAR !converting to Einstein /(m**2*hour)
else
PAR = PARz(0)*Wm22Em2*hour_sec !*short2PAR !converting to Einstein /(m**2*hour)
endif
minL = PAR*(1. + 2.*sqrt(k1_minL/k2_minL)) / (PAR + k1_minL + PAR*PAR/k2_minL)

Victor Stepanenko
committed
!minL = PAR/PAR_prod_max_warm*exp(1. - PAR/PAR_prod_max_warm)
minN = gas%phosph(i)/(halfsat_DIP_photosynt + gas%phosph(i))
prodox(i) = Pmax*minL*minN*Chl_a(i)

Victor Stepanenko
committed
prodox(i) = prodox(i)/(hour_sec*molmass_o2) ! Converting from mg/(l*h) to mol/(m**3*s)
if (carbon_model%par == 1) then ! Stefan and Fang model for respiration and BOD
! Oxygen sink by respiration
resp(i) = 1./YCHO2*k_r*theta_r**(wst%Tw2(i) - T0)*Chl_a(i)

Victor Stepanenko
committed
resp(i) = resp(i)/(day_sec *molmass_o2) ! Converting from mg/(l*day) to mol/(m**3*s)
! Biochemical oxygen demand (BOD)
BOD_ = Chla_aver*mO2C_dec*mCChla_dec ! stoichiometry details see in Stefan and Fang, 1994
step20 = STEP(wst%Tw2(i) - T0) ! step function around 20 Celsius
x = (theta_b1*step20 + theta_b2*(1-step20))*STEP(wst%Tw2(i) - T_md) ! using step function around 4 Celsius
if (x == 0.) then
bod(i) = 0.
else
bod(i) = k_b*x**(wst%Tw2(i) - T0)*BOD_
endif

Victor Stepanenko
committed
bod(i) = bod(i)/(day_sec *molmass_o2) ! --||-- (Converting from mg/(l*day) to mol/(m**3*s))
elseif (carbon_model%par == 2) then !Hanson et al. model for respiration and BOD
resp(i) = alpha_POCL*prodox(i)

Victor Stepanenko
committed
!> @todo{introduce different timescale for degradation of allochtonous DOC}
!Assuming all C atoms escaping POCD and DOC form CO2
bod(i) = (gas%POCD(i)/tau_POCD + & !kg_to_g/molmass_ch2o*

Victor Stepanenko
committed
& gas%DOC(i,1)/tau_DOC_auto + gas%DOC(i,2)/tau_DOC_allo) !Check units!

Victor Stepanenko
committed
select case (nSOD)
case(1) ! The model from Stefan and Fang (1994)
x = step10*theta_s1 + (1 - step10)*theta_s2 !using step function
sod(i) = Sb20*x**(wst%Tw2(i) - T0)/(day_sec *molmass_o2 * 1.E+3)

Victor Stepanenko
committed
case(2) ! The model from Walker and Sondgrass (1986)
kc = kc0*thetaC_SOD**(wst%Tw2(i) - 20.)
mubeta = mubeta0*thetamu_SOD**(wst%Tw2(i) - 25.)
sod(i) = kc*gas%oxyg(i,1) + mubeta*gas%oxyg(i,1)/(k_O2_SOD + gas%oxyg(i,1))

Victor Stepanenko
committed
k = gsp%ksoilcol(i) !The number of soil column intersecting i-th layer
if (kcompl(k) == 0) then !checking if SOD calculated for k-th column
if (soilcolconjtype == 1) then
j = bathymsoil(k,gs%ix,gs%iy)%icent
x = bathymsoil(k,gs%ix,gs%iy)%dzSLc
elseif (soilcolconjtype == 2) then
j = bathymsoil(k,gs%ix,gs%iy)%itop
x = bathymsoil(k,gs%ix,gs%iy)%dzSL
endif

Victor Stepanenko
committed
! Oxygen concentration at the soil surface from soil side
diff = tortuosity_coef*DIFF_WATER_OXYGEN(Tsoil(1,k))
oxysurf = oxygsoil(k) !OXSURF(Tsoil(1,k),0.5*dzs(1),diff,oxygsoil(k))
! Oxygen flux is calculated from logarithmic law
sod(i) = LOGFLUX(sqrt(wst%u2(j)*wst%u2(j) + wst%v2(j)*wst%v2(j)), &
& oxysurf/por(1) - gas%oxyg(j,1), x, z0_bot, z0_bot, 1._ireals, 1)

Victor Stepanenko
committed
! Oxygen concentration is updated to the next time step
call OXYGEN_TOPSOIL(Tsoil(1,k),sod(i),0.5*dzs(1),dt,oxygsoil(k))
kcompl(k) = 1
else
sod(i) = sod(i-1) ! SOD flux is the same for all water layer intesecting the same soil column
endif

Victor Stepanenko
committed
end select
if (i > 1) then
sod(i) = - sod(i) / area_int(i)*(area_half(i) - area_half(i-1)) / &
& (h*ddz05(i-1))
else
sod(i) = - sod(i) / area_int(i)*(area_half(i) - area_int(i)) / &
& (h*ddz05(i-1))
endif

Victor Stepanenko
committed
!sod (:) = sod (:)/(day_sec *molmass_o2 * 1.E+3) ! Converting from mg/(m*m*day) to mol/(m*m*s)
! Sedimentary oxygen demand at the bottom (flux)

Victor Stepanenko
committed
select case (nSOD)
case(1) ! The model from Stefan and Fang (1994)
step10 = STEP(wst%Tw2(gs%M+1) - 10.) ! step function around 10 Celsius

Victor Stepanenko
committed
x = step10*theta_s1 + (1 - step10)*theta_s2 ! using step function
sodbot = Sb20*x**(wst%Tw2(gs%M+1) - T0)/(day_sec *molmass_o2 * 1.E+3) ! Converting from mg/(m*m*day) to mol/(m*m*s)

Victor Stepanenko
committed
case(2) ! The model from Walker and Sondgrass (1986)
kc = kc0*thetaC_SOD**(wst%Tw2(gs%M+1) - 20.)
mubeta = mubeta0*thetamu_SOD**(wst%Tw2(gs%M+1) - 25.)
sodbot = kc*gas%oxyg(gs%M+1,1) + mubeta*gas%oxyg(gs%M+1,1)/(k_O2_SOD + gas%oxyg(gs%M+1,1))
case(3) ! The new SOD model

Victor Stepanenko
committed
diff = tortuosity_coef*DIFF_WATER_OXYGEN(Tsoil(1,gs%nsoilcols))
oxysurf = oxygsoil(gs%nsoilcols) !OXSURF(Tsoil(1,gs%nsoilcols),0.5*dzs(1),diff,oxygsoil(gs%nsoilcols))
sodbot = LOGFLUX(sqrt(wst%u2(gs%M+1)*wst%u2(gs%M+1) + wst%v2(gs%M+1)*wst%v2(gs%M+1)), &
& oxysurf/por(1) - gas%oxyg(gs%M+1,1), 0.25*gsp%ddz(gs%M)*h, z0_bot, z0_bot, 1._ireals, 1)

Victor Stepanenko
committed
call OXYGEN_TOPSOIL(Tsoil(1,gs%nsoilcols),sodbot,0.5*dzs(1),dt,oxygsoil(gs%nsoilcols))

Victor Stepanenko
committed
end select
deallocate(PARz)
END SUBROUTINE OXYGEN_PRODCONS
SUBROUTINE CHLOROPHYLLA(z_full, H_mixed_layer, H_photic_zone, extwat, RadWater, &
& gas, M, Chl_a, itroph)
! This subroutine specifies the chlorophyll profile
& C1_Chla_to_POCLphyto, C2_Chla_to_POCLphyto, &
& PAR_prod_max_warm, halfsat_DIP_photosynt, &

Victor Stepanenko
committed
& molmass_ch2o, Chla_to_extinct, &
& k1_c1, k2_c2
use UNITS , only : m3_to_l
use RADIATION, only : rad_type, nbands
use ARRAYS , only : gas_type
use DRIVING_PARAMS, only : carbon_model
use TIMEVAR, only : hour_sec
use PHYS_CONSTANTS, only : Wm22Em2
implicit none
! Input variables

Victor Stepanenko
committed
real(kind=ireals), intent(in) :: z_full(1:M+1) ! Depth at cell interfaces, m
real(kind=ireals), intent(in) :: H_mixed_layer ! Mixed layer depth, m
real(kind=ireals), intent(in) :: H_photic_zone ! Photic zone depth, m
real(kind=ireals), intent(in) :: extwat ! Extinction coefficient, m**(-1)
type(rad_type) , intent(inout) :: RadWater ! Radiation fluxes in water
type(gas_type) , intent(in) :: gas ! Gases, organic and inorganic species

Victor Stepanenko
committed
integer(kind=iintegers), intent(in) :: M ! Number of grid layers (cells)

Victor Stepanenko
committed
real(kind=ireals), intent(out) :: Chl_a(1:M+1) ! Chlorophyll-a density, mg/l
integer(kind=iintegers), intent(out) :: itroph ! Trophic status
integer(kind=iintegers), save :: chlmodel = 2
real(4) :: depthact
real(4) :: chla_aver
real(kind=iintegers) :: phi_n, phi_l, Chla_to_POCL_phyto, PAR
integer(kind=iintegers) :: i, nb
logical, save :: firstcall = .true.
if (firstcall) then
if (carbon_model%par == 1) chlmodel = 1
endif
select case (chlmodel)
case(1)
! Parameterization following Stefan and Fang (1994) with modifications:
! - no annual cycle
if (extwat > extwat1) then
! Eutrophic lake
chla_aver = chla_aver_eu
itroph = 3
elseif (extwat <= extwat1 .and. extwat > extwat2) then
! Mesotrophic lake
chla_aver = chla_aver_meso
itroph = 2
else
! Oligotrophic lake
chla_aver = chla_aver_oligo
itroph = 1
endif
depthact = max(H_mixed_layer,H_photic_zone)
do i = 1, M+1
Chl_a(i) = chla_aver*STEP(depthact - z_full(i)) ! step function
enddo
case(2)
! Parameterization following Chapra (2008) and
! (Sadeghian et al., Envir.Mod.Soft. 2018)
if (nbands > 1) then
nb = 2
else
nb = 1
endif
do i = 1, M+1
! Optimal PAR for photosynthesis is a reference value for warm period
if (i > 1) then
PAR = 0.5*(RadWater%flux(i-1,nb) + RadWater%flux(i,nb))
else
PAR = RadWater%flux(0,nb)
endif
PAR = PAR*Wm22Em2*hour_sec !convertion to einsten/(m**2*hour), the units of PAR_prod_max_warm

Victor Stepanenko
committed
!phi_l = PAR/PAR_prod_max_warm*exp(1. - PAR/PAR_prod_max_warm)
phi_l = PAR*(1. + 2.*sqrt(k1_c1/k2_c2)) / (PAR + k1_c1 + PAR*PAR/k2_c2)
phi_n = gas%phosph(i)/(halfsat_DIP_photosynt + gas%phosph(i)) !using half-saturation phosphorus for photosynthesis
!>@todo{use here phytoplankton instead of POCL}

Victor Stepanenko
committed
!if (phi_l > 0.5) then
! print*, phi_l, PAR, PAR_prod_max_warm, i
!endif
Chla_to_POCL_phyto = C1_Chla_to_POCLphyto + C2_Chla_to_POCLphyto*phi_n*(1.-phi_l)
!Assuming stoichiometry of POCL that of sugar

Victor Stepanenko
committed
Chl_a(i) = gas%POCL(i)*molmass_ch2o*Chla_to_POCL_phyto
!> @todo{add to extinction CDOC, detritus, pure water value}
!RadWater%extinct(i,nb) = 0.5 + Chla_to_extinct*Chl_a(i)*m3_to_l !1. -- extinction at zero chlorophyll-a
enddo

Victor Stepanenko
committed
!print*, 'Chl_a=', Chl_a
END SUBROUTINE CHLOROPHYLLA
!> Subroutine ADDOXPRODCONS adds to O_2 and CO_2 tendencies associated
!! with organics dynamics in a lake (photosynthesis, respiration,
!! BOD and SOD), and the same for DOC, POCL, POCD

Victor Stepanenko
committed
SUBROUTINE ADDOXPRODCONS(M,i_maxN,H_mixed_layer,H_photic_zone, &
& prodox,resp,bod,sod,RadWater,dt,ls,gas)
use ARRAYS, only : gas_type
use ARRAYS_BATHYM, only : layers_type

Victor Stepanenko
committed
use ARRAYS_GRID, only : gsp
use METH_OXYG_CONSTANTS, only : &

Victor Stepanenko
committed
& alpha_POCL, tau_POCD, tau_DOC_auto, tau_DOC_allo, &
& beta_POCL, tau_Dh_epi, tau_Dh_hypo, &

Victor Stepanenko
committed
& molmass_ch2o, &

Victor Stepanenko
committed
& DOMauto_PtoC, DOMallo_PtoC, POM_PtoC, &
& sedoxid_PtoC, pH, &
& SUVA_305, AQY, UV_weight, PAR_weight
use DRIVING_PARAMS, only : &
& carbon_model

Victor Stepanenko
committed
use PHYS_CONSTANTS, only : Kelvin0
use RADIATION, only : rad_type, nbands, bandbounds
implicit none
! Input variables

Victor Stepanenko
committed
!> Mixed layer depth, m
real(kind=ireals), intent(in) :: H_mixed_layer
!> Photic zone depth, m
real(kind=ireals), intent(in) :: H_photic_zone
!> Production of O2 by photosynthesis, mol/(m**3*s)

Victor Stepanenko
committed
real(kind=ireals), intent(inout) :: prodox(1:M+1)
!> Sink due to respiration, mol/(m**3*s)

Victor Stepanenko
committed
real(kind=ireals), intent(inout) :: resp(1:M+1)
!> Biochemical oxygen demand, mol/(m**3*s)
real(kind=ireals), intent(in) :: bod(1:M+1)
!> Sediment oxygen demand (sink), mol/(m**3*s)
real(kind=ireals), intent(in) :: sod(1:M+1)
!> Radiation fluxes in water and optical properties
type(rad_type) , intent(inout) :: RadWater
!> Time step, s
real(kind=ireals), intent(in) :: dt
!> Number of model layers (cells)
integer(kind=iintegers), intent(in) :: M
!> The computational level of maximal Brunt-Vaisala frequency
integer(kind=iintegers), intent(in) :: i_maxN
!> Physical layers' thicknesses
type(layers_type), intent(in) :: ls
!> Gas concentrations in water, carbon species content
type(gas_type), intent(inout) :: gas
real(kind=ireals) :: x, xx, hact, rad_CDOM, total_DOC
real(kind=ireals) :: E_POCL, D_DOC1, D_DOC2, P_POCL, R_POCL, Dh_POCL, D_POCD, tau_Dh, &
& Pd_DOC

Victor Stepanenko
committed
real(kind=ireals) :: bodcorr(1:M)
integer(kind=iintegers) :: i, nb
do i = 1, M

Victor Stepanenko
committed
!Limitation of photosynthesis by DIC availability
x = min(gas%DIC(i,1)/CO2O2_prod , dt*prodox(i))
!Limitation of photosynthesis by DIP availability
xx = min(gas%phosph(i)/(POM_PtoC*CO2O2_prod), dt*prodox(i))
x = min(x,xx)
gas%DIC(i,1) = gas%DIC(i,1) - x*CO2O2_resp
gas%oxyg(i,1) = gas%oxyg(i,1) + x
prodox(i) = x/dt

Victor Stepanenko
committed
!Limitation of respiration by available oxygen
gas%oxyg(i,1) = gas%oxyg(i,1) - x
gas%DIC(i,1) = gas%DIC(i,1) + x*CO2O2_resp
resp(i) = x/dt

Victor Stepanenko
committed
gas%oxyg(i,1) = gas%oxyg(i,1) - x
gas%DIC(i,1) = gas%DIC(i,1) + x*CO2O2_bod
bodcorr(i) = x/(dt*(bod(i)+small_value))

Victor Stepanenko
committed
gas%oxyg(i,1) = gas%oxyg(i,1) - x
gas%DIC(i,1) = gas%DIC(i,1) + x*CO2O2_sod

Victor Stepanenko
committed
gas%phosph(i) = gas%phosph(i) + x*sedoxid_PtoC
! Hanson et al. model tendencies for carbon species
if (carbon_model%par == 2) then
hact = max(H_mixed_layer,H_photic_zone)
do i = 1, M
! The death timescale assumed to be the same in hypolimion and during ice period

Victor Stepanenko
committed
!if (ls%l1 > 0 .or. i >= i_maxN) then
elseif (gsp%z_full(i) > hact) then
x = gsp%z_full(i) - hact
xx = ls%h1 - hact
tau_Dh = tau_Dh_epi - (tau_Dh_hypo - tau_Dh_epi)* &
& ((x/xx)**2 - 2.*x/xx) !quadratic interpolation with zero derivative at bottom
else
tau_Dh = tau_Dh_epi
endif
!Photodissociation, assuming constant CDOM attenuation coefficient inside CDOC spectrum interval
total_DOC = gas%DOC(i,1) + gas%DOC(i,2)
RadWater%extinct_CDOC(i) = SUVA_305*total_DOC
if (nbands > 1) then
! Summing UV and PAR parts overlapping with CDOM absorbance spectrum,
! assuming linear spectrumn in UV and constant value in PAR regions
rad_CDOM = RadWater%flux(i-1,1)*UV_weight + &
& RadWater%flux(i-1,2)*PAR_weight
else
rad_CDOM = RadWater%flux(i-1,1)
endif
Pd_DOC = rad_CDOM * &
& (1. - exp( - RadWater%extinct_CDOC(i)*gsp%ddz05(i-1)*ls%h1)) / &
& gsp%ddz05(i-1)*ls%h1 * AQY

Victor Stepanenko
committed
!Pd_DOC is subtracted from DOC but not taken into account in other
!equations, as CO is the main product of photodegradation and there is
!no enough evidence to assume it is fully added to DIC and not emitted to the atmosphere
!(Zuo and Jones, Water Research, 1997)
!print*, rad_CDOM, &
!& (1. - exp( - RadWater%extinct_CDOC(i)*gsp%ddz05(i-1)*ls%h1))/ &
!& gsp%ddz05(i-1)*ls%h1, AQY

Victor Stepanenko
committed
P_POCL = prodox(i) !*molmass_ch2o / kg_to_g

Victor Stepanenko
committed
R_POCL = resp(i) !alpha_POCL*P_POCL
E_POCL = beta_POCL*prodox(i) !*P_POCL

Victor Stepanenko
committed
!> @note{ using beta_POCL valid for mass concentrations is not strictly correct
!! for molar concentrations, as E_POCL and P_POCL may have different C-to-mass ratios}

Victor Stepanenko
committed
D_POCD = gas%POCD(i)/tau_POCD*bodcorr(i)

Victor Stepanenko
committed
D_DOC1 = gas%DOC(i,1)/tau_DOC_auto*bodcorr(i)
D_DOC2 = gas%DOC(i,2)/tau_DOC_allo*bodcorr(i)
!print*, (Pd_DOC/(total_DOC+small_value))**(-1)
gas%DOC(i,1) = gas%DOC(i,1) + dt*(E_POCL - D_DOC1 - &
& Pd_DOC*gas%DOC(i,1)/(total_DOC+small_value))
gas%DOC(i,2) = gas%DOC(i,2) + dt*( - D_DOC2 - &
& Pd_DOC*gas%DOC(i,2)/(total_DOC+small_value))
gas%POCL(i) = gas%POCL(i) + dt*(P_POCL - R_POCL - E_POCL - Dh_POCL)
gas%POCD(i) = gas%POCD(i) + dt*(Dh_POCL - D_POCD)

Victor Stepanenko
committed
gas%phosph(i) = gas%phosph(i) + dt*(D_DOC1*DOMauto_PtoC + D_DOC2*DOMallo_PtoC + &
& ( - P_POCL + R_POCL + D_POCD)*POM_PtoC)
END SUBROUTINE ADDOXPRODCONS
SUBROUTINE OXYGEN_TOPSOIL(Tsoil,influx,h,dt,oxygsoil)
!A bulk model for oxygen in top of soil column,
!calculates oxygen concentration in an aerobic top
!soil layer at the next timestep
use METH_OXYG_CONSTANTS, only : &
k_O2_SOD, mubeta0, thetamu_SOD
implicit none
!Input variables
real(kind=ireals), intent(in) :: Tsoil !Temperature of aerobic layer, C
real(kind=ireals), intent(in) :: influx !Oxygen flux from water column, positive downwards
real(kind=ireals), intent(in) :: h !Thickness of top aerobic soil layer, m
real(kind=ireals), intent(in) :: dt !Timestep, s
!Input/output variables
real(kind=ireals), intent(inout) :: oxygsoil !Mean oxygen concentration in the top soil layer
!Local variables
real(kind=ireals) :: mubeta
! Michaelis-Menthen (Monod) oxygen depletion according to Walker and Snodgrass, 1986,
! neglecting "chemical sediment oxygen demand"
mubeta = mubeta0*thetamu_SOD**(Tsoil - 25.)/h

Victor Stepanenko
committed
oxygsoil = (oxygsoil + influx/h*dt)/(1. + dt*mubeta/(k_O2_SOD + oxygsoil))
END SUBROUTINE OXYGEN_TOPSOIL
FUNCTION OXSURF(Tsoil,h,diff,oxmean)
!Calculates surface oxygen concentration from

Victor Stepanenko
committed
!mean concentration in anaerobic layer. Mean is calculated
!from analytical solution of problem for oxygen concentration
!d^2 C/d^2 z - alpha*C=0 with Dirichlet b.c.s
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
use METH_OXYG_CONSTANTS, only : &
k_O2_SOD, mubeta0, thetamu_SOD
implicit none
!Input variables
real(kind=ireals), intent(in) :: Tsoil !Temperature of aerobic layer, C
real(kind=ireals), intent(in) :: h !Thickness of anaerobic layer, m
real(kind=ireals), intent(in) :: diff !Oxygen diffusivity in anaerobic layer
real(kind=ireals), intent(in) :: oxmean !Mean oxygen concentration in anaerobic layer
!Output variables
real(kind=ireals) :: OXSURF
!Local variables
real(kind=ireals) :: alpha, mubeta
mubeta = mubeta0*thetamu_SOD**(Tsoil - 25.)/h
alpha = sqrt(mubeta/(k_O2_SOD*diff))
OXSURF = oxmean*alpha*h*(exp(alpha*h) + 1)/(exp(alpha*h) - 1.)
END FUNCTION OXSURF