From ead9d13c6cbe75ca3f8c1f70dc17f421b40180f0 Mon Sep 17 00:00:00 2001 From: "Hernan G. Arango" Date: Sat, 14 Dec 2024 20:20:01 -0500 Subject: [PATCH] Added IOP-based ecosystem model --- ROMS/Adjoint/Biology/ad_biology.F | 2 + ROMS/Adjoint/Biology/ad_iop_cdom.h | 634 ++++++++++++++++ ROMS/External/iop_cdom.in | 434 +++++++++++ ROMS/External/npzd_iop.in | 565 ++++++++++++++ ROMS/External/varinfo.yaml | 699 ++++++++++++++++++ ROMS/Functionals/ana_biology.h | 32 + ROMS/Include/cppdefs.h | 5 + ROMS/Include/globaldefs.h | 2 + ROMS/Modules/mod_biology.F | 18 + ROMS/Modules/mod_ncparam.F | 4 + ROMS/Nonlinear/Biology/biology.F | 18 + ROMS/Nonlinear/Biology/iop_cdom.h | 310 ++++++++ ROMS/Nonlinear/Biology/iop_cdom_def.h | 53 ++ ROMS/Nonlinear/Biology/iop_cdom_def_pio.h | 53 ++ ROMS/Nonlinear/Biology/iop_cdom_inp.h | 712 ++++++++++++++++++ ROMS/Nonlinear/Biology/iop_cdom_mod.h | 132 ++++ ROMS/Nonlinear/Biology/iop_cdom_var.h | 74 ++ ROMS/Nonlinear/Biology/iop_cdom_wrt.h | 41 ++ ROMS/Nonlinear/Biology/iop_cdom_wrt_pio.h | 41 ++ ROMS/Nonlinear/Biology/npzd_iop.h | 671 +++++++++++++++++ ROMS/Nonlinear/Biology/npzd_iop_def.h | 144 ++++ ROMS/Nonlinear/Biology/npzd_iop_def_pio.h | 144 ++++ ROMS/Nonlinear/Biology/npzd_iop_inp.h | 859 ++++++++++++++++++++++ ROMS/Nonlinear/Biology/npzd_iop_mod.h | 212 ++++++ ROMS/Nonlinear/Biology/npzd_iop_var.h | 179 +++++ ROMS/Nonlinear/Biology/npzd_iop_wrt.h | 96 +++ ROMS/Nonlinear/Biology/npzd_iop_wrt_pio.h | 96 +++ ROMS/Representer/Biology/rp_biology.F | 2 + ROMS/Representer/Biology/rp_iop_cdom.h | 404 ++++++++++ ROMS/Tangent/Biology/tl_biology.F | 2 + ROMS/Tangent/Biology/tl_iop_cdom.h | 374 ++++++++++ ROMS/Utility/checkdefs.F | 16 + ROMS/Utility/def_info.F | 8 + ROMS/Utility/read_biopar.F | 4 + ROMS/Utility/wrt_info.F | 8 + User/External/iop_cdom.in | 307 ++++++++ User/External/npzd_iop.in | 417 +++++++++++ User/Functionals/ana_biology.h | 32 + 38 files changed, 7804 insertions(+) create mode 100644 ROMS/Adjoint/Biology/ad_iop_cdom.h create mode 100644 ROMS/External/iop_cdom.in create mode 100644 ROMS/External/npzd_iop.in create mode 100644 ROMS/Nonlinear/Biology/iop_cdom.h create mode 100644 ROMS/Nonlinear/Biology/iop_cdom_def.h create mode 100644 ROMS/Nonlinear/Biology/iop_cdom_def_pio.h create mode 100644 ROMS/Nonlinear/Biology/iop_cdom_inp.h create mode 100644 ROMS/Nonlinear/Biology/iop_cdom_mod.h create mode 100644 ROMS/Nonlinear/Biology/iop_cdom_var.h create mode 100644 ROMS/Nonlinear/Biology/iop_cdom_wrt.h create mode 100644 ROMS/Nonlinear/Biology/iop_cdom_wrt_pio.h create mode 100644 ROMS/Nonlinear/Biology/npzd_iop.h create mode 100644 ROMS/Nonlinear/Biology/npzd_iop_def.h create mode 100644 ROMS/Nonlinear/Biology/npzd_iop_def_pio.h create mode 100644 ROMS/Nonlinear/Biology/npzd_iop_inp.h create mode 100644 ROMS/Nonlinear/Biology/npzd_iop_mod.h create mode 100644 ROMS/Nonlinear/Biology/npzd_iop_var.h create mode 100644 ROMS/Nonlinear/Biology/npzd_iop_wrt.h create mode 100644 ROMS/Nonlinear/Biology/npzd_iop_wrt_pio.h create mode 100644 ROMS/Representer/Biology/rp_iop_cdom.h create mode 100644 ROMS/Tangent/Biology/tl_iop_cdom.h create mode 100644 User/External/iop_cdom.in create mode 100644 User/External/npzd_iop.in diff --git a/ROMS/Adjoint/Biology/ad_biology.F b/ROMS/Adjoint/Biology/ad_biology.F index 6338dfde..29870ac5 100644 --- a/ROMS/Adjoint/Biology/ad_biology.F +++ b/ROMS/Adjoint/Biology/ad_biology.F @@ -13,6 +13,8 @@ # if defined BIO_FENNEL !!# include +# elif defined IOP_CDOM +# include # elif defined NEMURO !!# include # elif defined NPZD_FRANKS diff --git a/ROMS/Adjoint/Biology/ad_iop_cdom.h b/ROMS/Adjoint/Biology/ad_iop_cdom.h new file mode 100644 index 00000000..8d9bccb2 --- /dev/null +++ b/ROMS/Adjoint/Biology/ad_iop_cdom.h @@ -0,0 +1,634 @@ + SUBROUTINE ad_biology (ng,tile) +! +!git $Id$ +!************************************************** Hernan G. Arango *** +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!*********************************************************************** +! ! +! IOP-based, CDOM (Colored Dissolved Organic Matter) Model ! +! ! +! This routine computes the biological sources and sinks and adds ! +! then the global biological fields. ! +! ! +! It computes the absorption, scattering, and backscattering from ! +! the ecosystem variables. This facilitates direct comparisons ! +! between measuared and models IOPs (Inherent Optical Properties). ! +! It also possible to calculate remote sensing reflectances from ! +! model output for direct comparisons with remotely sensed ocean ! +! color (SeaWIFS, MODIS, etc) and data assimilation. ! +! ! +! Reference: ! +! ! +! Fennel, K., ... ! +! ! +!*********************************************************************** +! + USE mod_param + USE mod_forces + USE mod_grid + USE mod_ncparam + USE mod_ocean + USE mod_stepping +! +! Imported variable declarations. +! + integer, intent(in) :: ng, tile +! +! Local variable declarations. +! +#include "tile.h" +! +! Set header file name. +! +#ifdef DISTRIBUTE + IF (Lbiofile(iADM)) THEN +#else + IF (Lbiofile(iADM).and.(tile.eq.0)) THEN +#endif + Lbiofile(iADM)=.FALSE. + BIONAME(iADM)=__FILE__ + END IF +! +#ifdef PROFILE + CALL wclock_on (ng, iADM, 15) +#endif + CALL ad_biology_tile (ng, tile, & + & LBi, UBi, LBj, UBj, N(ng), NT(ng), & + & IminS, ImaxS, JminS, JmaxS, & + & nstp(ng), nnew(ng), & +#ifdef MASKING + & GRID(ng) % rmask, & +#endif + & GRID(ng) % Hz, & + & GRID(ng) % ad_Hz, & + & GRID(ng) % z_w, & + & GRID(ng) % ad_z_w, & + & FORCES(ng) % srflx, & + & FORCES(ng) % ad_srflx, & + & OCEAN(ng) % t, & + & OCEAN(ng) % ad_t) + +#ifdef PROFILE + CALL wclock_off (ng, iADM, 15) +#endif + + RETURN + END SUBROUTINE ad_biology +! +!----------------------------------------------------------------------- + SUBROUTINE ad_biology_tile (ng, tile, & + & LBi, UBi, LBj, UBj, UBk, UBt, & + & IminS, ImaxS, JminS, JmaxS, & + & nstp, nnew, & +#ifdef MASKING + & rmask, & +#endif + & Hz, ad_Hz, & + & z_w, ad_z_w, & + & srflx, ad_srflx, & + & t, ad_t) +!----------------------------------------------------------------------- +! + USE mod_param + USE mod_biology + USE mod_ncparam + USE mod_scalars +! +! Imported variable declarations. +! + integer, intent(in) :: ng, tile + integer, intent(in) :: LBi, UBi, LBj, UBj, UBk, UBt + integer, intent(in) :: IminS, ImaxS, JminS, JmaxS + integer, intent(in) :: nstp, nnew + +#ifdef ASSUMED_SHAPE +# ifdef MASKING + real(r8), intent(in) :: rmask(LBi:,LBj:) +# endif + real(r8), intent(in) :: Hz(LBi:,LBj:,:) + real(r8), intent(in) :: z_w(LBi:,LBj:,0:) + real(r8), intent(in) :: srflx(LBi:,LBj:) + real(r8), intent(in) :: t(LBi:,LBj:,:,:,:) + + real(r8), intent(inout) :: ad_Hz(LBi:,LBj:,:) + real(r8), intent(inout) :: ad_z_w(LBi:,LBj:,0:) + real(r8), intent(inout) :: ad_srflx(LBi:,LBj:) + real(r8), intent(inout) :: ad_t(LBi:,LBj:,:,:,:) +#else +# ifdef MASKING + real(r8), intent(in) :: rmask(LBi:UBi,LBj:UBj) +# endif + real(r8), intent(in) :: Hz(LBi:UBi,LBj:UBj,UBk) + real(r8), intent(in) :: z_w(LBi:UBi,LBj:UBj,0:UBk) + real(r8), intent(in) :: srflx(LBi:UBi,LBj:UBj) + real(r8), intent(in) :: t(LBi:UBi,LBj:UBj,UBk,3,UBt) + + real(r8), intent(inout) :: ad_Hz(LBi:UBi,LBj:UBj,UBk) + real(r8), intent(inout) :: ad_z_w(LBi:UBi,LBj:UBj,0:UBk) + real(r8), intent(inout) :: ad_srflx(LBi:UBi,LBj:UBj) + real(r8), intent(inout) :: ad_t(LBi:UBi,LBj:UBj,UBk,3,UBt) +#endif +! +! Local variable declarations. +! + integer :: Iter, i, ibio, itrc, j, k, kk, nb + integer :: Iteradj + + real(r8) :: Att, ExpAtt, Itop, PAR, PAR1 + real(r8) :: ad_Att, ad_ExpAtt, ad_Itop, ad_PAR + real(r8) :: cff, cff1, dtdays + real(r8) :: ad_cff + real(r8) :: adfac, adfac1 + + real(r8), dimension(IminS:ImaxS) :: PARsur + real(r8), dimension(IminS:ImaxS) :: ad_PARsur + + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio1 + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio_old + + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: ad_Bio + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: ad_Bio_old + + real(r8), dimension(IminS:ImaxS,N(ng)) :: Hz_inv + real(r8), dimension(IminS:ImaxS,N(ng)) :: Light + + real(r8), dimension(IminS:ImaxS,N(ng)) :: ad_Hz_inv + real(r8), dimension(IminS:ImaxS,N(ng)) :: ad_Light + +#include "set_bounds.h" +! +!----------------------------------------------------------------------- +! Add biological Source/Sink terms. +!----------------------------------------------------------------------- +! +! Set time-stepping size (days) according to the number of iterations. +! + dtdays=dt(ng)*sec2day/REAL(BioIter(ng),r8) +! +! Initialize private scratch variables and array. +! + ad_PAR=0.0_r8 + ad_Att=0.0_r8 + ad_ExpAtt=0.0_r8 + ad_Itop=0.0_r8 + ad_cff=0.0_r8 +! + DO k=1,N(ng) + DO i=IminS,ImaxS + ad_Hz_inv(i,k)=0.0_r8 + ad_Light(i,k)=0.0_r8 + END DO + END DO + DO i=IminS,ImaxS + ad_PARsur(i)=0.0_r8 + END DO + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,ibio)=0.0_r8 + Bio1(i,k,ibio)=0.0_r8 + ad_Bio(i,k,ibio)=0.0_r8 + ad_Bio_old(i,k,ibio)=0.0_r8 + END DO + END DO + END DO +! +! Start pipelined J-loop. +! + J_LOOP : DO j=Jstr,Jend +! +! Compute inverse thickness to avoid repeated divisions. +! + DO k=1,N(ng) + DO i=Istr,Iend + Hz_inv(i,k)=1.0_r8/Hz(i,j,k) + END DO + END DO +! +! Compute the required basic state arrays. +! +! Extract biological variables from tracer arrays, place them into +! scratch arrays, and restrict their values to be positive definite. +! At input, all tracers (index nnew) from predictor step have +! transport units (m Tunits) since we do not have yet the new +! values for zeta and Hz. These are known after the 2D barotropic +! time-stepping. +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,ibio)=MAX(0.0_r8,t(i,j,k,nstp,ibio)) + Bio_old(i,k,ibio)=Bio(i,k,ibio) + END DO + END DO + END DO +! +! Calculate surface Photosynthetically Available Radiation (PAR). The +! net shortwave radiation is scaled back to Watts/m2 and multiplied by +! the fraction that is photosynthetically available, PARfrac. +! + DO i=Istr,Iend + PARsur(i)=PARfrac(ng)*srflx(i,j)*rho0*Cp + END DO +! +!======================================================================= +! Start internal iterations to achieve convergence of the nonlinear +! backward-implicit solution. +!======================================================================= +! +! During the iterative procedure a series of fractional time steps are +! performed in a chained mode (splitting by different biological +! conversion processes) in sequence of the main food chain. In all +! stages the concentration of the component being consumed is treated +! in a fully implicit manner, so the algorithm guarantees non-negative +! values, no matter how strong the concentration of active consuming +! component (Phytoplankton or Zooplankton). The overall algorithm, +! as well as any stage of it, is formulated in conservative form +! (except explicit sinking) in sense that the sum of concentration of +! all components is conserved. +! +! In the implicit algorithm, we have for example (N: nutrient, +! P: phytoplankton), +! +! N(new) = N(old) - uptake * P(old) uptake = mu * N / (Kn + N) +! {Michaelis-Menten} +! below, we set +! The N in the numerator of +! cff = mu * P(old) / (Kn + N(old)) uptake is treated implicitly +! as N(new) +! +! so the time-stepping of the equations becomes: +! +! N(new) = N(old) / (1 + cff) (1) when substracting a sink term, +! consuming, divide by (1 + cff) +! and +! +! P(new) = P(old) + cff * N(new) (2) when adding a source term, +! growing, add (cff * source) +! +! Notice that if you substitute (1) in (2), you will get: +! +! P(new) = P(old) + cff * N(old) / (1 + cff) (3) +! +! If you add (1) and (3), you get +! +! N(new) + P(new) = N(old) + P(old) +! +! implying conservation regardless how "cff" is computed. Therefore, +! this scheme is unconditionally stable regardless of the conversion +! rate. It does not generate negative values since the constituent +! to be consumed is always treated implicitly. It is also biased +! toward damping oscillations. +! +! The iterative loop below is to iterate toward an universal Backward- +! Euler treatment of all terms. So if there are oscillations in the +! system, they are only physical oscillations. These iterations, +! however, do not improve the accuaracy of the solution. +! + ITER_LOOP: DO Iter=1,BioIter(ng) +! +! Compute light attenuation as function of depth. +! + DO i=Istr,Iend + PAR=PARsur(i) + IF (PARsur(i).gt.0.0_r8) THEN ! day time + DO k=N(ng),1,-1 +! +! Attenuate the light to the center of the grid cell. Here, AttSW is +! the light attenuation due to seawater. +! + Att=(AttSW(ng)+ & + & CDOM_LightAtt(ng)*Bio(i,k,aCDOM(i440n)))* & + & (z_w(i,j,k)-z_w(i,j,k-1)) + ExpAtt=EXP(-Att) + Itop=PAR + PAR=Itop*(1.0_r8-ExpAtt)/Att ! average at cell center + Light(i,k)=PAR +! +! Light attenuation at the bottom of the grid cell. It is the starting +! PAR value for the next (deeper) vertical grid cell. +! + PAR=Itop*ExpAtt + END DO + ELSE ! night time + DO k=1,N(ng) + Light(i,k)=0.0_r8 + END DO + END IF + END DO +! +! Degradation of CDOM absorption, aCDOM. +! + cff1=dtdays*CDOM_sigma(ng) + DO k=1,N(ng) + DO i=Istr,Iend + cff=cff1*Light(i,k) + DO nb=1,NBands + Bio(i,k,aCDOM(nb))=Bio(i,k,aCDOM(nb))/(1.0_r8+cff) + END DO + END DO + END DO + + END DO ITER_LOOP +! +!----------------------------------------------------------------------- +! Adjoint of update global tracer variables: Add increment due to BGC +! processes to tracer array in time index "nnew". Index "nnew" is +! solution after advection and mixing and has transport units +! (m Tunits) hence the increment is multiplied by Hz. Notice that +! we need to subtract original values "Bio_old" at the top of the +! routine to just account for the concentractions affected by BGC +! processes. This also takes into account any constraints +! (non-negative concentrations, carbon concentration range) specified +! before entering BGC kernel. If "Bio" were unchanged by BGC +! processes, the increment would be exactly zero. Notice that final +! tracer values, t(:,:,:,nnew,:) are not bounded >=0 so that we can +! preserve total inventory of nutrients when advection causes tracer +! concentration to go negative. +!----------------------------------------------------------------------- +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + cff=Bio(i,k,ibio)-Bio_old(i,k,ibio) +!^ tl_t(i,j,k,nnew,ibio)=tl_t(i,j,k,nnew,ibio)+ & +!^ & tl_cff*Hz(i,j,k)+cff*tl_Hz(i,j,k) +!^ + ad_Hz(i,j,k)=ad_Hz(i,j,k)+cff*ad_t(i,j,k,nnew,ibio) + ad_cff=add_cff+Hz(i,j,k)*ad_t(i,j,k,nnew,ibio) +!^ tl_cff=tl_Bio(i,k,ibio)-tl_Bio_old(i,k,ibio) +!^ + ad_Bio_old(i,k,ibio)=ad_Bio_old(i,k,ibio)-ad_cff + ad_Bio(i,k,ibio)=ad_Bio(i,k,ibio)+ad_cff + ad_cff=0.0_r8 + END DO + END DO + END DO +! +!======================================================================= +! Start internal iterations to achieve convergence of the nonlinear +! backward-implicit solution. +!======================================================================= +! + ITER_LOOP1: DO Iter=BioIter(ng),1,-1 +! +! Compute appropriate basic state arrays. +! +! +! Extract biological variables from tracer arrays, place them into +! scratch arrays, and restrict their values to be positive definite. +! At input, all tracers (index nnew) from predictor step have +! transport units (m Tunits) since we do not have yet the new +! values for zeta and Hz. These are known after the 2D barotropic +! time-stepping. +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,ibio)=MAX(0.0_r8,t(i,j,k,nstp,ibio)) + Bio_old(i,k,ibio)=Bio(i,k,ibio) + END DO + END DO + END DO +! +! Calculate surface Photosynthetically Available Radiation (PAR). The +! net shortwave radiation is scaled back to Watts/m2 and multiplied by +! the fraction that is photosynthetically available, PARfrac. +! + DO i=Istr,Iend + PARsur(i)=PARfrac(ng)*srflx(i,j)*rho0*Cp + END DO +! +!======================================================================= +! Start internal iterations to achieve convergence of the nonlinear +! backward-implicit solution. +!======================================================================= +! + DO Iteradj=1,Iter +! +! Compute light attenuation as function of depth. +! + DO i=Istr,Iend + PAR=PARsur(i) + IF (PARsur(i).gt.0.0_r8) THEN ! day time + DO k=N(ng),1,-1 +! +! Attenuate the light to the center of the grid cell. Here, AttSW is +! the light attenuation due to seawater. +! + Att=(AttSW(ng)+ & + & CDOM_LightAtt(ng)*Bio(i,k,aCDOM(i440n)))* & + & (z_w(i,j,k)-z_w(i,j,k-1)) + ExpAtt=EXP(-Att) + Itop=PAR + PAR=Itop*(1.0_r8-ExpAtt)/Att ! average at cell center + Light(i,k)=PAR +! +! Light attenuation at the bottom of the grid cell. It is the starting +! PAR value for the next (deeper) vertical grid cell. +! + PAR=Itop*ExpAtt + END DO + ELSE ! night time + DO k=1,N(ng) + Light(i,k)=0.0_r8 + END DO + END IF + END DO +! +! Degradation of CDOM absorption, aCDOM. +! + cff1=dtdays*CDOM_sigma(ng) + DO k=1,N(ng) + DO i=Istr,Iend + cff=cff1*Light(i,k) + DO nb=1,NBands + Bio1(i,k,aCDOM(nb))=Bio(i,k,aCDOM(nb)) + Bio(i,k,aCDOM(nb))=Bio(i,k,aCDOM(nb))/(1.0_r8+cff) + END DO + END DO + END DO + END DO +! +! End of compute basic state arrays. +! +! Adjoint of degradation of CDOM absorption, aCDOM. +! + cff1=dtdays*CDOM_sigma(ng) + DO k=1,N(ng) + DO i=Istr,Iend + cff=cff1*Light(i,k) + DO nb=1,NBands +!^ tl_Bio(i,k,aCDOM(nb))=(tl_Bio(i,k,aCDOM(nb))- & +!^ & tl_cff*Bio(i,k,aCDOM(nb)))/ & +!^ & (1.0_r8+cff) +!^ + adfac=ad_Bio(i,k,aCDOM(nb))/(1.0_r8+cff) + ad_cff=ad_cff-Bio(i,k,aCDOM(nb))*adfac + ad_Bio(i,k,aCDOM(nb))=adfac + END DO +!^ tl_cff=cff1*tl_Light(i,k) +!^ + ad_Light(i,k)=ad_Light(i,k)+cff1*ad_cff + ad_cff=0.0_r8 + END DO + END DO +! +! Compute adjoint light attenuation as function of depth. +! + DO i=Istr,Iend + PAR=PARsur(i) + IF (PARsur(i).gt.0.0_r8) THEN ! day time + DO k=1,N(ng) +! +! Compute the basic state PAR appropriate for each level. +! + PAR=PARsur(i) + DO kk=N(ng),k,-1 +! +! Compute average light attenuation for each grid cell. Here, AttSW is +! the light attenuation due to seawater and AttPhy is the attenuation +! due to phytoplankton (self-shading coefficient). +! + Att=(AttSW(ng)+ & + & CDOM_LightAtt(ng)*Bio1(i,kk,aCDOM(i440n)))* & + & (z_w(i,j,kk)-z_w(i,j,kk-1)) + ExpAtt=EXP(-Att) + Itop=PAR + PAR=Itop*(1.0_r8-ExpAtt)/Att ! average at center + PAR1=PAR +! +! Light attenuation at the bottom of the grid cell. It is the starting +! PAR value for the next (deeper) vertical grid cell. +! + PAR=Itop*ExpAtt + END DO +! +! Adjoint of light attenuation at the bottom of the grid cell. It is +! the starting PAR value for the next (deeper) vertical grid cell. +! +!^ tl_PAR=tl_Itop*ExpAtt+Itop*tl_ExpAtt +!^ + ad_ExpAtt=ad_ExpAtt+Itop*ad_PAR + ad_Itop=ad_Itop+ExpAtt*ad_PAR + ad_PAR=0.0_r8 +! +! Adjoint of compute average light attenuation for each grid cell. +! Here, AttSW is the light attenuation due to seawater and AttPhy is +! the attenuation due to phytoplankton (self-shading coefficient). +! +!^ tl_Light(i,k)=tl_PAR +!^ + ad_PAR=ad_PAR+ad_Light(i,k) + ad_Light(i,k)=0.0_r8 +!^ tl_PAR=(-tl_Att*PAR1+tl_Itop*(1.0_r8-ExpAtt)- & +!^ & Itop*tl_ExpAtt)/Att +!^ + adfac=ad_PAR/Att + ad_Att=ad_Att-PAR1*adfac + ad_ExpAtt=ad_ExpAtt-Itop*adfac + ad_Itop=ad_Itop+(1.0_r8-ExpAtt)*adfac + ad_PAR=0.0_r8 +!^ tl_Itop=tl_PAR +!^ + ad_PAR=ad_PAR+ad_Itop + ad_Itop=0.0_r8 +!^ tl_ExpAtt=-ExpAtt*tl_Att +!^ + ad_Att=ad_Att-ExpAtt*ad_ExpAtt + ad_ExpAtt=0.0_r8 +!^ tl_Att=CDOM_LightAtt(ng)*tl_Bio(i,k,aCDOM(i440n))* & +!^ & (z_w(i,j,k)-z_w(i,j,k-1))+ & +!^ & (AttSW(ng)+ & +!^ & CDOM_LightAtt(ng)*Bio1(i,k,aCDOM(i440n)))* & +!^ & (tl_z_w(i,j,k)-tl_z_w(i,j,k-1)) +!^ + adfac=(AttSW(ng)+ & + & CDOM_LightAtt(ng)*Bio1(i,k,aCDOM(i440n)))* & + & ad_Att + ad_Bio(i,k,aCDOM(i440n))=ad_Bio(i,k,aCDOM(i440n))+ & + & CDOM_LightAtt(ng)* & + & (z_w(i,j,k)-z_w(i,j,k-1))* & + & ad_Att + ad_z_w(i,j,k-1)=ad_z_w(i,j,k-1)-adfac + ad_z_w(i,j,k )=ad_z_w(i,j,k )+adfac + ad_Att=0.0_r8 + END DO + ELSE ! night time + DO k=1,N(ng) +!^ tl_Light(i,k)=0.0_r8 +!^ + ad_Light(i,k)=0.0_r8 + END DO + END IF +!^ tl_PAR=tl_PARsur(i) +!^ + ad_PARsur(i)=ad_PARsur(i)+ad_PAR + ad_PAR=0.0_r8 + END DO + + END DO ITER_LOOP1 +! +! Calculate adjoint surface Photosynthetically Available Radiation +! (PAR). The net shortwave radiation is scaled back to Watts/m2 +! and multiplied by the fraction that is photosynthetically +! available, PARfrac. +! + DO i=Istr,Iend +!^ tl_PARsur(i)=(tl_PARfrac(ng)*srflx(i,j)+ & +!^ & PARfrac(ng)*tl_srflx(i,j))*rho0*Cp +!^ + adfac=rho0*Cp*ad_PARsur(i) + ad_srflx(i,j)=ad_srflx(i,j)+PARfrac(ng)*adfac + ad_PARfrac(ng)=ad_PARfrac(ng)+srflx(i,j)*adfac + ad_PARsur(i)=0.0_r8 + END DO +! +! Extract biological variables from tracer arrays, place them into +! scratch arrays, and restrict their values to be positive definite. +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend +!^ tl_Bio_old(i,k,ibio)=tl_Bio(i,k,ibio) +!^ + ad_Bio(i,k,ibio)=ad_Bio(i,k,ibio)+ & + & ad_Bio_old(i,k,ibio) + ad_Bio_old(i,k,ibio)=0.0_r8 +!^ tl_Bio(i,k,ibio)=(0.5_r8- & +!^ & SIGN(0.5_r8,-t(i,j,k,nstp,ibio)))* & +!^ & tl_t(i,j,k,nstp,ibio) +!^ + ad_t(i,j,k,nstp,ibio)=ad_t(i,j,k,nstp,ibio)+ & + & (0.5_r8- & + & SIGN(0.5_r8,-t(i,j,k,nstp,ibio)))* & + & ad_Bio(i,k,ibio) + ad_Bio(i,k,ibio)=0.0_r8 + END DO + END DO + END DO +! +! Adjoint inverse thickness to avoid repeated divisions. +! + DO k=1,N(ng) + DO i=Istr,Iend +!^ tl_Hz_inv(i,k)=-Hz_inv(i,k)*Hz_inv(i,k)*tl_Hz(i,j,k) +!^ + ad_Hz(i,j,k)=ad_Hz(i,j,k)- & + & Hz_inv(i,k)*Hz_inv(i,k)*ad_Hz_inv(i,k) + ad_Hz_inv(i,k)=0.0_r8 + END DO + END DO + + END DO J_LOOP + + RETURN + END SUBROUTINE ad_biology_tile diff --git a/ROMS/External/iop_cdom.in b/ROMS/External/iop_cdom.in new file mode 100644 index 00000000..6d4c7f37 --- /dev/null +++ b/ROMS/External/iop_cdom.in @@ -0,0 +1,434 @@ +! IOP-based, CDOM Ecosystem Model Parameters. +! +!git $Id$ +!========================================================= Hernan G. Arango === +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!============================================================================== +! ! +! Input parameters can be entered in ANY order, provided that the parameter ! +! KEYWORD (usually, upper case) is typed correctly followed by "=" or "==" ! +! symbols. Any comment lines are allowed and must begin with an exclamation ! +! mark (!) in column one. Comments may appear to the right of a parameter ! +! specification to improve documentation. Comments will be ignored during ! +! reading. Blank lines are also allowed and ignored. Continuation lines in ! +! a parameter specification are allowed and must be preceded by a backslash ! +! (\). In some instances, more than one value is required for a parameter. ! +! If fewer values are provided, the last value is assigned for the entire ! +! parameter array. The multiplication symbol (*), without blank spaces in ! +! between, is allowed for a parameter specification. For example, in a two ! +! grids nested application: ! +! ! +! AKT_BAK == 2*1.0d-6 2*5.0d-6 ! m2/s ! +! ! +! indicates that the first two entries of array AKT_BAK, in fortran column- ! +! major order, will have the same value of "1.0d-6" for grid 1, whereas the ! +! next two entries will have the same value of "5.0d-6" for grid 2. ! +! ! +! In multiple levels of nesting and/or multiple connected domains step-ups, ! +! "Ngrids" entries are expected for some of these parameters. In such case, ! +! the order of the entries for a parameter is extremely important. It must ! +! follow the same order (1:Ngrids) as in the state variable declaration. The ! +! USER may follow the above guidelines for specifying his/her values. These ! +! parameters are marked by "==" plural symbol after the KEYWORD. ! +! ! +!============================================================================== +! +! NOTICE: Input parameter units are specified within brackets and default +! ****** values are specified within braces. +! +! Switch to control the computation of biology within nested and/or multiple +! connected grids. + + Lbiology == T + +! Maximum number of iterations to achieve convergence of the nonlinear +! solution. + + BioIter == 1 + +! Initial concentration for analytical uniform initial conditions for +! aCDOM (Colored Dissolved Organic Matter aborption) [1/meter]. + +BioIni(i440n) == 1.0d0 ! aCDOM at 440nm +BioIni(i510n) == 1.0d0 ! aCDOM at 510nm + +! Fraction of shortwave radiation that is photosynthetically active +! (nondimensional), {0.43d0}. + + PARfrac == 0.43d0 + +! Light attenuation due to seawater [1/m], {0.04d0}. + + AttSW == 0.04d0 + +! Light attenuation factor due to CDOM absorption [nondimensional]. + +CDOM_LightAtt == 0.8d0 + +! Light-dependent degradation rate for CDOM absorption [1/(Watt m-2 day)]. + + CDOM_sigma == 0.0005d0 + +! Harmonic/biharmonic horizontal diffusion of biological tracer for +! nonlinear model and adjoint-based algorithms: [1:NBT,Ngrids]. + + TNU2 == 20.0d0 20.0d0 ! m2/s + TNU4 == 2.0d+8 2.0d+8 ! m4/s + + ad_TNU2 == 20.0d0 20.0d0 ! m2/s + ad_TNU4 == 2.0d+8 2.0d+8 ! m4/s + +! Vertical mixing coefficients for biological tracers for nonlinear +! model and basic state scale factor in adjoint-based algorithms: +! [1:NBT,Ngrids]. + + AKT_BAK == 2*5.0d-6 ! m2/s + + ad_AKT_fac == 2*1.0d0 ! nondimensional + +! Nudging/relaxation time scales, inverse scales will be computed +! internally: [1:NBT,Ngrids]. + + TNUDG == 2*0.5d0 ! days + +! Set lateral boundary conditions keyword. Notice that a value is expected +! for each boundary segment per nested grid for each state variable. +! +! The biological tracer variables require [1:4,1:NBT,Ngrids] values. The +! boundary order is: 1=west, 2=south, 3=east, and 4=north. That is, +! anticlockwise starting at the western boundary. +! +! The keyword is case insensitive and usually has three characters. However, +! it is possible to have compound keywords, if applicable. For example, the +! keyword "RadNud" implies radiation boundary condition with nudging. This +! combination is usually used in active/passive radiation conditions. +! +! NOTICE: It is possible to specify the lateral boundary conditions for +! ====== all biological tracers in a compact form with a single entry. +! If so, all the biological tracers are assumed to have the same boundary +! condition as in the single entry. +! +! Keyword Lateral Boundary Condition Type +! +! Cla Clamped _____N_____ j=Mm +! Clo Closed | 4 | +! Gra Gradient | | +! Nes Nested 1 W E 3 +! Nud Nudging | | +! Per Periodic |_____S_____| +! Rad Radiation 2 j=1 +! i=1 i=Lm +! W S E N +! e o a o +! s u s r +! t t t t +! h h +! +! 1 2 3 4 + + LBC(isTvar) == Per Clo Per Clo \ ! idbio(1), CDOM at 440nm + Per Clo Per Clo ! idbio(2), CDOM at 510nm + +! Adjoint-based algorithms can have different lateral boundary +! conditions keywords. + +ad_LBC(isTvar) == Per Clo Per Clo \ ! idbio(1), CDOM at 440nm + Per Clo Per Clo ! idbio(6), CDOM at 440nm + +! Logical switches (TRUE/FALSE) to specify which variables to process for +! tracers climatology: [NBT,Ngrids] values are expected. See glossary below +! for details. + + LtracerCLM == 2*F + +! Logical switches (TRUE/FALSE) to specify which variables to consider on +! tracers point Sources/Sinks (like river runoff): [NBT,Ngrids] values are +! expected. See glossary below for details. + + LtracerSrc == 2*F + +! Logical switches (TRUE/FALSE) to activate writing of biological tracers +! into HISTORY/AVERAGE output files: [1:NBT,Ngrids]. + + Hout(idTvar) == 2*T ! biological tracer + Hout(idTsur) == 2*F ! surface tracer flux + +! Logical switches (TRUE/FALSE) to activate writing of time-averaged fields +! into AVERAGE output file: [1:NBT,Ngrids]. + + Aout(idTvar) == 6*T ! biological tracer + +! Logical switches (TRUE/FALSE) to activate writing of time-averaged, +! biological tracer diagnostic terms into DIAGNOSTIC output file: +! [1:NBT,Ngrids]. + + Dout(iTrate) == 6*T ! time rate of change + Dout(iThadv) == 6*T ! horizontal total advection + Dout(iTxadv) == 6*T ! horizontal XI-advection + Dout(iTyadv) == 6*T ! horizontal ETA-advection + Dout(iTvadv) == 6*T ! vertical advection + Dout(iThdif) == 6*T ! horizontal total diffusion + Dout(iTxdif) == 6*T ! horizontal XI-diffusion + Dout(iTydif) == 6*T ! horizontal ETA-diffusion + Dout(iTsdif) == 6*T ! horizontal S-diffusion + Dout(iTvdif) == 6*T ! vertical diffusion + +! +! GLOSSARY: +! ========= +! +!------------------------------------------------------------------------------ +! IOP-based, CDOM (Colored Dissolved Organic Matter) Ecosystem Model +! Parameters. Currently, it is configured with 2 biological tracers: +! +! idbio(1) CDOM absorption at 440nm +! idbio(2) CDOM absorption at 510nm +! +!------------------------------------------------------------------------------ +! +! Lbiology Switch to control the computation of a particular module +! within nested and/or multiple connected grids. By default +! this switch is set to TRUE in "mod_scalars" for all grids. +! Ngrids values are expected. The USER has the option, for +! example, to compute the biology in just one of the nested +! grids. If so, this switch needs to be consistent with the +! dimension parameter NBT in "mod_param". In order to make +! the model more efficient in memory usage, NBT(:) should +! be zero in such grids. +! +! BioIter Maximum number of iterations to achieve convergence of +! the nonlinear implicit solution. +! +! BioIni Initial concentration for analytical uniform initial +! conditions, [1/meter]. It is only used when +! ANA_BIOLOGY is activated. +! +! BioIni(i440n) CDOM absorption at 440nm +! BioIni(i510n) CDOM absorption at 510nm +! +! PARfrac Fraction of shortwave radiation that is photosynthetically +! active (nondimensional). +! +! AttSW Light attenuation due to seawater [1/m]. +! +! CDOM_LightAtt Light attenuation factor due to CDOM absorption +! [nondimensional]. +! +! CDOM_sigma Light-dependent degradation rate for CDOM absorption +! [1/(Watt m-2 day)]. +! +!------------------------------------------------------------------------------ +! Physical Parameters, [1:NBT,1:Ngrids] values are expected. +!------------------------------------------------------------------------------ +! +! TNU2 Nonlinear model lateral, harmonic, constant, mixing +! coefficient (m2/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, TNU2 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! TNU4 Nonlinear model lateral, biharmonic, constant, mixing +! coefficient (m4/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, TNU4 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! ad_TNU2 Adjoint-based algorithms lateral, harmonic, constant, +! mixing coefficient (m2/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, ad_TNU2 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! ad_TNU4 Adjoint-based algorithms lateral, biharmonic, constant, +! mixing coefficient (m4/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, ad_TNU4 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! AKT_BAK Background vertical mixing coefficient (m2/s) for biological +! tracer variables, [1:NBT,1:Ngrids] values are expected. +! +! +! ad_AKT_fac Adjoint-based algorithms vertical mixing, basic state, +! scale factor (nondimensional) for biological tracer +! variables; [1:NBT,1:Ngrids] values are expected. In +! some applications, a smaller/larger values of vertical +! mixing are necessary for stability. It is only used +! when FORWARD_MIXING is activated. +! +! TNUDG Nudging time scale (days), [1:NBT,1:Ngrids]. Inverse scale +! will be computed internally. +! +!------------------------------------------------------------------------------ +! Lateral boundary conditions parameters. +!------------------------------------------------------------------------------ +! +! The lateral boundary conditions are now specified with logical switches +! instead of CPP flags to allow nested grid configurations. Their values are +! load into structured array: +! +! LBC(1:4, nLBCvar, Ngrids) +! +! where 1:4 are the number of boundary edges, nLBCvar are the number LBC state +! variables, and Ngrids is the number of nested grids. For Example, to apply +! gradient boundary conditions to any tracer we use: +! +! LBC(iwest, isTvar(itrc), ng) % gradient +! LBC(ieast, isTvar(itrc), ng) % gradient +! LBC(isouth, isTvar(itrc), ng) % gradient +! LBC(inorth, isTvar(itrc), ng) % gradient +! +! The lateral boundary conditions for biological tracers are entered with +! a keyword. This keyword is case insensitive and usually has three characters. +! However, it is possible to have compound keywords, if applicable. For example, +! the keyword "RadNud" implies radiation boundary condition with nudging. This +! combination is usually used in active/passive radiation conditions. +! +! It is possible to specify the lateral boundary conditions for all biological +! tracers in a compact form with a single entry. for example, in a East-West +! periodic application we can just have: +! +! W S E N +! e o a o +! s u s r +! t t t t +! h h +! +! 1 2 3 4 +! +! LBC(isTvar) == Per Clo Per Clo +! +! Then, the standard input processing routine will assume that all the +! biological tracers have the same lateral boundary condition specified by +! the single entry. +! +! Keyword Lateral Boundary Condition Type +! +! Cla Clamped _____N_____ j=Mm +! Clo Closed | 4 | +! Gra Gradient | | +! Nes Nested 1 W E 3 +! Nud Nudging | | +! Per Periodic |_____S_____| +! Rad Radiation 2 j=1 +! i=1 i=Lm +! +! LBC(isTvar) Biological Tracers, [1:4, 1:NBT, Ngrids] values are expected. +! +! Similarly, the adjoint-based algorithms (ADM, TLM, RPM) can have different +! lateral boundary conditions keywords: +! +! ad_LBC(isTvar) Biological Tracers, [1:4, 1:NBT, Ngrids] values are expected. +! +!------------------------------------------------------------------------------ +! Tracer climatology processing switches. +!------------------------------------------------------------------------------ +! +! LtracerCLM Logical switches (T/F) to specify which tracer climatology +! variables to consider when the option TCLIMATOLOGY is +! activated; [1:NBT,1:Ngrids] values are expected. +! +! LtracerCLM(idbio(1),ng) CDOM absorption at 440nm +! LtracerCLM(idbio(2),ng) CDOM absorption at 510nm +! +! Recall that TCLIMATOLOGY is usually activated to nudge to +! tracer climatology (TLCM_NUDGING). The purpose of these +! switches is to control which climatology tracer fields +! (specially passive tracers) needs to be processed. So we +! may reduce the memory allocation for such array. +! +!------------------------------------------------------------------------------ +! Tracer point Sources/Sink sources switches. +!------------------------------------------------------------------------------ +! +! LtracerSrc Logical switches (T/F) to specify which tracer variables +! to consider when the option TS_PSOURCE is activated; +! [1:NBT,1:Ngrids] values are expected. +! +! LtracerSrc(idbio(1),ng) CDOM absorption at 440nm +! LtracerSrc(idbio(2),ng) CDOM absorption at 510nm +! +! Recall that TS_PSOURCE is usually activated to add river +! runoff as a point source. At minimum, it is necessary to +! specify both temperature and salinity for all rivers. The +! other tracers are optional. The user needs to know the +! correspondence between biological variables and indices +! idbio(1:NBT) when activating one or more of these switches. +! +! This logical switch REPLACES and ELIMINATES the need to +! have or read the variable "river_flag(river)" in the input +! rivers forcing NetCDF file: +! +! double river_flag(river) +! river_flag:long_name = "river runoff tracer flag" +! river_flag:option_0 = "all tracers are off" +! river_flag:option_1 = "only temperature" +! river_flag:option_2 = "only salinity" +! river_flag:option_3 = "both temperature and salinity" +! river_flag:units = "nondimensional" +! +! This logic was too cumbersome and complicated when +! additional tracers are considered. However, this change +! is backward compatible. +! +! The LtracerSrc switch will be used to activate the reading +! of respective tracer variable from input river forcing +! NetCDF file. If you want to add other tracer variables +! (other than temperature and salinity) as a source for a +! particular river(s), you just need to specify such values +! on those river(s). Then, set the values to ZERO on the +! other river(s) that do NOT require such river forcing for +! that tracer. Recall that you need to specify the tracer +! values for all rivers, even if their values are zero. +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of fields into HISTORY files. +!------------------------------------------------------------------------------ +! +! Hout Logical switches (T/F) to write out biological data into +! output HISTORY NetCDF file, [1:NBT,1:Ngrids] values are +! expected: +! +! Hout(idTvar) biological tracers +! Hout(idTsur) biological tracers surface flux +! +! idTvar(idbio(1))=aCDOM(i440n) CDOM absorption at 440nm +! idTvar(idbio(2))=aCDOM(i510n) CDOM absorption at 510nm +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of fields into AVERAGE file. +!------------------------------------------------------------------------------ +! +! Aout Logical switches to write out biological fields into +! output AVERAGE NetCDF file, [1:NBT,1:Ngrids] values +! are expected: +! +! Aout(idTvar) biological tracers +! +! The idTvar(idbio(:)) are the same to those in the HISTORY +! file. +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of time-averaged fields into +! DIAGNOSTIC file. +!------------------------------------------------------------------------------ +! +! Time-averaged, biological tracers diagnostic terms, [1:NBT,Ngrids] values +! expected: (if DIAGNOSTICS_TS) +! +! Dout(idDtrc(idbio(1:NBT),iT....),1:Ngrids) +! +! Dout(iTrate) Write out time rate of change. +! Dout(iThadv) Write out horizontal total advection. +! Dout(iTxadv) Write out horizontal XI-advection. +! Dout(iTyadv) Write out horizontal ETA-advection. +! Dout(iTvadv) Write out vertical advection. +! Dout(iThdif) Write out horizontal total diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTxdif) Write out horizonta1 XI-diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTydif) Write out horizontal ETA-diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTsdif) Write out horizontal S-diffusion, if TS_DIF2 or TS_DIF4 and +! rotated tensor (MIX_GEO_TS or MIX_ISO_TS). +! Dout(iTvdif) Write out vertical diffusion. +! diff --git a/ROMS/External/npzd_iop.in b/ROMS/External/npzd_iop.in new file mode 100644 index 00000000..6b1205b8 --- /dev/null +++ b/ROMS/External/npzd_iop.in @@ -0,0 +1,565 @@ +! IOP-based, NPZD Ecosystem Model Parameters. +! +!git $Id$ +!========================================================= Hernan G. Arango === +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!============================================================================== +! ! +! Input parameters can be entered in ANY order, provided that the parameter ! +! KEYWORD (usually, upper case) is typed correctly followed by "=" or "==" ! +! symbols. Any comment lines are allowed and must begin with an exclamation ! +! mark (!) in column one. Comments may appear to the right of a parameter ! +! specification to improve documentation. Comments will be ignored during ! +! reading. Blank lines are also allowed and ignored. Continuation lines in ! +! a parameter specification are allowed and must be preceded by a backslash ! +! (\). In some instances, more than one value is required for a parameter. ! +! If fewer values are provided, the last value is assigned for the entire ! +! parameter array. The multiplication symbol (*), without blank spaces in ! +! between, is allowed for a parameter specification. For example, in a two ! +! grids nested application: ! +! ! +! AKT_BAK == 2*1.0d-6 2*5.0d-6 ! m2/s ! +! ! +! indicates that the first two entries of array AKT_BAK, in fortran column- ! +! major order, will have the same value of "1.0d-6" for grid 1, whereas the ! +! next two entries will have the same value of "5.0d-6" for grid 2. ! +! ! +! In multiple levels of nesting and/or multiple connected domains step-ups, ! +! "Ngrids" entries are expected for some of these parameters. In such case, ! +! the order of the entries for a parameter is extremely important. It must ! +! follow the same order (1:Ngrids) as in the state variable declaration. The ! +! USER may follow the above guidelines for specifying his/her values. These ! +! parameters are marked by "==" plural symbol after the KEYWORD. ! +! ! +!============================================================================== +! +! NOTICE: Input parameter units are specified within brackets and default +! ****** values are specified within braces. +! +! Switch to control the computation of biology within nested and/or multiple +! connected grids. + + Lbiology == T + +! Maximum number of iterations to achieve convergence of the nonlinear +! solution. + + BioIter == 1 + +! Initial concentration for analytical uniform initial conditions for +! ecosystem tracers. Except for DIN, two values are expected for two +! spectral bands: 410nm and 510nm. + +BioIni(iDIN_) == 1.0d0 ! Dissolved Inorganic Nitrogen +BioIni(iAphy) == 1.0d0 1.0d0 ! Phytoplankton absorption at 440, 510nm +BioIni(iBphy) == 1.0d0 1.0d0 ! Phytoplankton scattering at 440, 510nm +BioIni(aCDOM) == 1.0d0 1.0d0 ! CDOM absorption at 440, 510nm +BioIni(iBdet) == 1.0d0 1.0d0 ! Detritus scatteing at 440, 510 nm + +! Fraction of shortwave radiation that is photosynthetically active +! (nondimensional), {0.43d0}. + + PARfrac == 0.43d0 + +! Light attenuation due to seawater [1/m], {0.04d0}. + + AttSW == 0.04d0 + +! Light attenuation factor due to CDOM absorption at 440nm +! [nondimensional]. + +CDOM_LightAtt == 0.8d0 + +! Light-dependent degradation rate for CDOM absorption at 440nm +! [1/(Watt m-2 day)]. + + CDOM_sigma == 0.01d0 + +! Half-saturation for phytoplankton nitrogen uptake [millimole_N m-3]. + + K_DIN == 0.5d0 + +! Phytoplankton, initial slope of the P-I curve [m2/Watt]. + + PhyIS == 0.025d0 + +! Phytoplankton mortality rate to the Detritus pool [1/day]. + + PhyMRD == 0.0d0 + +! Phytoplankton loss rate to the Nitrogen pool [1/day]. + + PhyMRN == 0.0d0 + +! Nitrogen uptake rate [1/day]. + + Vm_DIN == 1.0d0 + +! Detritus remineraliztion rate [1/day]. + + DetRR == 0.0d0 + +! Maximum photosynthetic rate [1/day]. + + PhotoRmax == 1.0d0 + +! Maximum ratio of phytoplankton backscatter to absorption +! [nondimensional]. + + ThetaM == 1.0d0 + +! Mapping from phytoplankton backscatter to Nitrogen biomass at 440 nm +! [millimole_N/m2]. + + BphyMap == 50.0d0 + +! Mapping from detritus backscatter to Nitrogen biomass at 440 nm +! [millimole_N/m2]. + + BdetMap == 8.0d0 + +! Phytoplankton sinking rate [m/day]. + + wPhy == 0.d0 + +! Detrital sinking rate [m/day]. + + wDet == 0.d0 + +! Harmonic/biharmonic horizontal diffusion of biological tracer for +! nonlinear model and adjoint-based algorithms: [1:NBT,Ngrids]. + + TNU2 == 9*20.0d0 ! m2/s + TNU4 == 9*2.0d8 ! m4/s + + ad_TNU2 == 9*0.0d0 ! m2/s + ad_TNU4 == 9*0.0d0 ! m4/s + +! Vertical mixing coefficients for biological tracers for nonlinear +! model and basic state scale factor in adjoint-based algorithms: +! [1:NBT,Ngrids]. + + AKT_BAK == 9*1.0d-6 ! m2/s + + ad_AKT_fac == 9*1.0d0 ! nondimensional + +! Nudging/relaxation time scales, inverse scales will be computed +! internally: [1:NBT,Ngrids]. + + TNUDG == 9*0.5d0 ! days + +! Set lateral boundary conditions keyword. Notice that a value is expected +! for each boundary segment per nested grid for each state variable. +! +! The biological tracer variables require [1:4,1:NBT,Ngrids] values. The +! boundary order is: 1=west, 2=south, 3=east, and 4=north. That is, +! anticlockwise starting at the western boundary. +! +! The keyword is case insensitive and usually has three characters. However, +! it is possible to have compound keywords, if applicable. For example, the +! keyword "RadNud" implies radiation boundary condition with nudging. This +! combination is usually used in active/passive radiation conditions. +! +! NOTICE: It is possible to specify the lateral boundary conditions for +! ====== all biological tracers in a compact form with a single entry. +! If so, all the biological tracers are assumed to have the same boundary +! condition as in the single entry. +! +! Keyword Lateral Boundary Condition Type +! +! Cla Clamped _____N_____ j=Mm +! Clo Closed | 4 | +! Gra Gradient | | +! Nes Nested 1 W E 3 +! Nud Nudging | | +! Per Periodic |_____S_____| +! Rad Radiation 2 j=1 +! i=1 i=Lm +! W S E N +! e o a o +! s u s r +! t t t t +! h h +! +! 1 2 3 4 + + LBC(isTvar) == Per Clo Per Clo \ ! idbio(1), DIN + Per Clo Per Clo \ ! idbio(2), phyt absorp 440nm + Per Clo Per Clo \ ! idbio(3), phyt backsc 440nm + Per Clo Per Clo \ ! idbio(4), CDOM absorp 440nm + Per Clo Per Clo \ ! idbio(5), detritus 440nm + Per Clo Per Clo \ ! idbio(6), phyt absorp 510nm + Per Clo Per Clo \ ! idbio(7), phyt backsc 510nm + Per Clo Per Clo \ ! idbio(8), CDOM absorp 510nm + Per Clo Per Clo ! idbio(9), detritus 510nm + +! Adjoint-based algorithms can have different lateral boundary +! conditions keywords. + +ad_LBC(isTvar) == Per Clo Per Clo \ ! idbio(1), DIN + Per Clo Per Clo \ ! idbio(2), phyt absorp 440nm + Per Clo Per Clo \ ! idbio(3), phyt backsc 440nm + Per Clo Per Clo \ ! idbio(4), CDOM absorp 440nm + Per Clo Per Clo \ ! idbio(5), detritus 440nm + Per Clo Per Clo \ ! idbio(6), phyt absorp 510nm + Per Clo Per Clo \ ! idbio(7), phyt backsc 510nm + Per Clo Per Clo \ ! idbio(8), CDOM absorp 510nm + Per Clo Per Clo ! idbio(9), detritus 510nm + +! Logical switches (TRUE/FALSE) to specify which variables to process for +! tracers climatology: [NBT,Ngrids] values are expected. See glossary below +! for details. + + LtracerCLM == 9*F + +! Logical switches (TRUE/FALSE) to specify which variables to consider on +! tracers point Sources/Sinks (like river runoff): [NBT,Ngrids] values are +! expected. See glossary below for details. + + LtracerSrc == 9*F + +! Logical switches (TRUE/FALSE) to activate writing of biological tracers +! into HISTORY/AVERAGE output files: [1:NBT,Ngrids]. + + Hout(idTvar) == 9*T ! biological tracer + Hout(idTsur) == 9*F ! surface tracer flux + +! Logical switches (TRUE/FALSE) to activate writing of time-averaged fields +! into AVERAGE output file: [1:NBT,Ngrids]. + + Aout(idTvar) == 9*T ! biological tracer + +! Logical switches (TRUE/FALSE) to activate writing of time-averaged, +! biological tracer diagnostic terms into DIAGNOSTIC output file: +! [1:NBT,Ngrids]. + + Dout(iTrate) == 9*T ! time rate of change + Dout(iThadv) == 9*T ! horizontal total advection + Dout(iTxadv) == 9*T ! horizontal XI-advection + Dout(iTyadv) == 9*T ! horizontal ETA-advection + Dout(iTvadv) == 9*T ! vertical advection + Dout(iThdif) == 9*T ! horizontal total diffusion + Dout(iTxdif) == 9*T ! horizontal XI-diffusion + Dout(iTydif) == 9*T ! horizontal ETA-diffusion + Dout(iTsdif) == 9*T ! horizontal S-diffusion + Dout(iTvdif) == 9*T ! vertical diffusion + +! +! GLOSSARY: +! ========= +! +!------------------------------------------------------------------------------ +! IOP-based, NPZD Ecosystem Model Parameters. Currently, it is configured with +! 9 biological tracers: +! +! idbio(1) Dissolved inorganic nitrogen +! idbio(2) Phytoplankton absorption at 440nm +! idbio(3) Phytoplankton backscattering at 440nm +! idbio(4) CDOM absorption at 440nm +! idbio(5) Detritus backscattering at 440nm +! idbio(6) Phytoplankton absorption at 510nm +! idbio(7) Phytoplankton backscattering at 510nm +! idbio(8) CDOM absorption at 510nm +! idbio(9) Detritus backscattering at 510nm +! +!------------------------------------------------------------------------------ +! +! Lbiology Switch to control the computation of a particular module +! within nested and/or multiple connected grids. By default +! this switch is set to TRUE in "mod_scalars" for all grids. +! Ngrids values are expected. The USER has the option, for +! example, to compute the biology in just one of the nested +! grids. If so, this switch needs to be consistent with the +! dimension parameter NBT in "mod_param". In order to make +! the model more efficient in memory usage, NBT(:) should +! be zero in such grids. +! +! BioIter Maximum number of iterations to achieve convergence of +! the nonlinear implicit solution. +! +! BioIni Initial concentration for analytical uniform initial +! conditions, [1/meter]. It is only used when +! ANA_BIOLOGY is activated. Except for DIN, two values are +! expected for two spectral bands: 410nm and 510nm. +! +! BioIni(iDIN_) Dissolved Inorganic Nitrogen +! BioIni(iAphy) Phytoplankton absorption at 440, 510nm +! BioIni(iBphy) Phytoplankton scattering at 440, 510nm +! BioIni(iBdet) Detritus absorption at 440, 510 nm +! BioIni(aCDOM) CDOM absorption at 440, 510nm +! +! PARfrac Fraction of shortwave radiation that is photosynthetically +! active (nondimensional). +! +! AttSW Light attenuation due to seawater [1/m]. +! +! CDOM_LightAtt Light attenuation factor due to CDOM absorption +! [nondimensional]. +! +! CDOM_sigma Light-dependent degradation rate for CDOM absorption +! [1/(Watt m-2 day)]. +! +! K_DIN Half-saturation for phytoplankton nitrogen uptake +! [millimole_N m-3]. +! +! PhyIS Phytoplankton, initial slope of the P-I curve [m2/Watt]. +! +! PhyMRD Phytoplankton mortality rate to the Detritus pool [1/day]. +! +! PhyMRN Phytoplankton loss rate to the Nitrogen pool [1/day]. +! +! Vm_DIN Nitrogen uptake rate [1/day]. +! +! DetRR Detritus remineraliztion rate [1/day]. +! +! PhotoRmax Maximum photosynthetic rate [1/day]. +! +! ThetaM Maximum ratio of phytoplankton backscatter to absorption +! [nondimensional]. +! +! BphyMap Mapping from phytoplankton backscatter to Nitrogen biomass +! at 440 nm [millimole_N/m2]. +! +! BdetMap Mapping from detritus backscatter to Nitrogen biomass +! at 440 nm [millimole_N/m2]. +! +! wPhy Phytoplankton sinking rate [m/day]. +! +! wDet Detrital sinking rate [m/day]. +! +!------------------------------------------------------------------------------ +! Physical Parameters, [1:NBT,1:Ngrids] values are expected. +!------------------------------------------------------------------------------ +! +! TNU2 Nonlinear model lateral, harmonic, constant, mixing +! coefficient (m2/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, TNU2 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! TNU4 Nonlinear model lateral, biharmonic, constant, mixing +! coefficient (m4/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, TNU4 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! ad_TNU2 Adjoint-based algorithms lateral, harmonic, constant, +! mixing coefficient (m2/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, ad_TNU2 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! ad_TNU4 Adjoint-based algorithms lateral, biharmonic, constant, +! mixing coefficient (m4/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, ad_TNU4 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! AKT_BAK Background vertical mixing coefficient (m2/s) for biological +! tracer variables, [1:NBT,1:Ngrids] values are expected. +! +! +! ad_AKT_fac Adjoint-based algorithms vertical mixing, basic state, +! scale factor (nondimensional) for biological tracer +! variables; [1:NBT,1:Ngrids] values are expected. In +! some applications, a smaller/larger values of vertical +! mixing are necessary for stability. It is only used +! when FORWARD_MIXING is activated. +! +! TNUDG Nudging time scale (days), [1:NBT,1:Ngrids]. Inverse scale +! will be computed internally. +! +!------------------------------------------------------------------------------ +! Lateral boundary conditions parameters. +!------------------------------------------------------------------------------ +! +! The lateral boundary conditions are now specified with logical switches +! instead of CPP flags to allow nested grid configurations. Their values are +! load into structured array: +! +! LBC(1:4, nLBCvar, Ngrids) +! +! where 1:4 are the number of boundary edges, nLBCvar are the number LBC state +! variables, and Ngrids is the number of nested grids. For Example, to apply +! gradient boundary conditions to any tracer we use: +! +! LBC(iwest, isTvar(itrc), ng) % gradient +! LBC(ieast, isTvar(itrc), ng) % gradient +! LBC(isouth, isTvar(itrc), ng) % gradient +! LBC(inorth, isTvar(itrc), ng) % gradient +! +! The lateral boundary conditions for biological tracers are entered with +! a keyword. This keyword is case insensitive and usually has three characters. +! However, it is possible to have compound keywords, if applicable. For example, +! the keyword "RadNud" implies radiation boundary condition with nudging. This +! combination is usually used in active/passive radiation conditions. +! +! It is possible to specify the lateral boundary conditions for all biological +! tracers in a compact form with a single entry. for example, in a East-West +! periodic application we can just have: +! +! W S E N +! e o a o +! s u s r +! t t t t +! h h +! +! 1 2 3 4 +! +! LBC(isTvar) == Per Clo Per Clo +! +! Then, the standard input processing routine will assume that all the +! biological tracers have the same lateral boundary condition specified by +! the single entry. +! +! Keyword Lateral Boundary Condition Type +! +! Cla Clamped _____N_____ j=Mm +! Clo Closed | 4 | +! Gra Gradient | | +! Nes Nested 1 W E 3 +! Nud Nudging | | +! Per Periodic |_____S_____| +! Rad Radiation 2 j=1 +! i=1 i=Lm +! +! LBC(isTvar) Biological Tracers, [1:4, 1:NBT, Ngrids] values are expected. +! +! Similarly, the adjoint-based algorithms (ADM, TLM, RPM) can have different +! lateral boundary conditions keywords: +! +! ad_LBC(isTvar) Biological Tracers, [1:4, 1:NBT, Ngrids] values are expected. +! +!------------------------------------------------------------------------------ +! Tracer climatology processing switches. +!------------------------------------------------------------------------------ +! +! LtracerCLM Logical switches (T/F) to specify which tracer climatology +! variables to consider when the option TCLIMATOLOGY is +! activated; [1:NBT,1:Ngrids] values are expected. +! +! LtracerCLM(idbio(1),ng) Dissolved inorganic Nitrogen +! LtracerCLM(idbio(2),ng) Phy absorption at 440nm +! LtracerCLM(idbio(3),ng) Phy backscattering at 440nm +! LtracerCLM(idbio(4),ng) CDOM absorption at 440nm +! LtracerCLM(idbio(5),ng) Det backscattering at 440nm +! LtracerCLM(idbio(6),ng) Phy absorption at 510nm +! LtracerCLM(idbio(7),ng) Phy backscattering at 510nm +! LtracerCLM(idbio(8),ng) CDOM absorption at 510nm +! LtracerCLM(idbio(9),ng) Det backscattering at 510nm +! +! Recall that TCLIMATOLOGY is usually activated to nudge to +! tracer climatology (TLCM_NUDGING). The purpose of these +! switches is to control which climatology tracer fields +! (specially passive tracers) needs to be processed. So we +! may reduce the memory allocation for such array. +! +!------------------------------------------------------------------------------ +! Tracer point Sources/Sink sources switches. +!------------------------------------------------------------------------------ +! +! LtracerSrc Logical switches (T/F) to specify which tracer variables +! to consider when the option TS_PSOURCE is activated; +! [1:NBT,1:Ngrids] values are expected. +! +! LtracerSrc(idbio(1),ng) Dissolved inorganic Nitrogen +! LtracerSrc(idbio(2),ng) Phy absorption at 440nm +! LtracerSrc(idbio(3),ng) Phy backscattering at 440nm +! LtracerSrc(idbio(4),ng) CDOM absorption at 440nm +! LtracerSrc(idbio(5),ng) Det backscattering at 440nm +! LtracerSrc(idbio(6),ng) Phy absorption at 510nm +! LtracerSrc(idbio(7),ng) Phy backscattering at 510nm +! LtracerSrc(idbio(8),ng) CDOM absorption at 510nm +! LtracerSrc(idbio(9),ng) Det backscattering at 510nm +! +! Recall that TS_PSOURCE is usually activated to add river +! runoff as a point source. At minimum, it is necessary to +! specify both temperature and salinity for all rivers. The +! other tracers are optional. The user needs to know the +! correspondence between biological variables and indices +! idbio(1:NBT) when activating one or more of these switches. +! +! This logical switch REPLACES and ELIMINATES the need to +! have or read the variable "river_flag(river)" in the input +! rivers forcing NetCDF file: +! +! double river_flag(river) +! river_flag:long_name = "river runoff tracer flag" +! river_flag:option_0 = "all tracers are off" +! river_flag:option_1 = "only temperature" +! river_flag:option_2 = "only salinity" +! river_flag:option_3 = "both temperature and salinity" +! river_flag:units = "nondimensional" +! +! This logic was too cumbersome and complicated when +! additional tracers are considered. However, this change +! is backward compatible. +! +! The LtracerSrc switch will be used to activate the reading +! of respective tracer variable from input river forcing +! NetCDF file. If you want to add other tracer variables +! (other than temperature and salinity) as a source for a +! particular river(s), you just need to specify such values +! on those river(s). Then, set the values to ZERO on the +! other river(s) that do NOT require such river forcing for +! that tracer. Recall that you need to specify the tracer +! values for all rivers, even if their values are zero. +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of fields into HISTORY files. +!------------------------------------------------------------------------------ +! +! Hout Logical switches (T/F) to write out biological data into +! output HISTORY NetCDF file, [1:NBT,1:Ngrids] values are +! expected: +! +! Hout(idTvar) biological tracers +! Hout(idTsur) biological tracers surface flux +! +! idTvar(idbio(1))=iDIN_ dissolved Inorganic Nitrogen +! idTvar(idbio(2))=iAphy(i440n) Phy absorption at 440nm +! idTvar(idbio(3))=iBphy(i440n) Phy backscattering at 440nm +! idTvar(idbio(4))=aCDOM(i440n) CDOM absorption at 440nm +! idTvar(idbio(5))=iBdet(i440n) Det backscattering at 440nm +! idTvar(idbio(6))=iAphy(i510n) Phy absorption at 510nm +! idTvar(idbio(7))=iBphy(i510n) Phy backscattering at 510nm +! idTvar(idbio(8))=aCDOM(i510n) CDOM absorption at 510nm +! idTvar(idbio(9))=iBdet(i510n) Det backscattering at 510nm +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of fields into AVERAGE file. +!------------------------------------------------------------------------------ +! +! Aout Logical switches to write out biological fields into +! output AVERAGE NetCDF file, [1:NBT,1:Ngrids] values +! are expected: +! +! Aout(idTvar) biological tracers +! +! The idTvar(idbio(:)) are the same to those in the HISTORY +! file. +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of time-averaged fields into +! DIAGNOSTIC file. +!------------------------------------------------------------------------------ +! +! Time-averaged, biological tracers diagnostic terms, [1:NBT,Ngrids] values +! expected: (if DIAGNOSTICS_TS) +! +! Dout(idDtrc(idbio(1:NBT),iT....),1:Ngrids) +! +! Dout(iTrate) Write out time rate of change. +! Dout(iThadv) Write out horizontal total advection. +! Dout(iTxadv) Write out horizontal XI-advection. +! Dout(iTyadv) Write out horizontal ETA-advection. +! Dout(iTvadv) Write out vertical advection. +! Dout(iThdif) Write out horizontal total diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTxdif) Write out horizonta1 XI-diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTydif) Write out horizontal ETA-diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTsdif) Write out horizontal S-diffusion, if TS_DIF2 or TS_DIF4 and +! rotated tensor (MIX_GEO_TS or MIX_ISO_TS). +! Dout(iTvdif) Write out vertical diffusion. +! diff --git a/ROMS/External/varinfo.yaml b/ROMS/External/varinfo.yaml index 54b4f46c..da479324 100644 --- a/ROMS/External/varinfo.yaml +++ b/ROMS/External/varinfo.yaml @@ -2564,6 +2564,105 @@ metadata: add_offset: 0.0d0 scale: 1.0d0 + - variable: river_DIN # Input + standard_name: mole_concentration_of_dissolved_inorganic_carbon_into_sea_water_from_rivers + long_name: river runoff dissolved inorganic nitrogen + units: millimole_nitrogen meter-3 # [millimole/m3] + field: river DIN + time: river_time + index_code: idRtrc(iDIN_) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: river_aPhytoplankton440 # Input + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_phytoplankton_from_rivers + long_name: river runoff phytoplankton light absorption at 440nm + units: meter-1 # [1/m] + field: river phytoplankton 440nm light absorption + time: river_time + index_code: idRtrc(iAphy(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: river_aPhytoplankton510 # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_phytoplankton_from_rivers + long_name: river runoff phytoplankton light absorption at 510nm + units: meter-1 # [1/m] + field: river phytoplankton 510nm light absorption + time: river_time + index_code: idRtrc(iAphy(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: river_bPhytoplankton440 # Input + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_phytoplankton_from_rivers + long_name: river runoff phytoplankton light backscattering at 440nm + units: meter-1 # [1/m] + field: river phytoplankton 440nm light backscattering + time: river_time + index_code: idRtrc(iBphy(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: river_bPhytoplankton510 # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_phytoplankton_from_rivers + long_name: river runoff phytoplankton light backscattering at 510nm + units: meter-1 # [1/m] + field: river phytoplankton 510nm light backscattering + time: river_time + index_code: idRtrc(iBphy(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: river_aCDOM440 # Input + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_colored_dissolved_organic_matter_from_rivers + long_name: river runoff CDOM light absorption at 440nm + units: meter-1 # [1/m] + field: river CDOM 440nm light absorption + time: river_time + index_code: idRtrc(aCDOM(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: river_aCDOM510 # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_colored_dissolved_organic_matter_from_rivers + long_name: river runoff CDOM light absorption at 510nm + units: meter-1 # [1/m] + field: river CDOM 510nm light absorption + time: river_time + index_code: idRtrc(aCDOM(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: river_bDetritus440 # Input + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_detritus_from_rivers + long_name: river runoff detritus light backscattering at 440nm + units: meter-1 # [1/m] + field: river detritus 440nm light backscattering + time: river_time + index_code: idRtrc(iBdet(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: river_bDetritus510 # Input + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_detritus_from_rivers + long_name: river runoff detritus light backscattering at 510nm + units: meter-1 # [1/m] + field: river detritus 510nm light backscattering + time: river_time + index_code: idRtrc(iBdet(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + ################################################# ### Surface/Bottom Boundary Layer Variables ### ################################################# @@ -5477,6 +5576,606 @@ metadata: add_offset: 0.0d0 scale: 1.0d0 + ################################################### + ### IOP-based NPZD and CDOM Ecosystem Variables ### + ################################################### + + - variable: DIN # Input/Output + standard_name: mole_concentration_of_dissolved_inorganic_nitrogen_in_sea_water + long_name: dissolved inorganic nitrogen + units: millimole_nitrogen meter-3 # [millimole/m3] + field: DIN + time: ocean_time + index_code: idTvar(iDIN_) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: DIN # Input/Output + standard_name: mole_concentration_of_dissolved_inorganic_nitrogen_in_sea_water + long_name: dissolved inorganic nitrogen functional + units: millimole_nitrogen meter-3 # [millimole/m3] + field: DIN + time: ocean_time + index_code: idTads(iDIN_) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton440 # Input/Output + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 440nm + units: meter-1 # [1/m] + field: phytoplankton 440nm light absorption + time: ocean_time + index_code: idTvar(iAphy(i440n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton440 # Input/Output + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 440nm functional + units: meter-1 # [1/m] + field: phytoplankton 440nm light absorption + time: ocean_time + index_code: idTads(iAphy(i440n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton510 # Input/Output + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 510nm + units: meter-1 # [1/m] + field: phytoplankton 510nm light absorption + time: ocean_time + index_code: idTvar(iAphy(i510n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton510 # Input/Output + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 510nm functional + units: meter-1 # [1/m] + field: phytoplankton 510nm light absorption + time: ocean_time + index_code: idTads(iAphy(i510n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton440 # Input/Output + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 440nm + units: meter-1 # [1/m] + field: phytoplankton 440nm light backscattering + time: ocean_time + index_code: idTvar(iBphy(i440n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton440 # Input/Output + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 440nm functional + units: meter-1 # [1/m] + field: phytoplankton 440nm light absorption + time: ocean_time + index_code: idTads(iBphy(i440n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton510 # Input/Output + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 510nm + units: meter-1 # [1/m] + field: phytoplankton 510nm light backscattering + time: ocean_time + index_code: idTvar(iBphy(i510n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton510 # Input/Output + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 510nm functional + units: meter-1 # [1/m] + field: phytoplankton 510nm light backscattering + time: ocean_time + index_code: idTads(iBphy(i510n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM440 # Input/Output + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 440nm + units: meter-1 # [1/m] + field: CDOM 440nm light absorption + time: ocean_time + index_code: idTvar(aCDOM(i440n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM440 # Input/Output + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 440nm functional + units: meter-1 # [1/m] + field: CDOM 440nm light absorption + time: ocean_time + index_code: idTads(aCDOM(i440n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM510 # Input/Output + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 510nm + units: meter-1 # [1/m] + field: CDOM 510nm light absorption + time: ocean_time + index_code: idTvar(aCDOM(i510n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM510 # Input/Output + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 510nm functional + units: meter-1 # [1/m] + field: CDOM 510nm light absorption + time: ocean_time + index_code: idTads(aCDOM(i510n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus440 # Input/Output + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_detritus + long_name: detritus light backscattering at 440nm + units: meter-1 # [1/m] + field: detritus 440nm light backscattering + time: ocean_time + index_code: idTvar(iBdet(i440n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus440 # Input/Output + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_detritus + long_name: detritus light backscattering at 440nm functional + units: meter-1 # [1/m] + field: detritus 440nm light backscattering + time: ocean_time + index_code: idTads(iBdet(i440n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus510 # Input/Output + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_detritus + long_name: detritus light backscattering at 510nm + units: meter-1 # [1/m] + field: detritus 510nm light backscattering + time: ocean_time + index_code: idTvar(iBdet(i510n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus510 # Input/Output + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_detritus + long_name: detritus light backscattering at 510nm functional + units: meter-1 # [1/m] + field: detritus 510nm light backscattering + time: ocean_time + index_code: idTads(iBdet(i510n)) + type: r3dvar + add_offset: 0.0d0 + scale: 1.0d0 + + # Lateral Boundary Condition Variables + + - variable: DIN_east # Input + standard_name: mole_concentration_of_dissolved_inorganic_carbon_into_sea_water + long_name: DIN eastern boundary condition + units: millimole_nitrogen meter-3 # [millimole/m3] + field: DIN eastern-boundary + time: DIN_time + index_code: idTbry(ieast,iDIN_) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: DIN_west # Input + standard_name: mole_concentration_of_dissolved_inorganic_carbon_into_sea_water + long_name: DIN western boundary condition + units: millimole_nitrogen meter-3 # [millimole/m3] + field: DIN western-boundary + time: DIN_time + index_code: idTbry(iwest,iDIN_) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: DIN_south # Input + standard_name: mole_concentration_of_dissolved_inorganic_carbon_into_sea_water + long_name: DIN southern boundary condition + units: millimole_nitrogen meter-3 # [millimole/m3] + field: DIN southern-boundary + time: DIN_time + index_code: idTbry(isouth,iDIN_) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: DIN_north # Input + standard_name: mole_concentration_of_dissolved_inorganic_carbon_into_sea_water + long_name: DIN northern boundary condition + units: millimole_nitrogen meter-3 # [millimole/m3] + field: DIN northern-boundary + time: DIN_time + index_code: idTbry(inorth,iDIN_) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton440_east # Input + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 440nm eastern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 440nm light absorption eastern-boundary + time: aPhytoplankton440_time + index_code: idTbry(ieast,iAphy(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton440_west # Input + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 440nm western boundary condition + units: meter-1 # [1/m] + field: phytoplankton 440nm light absorption western-boundary + time: aPhytoplankton440_time + index_code: idTbry(iwest,iAphy(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton440_south # Input + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 440nm southern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 440nm light absorption southern-boundary + time: aPhytoplankton440_time + index_code: idTbry(isouth,iAphy(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton440_north # Input + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 440nm northern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 440nm light absorption northern-boundary + time: aPhytoplankton440_time + index_code: idTbry(inorth,iAphy(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton510_east # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 510nm eastern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 510nm light absorption eastern-boundary + time: aPhytoplankton510_time + index_code: idTbry(ieast,iAphy(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton510_west # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 510nm western boundary condition + units: meter-1 # [1/m] + field: phytoplankton 510nm light absorption western-boundary + time: aPhytoplankton510_time + index_code: idTbry(iwest,iAphy(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton510_south # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 510nm southern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 510nm light absorption southern-boundary + time: aPhytoplankton510_time + index_code: idTbry(isouth,iAphy(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aPhytoplankton510_north # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_phytoplankton + long_name: phytoplankton light absorption at 510nm northern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 510nm light absorption northern-boundary + time: aPhytoplankton510_time + index_code: idTbry(inorth,iAphy(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton440_east # Input + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 440nm eastern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 440nm light backscattering eastern-boundary + time: bPhytoplankton440_time + index_code: idTbry(ieast,iBphy(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton440_west # Input + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 440nm western boundary condition + units: meter-1 # [1/m] + field: phytoplankton 440nm light backscattering western-boundary + time: bPhytoplankton440_time + index_code: idTbry(iwest,iBphy(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton440_south # Input + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 440nm southern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 440nm light backscattering southern-boundary + time: bPhytoplankton440_time + index_code: idTbry(isouth,iBphy(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton440_north # Input + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 440nm northern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 440nm light backscattering northern-boundary + time: bPhytoplankton440_time + index_code: idTbry(inorth,iBphy(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton510_east # Input + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 510nm eastern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 510nm light backscattering eastern-boundary + time: bPhytoplankton510_time + index_code: idTbry(ieast,iBphy(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton510_west # Input + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 510nm western boundary condition + units: meter-1 # [1/m] + field: phytoplankton 510nm light backscattering western-boundary + time: bPhytoplankton510_time + index_code: idTbry(iwest,iBphy(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton510_south # Input + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 510nm southern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 510nm light backscattering southern-boundary + time: bPhytoplankton510_time + index_code: idTbry(isouth,iBphy(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bPhytoplankton510_north # Input + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_phytoplankton + long_name: phytoplankton light backscattering at 510nm northern boundary condition + units: meter-1 # [1/m] + field: phytoplankton 510nm light backscattering northern-boundary + time: bPhytoplankton510_time + index_code: idTbry(inorth,iBphy(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM440_east # Input + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 440nm eastern boundary condition + units: meter-1 # [1/m] + field: CDOM 440nm light absorption eastern-boundary + time: aCDOM440_time + index_code: idTbry(ieast,aCDOM(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM440_west # Input + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 440nm western boundary condition + units: meter-1 # [1/m] + field: CDOM 440nm light absorption western-boundary + time: aCDOM440_time + index_code: idTbry(iwest,aCDOM(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM440_south # Input + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 440nm southern boundary condition + units: meter-1 # [1/m] + field: CDOM 440nm light absorption southern-boundary + time: aCDOM440_time + index_code: idTbry(isouth,aCDOM(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM440_north # Input + standard_name: sea_water_light_optical_absorption_at_440nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 440nm northern boundary condition + units: meter-1 # [1/m] + field: CDOM 440nm light absorption northern-boundary + time: aCDOM440_time + index_code: idTbry(inorth,aCDOM(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM510_east # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 510nm eastern boundary condition + units: meter-1 # [1/m] + field: CDOM 510nm light absorption eastern-boundary + time: aCDOM510_time + index_code: idTbry(ieast,aCDOM(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM510_west # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 510nm western boundary condition + units: meter-1 # [1/m] + field: CDOM 510nm light absorption western-boundary + time: aCDOM510_time + index_code: idTbry(iwest,aCDOM(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM510_south # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 510nm southern boundary condition + units: meter-1 # [1/m] + field: CDOM 510nm light absorption southern-boundary + time: aCDOM510_time + index_code: idTbry(isouth,aCDOM(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: aCDOM510_north # Input + standard_name: sea_water_light_optical_absorption_at_510nm_due_to_colored_dissolved_organic_matter + long_name: CDOM light absorption at 510nm northern boundary condition + units: meter-1 # [1/m] + field: CDOM 510nm light absorption northern-boundary + time: aCDOM510_time + index_code: idTbry(inorth,aCDOM(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus440_east # Input + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_detritus + long_name: detritus light backscattering at 440nm eastern boundary condition + units: meter-1 # [1/m] + field: detritus 440nm light backscattering eastern-boundary + time: bDetritus440_time + index_code: idTbry(ieast,iBdet(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus440_west # Input + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_detritus + long_name: detritus light backscattering at 440nm western boundary condition + units: meter-1 # [1/m] + field: detritus 440nm light backscattering western-boundary + time: bDetritus440_time + index_code: idTbry(iwest,iBdet(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus440_south # Input + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_detritus + long_name: detritus light backscattering at 440nm southern boundary condition + units: meter-1 # [1/m] + field: detritus 440nm light backscattering southern-boundary + time: bDetritus440_time + index_code: idTbry(isouth,iBdet(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus440_north # Input + standard_name: sea_water_light_optical_backscattering_at_440nm_due_to_detritus + long_name: detritus light backscattering at 440nm northern boundary condition + units: meter-1 # [1/m] + field: detritus 440nm light backscattering northern-boundary + time: bDetritus440_time + index_code: idTbry(inorth,iBdet(i440n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus510_east # Input + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_detritus + long_name: detritus light backscattering at 510nm eastern boundary condition + units: meter-1 # [1/m] + field: detritus 510nm light backscattering eastern-boundary + time: bDetritus510_time + index_code: idTbry(ieast,iBdet(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus510_west # Input + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_detritus + long_name: detritus light backscattering at 510nm western boundary condition + units: meter-1 # [1/m] + field: detritus 510nm light backscattering western-boundary + time: bDetritus510_time + index_code: idTbry(iwest,iBdet(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus510_south # Input + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_detritus + long_name: detritus light backscattering at 510nm southern boundary condition + units: meter-1 # [1/m] + field: detritus 510nm light backscattering southern-boundary + time: bDetritus510_time + index_code: idTbry(isouth,iBdet(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + + - variable: bDetritus510_north # Input + standard_name: sea_water_light_optical_backscattering_at_510nm_due_to_detritus + long_name: detritus light backscattering at 510nm northern boundary condition + units: meter-1 # [1/m] + field: detritus 510nm light backscattering northern-boundary + time: bDetritus510_time + index_code: idTbry(inorth,iBdet(i510n)) + type: nulvar + add_offset: 0.0d0 + scale: 1.0d0 + ############################################ ### EcoSim bio-optical Model Variables ### ### NO3, NH4, and PO4 already defined ### diff --git a/ROMS/Functionals/ana_biology.h b/ROMS/Functionals/ana_biology.h index d457f3f4..52271292 100644 --- a/ROMS/Functionals/ana_biology.h +++ b/ROMS/Functionals/ana_biology.h @@ -195,6 +195,38 @@ END DO END DO +#elif defined IOP_CDOM +! +!----------------------------------------------------------------------- +! IOP-based, CDOM (Colored Dissolver Organic Matter) ecosystem model. +!----------------------------------------------------------------------- +! + DO itrc=1,NBT + DO k=1,N(ng) + DO j=JstrT,JendT + DO i=IstrT,IendT + t(i,j,k,1,idbio(itrc))=BioIni(idbio(itrc),ng) + END DO + END DO + END DO + END DO + +#elif defined NPZD_IOP +! +!----------------------------------------------------------------------- +! IOP-based, NPZD ecosystem model. +!----------------------------------------------------------------------- +! + DO itrc=1,NBT + DO k=1,N(ng) + DO j=JstrT,JendT + DO i=IstrT,IendT + t(i,j,k,1,idbio(itrc))=BioIni(idbio(itrc),ng) + END DO + END DO + END DO + END DO + #elif defined NPZD_FRANKS || defined NPZD_POWELL ! !----------------------------------------------------------------------- diff --git a/ROMS/Include/cppdefs.h b/ROMS/Include/cppdefs.h index b6669ab1..f0449333 100644 --- a/ROMS/Include/cppdefs.h +++ b/ROMS/Include/cppdefs.h @@ -468,6 +468,11 @@ ** HYPOXIA_SRM if Hypoxia Simple Respiration Model ** ** OCMIP_OXYGEN_SC if O2 Schmidt number from Keeling et al. (1998) ** ** ** +** IOP-based, ecosystem model OPTIONS: ** +** ** +** IOP_CDOM if IOP-based CDOM ecosystem model ** +** NPZD_IOP if IOP-based NPZD ecosystem model ** +** ** ** NPZD biology model OPTIONS: ** ** ** ** NPZD_FRANKS if NPZD Biology model, Franks et al. (1986) ** diff --git a/ROMS/Include/globaldefs.h b/ROMS/Include/globaldefs.h index 69010bfd..0cd10aa5 100644 --- a/ROMS/Include/globaldefs.h +++ b/ROMS/Include/globaldefs.h @@ -799,8 +799,10 @@ #if defined BIO_FENNEL || \ defined ECOSIM || \ defined HYPOXIA_SRM || \ + defined IOP_CDOM || \ defined NEMURO || \ defined NPZD_FRANKS || \ + defined NPZD_IOP || \ defined NPZD_IRON || \ defined NPZD_POWELL || \ defined RED_TIDE diff --git a/ROMS/Modules/mod_biology.F b/ROMS/Modules/mod_biology.F index 3816bb03..55c54c16 100644 --- a/ROMS/Modules/mod_biology.F +++ b/ROMS/Modules/mod_biology.F @@ -20,8 +20,10 @@ ** ecosim.h ECOSIM ** ** fennel.h BIO_FENNEL ** ** hypoxia_srm.h HYPOXIA_SRM ** +** iop_cdom_mod.h IOP_CDOM ** ** nemuro.h NEMURO ** ** npzd_Franks.h NPZD_FRANKS ** +** npzd_iop.h NPZD_IOP ** ** npzd_iron.h NPZD_IRON ** ** npzd_Powell.h NPZD_POWELL ** ** red_tide.h RED_TIDE ** @@ -31,8 +33,10 @@ ** ecosim_mod.h ** ** fennel_mod.h ** ** hypoxia_srm_mod.h ** +** iop_cdom_mod.h ** ** nemuro_mod.h ** ** npzd_Franks_mod.h ** +** npzd_iop_mod.h ** ** npzd_iron_mod.h ** ** npzd_Powell_mod.h ** ** red_tide_mod.h ** @@ -42,8 +46,10 @@ ** ecosim.in ** ** bio_Fennel.in ** ** hypoxia_srm.in ** +** iop_cdom.in ** ** nemuro.in ** ** npzd_Franks.in ** +** npzd_iop.in ** ** npzd_iron.in ** ** npzd_Powell.in ** ** red_tide.in ** @@ -53,8 +59,10 @@ ** ecosim_inp.h ** ** fennel_inp.h ** ** hypoxia_srm_inp.h ** +** iop_cdom_inp.h ** ** nemuro_inp.h ** ** npzd_Franks_inp.h ** +** npzd_iop_inp.h ** ** npzd_iron_inp.h ** ** npzd_Powell_inp.h ** ** red_tide_inp.h ** @@ -65,8 +73,10 @@ ** ecosim_var.h ** ** fennel_var.h ** ** hypoxia_srm_var.h ** +** iop_cdom_var.h ** ** nemuro_var.h ** ** npzd_Franks_var.h ** +** npzd_iop_var.h ** ** npzd_iron_var.h ** ** npzd_Powell_var.h ** ** red_tide_var.h ** @@ -77,8 +87,10 @@ ** ecosim_def.h ** ** fennel_def.h ** ** hypoxia_srm_def.h ** +** iop_cdom_def.h ** ** nemuro_def.h ** ** npzd_Franks_def.h ** +** npzd_iop_def.h ** ** npzd_iron_def.h ** ** npzd_Powell_def.h ** ** red_tide_def.h ** @@ -89,8 +101,10 @@ ** ecosim_wrt.h ** ** fennel_wrt.h ** ** hypoxia_srm_wrt.h ** +** iop_cdom_wrt.h ** ** nemuro_wrt.h ** ** npzd_Franks_wrt.h ** +** npzd_iop_wrt.h ** ** npzd_iron_wrt.h ** ** npzd_Powell_wrt.h ** ** red_tide_wrt.h ** @@ -111,10 +125,14 @@ # include # elif defined HYPOXIA_SRM # include +# elif defined IOP_CDOM +# include # elif defined NEMURO # include # elif defined NPZD_FRANKS # include +# elif defined NPZD_IOP +# include # elif defined NPZD_IRON # include # elif defined NPZD_POWELL diff --git a/ROMS/Modules/mod_ncparam.F b/ROMS/Modules/mod_ncparam.F index d28d6bff..141428a2 100644 --- a/ROMS/Modules/mod_ncparam.F +++ b/ROMS/Modules/mod_ncparam.F @@ -2363,8 +2363,12 @@ SUBROUTINE initialize_ncparam # include # elif defined HYPOXIA_SRM # include +# elif defined IOP_CDOM +# include # elif defined NEMURO # include +# elif defined NPZD_IOP +# include # elif defined NPZD_FRANKS # include # elif defined NPZD_POWELL diff --git a/ROMS/Nonlinear/Biology/biology.F b/ROMS/Nonlinear/Biology/biology.F index 2bf398e1..34005a4c 100644 --- a/ROMS/Nonlinear/Biology/biology.F +++ b/ROMS/Nonlinear/Biology/biology.F @@ -15,8 +15,10 @@ ** ecosim.h ECOSIM ** ** fennel.h BIO_FENNEL ** ** hypoxia_srm.h HYPOXIA_SRM ** +** iop_cdom.h IOP_CDOM ** ** nemuro.h NEMURO ** ** npzd_Franks.h NPZD_FRANKS ** +** npzd_iop.h NPZD_IOP ** ** npzd_iron.h NPZD_IRON ** ** npzd_Powell.h NPZD_POWELL ** ** red_tide.h RED_TIDE ** @@ -26,8 +28,10 @@ ** ecosim_mod.h ** ** fennel_mod.h ** ** hypoxia_srm_mod.h ** +** iop_cdom_mod.h ** ** nemuro_mod.h ** ** npzd_Franks_mod.h ** +** npzd_iop_mod.h ** ** npzd_iron_mod.h ** ** npzd_Powell_mod.h ** ** red_tide_mod.h ** @@ -37,8 +41,10 @@ ** ecosim.in ** ** bio_Fennel.in ** ** hypoxia_srm.in ** +** iop_cdom.in ** ** nemuro.in ** ** npzd_Franks.in ** +** npzd_iop.in ** ** npzd_iron.in ** ** npzd_Powell.in ** ** red_tide.in ** @@ -48,8 +54,10 @@ ** ecosim_inp.h ** ** fennel_inp.h ** ** hypoxia_srm_inp.h ** +** iop_cdom_inp.h ** ** nemuro_inp.h ** ** npzd_Franks_inp.h ** +** npzd_iop_inp.h ** ** npzd_iron_inp.h ** ** npzd_Powell_inp.h ** ** red_tide_inp.h ** @@ -60,8 +68,10 @@ ** ecosim_var.h ** ** fennel_var.h ** ** hypoxia_srm_var.h ** +** iop_cdom_var.h ** ** nemuro_var.h ** ** npzd_Franks_var.h ** +** npzd_iop_var.h ** ** npzd_iron_var.h ** ** npzd_Powell_var.h ** ** red_tide_var.h ** @@ -72,8 +82,10 @@ ** ecosim_def.h ** ** fennel_def.h ** ** hypoxia_srm_def.h ** +** iop_cdom_def.h ** ** nemuro_def.h ** ** npzd_Franks_def.h ** +** npzd_iop_def.h ** ** npzd_iron_def.h ** ** npzd_Powell_def.h ** ** red_tide_def.h ** @@ -84,8 +96,10 @@ ** ecosim_wrt.h ** ** fennel_wrt.h ** ** hypoxia_srm_wrt.h ** +** iop_cdom_wrt.h ** ** nemuro_wrt.h ** ** npzd_Franks_wrt.h ** +** npzd_iop_wrt.h ** ** npzd_iron_wrt.h ** ** npzd_Powell_wrt.h ** ** red_tide_wrt.h ** @@ -105,10 +119,14 @@ # include # elif defined HYPOXIA_SRM # include +# elif defined IOP_CDOM +# include # elif defined NEMURO # include # elif defined NPZD_FRANKS # include +# elif defined NPZD_IOP +# include # elif defined NPZD_IRON # include # elif defined NPZD_POWELL diff --git a/ROMS/Nonlinear/Biology/iop_cdom.h b/ROMS/Nonlinear/Biology/iop_cdom.h new file mode 100644 index 00000000..cdd49e0a --- /dev/null +++ b/ROMS/Nonlinear/Biology/iop_cdom.h @@ -0,0 +1,310 @@ + SUBROUTINE biology (ng,tile) +! +!git $Id$ +!****************************************************** Katja Fennel *** +! Copyright (c) 2002-2024 The ROMS/TOMS Group Hernan G. Arango ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!*********************************************************************** +! ! +! IOP-based, CDOM (Colored Dissolved Organic Matter) Model ! +! ! +! This routine computes the biological sources and sinks and adds ! +! then the global biological fields. ! +! ! +! It computes the absorption, scattering, and backscattering from ! +! the ecosystem variables. This facilitates direct comparisons ! +! between measuared and models IOPs (Inherent Optical Properties). ! +! It also possible to calculate remote sensing reflectances from ! +! model output for direct comparisons with remotely sensed ocean ! +! color (SeaWIFS, MODIS, etc) and data assimilation. ! +! ! +! Reference: ! +! ! +! Fennel, K., ... ! +! ! +!*********************************************************************** +! + USE mod_param + USE mod_forces + USE mod_grid + USE mod_ncparam + USE mod_ocean + USE mod_stepping +! +! Imported variable declarations. +! + integer, intent(in) :: ng, tile +! +! Local variable declarations. +! +#include "tile.h" +! +! Set header file name. +! +#ifdef DISTRIBUTE + IF (Lbiofile(iNLM)) THEN +#else + IF (Lbiofile(iNLM).and.(tile.eq.0)) THEN +#endif + Lbiofile(iNLM)=.FALSE. + BIONAME(iNLM)=__FILE__ + END IF +! +#ifdef PROFILE + CALL wclock_on (ng, iNLM, 15) +#endif + CALL biology_tile (ng, tile, & + & LBi, UBi, LBj, UBj, N(ng), NT(ng), & + & IminS, ImaxS, JminS, JmaxS, & + & nstp(ng), nnew(ng), & +#ifdef MASKING + & GRID(ng) % rmask, & +#endif + & GRID(ng) % Hz, & + & GRID(ng) % z_w, & + & FORCES(ng) % srflx, & + & OCEAN(ng) % t) + +#ifdef PROFILE + CALL wclock_off (ng, iNLM, 15) +#endif + + RETURN + END SUBROUTINE biology +! +!----------------------------------------------------------------------- + SUBROUTINE biology_tile (ng, tile, & + & LBi, UBi, LBj, UBj, UBk, UBt, & + & IminS, ImaxS, JminS, JmaxS, & + & nstp, nnew, & +#ifdef MASKING + & rmask, & +#endif + & Hz, z_w, & + & srflx, & + & t) +!----------------------------------------------------------------------- +! + USE mod_param + USE mod_biology + USE mod_ncparam + USE mod_scalars +! +! Imported variable declarations. +! + integer, intent(in) :: ng, tile + integer, intent(in) :: LBi, UBi, LBj, UBj, UBk, UBt + integer, intent(in) :: IminS, ImaxS, JminS, JmaxS + integer, intent(in) :: nstp, nnew + +#ifdef ASSUMED_SHAPE +# ifdef MASKING + real(r8), intent(in) :: rmask(LBi:,LBj:) +# endif + real(r8), intent(in) :: Hz(LBi:,LBj:,:) + real(r8), intent(in) :: z_w(LBi:,LBj:,0:) + real(r8), intent(in) :: srflx(LBi:,LBj:) + real(r8), intent(inout) :: t(LBi:,LBj:,:,:,:) +#else +# ifdef MASKING + real(r8), intent(in) :: rmask(LBi:UBi,LBj:UBj) +# endif + real(r8), intent(in) :: Hz(LBi:UBi,LBj:UBj,UBk) + real(r8), intent(in) :: z_w(LBi:UBi,LBj:UBj,0:UBk) + real(r8), intent(in) :: srflx(LBi:UBi,LBj:UBj) + real(r8), intent(inout) :: t(LBi:UBi,LBj:UBj,UBk,3,UBt) +#endif +! +! Local variable declarations. +! + integer :: Iter, i, ibio, itrc, j, k, nb + + real(r8) :: Att, ExpAtt, Itop, PAR + real(r8) :: cff, cff1, dtdays + + real(r8), dimension(IminS:ImaxS) :: PARsur + + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio_old + + real(r8), dimension(IminS:ImaxS,N(ng)) :: Hz_inv + real(r8), dimension(IminS:ImaxS,N(ng)) :: Light + +#include "set_bounds.h" +! +!----------------------------------------------------------------------- +! Add biological Source/Sink terms. +!----------------------------------------------------------------------- +! +! Set time-stepping size (days) according to the number of iterations. +! + dtdays=dt(ng)*sec2day/REAL(BioIter(ng),r8) +! +! Start pipelined J-loop. +! + J_LOOP : DO j=Jstr,Jend +! +! Compute inverse thickness to avoid repeated divisions. +! + DO k=1,N(ng) + DO i=Istr,Iend + Hz_inv(i,k)=1.0_r8/Hz(i,j,k) + END DO + END DO +! +! Extract biological variables from tracer arrays, place them into +! scratch arrays, and restrict their values to be positive definite. +! At input, all tracers (index nnew) from predictor step have +! transport units (m Tunits) since we do not have yet the new +! values for zeta and Hz. These are known after the 2D barotropic +! time-stepping. +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,ibio)=MAX(0.0_r8,t(i,j,k,nstp,ibio)) + Bio_old(i,k,ibio)=Bio(i,k,ibio) + END DO + END DO + END DO +! +! Calculate surface Photosynthetically Available Radiation (PAR). The +! net shortwave radiation is scaled back to Watts/m2 and multiplied by +! the fraction that is photosynthetically available, PARfrac. +! + DO i=Istr,Iend + PARsur(i)=PARfrac(ng)*srflx(i,j)*rho0*Cp + END DO +! +!======================================================================= +! Start internal iterations to achieve convergence of the nonlinear +! backward-implicit solution. +!======================================================================= +! +! During the iterative procedure a series of fractional time steps are +! performed in a chained mode (splitting by different biological +! conversion processes) in sequence of the main food chain. In all +! stages the concentration of the component being consumed is treated +! in a fully implicit manner, so the algorithm guarantees non-negative +! values, no matter how strong the concentration of active consuming +! component (Phytoplankton or Zooplankton). The overall algorithm, +! as well as any stage of it, is formulated in conservative form +! (except explicit sinking) in sense that the sum of concentration of +! all components is conserved. +! +! In the implicit algorithm, we have for example (N: nutrient, +! P: phytoplankton), +! +! N(new) = N(old) - uptake * P(old) uptake = mu * N / (Kn + N) +! {Michaelis-Menten} +! below, we set +! The N in the numerator of +! cff = mu * P(old) / (Kn + N(old)) uptake is treated implicitly +! as N(new) +! +! so the time-stepping of the equations becomes: +! +! N(new) = N(old) / (1 + cff) (1) when substracting a sink term, +! consuming, divide by (1 + cff) +! and +! +! P(new) = P(old) + cff * N(new) (2) when adding a source term, +! growing, add (cff * source) +! +! Notice that if you substitute (1) in (2), you will get: +! +! P(new) = P(old) + cff * N(old) / (1 + cff) (3) +! +! If you add (1) and (3), you get +! +! N(new) + P(new) = N(old) + P(old) +! +! implying conservation regardless how "cff" is computed. Therefore, +! this scheme is unconditionally stable regardless of the conversion +! rate. It does not generate negative values since the constituent +! to be consumed is always treated implicitly. It is also biased +! toward damping oscillations. +! +! The iterative loop below is to iterate toward an universal Backward- +! Euler treatment of all terms. So if there are oscillations in the +! system, they are only physical oscillations. These iterations, +! however, do not improve the accuaracy of the solution. +! + ITER_LOOP: DO Iter=1,BioIter(ng) +! +! Compute light attenuation as function of depth. +! + DO i=Istr,Iend + PAR=PARsur(i) + IF (PARsur(i).gt.0.0_r8) THEN ! day time + DO k=N(ng),1,-1 +! +! Attenuate the light to the center of the grid cell. Here, AttSW is +! the light attenuation due to seawater and CDOM_LightAtt is the light +! attenuation due to CDOM absorption. +! + Att=(AttSW(ng)+ & + & CDOM_LightAtt(ng)*Bio(i,k,aCDOM(i440n)))* & + & (z_w(i,j,k)-z_w(i,j,k-1)) + ExpAtt=EXP(-Att) + Itop=PAR + PAR=Itop*(1.0_r8-ExpAtt)/Att ! average at cell center + Light(i,k)=PAR +! +! Light attenuation at the bottom of the grid cell. It is the starting +! PAR value for the next (deeper) vertical grid cell. +! + PAR=Itop*ExpAtt + END DO + ELSE ! night time + DO k=1,N(ng) + Light(i,k)=0.0_r8 + END DO + END IF + END DO +! +! Degradation of CDOM absorption, aCDOM. +! + cff1=dtdays*CDOM_sigma(ng) + DO k=1,N(ng) + DO i=Istr,Iend + cff=cff1*Light(i,k) + DO nb=1,NBands + Bio(i,k,aCDOM(nb))=Bio(i,k,aCDOM(nb))/(1.0_r8+cff) + END DO + END DO + END DO + + END DO ITER_LOOP +! +!----------------------------------------------------------------------- +! Update global tracer variables: Add increment due to BGC processes +! to tracer array in time index "nnew". Index "nnew" is solution after +! advection and mixing and has transport units (m Tunits) hence the +! increment is multiplied by Hz. Notice that we need to subtract +! original values "Bio_old" at the top of the routine to just account +! for the concentractions affected by BGC processes. This also takes +! into account any constraints (non-negative concentrations, carbon +! concentration range) specified before entering BGC kernel. If "Bio" +! were unchanged by BGC processes, the increment would be exactly +! zero. Notice that final tracer values, t(:,:,:,nnew,:) are not +! bounded >=0 so that we can preserve total inventory of nutrients +! when advection causes tracer concentration to go negative. +!----------------------------------------------------------------------- +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + cff=Bio(i,k,ibio)-Bio_old(i,k,ibio) + t(i,j,k,nnew,ibio)=t(i,j,k,nnew,ibio)+cff*Hz(i,j,k) + END DO + END DO + END DO + + END DO J_LOOP + + RETURN + END SUBROUTINE biology_tile diff --git a/ROMS/Nonlinear/Biology/iop_cdom_def.h b/ROMS/Nonlinear/Biology/iop_cdom_def.h new file mode 100644 index 00000000..dac17a92 --- /dev/null +++ b/ROMS/Nonlinear/Biology/iop_cdom_def.h @@ -0,0 +1,53 @@ +/* +** git $Id$ +*************************************************** Hernan G. Arango *** +** Copyright (c) 2002-2024 The ROMS/TOMS Group ** +** Licensed under a MIT/X style license ** +** See License_ROMS.md ** +************************************************************************ +** ** +** Defines IOP-based, CDOM ecosystem model input parameters in ** +** output NetCDF files. It is included in routine "def_info.F". ** +** ** +************************************************************************ +*/ + +! +! Define IOP-based, CDOM ecosystem model parameters. +! + Vinfo( 1)='BioIter' + Vinfo( 2)='number of iterations to achieve convergence' + status=def_var(ng, model, ncid, varid, nf90_int, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='PARfrac' + Vinfo( 2)='photosynthetically available radiation fraction' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='AttSW' + Vinfo( 2)='light attenuation due to sea water' + Vinfo( 3)='meter-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='CDOM_LightAtt' + Vinfo( 2)='light attenuation due to CDOM' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='CDOM_sigma' + Vinfo( 2)='light-dependent degradation rate for CDOM' + Vinfo( 3)='watt-1 m2 day-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN diff --git a/ROMS/Nonlinear/Biology/iop_cdom_def_pio.h b/ROMS/Nonlinear/Biology/iop_cdom_def_pio.h new file mode 100644 index 00000000..68177e75 --- /dev/null +++ b/ROMS/Nonlinear/Biology/iop_cdom_def_pio.h @@ -0,0 +1,53 @@ +/* +** git $Id$ +*************************************************** Hernan G. Arango *** +** Copyright (c) 2002-2024 The ROMS/TOMS Group ** +** Licensed under a MIT/X style license ** +** See License_ROMS.md ** +************************************************************************ +** ** +** Defines IOP-based, CDOM ecosystem model input parameters in ** +** output NetCDF files. It is included in routine "def_info.F". ** +** ** +************************************************************************ +*/ + +! +! Define IOP-based, CDOM ecosystem model parameters. +! + Vinfo( 1)='BioIter' + Vinfo( 2)='number of iterations to achieve convergence' + status=def_var(ng, model, pioFile, pioVar, PIO_int, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='PARfrac' + Vinfo( 2)='photosynthetically available radiation fraction' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='AttSW' + Vinfo( 2)='light attenuation due to sea water' + Vinfo( 3)='meter-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='CDOM_LightAtt' + Vinfo( 2)='light attenuation due to CDOM' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='CDOM_sigma' + Vinfo( 2)='light-dependent degradation rate for CDOM' + Vinfo( 3)='watt-1 m2 day-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN diff --git a/ROMS/Nonlinear/Biology/iop_cdom_inp.h b/ROMS/Nonlinear/Biology/iop_cdom_inp.h new file mode 100644 index 00000000..290f1175 --- /dev/null +++ b/ROMS/Nonlinear/Biology/iop_cdom_inp.h @@ -0,0 +1,712 @@ + SUBROUTINE read_BioPar (model, inp, out, Lwrite) +! +!git $Id$ +!================================================== Hernan G. Arango === +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!======================================================================= +! ! +! This routine reads in IOP-based, CDOM ecosystem model input ! +! parameters. They are specified in input script "cdom.in". ! +! ! +!======================================================================= +! + USE mod_param + USE mod_parallel + USE mod_biology + USE mod_ncparam + USE mod_scalars +! + USE inp_decode_mod +! + implicit none +! +! Imported variable declarations +! + logical, intent(in) :: Lwrite + integer, intent(in) :: model, inp, out +! +! Local variable declarations. +! + integer :: Npts, Nval + integer :: iTrcStr, iTrcEnd + integer :: i, ifield, igrid, itracer, itrc, ng, nline, status + + logical, dimension(NBT,Ngrids) :: Ltrc + + real(r8), dimension(Ngrids) :: Gbio + + real(r8), dimension(NBT,Ngrids) :: Rbio + + real(r8), dimension(nRval) :: Rval + + character (len=40 ) :: KeyWord + character (len=256) :: line + character (len=256), dimension(nCval) :: Cval +! +!----------------------------------------------------------------------- +! Initialize. +!----------------------------------------------------------------------- +! + igrid=1 ! nested grid counter + itracer=0 ! LBC tracer counter + iTrcStr=1 ! first LBC tracer to process + iTrcEnd=NBT ! last LBC tracer to process + nline=0 ! LBC multi-line counter +! +!----------------------------------------------------------------------- +! Read in IOP-based CDOM biological model parameters. +!----------------------------------------------------------------------- +! +#ifdef ANA_BIOLOGY + IF (.not.allocated(BioIni)) allocate ( BioIni(MT,Ngrids) ) +#endif + DO WHILE (.TRUE.) + READ (inp,'(a)',ERR=10,END=20) line + status=decode_line(line, KeyWord, Nval, Cval, Rval) + IF (status.gt.0) THEN + IF (TRIM(KeyWord).eq.'Lbiology') THEN + Npts=load_l(Nval, Cval, Ngrids, Lbiology) + ELSE IF (TRIM(KeyWord).eq.'BioIter') THEN + Npts=load_i(Nval, Rval, Ngrids, BioIter) +#ifdef ANA_BIOLOGY + ELSE IF (TRIM(KeyWord).eq.'BioIni(i440n)') THEN + Npts=load_r(Nval, Rval, Ngrids, Gbio) + DO ng=1,Ngrids + i=aCDOM(i440n) + BioIni(i,ng)=Gbio(ng) + END DO + ELSE IF (TRIM(KeyWord).eq.'BioIni(i510n)') THEN + Npts=load_r(Nval, Rval, Ngrids, Gbio) + DO ng=1,Ngrids + i=aCDOM(i510n) + BioIni(i,ng)=Gbio(ng) + END DO +#endif + ELSE IF (TRIM(KeyWord).eq.'AttSW') THEN + Npts=load_r(Nval, Rval, Ngrids, AttSW) + ELSE IF (TRIM(KeyWord).eq.'PARfrac') THEN + Npts=load_r(Nval, Rval, Ngrids, PARfrac) + ELSE IF (TRIM(KeyWord).eq.'CDOM_LightAtt') THEN + Npts=load_r(Nval, Rval, Ngrids, CDOM_LightAtt) + ELSE IF (TRIM(KeyWord).eq.'CDOM_sigma') THEN + Npts=load_r(Nval, Rval, Ngrids, CDOM_sigma) + ELSE IF (TRIM(KeyWord).eq.'TNU2') THEN + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + nl_tnu2(i,ng)=Rbio(itrc,ng) + END DO + END DO + ELSE IF (TRIM(KeyWord).eq.'TNU4') THEN + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + nl_tnu4(i,ng)=Rbio(itrc,ng) + END DO + END DO + ELSE IF (TRIM(KeyWord).eq.'ad_TNU2') THEN + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + ad_tnu2(i,ng)=Rbio(itrc,ng) + tl_tnu2(i,ng)=Rbio(itrc,ng) + END DO + END DO + ELSE IF (TRIM(KeyWord).eq.'ad_TNU4') THEN + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + ad_tnu4(i,ng)=Rbio(itrc,ng) + tl_tnu4(i,ng)=Rbio(itrc,ng) + END DO + END DO + ELSE IF (TRIM(KeyWord).eq.'AKT_BAK') THEN + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + Akt_bak(i,ng)=Rbio(itrc,ng) + END DO + END DO + ELSE IF (TRIM(KeyWord).eq.'ad_AKT_fac') THEN + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + ad_Akt_fac(i,ng)=Rbio(itrc,ng) + tl_Akt_fac(i,ng)=Rbio(itrc,ng) + END DO + END DO + ELSE IF (TRIM(KeyWord).eq.'TNUDG') THEN + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + Tnudg(i,ng)=Rbio(itrc,ng) + END DO + END DO + CASE ('LBC(isTvar)') + IF (itracer.lt.NBT) THEN + itracer=itracer+1 + ELSE + itracer=1 ! next nested grid + END IF + ifield=isTvar(idbio(itracer)) + Npts=load_lbc(Nval, Cval, line, nline, ifield, igrid, & + & iTrcStr, iTrcEnd, LBC) +#if defined ADJOINT || defined TANGENT || defined TL_IOMS + CASE ('ad_LBC(isTvar)') + IF (itracer.lt.NBT) THEN + itracer=itracer+1 + ELSE + itracer=1 ! next nested grid + END IF + ifield=isTvar(idbio(itracer)) + Npts=load_lbc(Nval, Cval, line, nline, ifield, igrid, & + & iTrcStr, iTrcEnd, ad_LBC) +#endif +#ifdef TCLIMATOLOGY + CASE ('LtracerCLM') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + LtracerCLM(i,ng)=Ltrc(itrc,ng) + END DO + END DO +#endif +#ifdef TS_PSOURCE + ELSE IF (TRIM(KeyWord).eq.'LtracerSrc') THEN + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + LtracerSrc(i,ng)=Ltrc(itrc,ng) + END DO + END DO +#endif + ELSE IF (TRIM(KeyWord).eq.'Hout(idTvar)') THEN + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTvar(idbio(itrc)) + IF (i.eq.0) THEN + IF (Master) WRITE (out,30) & + & 'idTvar(idbio(', itrc, '))' + exit_flag=5 + RETURN + END IF + Hout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + ELSE IF (TRIM(KeyWord).eq.'Hout(idTsur)') THEN + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTsur(idbio(itrc)) + IF (i.eq.0) THEN + IF (Master) WRITE (out,30) & + & 'idTsur(idbio(', itrc, '))' + exit_flag=5 + RETURN + END IF + Hout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Qout(idTvar)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTvar(idbio(itrc)) + Qout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Qout(idsurT)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idsurT(idbio(itrc)) + IF (i.eq.0) THEN + IF (Master) WRITE (out,30) & + & 'idsurT(idbio(', itrc, '))' + exit_flag=5 + RETURN + END IF + Qout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Qout(idTsur)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTsur(idbio(itrc)) + Qout(i,ng)=Ltrc(itrc,ng) + END DO + END DO +#if defined AVERAGES || \ + (defined AD_AVERAGES && defined ADJOINT) || \ + (defined RP_AVERAGES && defined TL_IOMS) || \ + (defined TL_AVERAGES && defined TANGENT) + CASE ('Aout(idTvar)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTvar(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Aout(idTTav)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTTav(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Aout(idUTav)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idUTav(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Aout(idVTav)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idVTav(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Aout(iHUTav)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=iHUTav(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Aout(iHVTav)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=iHVTav(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO +#endif +#ifdef DIAGNOSTICS_TS + CASE ('Dout(iTrate)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTrate),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iThadv)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iThadv),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iTxadv)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTxadv),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iTyadv)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTyadv),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iTvadv)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTvadv),ng)=Ltrc(i,ng) + END DO + END DO +# if defined TS_DIF2 || defined TS_DIF4 + CASE ('Dout(iThdif)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iThdif),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iTxdif)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTxdif),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iTydif)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTydif),ng)=Ltrc(i,ng) + END DO + END DO +# if defined MIX_GEO_TS || defined MIX_ISO_TS + CASE ('Dout(iTsdif)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTsdif),ng)=Ltrc(i,ng) + END DO + END DO +# endif +# endif + CASE ('Dout(iTvdif)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTvdif),ng)=Ltrc(i,ng) + END DO + END DO +#endif + END SELECT + END IF + END DO + 10 IF (Master) WRITE (out,40) line + exit_flag=4 + RETURN + 20 CONTINUE +! +!----------------------------------------------------------------------- +! Report input parameters. +!----------------------------------------------------------------------- +! + IF (Lwrite) THEN + DO ng=1,Ngrids + IF (Lbiology(ng)) THEN + WRITE (out,50) ng + WRITE (out,60) BioIter(ng), 'BioIter', & + & 'Number of iterations for nonlinear convergence.' +#ifdef ANA_BIOLOGY + WRITE (out,70) BioIni(aCDOM(i440n),ng), & + & 'BioIni(i440n)', & + & 'CDOM absorption at 440nm (1/m).' + WRITE (out,70) BioIni(aCDOM(i510n),ng), & + & 'BioIni(i510n)', & + & 'CDOM absorption at 510nm (1/m).' +#endif + WRITE (out,70) AttSW(ng), 'AttSW', & + & 'Light attenuation of seawater (m-1).' + WRITE (out,80) PARfrac(ng), 'PARfrac', & + & 'Fraction of shortwave radiation that is', & + & 'photosynthetically active (nondimensional).' + WRITE (out,80) CDOM_LightAtt(ng), 'CDOM_LightAtt', & + & 'Factor for light attenuation due to CDOM', & + & '(nondimensional).' + WRITE (out,80) CDOM_sigma(ng), 'CDOM_sigma', & + & 'Light dependent degradation term for CDOM', & + & '(1/(W m-2 d)).' +#ifdef TS_DIF2 + DO itrc=1,NBT + i=idbio(itrc) + WRITE (out,90) nl_tnu2(i,ng), 'nl_tnu2', i, & + & 'NLM horizontal, harmonic mixing coefficient', & + & '(m2/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# ifdef ADJOINT + WRITE (out,90) ad_tnu2(i,ng), 'ad_tnu2', i, & + & 'ADM horizontal, harmonic mixing coefficient', & + & '(m2/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif +# if defined TANGENT || defined TL_IOMS + WRITE (out,90) tl_tnu2(i,ng), 'tl_tnu2', i, & + & 'TLM horizontal, harmonic mixing coefficient', & + & '(m2/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif + END DO +#endif +#ifdef TS_DIF4 + DO itrc=1,NBT + i=idbio(itrc) + WRITE (out,90) nl_tnu4(i,ng), 'nl_tnu4', i, & + & 'NLM horizontal, biharmonic mixing coefficient', & + & '(m4/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# ifdef ADJOINT + WRITE (out,90) ad_tnu4(i,ng), 'ad_tnu4', i, & + & 'ADM horizontal, biharmonic mixing coefficient', & + & '(m4/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif +# if defined TANGENT || defined TL_IOMS + WRITE (out,90) tl_tnu4(i,ng), 'tl_tnu4', i, & + & 'TLM horizontal, biharmonic mixing coefficient', & + & '(m4/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif + END DO +#endif + DO itrc=1,NBT + i=idbio(itrc) + WRITE(out,90) Akt_bak(i,ng), 'Akt_bak', i, & + & 'Background vertical mixing coefficient (m2/s)', & + & 'for tracer ', i, TRIM(Vname(1,idTvar(i))) + END DO +#ifdef FORWARD_MIXING + DO itrc=1,NBT + i=idbio(itrc) +# ifdef ADJOINT + WRITE (out,90) ad_Akt_fac(i,ng), 'ad_Akt_fac', i, & + & 'ADM basic state vertical mixing scale factor', & + & 'for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif +# if defined TANGENT || defined TL_IOMS + WRITE (out,90) tl_Akt_fac(i,ng), 'tl_Akt_fac', i, & + & 'TLM basic state vertical mixing scale factor', & + & 'for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif + END DO +#endif +#ifdef TS_PSOURCE + DO itrc=1,NBT + i=idbio(itrc) + WRITE (out,100) LtracerSrc(i,ng), 'LtracerSrc', & + & i, 'Processing point sources/Sink on tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO +#endif + DO itrc=1,NBT + i=idbio(itrc) + WRITE (out,90) Tnudg(i,ng), 'Tnudg', i, & + & 'Nudging/relaxation time scale (days)', & + & 'for tracer ', i, TRIM(Vname(1,idTvar(i))) + END DO + IF ((nHIS(ng).gt.0).and.ANY(Hout(:,ng))) THEN + WRITE (out,'(1x)') + DO itrc=1,NBT + i=idbio(itrc) + IF (Hout(idTvar(i),ng)) WRITE (out,110) & + & Hout(idTvar(i),ng), 'Hout(idTvar)', & + & 'Write out tracer ', i, TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Hout(idTsur(i),ng)) WRITE (out,110) & + & Hout(idTsur(i),ng), 'Hout(idTsur)', & + & 'Write out tracer flux ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + END IF + IF ((nQCK(ng).gt.0).and.ANY(Qout(:,ng))) THEN + WRITE (out,'(1x)') + DO itrc=1,NBT + i=idbio(itrc) + IF (Qout(idTvar(i),ng)) WRITE (out,110) & + & Qout(idTvar(i),ng), 'Qout(idTvar)', & + & 'Write out tracer ', i, TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Qout(idsurT(i),ng)) WRITE (out,110) & + & Qout(idsurT(i),ng), 'Qout(idsurT)', & + & 'Write out surface tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Qout(idTsur(i),ng)) WRITE (out,110) & + & Qout(idTsur(i),ng), 'Qout(idTsur)', & + & 'Write out tracer flux ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + END IF +#if defined AVERAGES || \ + (defined AD_AVERAGES && defined ADJOINT) || \ + (defined RP_AVERAGES && defined TL_IOMS) || \ + (defined TL_AVERAGES && defined TANGENT) + IF ((nAVG(ng).gt.0).and.ANY(Aout(:,ng))) THEN + WRITE (out,'(1x)') + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(idTvar(i),ng)) WRITE (out,110) & + & Aout(idTvar(i),ng), 'Aout(idTvar)', & + & 'Write out averaged tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(idTTav(i),ng)) WRITE (out,110) & + & Aout(idTTav(i),ng), 'Aout(idTTav)', & + & 'Write out averaged for tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(idUTav(i),ng)) WRITE (out,110) & + & Aout(idUTav(i),ng), 'Aout(idUTav)', & + & 'Write out averaged for tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(idVTav(i),ng)) WRITE (out,110) & + & Aout(idVTav(i),ng), 'Aout(idVTav)', & + & 'Write out averaged for tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(iHUTav(i),ng)) WRITE (out,110) & + & Aout(iHUTav(i),ng), 'Aout(iHUTav)', & + & 'Write out averaged for tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(iHVTav(i),ng)) WRITE (out,110) & + & Aout(iHVTav(i),ng), 'Aout(iHVTav)', & + & 'Write out averaged for tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + END IF +#endif +#ifdef DIAGNOSTICS_TS + IF ((nDIA(ng).gt.0).and.ANY(Dout(:,ng))) THEN + WRITE (out,'(1x)') + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTrate),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTrate)', & + & 'Write out rate of change of tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iThadv),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iThadv)', & + & 'Write out horizontal advection, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTxadv),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTxadv)', & + & 'Write out horizontal X-advection, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTyadv),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTyadv)', & + & 'Write out horizontal Y-advection, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTvadv),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTvadv)', & + & 'Write out vertical advection, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO +# if defined TS_DIF2 || defined TS_DIF4 + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iThdif),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iThdif)', & + & 'Write out horizontal diffusion, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(i,iTxdif),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTxdif)', & + & 'Write out horizontal X-diffusion, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTydif),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTydif)', & + & 'Write out horizontal Y-diffusion, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO +# if defined MIX_GEO_TS || defined MIX_ISO_TS + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTsdif),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTsdif)', & + & 'Write out horizontal S-diffusion, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO +# endif +# endif + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTvdif),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTvdif)', & + & 'Write out vertical diffusion, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + END IF +#endif + END IF + END DO + END IF +! +!----------------------------------------------------------------------- +! Rescale biological tracer parameters +!----------------------------------------------------------------------- +! +! Take the square root of the biharmonic coefficients so it can +! be applied to each harmonic operator. +! + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + nl_tnu4(i,ng)=SQRT(ABS(nl_tnu4(i,ng))) +#ifdef ADJOINT + ad_tnu4(i,ng)=SQRT(ABS(ad_tnu4(i,ng))) +#endif +#if defined TANGENT || defined TL_IOMS + tl_tnu4(i,ng)=SQRT(ABS(tl_tnu4(i,ng))) +#endif +! +! Compute inverse nudging coefficients (1/s) used in various tasks. +! + IF (Tnudg(i,ng).gt.0.0_r8) THEN + Tnudg(i,ng)=1.0_r8/(Tnudg(i,ng)*86400.0_r8) + ELSE + Tnudg(i,ng)=0.0_r8 + END IF + END DO + END DO + + 30 FORMAT (/,' read_BioPar - variable info not yet loaded, ', & + & a,i2.2,a) + 40 FORMAT (/,' read_BioPar - Error while processing line: ',/,a) + 50 FORMAT (/,/,' CDOM Model Parameters, Grid: ',i2.2, & + & /, ' ==================================',/) + 60 FORMAT (1x,i10,2x,a,t30,a) + 70 FORMAT (1p,e11.4,2x,a,t30,a) + 80 FORMAT (1p,e11.4,2x,a,t30,a,/,t32,a) + 90 FORMAT (1p,e11.4,2x,a,'(',i2.2,')',t30,a,/,t32,a,i2.2,':',1x,a) + 100 FORMAT (10x,l1,2x,a,'(',i2.2,')',t30,a,i2.2,':',1x,a) + 110 FORMAT (10x,l1,2x,a,t30,a,i2.2,':',1x,a) + + RETURN + END SUBROUTINE read_BioPar diff --git a/ROMS/Nonlinear/Biology/iop_cdom_mod.h b/ROMS/Nonlinear/Biology/iop_cdom_mod.h new file mode 100644 index 00000000..4cae1435 --- /dev/null +++ b/ROMS/Nonlinear/Biology/iop_cdom_mod.h @@ -0,0 +1,132 @@ +! +!git $Id$ +!================================================== Hernan G. Arango === +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!======================================================================= +! ! +! Parameters for IOP-based, CDOM ecosystem model: ! +! ! +! AttSW Light attenuation due to sea water (1/m). ! +! BioIter Maximum number of iterations to achieve convergence ! +! of the nonlinear solution. ! +! BioIni Initial concentration for analytical initial ! +! (uniform) conditions. ! +! CDOM_LightAtt Factor for light attenuation due to CDOM ! +! (nondimensional). ! +! CDOM_sigma Light-dependent degradation term for CDOM ! +! (1/(Watt m-2 day)). ! +! PARfrac Fraction of shortwave radiation that is available ! +! for photosyntesis (nondimensional). ! +! ! +!======================================================================= +! + USE mod_param +! + implicit none +! +! Set number of spectral bands to consider. +! + integer, parameter :: NBands = 2 +! +! Set biological tracer identification indices. +! + integer, allocatable :: idbio(:) ! Biological tracers + integer :: aCDOM(NBands) ! CDOM absorption + integer :: i440n ! 440nm spectral band + integer :: i510n ! 510nm spectral band +! +! Biological parameters. +! + integer, allocatable :: BioIter(:) + + real(r8), allocatable :: BioIni(:,:) + + real(r8), allocatable :: AttSW(:) ! 1/m + real(r8), allocatable :: CDOM_LightAtt(:) ! nondimensonal + real(r8), allocatable :: CDOM_sigma(:) ! 1/(W m-2 day) + real(r8), allocatable :: PARfrac(:) ! nondimensional + +#ifdef TANGENT + real(r8), allocatable :: tl_PARfrac(:) ! nondimensional +#endif +#ifdef ADJOINT + real(r8), allocatable :: ad_PARfrac(:) ! nondimensional +#endif + + CONTAINS + + SUBROUTINE initialize_biology +! +!======================================================================= +! ! +! This routine sets several variables needed by the biology model. ! +! It allocates and assigns biological tracers indices. ! +! ! +!======================================================================= +! +! Local variable declarations +! + integer :: i, ic +! +!----------------------------------------------------------------------- +! Set number of biological tracers. +!----------------------------------------------------------------------- +! + NBT=2 +! +!----------------------------------------------------------------------- +! Allocate various module variables. +!----------------------------------------------------------------------- +! + IF (.not.allocated(BioIter)) THEN + allocate ( BioIter(Ngrids) ) + END IF + IF (.not.allocated(AttSW)) THEN + allocate ( AttSW(Ngrids) ) + END IF + IF (.not.allocated(CDOM_LightAtt)) THEN + allocate ( CDOM_LightAtt(Ngrids) ) + END IF + IF (.not.allocated(CDOM_sigma)) THEN + allocate ( CDOM_sigma(Ngrids) ) + END IF + IF (.not.allocated(PARfrac)) THEN + allocate ( PARfrac(Ngrids) ) + END IF + +#ifdef TANGENT + IF (.not.allocated(tl_PARfrac)) THEN + allocate ( tl_PARfrac(Ngrids) ) + END IF +#endif +#ifdef ADJOINT + IF (.not.allocated(ad_PARfrac)) THEN + allocate ( ad_PARfrac(Ngrids) ) + END IF +#endif +! +! Allocate biological tracer vector. +! + IF (.not.allocated(idbio)) THEN + allocate ( idbio(NBT) ) + END IF +! +!----------------------------------------------------------------------- +! Initialize tracer identification indices. +!----------------------------------------------------------------------- +! + ic=NAT+NPT+NCS+NNS + DO i=1,NBT + idbio(i)=ic+i + END DO + DO i=1,NBands + aCDOM(i)=ic+1 + ic=ic+1 + END DO + i440n=1 + i510n=2 + + RETURN + END SUBROUTINE initialize_biology diff --git a/ROMS/Nonlinear/Biology/iop_cdom_var.h b/ROMS/Nonlinear/Biology/iop_cdom_var.h new file mode 100644 index 00000000..9803be34 --- /dev/null +++ b/ROMS/Nonlinear/Biology/iop_cdom_var.h @@ -0,0 +1,74 @@ +/* +** git $Id$ +*************************************************** Hernan G. Arango *** +** Copyright (c) 2002-2024 The ROMS/TOMS Group ** +** Licensed under a MIT/X style license ** +** See License_ROMS.md ** +************************************************************************ +** ** +** Assigns metadata indices for the IOP-based, CDOM ecosystem model ** +** variables that are used in input and output NetCDF files. The ** +** metadata information is read from "varinfo.dat". ** +** ** +** This file is included in file "mod_ncparam.F", routine ** +** "initialize_ncparm". ** +** ** +************************************************************************ +*/ + +/* +** Model state biological tracers. +*/ + + CASE ('idTvar(aCDOM(i440n))') + idTvar(aCDOM(i440n))=varid + CASE ('idTvar(aCDOM(i510n))') + idTvar(aCDOM(i510n))=varid + +#if defined AD_SENSITIVITY || defined IS4DVAR_SENSITIVITY || \ + defined OPT_OBSERVATIONS || defined SENSITIVITY_4DVAR || \ + defined SO_SEMI + +/* +** Adjoint sensitivity state biological tracers. +*/ + + CASE ('idTads(aCDOM(i440n))') + idTads(aCDOM(i440n))=varid + CASE ('idTads(aCDOM(i510n))') + idTads(aCDOM(i510n))=varid +#endif + +/* +** Biological tracers open boundary conditions. +*/ + + CASE ('idTbry(iwest,aCDOM(i440n))') + idTbry(iwest,aCDOM(i440n))=varid + CASE ('idTbry(ieast,aCDOM(i440n))') + idTbry(ieast,aCDOM(i440n))=varid + CASE ('idTbry(isouth,aCDOM(i440n))') + idTbry(isouth,aCDOM(i440n))=varid + CASE ('idTbry(inorth,aCDOM(i440n))') + idTbry(inorth,aCDOM(i440n))=varid + + CASE ('idTbry(iwest,aCDOM(i510n))') + idTbry(iwest,aCDOM(i510n))=varid + CASE ('idTbry(ieast,aCDOM(i510n))') + idTbry(ieast,aCDOM(i510n))=varid + CASE ('idTbry(isouth,aCDOM(i510n))') + idTbry(isouth,aCDOM(i510n))=varid + CASE ('idTbry(inorth,aCDOM(i510n))') + idTbry(inorth,aCDOM(i510n))=varid + +#ifdef TS_PSOURCE + +/* +** Biological tracers point Source/Sinks (river runoff). +*/ + + CASE ('idRtrc(aCDOM(i440n))') + idRtrc(aCDOM(i440n))=varid + CASE ('idRtrc(aCDOM(i510n))') + idRtrc(aCDOM(i510n))=varid +#endif diff --git a/ROMS/Nonlinear/Biology/iop_cdom_wrt.h b/ROMS/Nonlinear/Biology/iop_cdom_wrt.h new file mode 100644 index 00000000..23615b2e --- /dev/null +++ b/ROMS/Nonlinear/Biology/iop_cdom_wrt.h @@ -0,0 +1,41 @@ +/* +** git $Id$ +*************************************************** Hernan G. Arango *** +** Copyright (c) 2002-2024 The ROMS/TOMS Group ** +** Licensed under a MIT/X style license ** +** See License_ROMS.md ** +************************************************************************ +** ** +** Writes IOP-based, CDOM ecosystem model input parameters into ** +** output NetCDF files. It is included in routine "wrt_info.F". ** +** ** +************************************************************************ +*/ + +! +! Write out IOP-based, CDOM ecosystem model parameters. +! + CALL netcdf_put_ivar (ng, model, ncname, 'BioIter', & + & BioIter(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'PARfrac', & + & PARfrac(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'AttSW', & + & AttSW(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'CDOM_LightAtt', & + & CDOM_LightAtt(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'CDOM_sigma', & + & CDOM_sigma(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN diff --git a/ROMS/Nonlinear/Biology/iop_cdom_wrt_pio.h b/ROMS/Nonlinear/Biology/iop_cdom_wrt_pio.h new file mode 100644 index 00000000..4b42f430 --- /dev/null +++ b/ROMS/Nonlinear/Biology/iop_cdom_wrt_pio.h @@ -0,0 +1,41 @@ +/* +** git $Id$ +*************************************************** Hernan G. Arango *** +** Copyright (c) 2002-2024 The ROMS/TOMS Group ** +** Licensed under a MIT/X style license ** +** See License_ROMS.md ** +************************************************************************ +** ** +** Writes IOP-based, CDOM ecosystem model input parameters into ** +** output NetCDF files. It is included in routine "wrt_info.F". ** +** ** +************************************************************************ +*/ + +! +! Write out IOP-based, CDOM ecosystem model parameters. +! + CALL pio_netcdf_put_ivar (ng, model, ncname, 'BioIter', & + & BioIter(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'PARfrac', & + & PARfrac(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'AttSW', & + & AttSW(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'CDOM_LightAtt', & + & CDOM_LightAtt(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'CDOM_sigma', & + & CDOM_sigma(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN diff --git a/ROMS/Nonlinear/Biology/npzd_iop.h b/ROMS/Nonlinear/Biology/npzd_iop.h new file mode 100644 index 00000000..9ab5f439 --- /dev/null +++ b/ROMS/Nonlinear/Biology/npzd_iop.h @@ -0,0 +1,671 @@ + SUBROUTINE biology (ng,tile) +! +!git $Id$ +!****************************************************** Katja Fennel *** +! Copyright (c) 2002-2024 The ROMS/TOMS Group Hernan G. Arango ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!*********************************************************************** +! ! +! Nutrient-Phytoplankton-Zooplankton-Detritus IOP-based Model ! +! ! +! This routine computes the biological sources and sinks and adds ! +! then the global biological fields. ! +! ! +! It computes the absorption, scattering, and backscattering from ! +! the ecosystem variables. This facilitates direct comparisons ! +! between measuared and models IOPs (Inherent Optical Properties). ! +! It also possible to calculate remote sensing reflectances from ! +! model output for direct comparisons with remotely sensed ocean ! +! color (SeaWIFS, MODIS, etc) and data assimilation. ! +! ! +! Reference: ! +! ! +! Fennel, K., Craig S., M. Lehmann, ... ! +! ! +!*********************************************************************** +! + USE mod_param + USE mod_forces + USE mod_grid + USE mod_ocean + USE mod_stepping +! +! Imported variable declarations. +! + integer, intent(in) :: ng, tile +! +! Local variable declarations. +! +#include "tile.h" +! +#ifdef PROFILE + CALL wclock_on (ng, iNLM, 15) +#endif + CALL biology_tile (ng, tile, & + & LBi, UBi, LBj, UBj, N(ng), NT(ng), & + & IminS, ImaxS, JminS, JmaxS, & + & nstp(ng), nnew(ng), & +#ifdef MASKING + & GRID(ng) % rmask, & +#endif + & GRID(ng) % Hz, & + & GRID(ng) % z_r, & + & GRID(ng) % z_w, & + & FORCES(ng) % srflx, & + & OCEAN(ng) % t) + +#ifdef PROFILE + CALL wclock_off (ng, iNLM, 15) +#endif + RETURN + END SUBROUTINE biology +! +!----------------------------------------------------------------------- + SUBROUTINE biology_tile (ng, tile, & + & LBi, UBi, LBj, UBj, UBk, UBt, & + & IminS, ImaxS, JminS, JmaxS, & + & nstp, nnew, & +#ifdef MASKING + & rmask, & +#endif + & Hz, z_r, z_w, & + & srflx, & + & t) +!----------------------------------------------------------------------- +! + USE mod_param + USE mod_biology + USE mod_ncparam + USE mod_scalars +! +! Imported variable declarations. +! + integer, intent(in) :: ng, tile + integer, intent(in) :: LBi, UBi, LBj, UBj, UBk, UBt + integer, intent(in) :: IminS, ImaxS, JminS, JmaxS + integer, intent(in) :: nstp, nnew + +#ifdef ASSUMED_SHAPE +# ifdef MASKING + real(r8), intent(in) :: rmask(LBi:,LBj:) +# endif + real(r8), intent(in) :: Hz(LBi:,LBj:,:) + real(r8), intent(in) :: z_r(LBi:,LBj:,:) + real(r8), intent(in) :: z_w(LBi:,LBj:,0:) + real(r8), intent(in) :: srflx(LBi:,LBj:) + real(r8), intent(inout) :: t(LBi:,LBj:,:,:,:) +#else +# ifdef MASKING + real(r8), intent(in) :: rmask(LBi:UBi,LBj:UBj) +# endif + real(r8), intent(in) :: Hz(LBi:UBi,LBj:UBj,UBk) + real(r8), intent(in) :: z_r(LBi:UBi,LBj:UBj,UBk) + real(r8), intent(in) :: z_w(LBi:UBi,LBj:UBj,0:UBk) + real(r8), intent(in) :: srflx(LBi:UBi,LBj:UBj) + real(r8), intent(inout) :: t(LBi:UBi,LBj:UBj,UBk,3,UBt) +#endif +! +! Local variable declarations. +! + integer, parameter :: Nsink = 6 + + integer :: nb + integer :: Iter, i, ibio, isink, itime, itrc, iTrcMax, j, k, ks + + integer, dimension(Nsink) :: idsink + + real(r8), parameter :: eps = 1.0e-20_r8 + real(r8), parameter :: MinVal = 1.0e-6_r8 + + real(r8) :: Att, ExpAtt, Itop, PAR, PP, PPN, rhoChl + real(r8) :: cff, cff1, dtdays + real(r8) :: cffL, cffR, cu, dltL, dltR + + real(r8), dimension(Nsink) :: Wbio + + integer, dimension(IminS:ImaxS,N(ng)) :: ksource + + real(r8), dimension(IminS:ImaxS) :: PARsur + + real(r8), dimension(NT(ng),2) :: BioTrc + + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio_old + + real(r8), dimension(IminS:ImaxS,0:N(ng)) :: FC + + real(r8), dimension(IminS:ImaxS,N(ng)) :: Hz_inv + real(r8), dimension(IminS:ImaxS,N(ng)) :: Hz_inv2 + real(r8), dimension(IminS:ImaxS,N(ng)) :: Hz_inv3 + real(r8), dimension(IminS:ImaxS,N(ng)) :: Light + real(r8), dimension(IminS:ImaxS,N(ng)) :: WL + real(r8), dimension(IminS:ImaxS,N(ng)) :: WR + real(r8), dimension(IminS:ImaxS,N(ng)) :: bL + real(r8), dimension(IminS:ImaxS,N(ng)) :: bR + real(r8), dimension(IminS:ImaxS,N(ng)) :: qc + +#include "set_bounds.h" +! +!----------------------------------------------------------------------- +! Add biological Source/Sink terms. +!----------------------------------------------------------------------- +! +! Set time-stepping size (days) according to the number of iterations. +! + dtdays=dt(ng)*sec2day/REAL(BioIter(ng),r8) +! +! Set vertical sinking indentification vector. +! + idsink(1)=iAphy(i440n) ! Phytoplankton absorption at 440nm + idsink(2)=iBphy(i440n) ! Phytoplankton backscatter at 440nm + idsink(3)=iBdet(i440n) ! Detritus backscatter at 440nm + idsink(4)=iAphy(i510n) ! Phytoplankton absorption at 510nm + idsink(5)=iBphy(i510n) ! Phytoplankton backscatter at 510nm + idsink(6)=iBdet(i510n) ! Detritus backscatter at 510nm +! +! Set vertical sinking velocity vector in the same order as the +! identification vector, IDSINK. +! + Wbio(1)=wPhy(ng) ! Phytoplankton absorption at 440nm + Wbio(2)=wPhy(ng) ! Phytoplankton backscatter at 440nm + Wbio(3)=wDet(ng) ! Detritus backscatter at 440nm + Wbio(4)=wPhy(ng) ! Phytoplankton absorption at 510nm + Wbio(5)=wPhy(ng) ! Phytoplankton backscatter at 510nm + Wbio(6)=wDet(ng) ! Detritus backscatter at 510nm +! +! Compute inverse thickness to avoid repeated divisions. +! + J_LOOP : DO j=Jstr,Jend + DO k=1,N(ng) + DO i=Istr,Iend + Hz_inv(i,k)=1.0_r8/Hz(i,j,k) + END DO + END DO + DO k=1,N(ng)-1 + DO i=Istr,Iend + Hz_inv2(i,k)=1.0_r8/(Hz(i,j,k)+Hz(i,j,k+1)) + END DO + END DO + DO k=2,N(ng)-1 + DO i=Istr,Iend + Hz_inv3(i,k)=1.0_r8/(Hz(i,j,k-1)+Hz(i,j,k)+Hz(i,j,k+1)) + END DO + END DO +! +! Extract biological variables from tracer arrays, place them into +! scratch arrays, and restrict their values to be positive definite. +! At input, all tracers (index nnew) from predictor step have +! transport units (m Tunits) since we do not have yet the new +! values for zeta and Hz. These are known after the 2D barotropic +! time-stepping. +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,ibio)=MAX(0.0_r8,t(i,j,k,nstp,ibio)) + END DO + END DO + END DO +! +! Set upper and lower bounds for all IOP variables. +! + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,iDIN_)=MIN(Bio(i,k,iDIN_),30.0_r8) + Bio(i,k,iDIN_)=MAX(Bio(i,k,iDIN_),0.1_r8) + + Bio(i,k,iAphy(1))=MIN(Bio(i,k,iAphy(i440n)),2.0_r8) + Bio(i,k,iAphy(1))=MAX(Bio(i,k,iAphy(i440n)),0.000001_r8) + + Bio(i,k,iAphy(2))=MIN(Bio(i,k,iAphy(i510n)),2.0_r8) + Bio(i,k,iAphy(2))=MAX(Bio(i,k,iAphy(i510n)),0.000001_r8) + + Bio(i,k,iBphy(1))=MIN(Bio(i,k,iBphy(i440n)),4.0_r8) + Bio(i,k,iBphy(1))=MAX(Bio(i,k,iBphy(i440n)),0.00001_r8) + + Bio(i,k,iBphy(2))=MIN(Bio(i,k,iBphy(i510n)),4.0_r8) + Bio(i,k,iBphy(2))=MAX(Bio(i,k,iBphy(i510n)),0.00001_r8) + + Bio(i,k,iBdet(1))=MIN(Bio(i,k,iBdet(i440n)),4.0_r8) + Bio(i,k,iBdet(1))=MAX(Bio(i,k,iBdet(i440n)),0.00001_r8) + + Bio(i,k,iBdet(2))=MIN(Bio(i,k,iBdet(i510n)),4.0_r8) + Bio(i,k,iBdet(2))=MAX(Bio(i,k,iBdet(i510n)),0.00001_r8) + END DO + END DO +! +! Load biological tracers into Bio_old. +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + Bio_old(i,k,ibio)=Bio(i,k,ibio) + END DO + END DO + END DO +! +! Calculate surface Photosynthetically Available Radiation (PAR). The +! net shortwave radiation is scaled back to Watts/m2 and multiplied by +! the fraction that is photosynthetically available, PARfrac. +! + DO i=Istr,Iend +#ifdef CONST_PAR +! +! Specify constant surface irradiance. +! + PARsur(i)=158.075_r8 +#else + PARsur(i)=PARfrac(ng)*srflx(i,j)*rho0*Cp +#endif + END DO +! +!======================================================================= +! Start internal iterations to achieve convergence of the nonlinear +! backward-implicit solution. +!======================================================================= +! +! During the iterative procedure a series of fractional time steps are +! performed in a chained mode (splitting by different biological +! conversion processes) in sequence of the main food chain. In all +! stages the concentration of the component being consumed is treated +! in a fully implicit manner, so the algorithm guarantees non-negative +! values, no matter how strong the concentration of active consuming +! component (Phytoplankton or Zooplankton). The overall algorithm, +! as well as any stage of it, is formulated in conservative form +! (except explicit sinking) in sense that the sum of concentration of +! all components is conserved. +! +! In the implicit algorithm, we have for example (N: nutrient, +! P: phytoplankton), +! +! N(new) = N(old) - uptake * P(old) uptake = mu * N / (Kn + N) +! {Michaelis-Menten} +! below, we set +! The N in the numerator of +! cff = mu * P(old) / (Kn + N(old)) uptake is treated implicitly +! as N(new) +! +! so the time-stepping of the equations becomes: +! +! N(new) = N(old) / (1 + cff) (1) when substracting a sink term, +! consuming, divide by (1 + cff) +! and +! +! P(new) = P(old) + cff * N(new) (2) when adding a source term, +! growing, add (cff * source) +! +! Notice that if you substitute (1) in (2), you will get: +! +! P(new) = P(old) + cff * N(old) / (1 + cff) (3) +! +! If you add (1) and (3), you get +! +! N(new) + P(new) = N(old) + P(old) +! +! implying conservation regardless how "cff" is computed. Therefore, +! this scheme is unconditionally stable regardless of the conversion +! rate. It does not generate negative values since the constituent +! to be consumed is always treated implicitly. It is also biased +! toward damping oscillations. +! +! The iterative loop below is to iterate toward an universal Backward- +! Euler treatment of all terms. So if there are oscillations in the +! system, they are only physical oscillations. These iterations, +! however, do not improve the accuaracy of the solution. +! + ITER_LOOP: DO Iter=1,BioIter(ng) +! +! Compute light attenuation as function of depth. +! + DO i=Istr,Iend + PAR=PARsur(i) + IF (PARsur(i).gt.0.0_r8) THEN ! day time + DO k=N(ng),1,-1 +! +! Attenuate the light to the center of the grid cell. Here, AttSW is +! the light attenuation due to seawater and CDOM_LightAtt is the light +! attenuation due to CDOM absorption. +! + Att=(AttSW(ng)+ & + & CDOM_LightAtt(ng)*Bio(i,k,aCDOM(i440n)))* & + & (z_w(i,j,k)-z_w(i,j,k-1)) + ExpAtt=EXP(-Att) + Itop=PAR + PAR=Itop*(1.0_r8-ExpAtt)/Att ! average at cell center + Light(i,k)=PAR +! +! Light attenuation at the bottom of the grid cell. It is the starting +! PAR value for the next (deeper) vertical grid cell. +! + PAR=Itop*ExpAtt + END DO + ELSE ! night time + DO k=1,N(ng) + Light(i,k)=0.0_r8 + END DO + END IF + END DO +! +! Chlorophyll synthesis and phytoplankton growth. Notice that for DIN +! equations it does not matter whether we use i440n or i510n indices. +! + cff=dtdays*PhotoRmax(ng) + DO k=1,N(ng) + DO i=Istr,Iend + cff1=PhyIS(ng)*Bio(i,k,iAphy(i440n))* & + & Light(i,k)/(Bio(i,k,iBphy(i440n))+eps) + PP=cff*(1.0_r8-EXP(-cff1/(PhotoRmax(ng)+eps))) + IF (Bio(i,k,iDIN_).gt.0.1_r8) THEN + PPN=PP*Vm_DIN(ng)/(K_DIN(ng)+Bio(i,k,iDIN_)) + ELSE + PPN=0.0_r8 + END IF + rhoChl=ThetaM(ng)*PP/(cff1+eps) + DO nb=1,NBands + Bio(i,k,iAphy(nb))=Bio(i,k,iAphy(nb))+ & + & rhoChl*PPN*Bio(i,k,iDIN_)* & + & Bio(i,k,iAphy(nb)) + END DO + Bio(i,k,iDIN_)=Bio(i,k,iDIN_)/ & + & (1.0_r8+ & + & BphyMap(ng)*PPN*Bio(i,k,iBphy(i440n))) + DO nb=1,NBands + Bio(i,k,iBphy(nb))=Bio(i,k,iBphy(nb))+ & + & PPN*Bio(i,k,iBphy(nb))* & + & Bio(i,k,iDIN_) + END DO + END DO + END DO +! +! Phytoplankton mortality (also applies to chlorophyll). +! + cff=dtdays*PhyMRD(ng) + cff1=cff*BphyMap(ng)/BdetMap(ng) + DO k=1,N(ng) + DO i=Istr,Iend + DO nb=1,NBands + Bio(i,k,iAphy(nb))=Bio(i,k,iAphy(nb))/(1.0_r8+cff) + Bio(i,k,iBphy(nb))=Bio(i,k,iBphy(nb))/(1.0_r8+cff) + Bio(i,k,iBdet(nb))=Bio(i,k,iBdet(nb))+ & + & cff1*Bio(i,k,iBphy(nb)) + END DO + END DO + END DO +! +! Phytoplankton loss to DIN (also applies to chlorophyll). +! + cff=dtdays*PhyMRN(ng) + cff1=cff*BphyMap(ng) + DO k=1,N(ng) + DO i=Istr,Iend + DO nb=1,NBands + Bio(i,k,iAphy(nb))=Bio(i,k,iAphy(nb))/(1.0_r8+cff) + Bio(i,k,iBphy(nb))=Bio(i,k,iBphy(nb))/(1.0_r8+cff) + END DO + Bio(i,k,iDIN_)=Bio(i,k,iDIN_)+ & + & cff1*Bio(i,k,iBphy(1)) + END DO + END DO +! +! Nutrient remineralization to detritus +! + cff=dtdays*DetRR(ng) + cff1=cff*BdetMap(ng) + DO k=1,N(ng) + DO i=Istr,Iend + DO nb=1,NBands + Bio(i,k,iBdet(nb))=Bio(i,k,iBdet(nb))/(1.0_r8+cff) + END DO + Bio(i,k,iDIN_)=Bio(i,k,iDIN_)+ & + & cff1*Bio(i,k,iBdet(1)) + END DO + END DO +! +! Degradation of aCDOM. +! + cff1=dtdays*CDOM_sigma(ng) + DO k=1,N(ng) + DO i=Istr,Iend + cff=cff1*Light(i,k) + DO nb=1,NBands + Bio(i,k,aCDOM(nb))=Bio(i,k,aCDOM(nb))/(1.0_r8+cff) + END DO + END DO + END DO +! +!----------------------------------------------------------------------- +! Vertical sinking terms: Phytoplankton and Detritus +!----------------------------------------------------------------------- +! +! Reconstruct vertical profile of selected biological constituents +! "Bio(:,:,isink)" in terms of a set of parabolic segments within each +! grid box. Then, compute semi-Lagrangian flux due to sinking. +! + SINK_LOOP: DO isink=1,Nsink + ibio=idsink(isink) +! +! Copy concentration of biological particulates into scratch array +! "qc" (q-central, restrict it to be positive) which is hereafter +! interpreted as a set of grid-box averaged values for biogeochemical +! constituent concentration. +! + DO k=1,N(ng) + DO i=Istr,Iend + qc(i,k)=Bio(i,k,ibio) + END DO + END DO +! + DO k=N(ng)-1,1,-1 + DO i=Istr,Iend + FC(i,k)=(qc(i,k+1)-qc(i,k))*Hz_inv2(i,k) + END DO + END DO + DO k=2,N(ng)-1 + DO i=Istr,Iend + dltR=Hz(i,j,k)*FC(i,k) + dltL=Hz(i,j,k)*FC(i,k-1) + cff=Hz(i,j,k-1)+2.0_r8*Hz(i,j,k)+Hz(i,j,k+1) + cffR=cff*FC(i,k) + cffL=cff*FC(i,k-1) +! +! Apply PPM monotonicity constraint to prevent oscillations within the +! grid box. +! + IF ((dltR*dltL).le.0.0_r8) THEN + dltR=0.0_r8 + dltL=0.0_r8 + ELSE IF (ABS(dltR).gt.ABS(cffL)) THEN + dltR=cffL + ELSE IF (ABS(dltL).gt.ABS(cffR)) THEN + dltL=cffR + END IF +! +! Compute right and left side values (bR,bL) of parabolic segments +! within grid box Hz(k); (WR,WL) are measures of quadratic variations. +! +! NOTE: Although each parabolic segment is monotonic within its grid +! box, monotonicity of the whole profile is not guaranteed, +! because bL(k+1)-bR(k) may still have different sign than +! qc(i,k+1)-qc(i,k). This possibility is excluded, +! after bL and bR are reconciled using WENO procedure. +! + cff=(dltR-dltL)*Hz_inv3(i,k) + dltR=dltR-cff*Hz(i,j,k+1) + dltL=dltL+cff*Hz(i,j,k-1) + bR(i,k)=qc(i,k)+dltR + bL(i,k)=qc(i,k)-dltL + WR(i,k)=(2.0_r8*dltR-dltL)**2 + WL(i,k)=(dltR-2.0_r8*dltL)**2 + END DO + END DO + cff=1.0E-14_r8 + DO k=2,N(ng)-2 + DO i=Istr,Iend + dltL=MAX(cff,WL(i,k )) + dltR=MAX(cff,WR(i,k+1)) + bR(i,k)=(dltR*bR(i,k)+dltL*bL(i,k+1))/(dltR+dltL) + bL(i,k+1)=bR(i,k) + END DO + END DO + DO i=Istr,Iend + FC(i,N(ng))=0.0_r8 ! NO-flux boundary condition +#if defined LINEAR_CONTINUATION + bL(i,N(ng))=bR(i,N(ng)-1) + bR(i,N(ng))=2.0_r8*qc(i,N(ng))-bL(i,N(ng)) +#elif defined NEUMANN + bL(i,N(ng))=bR(i,N(ng)-1) + bR(i,N(ng))=1.5_r8*qc(i,N(ng))-0.5_r8*bL(i,N(ng)) +#else + bR(i,N(ng))=qc(i,N(ng)) ! default strictly monotonic + bL(i,N(ng))=qc(i,N(ng)) ! conditions + bR(i,N(ng)-1)=qc(i,N(ng)) +#endif +#if defined LINEAR_CONTINUATION + bR(i,1)=bL(i,2) + bL(i,1)=2.0_r8*qc(i,1)-bR(i,1) +#elif defined NEUMANN + bR(i,1)=bL(i,2) + bL(i,1)=1.5_r8*qc(i,1)-0.5_r8*bR(i,1) +#else + bL(i,2)=qc(i,1) ! bottom grid boxes are + bR(i,1)=qc(i,1) ! re-assumed to be + bL(i,1)=qc(i,1) ! piecewise constant. +#endif + END DO +! +! Apply monotonicity constraint again, since the reconciled interfacial +! values may cause a non-monotonic behavior of the parabolic segments +! inside the grid box. +! + DO k=1,N(ng) + DO i=Istr,Iend + dltR=bR(i,k)-qc(i,k) + dltL=qc(i,k)-bL(i,k) + cffR=2.0_r8*dltR + cffL=2.0_r8*dltL + IF ((dltR*dltL).lt.0.0_r8) THEN + dltR=0.0_r8 + dltL=0.0_r8 + ELSE IF (ABS(dltR).gt.ABS(cffL)) THEN + dltR=cffL + ELSE IF (ABS(dltL).gt.ABS(cffR)) THEN + dltL=cffR + END IF + bR(i,k)=qc(i,k)+dltR + bL(i,k)=qc(i,k)-dltL + END DO + END DO +! +! After this moment reconstruction is considered complete. The next +! stage is to compute vertical advective fluxes, FC. It is expected +! that sinking may occurs relatively fast, the algorithm is designed +! to be free of CFL criterion, which is achieved by allowing +! integration bounds for semi-Lagrangian advective flux to use as +! many grid boxes in upstream direction as necessary. +! +! In the two code segments below, WL is the z-coordinate of the +! departure point for grid box interface z_w with the same indices; +! FC is the finite volume flux; ksource(:,k) is index of vertical +! grid box which contains the departure point (restricted by N(ng)). +! During the search: also add in content of whole grid boxes +! participating in FC. +! + cff=dtdays*ABS(Wbio(isink)) + DO k=1,N(ng) + DO i=Istr,Iend + FC(i,k-1)=0.0_r8 + WL(i,k)=z_w(i,j,k-1)+cff + WR(i,k)=Hz(i,j,k)*qc(i,k) + ksource(i,k)=k + END DO + END DO + DO k=1,N(ng) + DO ks=k,N(ng)-1 + DO i=Istr,Iend + IF (WL(i,k).gt.z_w(i,j,ks)) THEN + ksource(i,k)=ks+1 + FC(i,k-1)=FC(i,k-1)+WR(i,ks) + END IF + END DO + END DO + END DO +! +! Finalize computation of flux: add fractional part. +! + DO k=1,N(ng) + DO i=Istr,Iend + ks=ksource(i,k) + cu=MIN(1.0_r8,(WL(i,k)-z_w(i,j,ks-1))*Hz_inv(i,ks)) + FC(i,k-1)=FC(i,k-1)+ & + & Hz(i,j,ks)*cu* & + & (bL(i,ks)+ & + & cu*(0.5_r8*(bR(i,ks)-bL(i,ks))- & + & (1.5_r8-cu)* & + & (bR(i,ks)+bL(i,ks)- & + & 2.0_r8*qc(i,ks)))) + END DO + END DO + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,ibio)=qc(i,k)+(FC(i,k)-FC(i,k-1))*Hz_inv(i,k) + END DO + END DO + +#ifdef BIO_SEDIMENT +! +! Particulate flux reaching the seafloor is remineralized and returned +! to the dissolved nitrate pool. Without this conversion, particulate +! material falls out of the system. This is a temporary fix to restore +! total nitrogen conservation. It will be replaced later by a +! parameterization that includes the time delay of remineralization +! and dissolved oxygen. +! + IF (ibio.eq.iBphy(1)) THEN + DO i=Istr,Iend + cff1=FC(i,0)*Hz_inv(i,1) + Bio(i,1,iDIN_)=Bio(i,1,iDIN_)+cff1*BphyMap(ng) + END DO + END IF + IF (ibio.eq.iBdet(1)) THEN + DO i=Istr,Iend + cff1=FC(i,0)*Hz_inv(i,1) + Bio(i,1,iDIN_)=Bio(i,1,iDIN_)+cff1*BdetMap(ng) + END DO + END IF +#endif + + END DO SINK_LOOP + END DO ITER_LOOP +! +!----------------------------------------------------------------------- +! Update global tracer variables: Add increment due to BGC processes +! to tracer array in time index "nnew". Index "nnew" is solution after +! advection and mixing and has transport units (m Tunits) hence the +! increment is multiplied by Hz. Notice that we need to subtract +! original values "Bio_old" at the top of the routine to just account +! for the concentractions affected by BGC processes. This also takes +! into account any constraints (non-negative concentrations, carbon +! concentration range) specified before entering BGC kernel. If "Bio" +! were unchanged by BGC processes, the increment would be exactly +! zero. Notice that final tracer values, t(:,:,:,nnew,:) are not +! bounded >=0 so that we can preserve total inventory of nutrients +! when advection causes tracer concentration to go negative. +!----------------------------------------------------------------------- +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + cff=Bio(i,k,ibio)-Bio_old(i,k,ibio) + t(i,j,k,nnew,ibio)=t(i,j,k,nnew,ibio)+cff*Hz(i,j,k) + END DO + END DO + END DO + + END DO J_LOOP + + RETURN + END SUBROUTINE biology_tile diff --git a/ROMS/Nonlinear/Biology/npzd_iop_def.h b/ROMS/Nonlinear/Biology/npzd_iop_def.h new file mode 100644 index 00000000..40f8e45c --- /dev/null +++ b/ROMS/Nonlinear/Biology/npzd_iop_def.h @@ -0,0 +1,144 @@ +/* +** git $Id$ +*************************************************** Hernan G. Arango *** +** Copyright (c) 2002-2024 The ROMS/TOMS Group ** +** Licensed under a MIT/X style license ** +** See License_ROMS.md ** +************************************************************************ +** ** +** Defines IOP-based, NPZD ecosystem model input parameters in ** +** output NetCDF files. It is included in routine "def_info.F". ** +** ** +************************************************************************ +*/ + +! +! Define IOP-based, NPZD ecosystem model parameters. +! + Vinfo( 1)='BioIter' + Vinfo( 2)='number of iterations to achieve convergence' + status=def_var(ng, model, ncid, varid, nf90_int, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='PARfrac' + Vinfo( 2)='photosynthetically available radiation fraction' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='AttSW' + Vinfo( 2)='light attenuation due to sea water' + Vinfo( 3)='meter-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='CDOM_LightAtt' + Vinfo( 2)='light attenuation due to CDOM' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='CDOM_sigma' + Vinfo( 2)='light-dependent degradation rate for CDOM' + Vinfo( 3)='watt-1 m2 day-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='K_DIN' + Vinfo( 2)='Half-saturation for phytoplankton nitrogen uptake' + Vinfo( 3)='millimole_N meter-3' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='PhyIS' + Vinfo( 2)='phytoplankton initial slope of the P-I cureve' + Vinfo( 3)='meter2 watt-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='PhyMRD' + Vinfo( 2)='phytoplankton mortality rate to the detritus pool' + Vinfo( 3)='day-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='PhyMRN' + Vinfo( 2)='phytoplankton mortality rate to the Nitrogen pool' + Vinfo( 3)='day-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='Vm_DIN' + Vinfo( 2)='nitrogen uptake rate' + Vinfo( 3)='day-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='DetRR' + Vinfo( 2)='detritus remineralization rate' + Vinfo( 3)='day-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='ThetaM' + Vinfo( 2)='Maximum ratio of phytoplankton backscatter to '// & + & 'absorption' + Vinfo( 3)='nondimensional' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='BphyMap' + Vinfo( 2)='Mapping from phytoplankton backscatter to '// & + & 'Nitrogen biomass at 440 nm' + Vinfo( 3)='millimole_N meter-2' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='BdetMap' + Vinfo( 2)='Mapping from detritus backscatter to Nitrogen '// & + & 'biomass at 440 nm' + Vinfo( 3)='millimole_N meter-2' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='wPhy' + Vinfo( 2)='phytoplankton sinking rate' + Vinfo( 3)='m day-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN + + Vinfo( 1)='wDet' + Vinfo( 2)='detrital sinking rate' + Vinfo( 3)='m day-1' + status=def_var(ng, model, ncid, varid, NF_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (exit_flag.ne.NoError) RETURN diff --git a/ROMS/Nonlinear/Biology/npzd_iop_def_pio.h b/ROMS/Nonlinear/Biology/npzd_iop_def_pio.h new file mode 100644 index 00000000..2868336b --- /dev/null +++ b/ROMS/Nonlinear/Biology/npzd_iop_def_pio.h @@ -0,0 +1,144 @@ +/* +** git $Id$ +*************************************************** Hernan G. Arango *** +** Copyright (c) 2002-2024 The ROMS/TOMS Group ** +** Licensed under a MIT/X style license ** +** See License_ROMS.md ** +************************************************************************ +** ** +** Defines IOP-based, NPZD ecosystem model input parameters in ** +** output NetCDF files. It is included in routine "def_info.F". ** +** ** +************************************************************************ +*/ + +! +! Define IOP-based, NPZD ecosystem model parameters. +! + Vinfo( 1)='BioIter' + Vinfo( 2)='number of iterations to achieve convergence' + status=def_var(ng, model, pioFile, pioVar, PIO_int, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='PARfrac' + Vinfo( 2)='photosynthetically available radiation fraction' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='AttSW' + Vinfo( 2)='light attenuation due to sea water' + Vinfo( 3)='meter-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='CDOM_LightAtt' + Vinfo( 2)='light attenuation due to CDOM' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='CDOM_sigma' + Vinfo( 2)='light-dependent degradation rate for CDOM' + Vinfo( 3)='watt-1 m2 day-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='K_DIN' + Vinfo( 2)='Half-saturation for phytoplankton nitrogen uptake' + Vinfo( 3)='millimole_N meter-3' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='PhyIS' + Vinfo( 2)='phytoplankton initial slope of the P-I cureve' + Vinfo( 3)='meter2 watt-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='PhyMRD' + Vinfo( 2)='phytoplankton mortality rate to the detritus pool' + Vinfo( 3)='day-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='PhyMRN' + Vinfo( 2)='phytoplankton mortality rate to the Nitrogen pool' + Vinfo( 3)='day-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='Vm_DIN' + Vinfo( 2)='nitrogen uptake rate' + Vinfo( 3)='day-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='DetRR' + Vinfo( 2)='detritus remineralization rate' + Vinfo( 3)='day-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='ThetaM' + Vinfo( 2)='Maximum ratio of phytoplankton backscatter to '// & + & 'absorption' + Vinfo( 3)='nondimensional' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='BphyMap' + Vinfo( 2)='Mapping from phytoplankton backscatter to '// & + & 'Nitrogen biomass at 440 nm' + Vinfo( 3)='millimole_N meter-2' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='BdetMap' + Vinfo( 2)='Mapping from detritus backscatter to Nitrogen '// & + & 'biomass at 440 nm' + Vinfo( 3)='millimole_N meter-2' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='wPhy' + Vinfo( 2)='phytoplankton sinking rate' + Vinfo( 3)='m day-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + Vinfo( 1)='wDet' + Vinfo( 2)='detrital sinking rate' + Vinfo( 3)='m day-1' + status=def_var(ng, model, pioFile, pioVar, PIO_TYPE, & + & 1, (/0/), Aval, Vinfo, ncname, & + & SetParAccess = .FALSE.) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN diff --git a/ROMS/Nonlinear/Biology/npzd_iop_inp.h b/ROMS/Nonlinear/Biology/npzd_iop_inp.h new file mode 100644 index 00000000..f76395ba --- /dev/null +++ b/ROMS/Nonlinear/Biology/npzd_iop_inp.h @@ -0,0 +1,859 @@ + SUBROUTINE read_BioPar (model, inp, out, Lwrite) +! +!git $Id$ +!================================================== Hernan G. Arango === +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!======================================================================= +! ! +! This routine reads in IOP-based, NPZD ecosystem model input ! +! parameters. They are specified in input script "cdom.in". ! +! ! +!======================================================================= +! + USE mod_param + USE mod_parallel + USE mod_biology + USE mod_ncparam + USE mod_scalars +! + USE inp_decode_mod +! + implicit none +! +! Imported variable declarations +! + logical, intent(in) :: Lwrite + integer, intent(in) :: model, inp, out +! +! Local variable declarations. +! + integer :: Npts, Nval + integer :: iTrcStr, iTrcEnd + integer :: i, ifield, igrid, itracer, itrc, ng, nline, status + + logical, dimension(NBT,Ngrids) :: Ltrc + + real(r8), dimension(Nbands,Ngrids) :: Gbio + + real(r8), dimension(NBT,Ngrids) :: Rbio + + real(r8), dimension(100) :: Rval + + character (len=5 ) :: band + character (len=40 ) :: KeyWord + character (len=256) :: line + character (len=256), dimension(200) :: Cval +! +!----------------------------------------------------------------------- +! Initialize. +!----------------------------------------------------------------------- +! + igrid=1 ! nested grid counter + itracer=0 ! LBC tracer counter + iTrcStr=1 ! first LBC tracer to process + iTrcEnd=NBT ! last LBC tracer to process + nline=0 ! LBC multi-line counter +! +!----------------------------------------------------------------------- +! Read in IOP-based< CDOM biological model parameters. +!----------------------------------------------------------------------- +! +#ifdef ANA_BIOLOGY + IF (.not.allocated(BioIni)) allocate ( BioIni(MT,Ngrids) ) +#endif + DO WHILE (.TRUE.) + READ (inp,'(a)',ERR=10,END=20) line + status=decode_line(line, KeyWord, Nval, Cval, Rval) + IF (status.gt.0) THEN + SELECT CASE (TRIM(KeyWord)) + CASE ('Lbiology') + Npts=load_l(Nval, Cval, Ngrids, Lbiology) + CASE ('BioIter') + Npts=load_i(Nval, Rval, Ngrids, BioIter) +#ifdef ANA_BIOLOGY + CASE ('BioIni(iDIN_)') + Npts=load_r(Nval, Rval, Ngrids, BioIni(iDIN_,1)) + CASE ('BioIni(iAphy)') + Npts=load_r(Nval, Rval, Nbands, Ngrids, Gbio) + DO ng=1,Ngrids + DO nb=1,Nbands + i=iAphy(nb) + BioIni(i,ng)=Gbio(nb,ng) + END DO + END DO + CASE (TRIM(KeyWord).eq.'BioIni(iBphy)') + Npts=load_r(Nval, Rval, Nbands, Ngrids, Gbio) + DO ng=1,Ngrids + DO nb=1,Nbands + i=iBphy(nb) + BioIni(i,ng)=Gbio(nb,ng) + END DO + END DO + CASE ('BioIni(aCDOM)') + Npts=load_r(Nval, Rval, Nbands, Ngrids, Gbio) + DO ng=1,Ngrids + DO nb=1,Nbands + i=aCDOM(nb) + BioIni(i,ng)=Gbio(nb,ng) + END DO + END DO + CASE ('BioIni(iBdet)') + Npts=load_r(Nval, Rval, Nbands, Ngrids, Gbio) + DO ng=1,Ngrids + DO nb=1,Nbands + i=iBdet(nb) + BioIni(i,ng)=Gbio(nb,ng) + END DO + END DO +#endif + CASE ('PARfrac') + Npts=load_r(Nval, Rval, Ngrids, PARfrac) + CASE ('AttSW') + Npts=load_r(Nval, Rval, Ngrids, AttSW) + CASE ('CDOM_LightAtt') + Npts=load_r(Nval, Rval, Ngrids, CDOM_LightAtt) + CASE ('CDOM_sigma') + Npts=load_r(Nval, Rval, Ngrids, CDOM_sigma) + CASE ('K_DIN') + Npts=load_r(Nval, Rval, Ngrids, K_DIN) + CASE ('PhyIS') + Npts=load_r(Nval, Rval, Ngrids, PhyIS) + CASE ('PhyMRD') + Npts=load_r(Nval, Rval, Ngrids, PhyMRD) + CASE ('PhyMRN') + Npts=load_r(Nval, Rval, Ngrids, PhyMRN) + CASE ('Vm_DIN') + Npts=load_r(Nval, Rval, Ngrids, Vm_DIN) + CASE ('DetRR') + Npts=load_r(Nval, Rval, Ngrids, DetRR) + CASE ('PhotoRmax') + Npts=load_r(Nval, Rval, Ngrids, PhotoRmax) + CASE ('ThetaM') + Npts=load_r(Nval, Rval, Ngrids, ThetaM) + CASE ('BphyMap') + Npts=load_r(Nval, Rval, Ngrids, BphyMap) + CASE ('BdetMap') + Npts=load_r(Nval, Rval, Ngrids, BdetMap) + CASE ('wPhy') + Npts=load_r(Nval, Rval, Ngrids, wPhy) + CASE ('wDet') + Npts=load_r(Nval, Rval, Ngrids, wDet) + CASE ('TNU2') + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + nl_tnu2(i,ng)=Rbio(itrc,ng) + END DO + END DO + CASE ('TNU4') + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + nl_tnu4(i,ng)=Rbio(itrc,ng) + END DO + END DO + CASE ('ad_TNU2') + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + ad_tnu2(i,ng)=Rbio(itrc,ng) + tl_tnu2(i,ng)=Rbio(itrc,ng) + END DO + END DO + CASE ('ad_TNU4') + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + ad_tnu4(i,ng)=Rbio(itrc,ng) + tl_tnu4(i,ng)=Rbio(itrc,ng) + END DO + END DO + CASE ('LtracerSponge') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + LtracerSponge(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('AKT_BAK') + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + Akt_bak(i,ng)=Rbio(itrc,ng) + END DO + END DO + CASE ('ad_AKT_fac') + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + ad_Akt_fac(i,ng)=Rbio(itrc,ng) + tl_Akt_fac(i,ng)=Rbio(itrc,ng) + END DO + END DO + CASE ('TNUDG') + Npts=load_r(Nval, Rval, NBT, Ngrids, Rbio) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + Tnudg(i,ng)=Rbio(itrc,ng) + END DO + END DO + CASE ('LBC(isTvar)') + IF (itracer.lt.NBT) THEN + itracer=itracer+1 + ELSE + itracer=1 ! next nested grid + END IF + ifield=isTvar(idbio(itracer)) + Npts=load_lbc(Nval, Cval, line, nline, ifield, igrid, & + & idbio(iTrcStr), idbio(iTrcEnd), & + & Vname(1,idTvar(idbio(itracer))), LBC) +#if defined ADJOINT || defined TANGENT || defined TL_IOMS + CASE ('ad_LBC(isTvar)') + IF (itracer.lt.NBT) THEN + itracer=itracer+1 + ELSE + itracer=1 ! next nested grid + END IF + ifield=isTvar(idbio(itracer)) + Npts=load_lbc(Nval, Cval, line, nline, ifield, igrid, & + & idbio(iTrcStr), idbio(iTrcEnd), & + & Vname(1,idTvar(idbio(itracer))), ad_LBC) +#endif + CASE ('LtracerSrc') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + LtracerSrc(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('LtracerCLM') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + LtracerCLM(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('LnudgeTCLM') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + LnudgeTCLM(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Hout(idTvar)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTvar(idbio(itrc)) + IF (i.eq.0) THEN + IF (Master) WRITE (out,30) & + & 'idTvar(idbio(', itrc, '))' + exit_flag=5 + RETURN + END IF + Hout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Hout(idTsur)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTsur(idbio(itrc)) + IF (i.eq.0) THEN + IF (Master) WRITE (out,30) & + & 'idTsur(idbio(', itrc, '))' + exit_flag=5 + RETURN + END IF + Hout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Qout(idTvar)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTvar(idbio(itrc)) + Qout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Qout(idsurT)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idsurT(idbio(itrc)) + IF (i.eq.0) THEN + IF (Master) WRITE (out,30) & + & 'idsurT(idbio(', itrc, '))' + exit_flag=5 + RETURN + END IF + Qout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Qout(idTsur)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTsur(idbio(itrc)) + Qout(i,ng)=Ltrc(itrc,ng) + END DO + END DO +#if defined AVERAGES || \ + (defined AD_AVERAGES && defined ADJOINT) || \ + (defined RP_AVERAGES && defined TL_IOMS) || \ + (defined TL_AVERAGES && defined TANGENT) + CASE ('Aout(idTvar)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTvar(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Aout(idTTav)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idTTav(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Aout(idUTav)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idUTav(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Aout(idVTav)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=idVTav(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Aout(iHUTav)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=iHUTav(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO + CASE ('Aout(iHVTav)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO itrc=1,NBT + i=iHVTav(idbio(itrc)) + Aout(i,ng)=Ltrc(itrc,ng) + END DO + END DO +#endif +#ifdef DIAGNOSTICS_TS + CASE ('Dout(iTrate)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTrate),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iThadv)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iThadv),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iTxadv)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTxadv),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iTyadv)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTyadv),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iTvadv)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTvadv),ng)=Ltrc(i,ng) + END DO + END DO +# if defined TS_DIF2 || defined TS_DIF4 + CASE ('Dout(iThdif)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iThdif),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iTxdif)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTxdif),ng)=Ltrc(i,ng) + END DO + END DO + CASE ('Dout(iTydif)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTydif),ng)=Ltrc(i,ng) + END DO + END DO +# if defined MIX_GEO_TS || defined MIX_ISO_TS + CASE ('Dout(iTsdif)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTsdif),ng)=Ltrc(i,ng) + END DO + END DO +# endif +# endif + CASE ('Dout(iTvdif)') + Npts=load_l(Nval, Cval, NBT, Ngrids, Ltrc) + DO ng=1,Ngrids + DO i=1,NBT + itrc=idbio(i) + Dout(idDtrc(itrc,iTvdif),ng)=Ltrc(i,ng) + END DO + END DO +#endif + END SELECT + END IF + END DO + 10 IF (Master) WRITE (out,40) line + exit_flag=4 + RETURN + 20 CONTINUE +! +!----------------------------------------------------------------------- +! Report input parameters. +!----------------------------------------------------------------------- +! + IF (Lwrite) THEN + DO ng=1,Ngrids + IF (Lbiology(ng)) THEN + WRITE (out,50) ng + WRITE (out,60) BioIter(ng), 'BioIter', & + & 'Number of iterations for nonlinear convergence.' +#ifdef ANA_BIOLOGY + WRITE (out,70) BioIni(idbio(iDIN_),ng), 'BioIni(iDIN_)', & + & 'Dissolved Inorganic Nitrogen (mmold/m3)' + DO nb=1,Nbands + IF (nb.eq.1) THEN + band='440nm' + ELSE IF (nb.eq.2) THEN + band='510nm' + END IF + WRITE (out,80) BioIni(iAphy(nb),ng), & + & 'BioIni(iAphy(', nb ,'))', & + & 'Phytoplankton absorption (1/m) at ', band + WRITE (out,80) BioIni(iBphy(nb),ng), & + & 'BioIni(iBphy(', nb, '))', & + & 'Phytoplankton backscattering (1/m) at ', band + WRITE (out,80) BioIni(aCDOM(nb),ng), & + & 'BioIni(aCDOM(', nb, '))', & + & 'CDOM absorption (1/m) at ', band + WRITE (out,80) BioIni(iBdet(nb),ng), & + & 'BioIni(iBdet(', nb, '))', & + & 'Detritus backscattering (1/m) at ', band + END DO +#endif + WRITE (out,90) PARfrac(ng), 'PARfrac', & + & 'Fraction of shortwave radiation that is', & + & 'photosynthetically active (nondimensional).' + WRITE (out,70) AttSW(ng), 'AttSW', & + & 'Light attenuation of seawater (m-1).' + WRITE (out,90) CDOM_LightAtt(ng), 'CDOM_LightAtt', & + & 'Factor for light attenuation due to CDOM', & + & '(nondimensional).' + WRITE (out,90) CDOM_sigma(ng), 'CDOM_sigma', & + & 'Light dependent degradation term for CDOM', & + & '(1/(W m-2 d)).' + WRITE (out,90) K_DIN(ng), 'K_DIN', & + & 'Half-saturation for phytoplankton nitrogen uptake', & + & '(mmole_N/m3).' + WRITE (out,90) PhyIS(ng), 'PhyIS', & + & 'Phytoplankton growth, initial slope of P-I curve', & + & '(m2/W).' + WRITE (out,70) PhyMRD(ng), 'PhyMRD', & + & 'Phytoplankton mortality rate to Detritus (day-1)' + WRITE (out,70) PhyMRN(ng), 'PhyMRN', & + & 'Phytoplankton mortality rate to Nitrogen (day-1)' + WRITE (out,70) Vm_DIN(ng), 'Vm_DIN', & + & 'Nitrogen upatake rate (day-1).' + WRITE (out,70) DetRR(ng), 'DetRR', & + & 'Detritus remineralization rate (day-1).' + WRITE (out,70) PhotoRmax(ng), 'PhotoRmax', & + & 'Maximum photosynthetic rate (day-1).' + WRITE (out,90) ThetaM(ng), 'ThetaM', & + & 'Maximum ratio of phytoplankton backscatter to', & + & 'absorption (nondimensional).' + WRITE (out,90) BphyMap(ng), 'BphyMap', & + & 'Mapping from phytoplankton backscatter to Nitrogen', & + & 'biomass at 440 nm (mmole_N/m2).' + WRITE (out,90) BdetMap(ng), 'BdetMap', & + & 'Mapping from detritus backscatter to Nitrogen', & + & 'biomass at 440 nm (mmole_N/m2).' + WRITE (out,70) wPhy(ng), 'wPhy', & + & 'Phytoplankton sinking rate (m/day).' + WRITE (out,70) wDet(ng), 'wDet', & + & 'Detrital sinking rate (m/day).' +#ifdef TS_DIF2 + DO itrc=1,NBT + i=idbio(itrc) + WRITE (out,100) nl_tnu2(i,ng), 'nl_tnu2', i, & + & 'NLM Horizontal, harmonic mixing coefficient', & + & '(m2/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# ifdef ADJOINT + WRITE (out,100) ad_tnu2(i,ng), 'ad_tnu2', i, & + & 'ADM Horizontal, harmonic mixing coefficient', & + & '(m2/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif +# if defined TANGENT || defined TL_IOMS + WRITE (out,100) tl_tnu2(i,ng), 'tl_tnu2', i, & + & 'TLM Horizontal, harmonic mixing coefficient', & + & '(m2/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif + END DO +#endif +#ifdef TS_DIF4 + DO itrc=1,NBT + i=idbio(itrc) + WRITE (out,100) nl_tnu4(i,ng), 'nl_tnu4', i, & + & 'NLM Horizontal, biharmonic mixing coefficient', & + & '(m4/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# ifdef ADJOINT + WRITE (out,100) ad_tnu4(i,ng), 'ad_tnu4', i, & + & 'ADM Horizontal, biharmonic mixing coefficient', & + & '(m4/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif +# if defined TANGENT || defined TL_IOMS + WRITE (out,100) tl_tnu4(i,ng), 'tl_tnu4', i, & + & 'TLM Horizontal, biharmonic mixing coefficient', & + & '(m4/s) for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif + END DO +#endif + DO itrc=1,NBT + i=idbio(itrc) + IF (LtracerSponge(i,ng)) THEN + WRITE (out,110) LtracerSponge(i,ng), 'LtracerSponge', & + & i, 'Turning ON sponge on tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + ELSE + WRITE (out,110) LtracerSponge(i,ng), 'LtracerSponge', & + & i, 'Turning OFF sponge on tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END IF + END DO + DO itrc=1,NBT + i=idbio(itrc) + WRITE(out,100) Akt_bak(i,ng), 'Akt_bak', i, & + & 'Background vertical mixing coefficient (m2/s)', & + & 'for tracer ', i, TRIM(Vname(1,idTvar(i))) + END DO +#ifdef FORWARD_MIXING + DO itrc=1,NBT + i=idbio(itrc) +# ifdef ADJOINT + WRITE (out,100) ad_Akt_fac(i,ng), 'ad_Akt_fac', i, & + & 'ADM basic state vertical mixing scale factor', & + & 'for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif +# if defined TANGENT || defined TL_IOMS + WRITE (out,100) tl_Akt_fac(i,ng), 'tl_Akt_fac', i, & + & 'TLM basic state vertical mixing scale factor', & + & 'for tracer ', i, TRIM(Vname(1,idTvar(i))) +# endif + END DO +#endif + DO itrc=1,NBT + i=idbio(itrc) + WRITE (out,100) Tnudg(i,ng), 'Tnudg', i, & + & 'Nudging/relaxation time scale (days)', & + & 'for tracer ', i, TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (LtracerSrc(i,ng)) THEN + WRITE (out,110) LtracerSrc(i,ng), 'LtracerSrc', & + & i, 'Turning ON point sources/Sink on tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + ELSE + WRITE (out,100) LtracerSrc(i,ng), 'LtracerSrc', & + & i, 'Turning OFF point sources/Sink on tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END IF + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (LtracerCLM(i,ng)) THEN + WRITE (out,110) LtracerCLM(i,ng), 'LtracerCLM', i, & + & 'Turning ON processing of climatology tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + ELSE + WRITE (out,110) LtracerCLM(i,ng), 'LtracerCLM', i, & + & 'Turning OFF processing of climatology tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END IF + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (LnudgeTCLM(i,ng)) THEN + WRITE (out,110) LnudgeTCLM(i,ng), 'LnudgeTCLM', i, & + & 'Turning ON nudging of climatology tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + ELSE + WRITE (out,110) LnudgeTCLM(i,ng), 'LnudgeTCLM', i, & + & 'Turning OFF nudging of climatology tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END IF + END DO + IF ((nHIS(ng).gt.0).and.ANY(Hout(:,ng))) THEN + WRITE (out,'(1x)') + DO itrc=1,NBT + i=idbio(itrc) + IF (Hout(idTvar(i),ng)) WRITE (out,110) & + & Hout(idTvar(i),ng), 'Hout(idTvar)', & + & 'Write out tracer ', i, TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Hout(idTsur(i),ng)) WRITE (out,110) & + & Hout(idTsur(i),ng), 'Hout(idTsur)', & + & 'Write out tracer flux ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + END IF + IF ((nQCK(ng).gt.0).and.ANY(Qout(:,ng))) THEN + WRITE (out,'(1x)') + DO itrc=1,NBT + i=idbio(itrc) + IF (Qout(idTvar(i),ng)) WRITE (out,160) & + & Qout(idTvar(i),ng), 'Qout(idTvar)', & + & 'Write out tracer ', i, TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Qout(idsurT(i),ng)) WRITE (out,160) & + & Qout(idsurT(i),ng), 'Qout(idsurT)', & + & 'Write out surface tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Qout(idTsur(i),ng)) WRITE (out,160) & + & Qout(idTsur(i),ng), 'Qout(idTsur)', & + & 'Write out tracer flux ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + END IF +#if defined AVERAGES || \ + (defined AD_AVERAGES && defined ADJOINT) || \ + (defined RP_AVERAGES && defined TL_IOMS) || \ + (defined TL_AVERAGES && defined TANGENT) + IF ((nAVG(ng).gt.0).and.ANY(Aout(:,ng))) THEN + WRITE (out,'(1x)') + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(idTvar(i),ng)) WRITE (out,110) & + & Aout(idTvar(i),ng), 'Aout(idTvar)', & + & 'Write out averaged tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(idTTav(i),ng)) WRITE (out,110) & + & Aout(idTTav(i),ng), 'Aout(idTTav)', & + & 'Write out averaged for tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(idUTav(i),ng)) WRITE (out,110) & + & Aout(idUTav(i),ng), 'Aout(idUTav)', & + & 'Write out averaged for tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(idVTav(i),ng)) WRITE (out,110) & + & Aout(idVTav(i),ng), 'Aout(idVTav)', & + & 'Write out averaged for tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(iHUTav(i),ng)) WRITE (out,110) & + & Aout(iHUTav(i),ng), 'Aout(iHUTav)', & + & 'Write out averaged for tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + DO itrc=1,NBT + i=idbio(itrc) + IF (Aout(iHVTav(i),ng)) WRITE (out,110) & + & Aout(iHVTav(i),ng), 'Aout(iHVTav)', & + & 'Write out averaged for tracer ', i, & + & TRIM(Vname(1,idTvar(i))) + END DO + END IF +#endif +#ifdef DIAGNOSTICS_TS + IF ((nDIA(ng).gt.0).and.ANY(Dout(:,ng))) THEN + WRITE (out,'(1x)') + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTrate),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTrate)', & + & 'Write out rate of change of tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iThadv),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iThadv)', & + & 'Write out horizontal advection, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTxadv),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTxadv)', & + & 'Write out horizontal X-advection, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTyadv),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTyadv)', & + & 'Write out horizontal Y-advection, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTvadv),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTvadv)', & + & 'Write out vertical advection, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO +# if defined TS_DIF2 || defined TS_DIF4 + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iThdif),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iThdif)', & + & 'Write out horizontal diffusion, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(i,iTxdif),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTxdif)', & + & 'Write out horizontal X-diffusion, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTydif),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTydif)', & + & 'Write out horizontal Y-diffusion, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO +# if defined MIX_GEO_TS || defined MIX_ISO_TS + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTsdif),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTsdif)', & + & 'Write out horizontal S-diffusion, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO +# endif +# endif + DO i=1,NBT + itrc=idbio(i) + IF (Dout(idDtrc(itrc,iTvdif),ng)) & + & WRITE (out,110) .TRUE., 'Dout(iTvdif)', & + & 'Write out vertical diffusion, tracer ', itrc, & + & TRIM(Vname(1,idTvar(itrc))) + END DO + END IF +#endif + END IF + END DO + END IF +! +!----------------------------------------------------------------------- +! Rescale biological tracer parameters. +!----------------------------------------------------------------------- +! +! Take the square root of the biharmonic coefficients so it can +! be applied to each harmonic operator. +! + DO ng=1,Ngrids + DO itrc=1,NBT + i=idbio(itrc) + nl_tnu4(i,ng)=SQRT(ABS(nl_tnu4(i,ng))) +#ifdef ADJOINT + ad_tnu4(i,ng)=SQRT(ABS(ad_tnu4(i,ng))) +#endif +#if defined TANGENT || defined TL_IOMS + tl_tnu4(i,ng)=SQRT(ABS(tl_tnu4(i,ng))) +#endif +! +! Compute inverse nudging coefficients (1/s) used in various tasks. +! + IF (Tnudg(i,ng).gt.0.0_r8) THEN + Tnudg(i,ng)=1.0_r8/(Tnudg(i,ng)*86400.0_r8) + ELSE + Tnudg(i,ng)=0.0_r8 + END IF + END DO + END DO + + 30 FORMAT (/,' read_BioPar - variable info not yet loaded, ', & + & a,i2.2,a) + 40 FORMAT (/,' read_BioPar - Error while processing line: ',/,a) + 50 FORMAT (/,/,' CDOM Model Parameters, Grid: ',i2.2, & + & /, ' ==================================',/) + 60 FORMAT (1x,i10,2x,a,t31,a) + 70 FORMAT (1p,e11.4,2x,a,t31,a) + 80 FORMAT (1p,e11.4,2x,a,i1,a,t31,a,a) + 90 FORMAT (1p,e11.4,2x,a,t31,a,/,t33,a) + 100 FORMAT (1p,e11.4,2x,a,'(',i2.2,')',t31,a,/,t33,a,i2.2,':',1x,a) + 110 FORMAT (10x,l1,2x,a,'(',i2.2,')',t31,a,i2.2,':',1x,a) + 120 FORMAT (10x,l1,2x,a,t31,a,i2.2,':',1x,a) + + RETURN + END SUBROUTINE read_BioPar diff --git a/ROMS/Nonlinear/Biology/npzd_iop_mod.h b/ROMS/Nonlinear/Biology/npzd_iop_mod.h new file mode 100644 index 00000000..ed715401 --- /dev/null +++ b/ROMS/Nonlinear/Biology/npzd_iop_mod.h @@ -0,0 +1,212 @@ +! +!git $Id$ +!================================================== Hernan G. Arango === +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!======================================================================= +! ! +! Parameters for IOP-based, NPZD ecosystem model: ! +! ! +! AttSW Light attenuation due to sea water (1/m). ! +! BioIter Maximum number of iterations to achieve convergence ! +! of the nonlinear solution. ! +! BioIni Initial concentration for analytical initial ! +! (uniform) conditions. ! +! AttSW Light attenuation due to seawater (1/m). ! +! BphyMap Mapping from phytoplankton backscatter to Nitrogen ! +! biomass at 440 nm (millimole_N/m2). ! +! BdetMap Mapping from detritus backscatter to Nitrogen ! +! biomass at 440 nm (millimole_N/m2). ! +! CDOM_LightAtt Light attenuation factor due to CDOM absorption ! +! (nondimensional). ! +! CDOM_sigma Light-dependent degradation rate for CDOM absorption ! +! (1/(Watt m-2 day)). ! +! DetRR Detritus remineraliztion rate (1/day). ! +! K_DIN Half-saturation for phytoplankton nitrogen uptake ! +! (millimole_N m-3). ! +! PARfrac Fraction of shortwave radiation that is ! +! photosynthetically active (nondimensional). ! +! PhotoRmax Maximum photosynthetic rate (1/day). ! +! PhyIS Phytoplankton, initial slope of the P-I curve ! +! (m2/Watt). ! +! PhyMRD Phytoplankton mortality rate to the Detritus pool ! +! (1/day). ! +! PhyMRN Phytoplankton loss rate to the Nitrogen pool ! +! (1/day). ! +! ThetaM Maximum ratio of phytoplankton backscatter to ! +! absorption (nondimensional). ! +! Vm_DIN Nitrogen uptake rate (1/day). ! +! wDet Detrital sinking rate (m/day). ! +! wPhy Phytoplankton sinking rate (m/day). ! +! ! +!======================================================================= +! + USE mod_param +! + implicit none +! +! Set number of spectral bands to consider. +! + integer, parameter :: NBands = 2 +! +! Set biological tracer identification indices. +! + integer, allocatable :: idbio(:) ! Biological tracers + integer :: iAphy(NBands) ! Phytoplankton absorption + integer :: iBphy(NBands) ! Phytoplankton backscattering + integer :: iBdet(NBands) ! Detritus backscattering + integer :: aCDOM(NBands) ! CDOM absorption + integer :: iDIN_ ! Dissolved Inorganic Nitrogen + integer :: i440n ! 440nm spectral band + integer :: i510n ! 510nm spectral band +! +! Biological parameters. +! + integer, allocatable :: BioIter(:) + + real(r8), allocatable :: BioIni(:,:) + + real(r8), allocatable :: AttSW(:) ! 1/m + real(r8), allocatable :: BphyMap(:) ! mmole_N/m2 + real(r8), allocatable :: BdetMap(:) ! mmole_N/m2 + real(r8), allocatable :: CDOM_LightAtt(:) ! nondimensional + real(r8), allocatable :: CDOM_sigma(:) ! 1/(W m-2 day) + real(r8), allocatable :: DetRR(:) ! 1/day + real(r8), allocatable :: K_DIN(:) ! millimol_N m-3 + real(r8), allocatable :: PARfrac(:) ! nondimensional + real(r8), allocatable :: PhotoRmax(:) ! 1/day + real(r8), allocatable :: PhyIS(:) ! m2/W + real(r8), allocatable :: PhyMRD(:) ! 1/day + real(r8), allocatable :: PhyMRN(:) ! 1/day + real(r8), allocatable :: ThetaM(:) ! nondimensional + real(r8), allocatable :: Vm_DIN(:) ! 1/day + real(r8), allocatable :: wDet(:) ! m/day + real(r8), allocatable :: wPhy(:) ! m/day + +#ifdef TANGENT + real(r8), allocatable :: tl_PARfrac(:) ! nondimensional +#endif +#ifdef ADJOINT + real(r8), allocatable :: ad_PARfrac(:) ! nondimensional +#endif + + CONTAINS + + SUBROUTINE initialize_biology +! +!======================================================================= +! ! +! This routine sets several variables needed by the biology model. ! +! It allocates and assigns biological tracers indices. ! +! ! +!======================================================================= +! +! Local variable declarations +! + integer :: i, ic +! +!----------------------------------------------------------------------- +! Set number of biological tracers. +!----------------------------------------------------------------------- +! + NBT=9 +! +!----------------------------------------------------------------------- +! Allocate various module variables. +!----------------------------------------------------------------------- +! + IF (.not.allocated(BioIter)) THEN + allocate ( BioIter(Ngrids) ) + END IF + IF (.not.allocated(AttSW)) THEN + allocate ( AttSW(Ngrids) ) + END IF + IF (.not.allocated(BphyMap)) THEN + allocate ( BphyMap(Ngrids) ) + END IF + IF (.not.allocated(BdetMap)) THEN + allocate ( BdetMap(Ngrids) ) + END IF + IF (.not.allocated(CDOM_LightAtt)) THEN + allocate ( CDOM_LightAtt(Ngrids) ) + END IF + IF (.not.allocated(CDOM_sigma)) THEN + allocate ( CDOM_sigma(Ngrids) ) + END IF + IF (.not.allocated(DetRR)) THEN + allocate ( DetRR(Ngrids) ) + END IF + IF (.not.allocated(K_DIN)) THEN + allocate ( K_DIN(Ngrids) ) + END IF + IF (.not.allocated(PARfrac)) THEN + allocate ( PARfrac(Ngrids) ) + END IF + IF (.not.allocated(PhotoRmax)) THEN + allocate ( PhotoRmax(Ngrids) ) + END IF + IF (.not.allocated(PhyIS)) THEN + allocate ( PhyIS(Ngrids) ) + END IF + IF (.not.allocated(PhyMRD)) THEN + allocate ( PhyMRD(Ngrids) ) + END IF + IF (.not.allocated(PhyMRN)) THEN + allocate ( PhyMRN(Ngrids) ) + END IF + IF (.not.allocated(ThetaM)) THEN + allocate ( ThetaM(Ngrids) ) + END IF + IF (.not.allocated(Vm_DIN)) THEN + allocate ( Vm_DIN(Ngrids) ) + END IF + IF (.not.allocated(wDet)) THEN + allocate ( wDet(Ngrids) ) + END IF + IF (.not.allocated(wPhy)) THEN + allocate ( wPhy(Ngrids) ) + END IF + +#ifdef TANGENT + IF (.not.allocated(tl_PARfrac)) THEN + allocate ( tl_PARfrac(Ngrids) ) + END IF +#endif +#ifdef ADJOINT + IF (.not.allocated(ad_PARfrac)) THEN + allocate ( ad_PARfrac(Ngrids) ) + END IF +#endif +! +! Allocate biological tracer vector. +! + IF (.not.allocated(idbio)) THEN + allocate ( idbio(NBT) ) + END IF +! +!----------------------------------------------------------------------- +! Initialize tracer identification indices. +!----------------------------------------------------------------------- +! + ic=NAT+NPT+NCS+NNS + DO i=1,NBT + idbio(i)=ic+i + END DO + ic=ic+1 + iDIN_=ic + DO i=1,NBands + iAphy(i)=ic+1 + ic=ic+1 + iBphy(i)=ic+1 + ic=ic+1 + iBdet(i)=ic+1 + ic=ic+1 + aCDOM(i)=ic+1 + ic=ic+1 + END DO + i440n=1 + i510n=2 + + RETURN + END SUBROUTINE initialize_biology diff --git a/ROMS/Nonlinear/Biology/npzd_iop_var.h b/ROMS/Nonlinear/Biology/npzd_iop_var.h new file mode 100644 index 00000000..be404541 --- /dev/null +++ b/ROMS/Nonlinear/Biology/npzd_iop_var.h @@ -0,0 +1,179 @@ +/* +** git $Id$ +*************************************************** Hernan G. Arango *** +** Copyright (c) 2002-2024 The ROMS/TOMS Group ** +** Licensed under a MIT/X style license ** +** See License_ROMS.md ** +************************************************************************ +** ** +** Assigns metadata indices for the IOP-based, NPZD ecosystem model ** +** variables that are used in input and output NetCDF files. The ** +** metadata information is read from "varinfo.dat". ** +** ** +** This file is included in file "mod_ncparam.F", routine ** +** "initialize_ncparm". ** +** ** +************************************************************************ +*/ + +/* +** Model state biological tracers. +*/ + + CASE ('idTvar(iDIN_)') + idTvar(iDIN_)=varid + CASE ('idTvar(iAphy(i440n))') + idTvar(iAphy(i440n))=varid + CASE ('idTvar(iAphy(i510n))') + idTvar(iAphy(i510n))=varid + CASE ('idTvar(iBphy(i440n))') + idTvar(iBphy(i440n))=varid + CASE ('idTvar(iBphy(i510n))') + idTvar(iBphy(i510n))=varid + CASE ('idTvar(aCDOM(i440n))') + idTvar(aCDOM(i440n))=varid + CASE ('idTvar(aCDOM(i510n))') + idTvar(aCDOM(i510n))=varid + CASE ('idTvar(iBdet(i440n))') + idTvar(iBdet(i440n))=varid + CASE ('idTvar(iBdet(i510n))') + idTvar(iBdet(i510n))=varid + +#if defined AD_SENSITIVITY || defined IS4DVAR_SENSITIVITY || \ + defined OPT_OBSERVATIONS || defined SENSITIVITY_4DVAR || \ + defined SO_SEMI + +/* +** Adjoint sensitivity state biological tracers. +*/ + + CASE ('idTads(iDIN_)') + idTads(iDIN_)=varid + CASE ('idTads(iAphy(i440n))') + idTads(iAphy(i440n))=varid + CASE ('idTads(iAphy(i510n))') + idTads(iAphy(i510n))=varid + CASE ('idTads(iBphy(i440n))') + idTads(iBphy(i440n))=varid + CASE ('idTads(iBphy(i510n))') + idTads(iBphy(i510n))=varid + CASE ('idTads(aCDOM(i440n))') + idTads(aCDOM(i440n))=varid + CASE ('idTads(aCDOM(i510n))') + idTads(aCDOM(i510n))=varid + CASE ('idTads(iBdet(i440n))') + idTads(iBdet(i440n))=varid + CASE ('idTads(iBdet(i510n))') + idTads(iBdet(i510n))=varid +#endif + +/* +** Biological tracers open boundary conditions. +*/ + + CASE ('idTbry(iwest,iDIN_)') + idTbry(iwest,iDIN_)=varid + CASE ('idTbry(ieast,iDIN_)') + idTbry(ieast,iDIN_)=varid + CASE ('idTbry(isouth,iDIN_)') + idTbry(isouth,iDIN_)=varid + CASE ('idTbry(inorth,iDIN_)') + idTbry(inorth,iDIN_)=varid + + CASE ('idTbry(iwest,iAphy(i440n))') + idTbry(iwest,iAphy(i440n))=varid + CASE ('idTbry(ieast,iAphy(i440n))') + idTbry(ieast,iAphy(i440n))=varid + CASE ('idTbry(isouth,iAphy(i440n))') + idTbry(isouth,iAphy(i440n))=varid + CASE ('idTbry(inorth,iAphy(i440n))') + idTbry(inorth,iAphy(i440n))=varid + + CASE ('idTbry(iwest,iAphy(i510n))') + idTbry(iwest,iAphy(i510n))=varid + CASE ('idTbry(ieast,iAphy(i510n))') + idTbry(ieast,iAphy(i510n))=varid + CASE ('idTbry(isouth,iAphy(i510n))') + idTbry(isouth,iAphy(i510n))=varid + CASE ('idTbry(inorth,iAphy(i510n))') + idTbry(inorth,iAphy(i510n))=varid + + CASE ('idTbry(iwest,iBphy(i440n))') + idTbry(iwest,iBphy(i440n))=varid + CASE ('idTbry(ieast,iBphy(i440n))') + idTbry(ieast,iBphy(i440n))=varid + CASE ('idTbry(isouth,iBphy(i440n))') + idTbry(isouth,iBphy(i440n))=varid + CASE ('idTbry(inorth,iBphy(i440n))') + idTbry(inorth,iBphy(i440n))=varid + + CASE ('idTbry(iwest,iBphy(i510n))') + idTbry(iwest,iBphy(i510n))=varid + CASE ('idTbry(ieast,iBphy(i510n))') + idTbry(ieast,iBphy(i510n))=varid + CASE ('idTbry(isouth,iBphy(i510n))') + idTbry(isouth,iBphy(i510n))=varid + CASE ('idTbry(inorth,iBphy(i510n))') + idTbry(inorth,iBphy(i510n))=varid + + CASE ('idTbry(iwest,aCDOM(i440n))') + idTbry(iwest,aCDOM(i440n))=varid + CASE ('idTbry(ieast,aCDOM(i440n))') + idTbry(ieast,aCDOM(i440n))=varid + CASE ('idTbry(isouth,aCDOM(i440n))') + idTbry(isouth,aCDOM(i440n))=varid + CASE ('idTbry(inorth,aCDOM(i440n))') + idTbry(inorth,aCDOM(i440n))=varid + + CASE ('idTbry(iwest,aCDOM(i510n))') + idTbry(iwest,aCDOM(i510n))=varid + CASE ('idTbry(ieast,aCDOM(i510n))') + idTbry(ieast,aCDOM(i510n))=varid + CASE ('idTbry(isouth,aCDOM(i510n))') + idTbry(isouth,aCDOM(i510n))=varid + CASE ('idTbry(inorth,aCDOM(i510n))') + idTbry(inorth,aCDOM(i510n))=varid + + CASE ('idTbry(iwest,iBdet(i440n))') + idTbry(iwest,iBdet(i440n))=varid + CASE ('idTbry(ieast,iBdet(i440n))') + idTbry(ieast,iBdet(i440n))=varid + CASE ('idTbry(isouth,iBdet(i440n))') + idTbry(isouth,iBdet(i440n))=varid + CASE ('idTbry(inorth,iBdet(i440n))') + idTbry(inorth,iBdet(i440n))=varid + + CASE ('idTbry(iwest,iBdet(i510n))') + idTbry(iwest,iBdet(i510n))=varid + CASE ('idTbry(ieast,iBdet(i510n))') + idTbry(ieast,iBdet(i510n))=varid + CASE ('idTbry(isouth,iBdet(i510n))') + idTbry(isouth,iBdet(i510n))=varid + CASE ('idTbry(inorth,iBdet(i510n))') + idTbry(inorth,iBdet(i510n))=varid + +#ifdef TS_PSOURCE + +/* +** Biological tracers point Source/Sinks (river runoff). +*/ + + CASE ('idRtrc(iDIN_)') + idRtrc(iDIN_)=varid + CASE ('idRtrc(iAphy(i440n))') + idRtrc(iAphy(i440n))=varid + CASE ('idRtrc(iAphy(i510n))') + idRtrc(iAphy(i510n))=varid + CASE ('idRtrc(iBphy(i440n))') + idRtrc(iBphy(i440n))=varid + CASE ('idRtrc(iBphy(i510n))') + idRtrc(iBphy(i510n))=varid + CASE ('idRtrc(aCDOM(i440n))') + idRtrc(aCDOM(i440n))=varid + CASE ('idRtrc(aCDOM(i510n))') + idRtrc(aCDOM(i510n))=varid + CASE ('idRtrc(iBdet(i440n))') + idRtrc(iBdet(i440n))=varid + CASE ('idRtrc(iBdet(i510n))') + idRtrc(iBdet(i510n))=varid +#endif diff --git a/ROMS/Nonlinear/Biology/npzd_iop_wrt.h b/ROMS/Nonlinear/Biology/npzd_iop_wrt.h new file mode 100644 index 00000000..5fc5793e --- /dev/null +++ b/ROMS/Nonlinear/Biology/npzd_iop_wrt.h @@ -0,0 +1,96 @@ +/* +** git $Id$ +*************************************************** Hernan G. Arango *** +** Copyright (c) 2002-2024 The ROMS/TOMS Group ** +** Licensed under a MIT/X style license ** +** See License_ROMS.md ** +************************************************************************ +** ** +** Writes IOP-based, NPZD ecosystem model input parameters into ** +** output NetCDF files. It is included in routine "wrt_info.F". ** +** ** +************************************************************************ +*/ + +! +! Write out IOP-based, NPZD ecosystem model parameters. +! + CALL netcdf_put_ivar (ng, model, ncname, 'BioIter', & + & BioIter(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'PARfrac', & + & PARfrac(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'AttSW', & + & AttSW(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'CDOM_LightAtt', & + & CDOM_LightAtt(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'CDOM_sigma', & + & CDOM_sigma(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'K_DIN', & + & K_DIN(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'PhyIS', & + & PhyIS(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'PhyMRD', & + & PhyMRD(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'PhyMRN', & + & PhyMRN(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'Vm_DIN', & + & Vm_DIN(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'DetRR', & + & DetRR(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'ThetaM', & + & ThetaM(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'BphyMap', & + & BphyMap(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'BdetMap', & + & BdetMap(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'wPhy', & + & wPhy(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN + + CALL netcdf_put_fvar (ng, model, ncname, 'wDet', & + & wDet(ng), (/0/), (/0/), & + & ncid = ncid) + IF (exit_flag.ne.NoError) RETURN diff --git a/ROMS/Nonlinear/Biology/npzd_iop_wrt_pio.h b/ROMS/Nonlinear/Biology/npzd_iop_wrt_pio.h new file mode 100644 index 00000000..9ecef5fd --- /dev/null +++ b/ROMS/Nonlinear/Biology/npzd_iop_wrt_pio.h @@ -0,0 +1,96 @@ +/* +** git $Id$ +*************************************************** Hernan G. Arango *** +** Copyright (c) 2002-2024 The ROMS/TOMS Group ** +** Licensed under a MIT/X style license ** +** See License_ROMS.md ** +************************************************************************ +** ** +** Writes IOP-based, NPZD ecosystem model input parameters into ** +** output NetCDF files. It is included in routine "wrt_info.F". ** +** ** +************************************************************************ +*/ + +! +! Write out IOP-based, NPZD ecosystem model parameters. +! + CALL pio_netcdf_put_ivar (ng, model, ncname, 'BioIter', & + & BioIter(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'PARfrac', & + & PARfrac(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'AttSW', & + & AttSW(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'CDOM_LightAtt', & + & CDOM_LightAtt(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'CDOM_sigma', & + & CDOM_sigma(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'K_DIN', & + & K_DIN(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'PhyIS', & + & PhyIS(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'PhyMRD', & + & PhyMRD(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'PhyMRN', & + & PhyMRN(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'Vm_DIN', & + & Vm_DIN(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'DetRR', & + & DetRR(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'ThetaM', & + & ThetaM(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'BphyMap', & + & BphyMap(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'BdetMap', & + & BdetMap(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'wPhy', & + & wPhy(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN + + CALL pio_netcdf_put_fvar (ng, model, ncname, 'wDet', & + & wDet(ng), (/0/), (/0/), & + & pioFile = pioFile) + IF (FoundError(exit_flag, NoError, __LINE__, MyFile)) RETURN diff --git a/ROMS/Representer/Biology/rp_biology.F b/ROMS/Representer/Biology/rp_biology.F index 93cf5931..4b9d7783 100644 --- a/ROMS/Representer/Biology/rp_biology.F +++ b/ROMS/Representer/Biology/rp_biology.F @@ -13,6 +13,8 @@ # if defined BIO_FENNEL !!# include +# elif defined IOP_CDOM +# include # elif defined NEMURO !!# include # elif defined NPZD_FRANKS diff --git a/ROMS/Representer/Biology/rp_iop_cdom.h b/ROMS/Representer/Biology/rp_iop_cdom.h new file mode 100644 index 00000000..7b3f9e31 --- /dev/null +++ b/ROMS/Representer/Biology/rp_iop_cdom.h @@ -0,0 +1,404 @@ + SUBROUTINE rp_biology (ng,tile) +! +!git $Id$ +!************************************************** Hernan G. Arango *** +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!*********************************************************************** +! ! +! IOP-based, CDOM (Colored Dissolved Organic Matter) Model ! +! ! +! This routine computes the biological sources and sinks and adds ! +! then the global biological fields. ! +! ! +! It computes the absorption, scattering, and backscattering from ! +! the ecosystem variables. This facilitates direct comparisons ! +! between measuared and models IOPs (Inherent Optical Properties). ! +! It also possible to calculate remote sensing reflectances from ! +! model output for direct comparisons with remotely sensed ocean ! +! color (SeaWIFS, MODIS, etc) and data assimilation. ! +! ! +! Reference: ! +! ! +! Fennel, K., ... ! +! ! +!*********************************************************************** +! + USE mod_param + USE mod_forces + USE mod_grid + USE mod_ncparam + USE mod_ocean + USE mod_stepping +! +! Imported variable declarations. +! + integer, intent(in) :: ng, tile +! +! Local variable declarations. +! +#include "tile.h" +! +! Set header file name. +! +#ifdef DISTRIBUTE + IF (Lbiofile(iRPM)) THEN +#else + IF (Lbiofile(iRPM).and.(tile.eq.0)) THEN +#endif + Lbiofile(iRPM)=.FALSE. + BIONAME(iRPM)=__FILE__ + END IF +! +#ifdef PROFILE + CALL wclock_on (ng, iRPM, 15) +#endif + CALL rp_biology_tile (ng, tile, & + & LBi, UBi, LBj, UBj, N(ng), NT(ng), & + & IminS, ImaxS, JminS, JmaxS, & + & nstp(ng), nnew(ng), & +#ifdef MASKING + & GRID(ng) % rmask, & +#endif + & GRID(ng) % Hz, & + & GRID(ng) % tl_Hz, & + & GRID(ng) % z_w, & + & GRID(ng) % tl_z_w, & + & FORCES(ng) % srflx, & + & FORCES(ng) % tl_srflx, & + & OCEAN(ng) % t, & + & OCEAN(ng) % tl_t) + +#ifdef PROFILE + CALL wclock_off (ng, iRPM, 15) +#endif + + RETURN + END SUBROUTINE rp_biology +! +!----------------------------------------------------------------------- + SUBROUTINE rp_biology_tile (ng, tile, & + & LBi, UBi, LBj, UBj, UBk, UBt, & + & IminS, ImaxS, JminS, JmaxS, & + & nstp, nnew, & +#ifdef MASKING + & rmask, & +#endif + & Hz, tl_Hz, & + & z_w, tl_z_w, & + & srflx, tl_srflx, & + & t, tl_t) +!----------------------------------------------------------------------- +! + USE mod_param + USE mod_biology + USE mod_ncparam + USE mod_scalars +! +! Imported variable declarations. +! + integer, intent(in) :: ng, tile + integer, intent(in) :: LBi, UBi, LBj, UBj, UBk, UBt + integer, intent(in) :: IminS, ImaxS, JminS, JmaxS + integer, intent(in) :: nstp, nnew + +#ifdef ASSUMED_SHAPE +# ifdef MASKING + real(r8), intent(in) :: rmask(LBi:,LBj:) +# endif + real(r8), intent(in) :: Hz(LBi:,LBj:,:) + real(r8), intent(in) :: z_w(LBi:,LBj:,0:) + real(r8), intent(in) :: srflx(LBi:,LBj:) + real(r8), intent(in) :: t(LBi:,LBj:,:,:,:) + + real(r8), intent(in) :: tl_Hz(LBi:,LBj:,:) + real(r8), intent(in) :: tl_z_w(LBi:,LBj:,0:) + real(r8), intent(in) :: tl_srflx(LBi:,LBj:) + real(r8), intent(inout) :: tl_t(LBi:,LBj:,:,:,:) +#else +# ifdef MASKING + real(r8), intent(in) :: rmask(LBi:UBi,LBj:UBj) +# endif + real(r8), intent(in) :: Hz(LBi:UBi,LBj:UBj,UBk) + real(r8), intent(in) :: z_w(LBi:UBi,LBj:UBj,0:UBk) + real(r8), intent(in) :: srflx(LBi:UBi,LBj:UBj) + real(r8), intent(in) :: t(LBi:UBi,LBj:UBj,UBk,3,UBt) + + real(r8), intent(in) :: tl_Hz(LBi:UBi,LBj:UBj,UBk) + real(r8), intent(in) :: tl_z_w(LBi:UBi,LBj:UBj,0:UBk) + real(r8), intent(in) :: tl_srflx(LBi:UBi,LBj:UBj) + real(r8), intent(inout) :: tl_t(LBi:UBi,LBj:UBj,UBk,3,UBt) +#endif +! +! Local variable declarations. +! + integer :: Iter, i, ibio, itrc, j, k, nb + integer :: Iteradj + + real(r8) :: Att, ExpAtt, Itop, PAR + real(r8) :: tl_Att, tl_ExpAtt, tl_Itop, tl_PAR + real(r8) :: cff, cff1, dtdays + real(r8) :: tl_cff + + real(r8), dimension(IminS:ImaxS) :: PARsur + real(r8), dimension(IminS:ImaxS) :: tl_PARsur + + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio_old + + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: tl_Bio + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: tl_Bio_old + + real(r8), dimension(IminS:ImaxS,N(ng)) :: Hz_inv + real(r8), dimension(IminS:ImaxS,N(ng)) :: Light + + real(r8), dimension(IminS:ImaxS,N(ng)) :: tl_Hz_inv + real(r8), dimension(IminS:ImaxS,N(ng)) :: tl_Light + +#include "set_bounds.h" +! +!----------------------------------------------------------------------- +! Add biological Source/Sink terms. +!----------------------------------------------------------------------- +! +! Set time-stepping size (days) according to the number of iterations. +! + dtdays=dt(ng)*sec2day/REAL(BioIter(ng),r8) +! +! Initialize local Bio scratch arrays. +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,ibio)=0.0_r8 + tl_Bio(i,k,ibio)=0.0_r8 + END DO + END DO + END DO +! +! Start pipelined J-loop. +! + J_LOOP : DO j=Jstr,Jend +! +! Compute inverse thickness to avoid repeated divisions. +! + DO k=1,N(ng) + DO i=Istr,Iend + Hz_inv(i,k)=1.0_r8/Hz(i,j,k) + tl_Hz_inv(i,k)=-Hz_inv(i,k)*Hz_inv(i,k)*tl_Hz(i,j,k)+ & +#ifdef TL_IOMS + & 2.0_r8*Hz_inv(i,k) +#endif + END DO + END DO +! +! Extract biological variables from tracer arrays, place them into +! scratch arrays, and restrict their values to be positive definite. +! At input, all tracers (index nnew) from predictor step have +! transport units (m Tunits) since we do not have yet the new +! values for zeta and Hz. These are known after the 2D barotropic +! time-stepping. +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,ibio)=MAX(0.0_r8,t(i,j,k,nstp,ibio)) + tl_Bio(i,k,ibio)=(0.5_r8- & + & SIGN(0.5_r8,-t(i,j,k,nstp,ibio)))* & + & tl_t(i,j,k,nstp,ibio) + Bio_old(i,k,ibio)=Bio(i,k,ibio) + tl_Bio_old(i,k,ibio)=tl_Bio(i,k,ibio) + END DO + END DO + END DO +! +! Calculate surface Photosynthetically Available Radiation (PAR). The +! net shortwave radiation is scaled back to Watts/m2 and multiplied by +! the fraction that is photosynthetically available, PARfrac. +! + DO i=Istr,Iend + PARsur(i)=PARfrac(ng)*srflx(i,j)*rho0*Cp + tl_PARsur(i)=(tl_PARfrac(ng)*srflx(i,j)+ & + & PARfrac(ng)*tl_srflx(i,j))*rho0*Cp- & +#ifdef TL_IOMS + & PARsur(i) +#endif + END DO +! +!======================================================================= +! Start internal iterations to achieve convergence of the nonlinear +! backward-implicit solution. +!======================================================================= +! +! During the iterative procedure a series of fractional time steps are +! performed in a chained mode (splitting by different biological +! conversion processes) in sequence of the main food chain. In all +! stages the concentration of the component being consumed is treated +! in a fully implicit manner, so the algorithm guarantees non-negative +! values, no matter how strong the concentration of active consuming +! component (Phytoplankton or Zooplankton). The overall algorithm, +! as well as any stage of it, is formulated in conservative form +! (except explicit sinking) in sense that the sum of concentration of +! all components is conserved. +! +! In the implicit algorithm, we have for example (N: nutrient, +! P: phytoplankton), +! +! N(new) = N(old) - uptake * P(old) uptake = mu * N / (Kn + N) +! {Michaelis-Menten} +! below, we set +! The N in the numerator of +! cff = mu * P(old) / (Kn + N(old)) uptake is treated implicitly +! as N(new) +! +! so the time-stepping of the equations becomes: +! +! N(new) = N(old) / (1 + cff) (1) when substracting a sink term, +! consuming, divide by (1 + cff) +! and +! +! P(new) = P(old) + cff * N(new) (2) when adding a source term, +! growing, add (cff * source) +! +! Notice that if you substitute (1) in (2), you will get: +! +! P(new) = P(old) + cff * N(old) / (1 + cff) (3) +! +! If you add (1) and (3), you get +! +! N(new) + P(new) = N(old) + P(old) +! +! implying conservation regardless how "cff" is computed. Therefore, +! this scheme is unconditionally stable regardless of the conversion +! rate. It does not generate negative values since the constituent +! to be consumed is always treated implicitly. It is also biased +! toward damping oscillations. +! +! The iterative loop below is to iterate toward an universal Backward- +! Euler treatment of all terms. So if there are oscillations in the +! system, they are only physical oscillations. These iterations, +! however, do not improve the accuaracy of the solution. +! + ITER_LOOP: DO Iter=1,BioIter(ng) +! +! Compute light attenuation as function of depth. +! + DO i=Istr,Iend + PAR=PARsur(i) +#ifdef TL_IOMS + tl_PAR=PARsur(i) +#else + tl_PAR=tl_PARsur(i) +#endif + IF (PARsur(i).gt.0.0_r8) THEN ! day time + DO k=N(ng),1,-1 +! +! Attenuate the light to the center of the grid cell. Here, AttSW is +! the light attenuation due to seawater. +! + Att=(AttSW(ng)+ & + & CDOM_LightAtt(ng)*Bio(i,k,aCDOM(i440n)))* & + & (z_w(i,j,k)-z_w(i,j,k-1)) + tl_Att=CDOM_LightAtt(ng)*tl_Bio(i,k,aCDOM(i440n))* & + & (z_w(i,j,k)-z_w(i,j,k-1))+ & + & (AttSW(ng)+ & + & CDOM_LightAtt(ng)*Bio(i,k,aCDOM(i440n)))* & + & (tl_z_w(i,j,k)-tl_z_w(i,j,k-1))- & +#ifdef TL_IOMS + & CDOM_LightAtt(ng)*Bio1(i,k,aCDOM(i440n))* & + & (z_w(i,j,k)-z_w(i,j,k-1)) +#endif + ExpAtt=EXP(-Att) + tl_ExpAtt=-ExpAtt*tl_Att+ & +#ifdef TL_IOMS + & (1.0_r8+Att)*ExpAtt +#endif + Itop=PAR + tl_Itop=tl_PAR + PAR=Itop*(1.0_r8-ExpAtt)/Att ! average at center + tl_PAR=(-tl_Att*PAR+tl_Itop*(1.0_r8-ExpAtt)- & + & Itop*tl_ExpAtt)/Att+ & +#ifdef TL_IOMS + & Itop/Att +#endif + Light(i,k)=PAR + tl_Light(i,k)=tl_PAR +! +! Light attenuation at the bottom of the grid cell. It is the starting +! PAR value for the next (deeper) vertical grid cell. +! + PAR=Itop*ExpAtt + tl_PAR=tl_Itop*ExpAtt+Itop*tl_ExpAtt- & +#ifdef TL_IOMS + & PAR +#endif + END DO + ELSE ! night time + DO k=1,N(ng) + Light(i,k)=0.0_r8 + tl_Light(i,k)=0.0_r8 + END DO + END IF + END DO +! +! Degradation of CDOM absorption, aCDOM. +! + cff1=dtdays*CDOM_sigma(ng) + DO k=1,N(ng) + DO i=Istr,Iend + cff=cff1*Light(i,k) + tl_cff=cff1*tl_Light(i,k) + DO nb=1,NBands + Bio(i,k,aCDOM(nb))=Bio(i,k,aCDOM(nb))/(1.0_r8+cff) + tl_Bio(i,k,aCDOM(nb))=(tl_Bio(i,k,aCDOM(nb))- & + & tl_cff*Bio(i,k,aCDOM(nb)))/ & + & (1.0_r8+cff)+ & +#ifdef TL_IOMS + & cff*Bio(i,k,aCDOM(nb))/ & + & (1.0_r8+cff) +#endif + END DO + END DO + END DO + + END DO ITER_LOOP +! +!----------------------------------------------------------------------- +! Update global tracer variables: Add increment due to BGC processes +! to tracer array in time index "nnew". Index "nnew" is solution after +! advection and mixing and has transport units (m Tunits) hence the +! increment is multiplied by Hz. Notice that we need to subtract +! original values "Bio_old" at the top of the routine to just account +! for the concentractions affected by BGC processes. This also takes +! into account any constraints (non-negative concentrations, carbon +! concentration range) specified before entering BGC kernel. If "Bio" +! were unchanged by BGC processes, the increment would be exactly +! zero. Notice that final tracer values, t(:,:,:,nnew,:) are not +! bounded >=0 so that we can preserve total inventory of nutrients +! when advection causes tracer concentration to go negative. +!----------------------------------------------------------------------- +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + cff=Bio(i,k,ibio)-Bio_old(i,k,ibio) + tl_cff=tl_Bio(i,k,ibio)-tl_Bio_old(i,k,ibio) +!^ t(i,j,k,nnew,ibio)=t(i,j,k,nnew,ibio)+cff*Hz(i,j,k) +!^ + tl_t(i,j,k,nnew,ibio)=tl_t(i,j,k,nnew,ibio)+ & + & tl_cff*Hz(i,j,k)+cff*tl_Hz(i,j,k)- & +#ifdef TL_IOMS + & cff*Hz(i,j,k) +#endif + END DO + END DO + END DO + + END DO J_LOOP + + RETURN + END SUBROUTINE rp_biology_tile diff --git a/ROMS/Tangent/Biology/tl_biology.F b/ROMS/Tangent/Biology/tl_biology.F index 7483d8ac..ef7bf03c 100644 --- a/ROMS/Tangent/Biology/tl_biology.F +++ b/ROMS/Tangent/Biology/tl_biology.F @@ -13,6 +13,8 @@ # if defined BIO_FENNEL !!# include +# elif defined IOP_CDOM +# include # elif defined NEMURO !!# include # elif defined NPZD_FRANKS diff --git a/ROMS/Tangent/Biology/tl_iop_cdom.h b/ROMS/Tangent/Biology/tl_iop_cdom.h new file mode 100644 index 00000000..e4cb5be4 --- /dev/null +++ b/ROMS/Tangent/Biology/tl_iop_cdom.h @@ -0,0 +1,374 @@ + SUBROUTINE tl_biology (ng,tile) +! +!git $Id$ +!************************************************** Hernan G. Arango *** +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!*********************************************************************** +! ! +! IOP-based, CDOM (Colored Dissolved Organic Matter) Model ! +! ! +! This routine computes the biological sources and sinks and adds ! +! then the global biological fields. ! +! ! +! It computes the absorption, scattering, and backscattering from ! +! the ecosystem variables. This facilitates direct comparisons ! +! between measuared and models IOPs (Inherent Optical Properties). ! +! It also possible to calculate remote sensing reflectances from ! +! model output for direct comparisons with remotely sensed ocean ! +! color (SeaWIFS, MODIS, etc) and data assimilation. ! +! ! +! Reference: ! +! ! +! Fennel, K., ... ! +! ! +!*********************************************************************** +! + USE mod_param + USE mod_forces + USE mod_grid + USE mod_ncparam + USE mod_ocean + USE mod_stepping +! +! Imported variable declarations. +! + integer, intent(in) :: ng, tile +! +! Local variable declarations. +! +#include "tile.h" +! +! Set header file name. +! +#ifdef DISTRIBUTE + IF (Lbiofile(iTLM)) THEN +#else + IF (Lbiofile(iTLM).and.(tile.eq.0)) THEN +#endif + Lbiofile(iTLM)=.FALSE. + BIONAME(iTLM)=__FILE__ + END IF +! +#ifdef PROFILE + CALL wclock_on (ng, iTLM, 15) +#endif + CALL tl_biology_tile (ng, tile, & + & LBi, UBi, LBj, UBj, N(ng), NT(ng), & + & IminS, ImaxS, JminS, JmaxS, & + & nstp(ng), nnew(ng), & +#ifdef MASKING + & GRID(ng) % rmask, & +#endif + & GRID(ng) % Hz, & + & GRID(ng) % tl_Hz, & + & GRID(ng) % z_w, & + & GRID(ng) % tl_z_w, & + & FORCES(ng) % srflx, & + & FORCES(ng) % tl_srflx, & + & OCEAN(ng) % t, & + & OCEAN(ng) % tl_t) + +#ifdef PROFILE + CALL wclock_off (ng, iTLM, 15) +#endif + + RETURN + END SUBROUTINE tl_biology +! +!----------------------------------------------------------------------- + SUBROUTINE tl_biology_tile (ng, tile, & + & LBi, UBi, LBj, UBj, UBk, UBt, & + & IminS, ImaxS, JminS, JmaxS, & + & nstp, nnew, & +#ifdef MASKING + & rmask, & +#endif + & Hz, tl_Hz, & + & z_w, tl_z_w, & + & srflx, tl_srflx, & + & t, tl_t) +!----------------------------------------------------------------------- +! + USE mod_param + USE mod_biology + USE mod_ncparam + USE mod_scalars +! +! Imported variable declarations. +! + integer, intent(in) :: ng, tile + integer, intent(in) :: LBi, UBi, LBj, UBj, UBk, UBt + integer, intent(in) :: IminS, ImaxS, JminS, JmaxS + integer, intent(in) :: nstp, nnew + +#ifdef ASSUMED_SHAPE +# ifdef MASKING + real(r8), intent(in) :: rmask(LBi:,LBj:) +# endif + real(r8), intent(in) :: Hz(LBi:,LBj:,:) + real(r8), intent(in) :: z_w(LBi:,LBj:,0:) + real(r8), intent(in) :: srflx(LBi:,LBj:) + real(r8), intent(in) :: t(LBi:,LBj:,:,:,:) + + real(r8), intent(in) :: tl_Hz(LBi:,LBj:,:) + real(r8), intent(in) :: tl_z_w(LBi:,LBj:,0:) + real(r8), intent(in) :: tl_srflx(LBi:,LBj:) + real(r8), intent(inout) :: tl_t(LBi:,LBj:,:,:,:) +#else +# ifdef MASKING + real(r8), intent(in) :: rmask(LBi:UBi,LBj:UBj) +# endif + real(r8), intent(in) :: Hz(LBi:UBi,LBj:UBj,UBk) + real(r8), intent(in) :: z_w(LBi:UBi,LBj:UBj,0:UBk) + real(r8), intent(in) :: srflx(LBi:UBi,LBj:UBj) + real(r8), intent(in) :: t(LBi:UBi,LBj:UBj,UBk,3,UBt) + + real(r8), intent(in) :: tl_Hz(LBi:UBi,LBj:UBj,UBk) + real(r8), intent(in) :: tl_z_w(LBi:UBi,LBj:UBj,0:UBk) + real(r8), intent(in) :: tl_srflx(LBi:UBi,LBj:UBj) + real(r8), intent(inout) :: tl_t(LBi:UBi,LBj:UBj,UBk,3,UBt) +#endif +! +! Local variable declarations. +! + integer :: Iter, i, ibio, itrc, j, k, nb + integer :: Iteradj + + real(r8) :: Att, ExpAtt, Itop, PAR + real(r8) :: tl_Att, tl_ExpAtt, tl_Itop, tl_PAR + real(r8) :: cff, cff1, dtdays + real(r8) :: tl_cff + + real(r8), dimension(IminS:ImaxS) :: PARsur + real(r8), dimension(IminS:ImaxS) :: tl_PARsur + + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio_old + + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: tl_Bio + real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: tl_Bio_old + + real(r8), dimension(IminS:ImaxS,N(ng)) :: Hz_inv + real(r8), dimension(IminS:ImaxS,N(ng)) :: Light + + real(r8), dimension(IminS:ImaxS,N(ng)) :: tl_Hz_inv + real(r8), dimension(IminS:ImaxS,N(ng)) :: tl_Light + +#include "set_bounds.h" +! +!----------------------------------------------------------------------- +! Add biological Source/Sink terms. +!----------------------------------------------------------------------- +! +! Set time-stepping size (days) according to the number of iterations. +! + dtdays=dt(ng)*sec2day/REAL(BioIter(ng),r8) +! +! Initialize local Bio scratch arrays. +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,ibio)=0.0_r8 + tl_Bio(i,k,ibio)=0.0_r8 + END DO + END DO + END DO +! +! Start pipelined J-loop. +! + J_LOOP : DO j=Jstr,Jend +! +! Compute inverse thickness to avoid repeated divisions. +! + DO k=1,N(ng) + DO i=Istr,Iend + Hz_inv(i,k)=1.0_r8/Hz(i,j,k) + tl_Hz_inv(i,k)=-Hz_inv(i,k)*Hz_inv(i,k)*tl_Hz(i,j,k) + END DO + END DO +! +! Extract biological variables from tracer arrays, place them into +! scratch arrays, and restrict their values to be positive definite. +! At input, all tracers (index nnew) from predictor step have +! transport units (m Tunits) since we do not have yet the new +! values for zeta and Hz. These are known after the 2D barotropic +! time-stepping. +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + Bio(i,k,ibio)=MAX(0.0_r8,t(i,j,k,nstp,ibio)) + tl_Bio(i,k,ibio)=(0.5_r8- & + & SIGN(0.5_r8,-t(i,j,k,nstp,ibio)))* & + & tl_t(i,j,k,nstp,ibio) + Bio_old(i,k,ibio)=Bio(i,k,ibio) + tl_Bio_old(i,k,ibio)=tl_Bio(i,k,ibio) + END DO + END DO + END DO +! +! Calculate surface Photosynthetically Available Radiation (PAR). The +! net shortwave radiation is scaled back to Watts/m2 and multiplied by +! the fraction that is photosynthetically available, PARfrac. +! + DO i=Istr,Iend + PARsur(i)=PARfrac(ng)*srflx(i,j)*rho0*Cp + tl_PARsur(i)=(tl_PARfrac(ng)*srflx(i,j)+ & + & PARfrac(ng)*tl_srflx(i,j))*rho0*Cp + END DO +! +!======================================================================= +! Start internal iterations to achieve convergence of the nonlinear +! backward-implicit solution. +!======================================================================= +! +! During the iterative procedure a series of fractional time steps are +! performed in a chained mode (splitting by different biological +! conversion processes) in sequence of the main food chain. In all +! stages the concentration of the component being consumed is treated +! in a fully implicit manner, so the algorithm guarantees non-negative +! values, no matter how strong the concentration of active consuming +! component (Phytoplankton or Zooplankton). The overall algorithm, +! as well as any stage of it, is formulated in conservative form +! (except explicit sinking) in sense that the sum of concentration of +! all components is conserved. +! +! In the implicit algorithm, we have for example (N: nutrient, +! P: phytoplankton), +! +! N(new) = N(old) - uptake * P(old) uptake = mu * N / (Kn + N) +! {Michaelis-Menten} +! below, we set +! The N in the numerator of +! cff = mu * P(old) / (Kn + N(old)) uptake is treated implicitly +! as N(new) +! +! so the time-stepping of the equations becomes: +! +! N(new) = N(old) / (1 + cff) (1) when substracting a sink term, +! consuming, divide by (1 + cff) +! and +! +! P(new) = P(old) + cff * N(new) (2) when adding a source term, +! growing, add (cff * source) +! +! Notice that if you substitute (1) in (2), you will get: +! +! P(new) = P(old) + cff * N(old) / (1 + cff) (3) +! +! If you add (1) and (3), you get +! +! N(new) + P(new) = N(old) + P(old) +! +! implying conservation regardless how "cff" is computed. Therefore, +! this scheme is unconditionally stable regardless of the conversion +! rate. It does not generate negative values since the constituent +! to be consumed is always treated implicitly. It is also biased +! toward damping oscillations. +! +! The iterative loop below is to iterate toward an universal Backward- +! Euler treatment of all terms. So if there are oscillations in the +! system, they are only physical oscillations. These iterations, +! however, do not improve the accuaracy of the solution. +! + ITER_LOOP: DO Iter=1,BioIter(ng) +! +! Compute light attenuation as function of depth. +! + DO i=Istr,Iend + PAR=PARsur(i) + tl_PAR=tl_PARsur(i) + IF (PARsur(i).gt.0.0_r8) THEN ! day time + DO k=N(ng),1,-1 +! +! Attenuate the light to the center of the grid cell. Here, AttSW is +! the light attenuation due to seawater. +! + Att=(AttSW(ng)+ & + & CDOM_LightAtt(ng)*Bio(i,k,aCDOM(i440n)))* & + & (z_w(i,j,k)-z_w(i,j,k-1)) + tl_Att=CDOM_LightAtt(ng)*tl_Bio(i,k,aCDOM(i440n))* & + & (z_w(i,j,k)-z_w(i,j,k-1))+ & + & (AttSW(ng)+ & + & CDOM_LightAtt(ng)*Bio(i,k,aCDOM(i440n)))* & + & (tl_z_w(i,j,k)-tl_z_w(i,j,k-1)) + ExpAtt=EXP(-Att) + tl_ExpAtt=-ExpAtt*tl_Att + Itop=PAR + tl_Itop=tl_PAR + PAR=Itop*(1.0_r8-ExpAtt)/Att ! average at center + tl_PAR=(-tl_Att*PAR+tl_Itop*(1.0_r8-ExpAtt)- & + & Itop*tl_ExpAtt)/Att + Light(i,k)=PAR + tl_Light(i,k)=tl_PAR +! +! Light attenuation at the bottom of the grid cell. It is the starting +! PAR value for the next (deeper) vertical grid cell. +! + PAR=Itop*ExpAtt + tl_PAR=tl_Itop*ExpAtt+Itop*tl_ExpAtt + END DO + ELSE ! night time + DO k=1,N(ng) + Light(i,k)=0.0_r8 + tl_Light(i,k)=0.0_r8 + END DO + END IF + END DO +! +! Degradation of CDOM absorption, aCDOM. +! + cff1=dtdays*CDOM_sigma(ng) + DO k=1,N(ng) + DO i=Istr,Iend + cff=cff1*Light(i,k) + tl_cff=cff1*tl_Light(i,k) + DO nb=1,NBands + Bio(i,k,aCDOM(nb))=Bio(i,k,aCDOM(nb))/(1.0_r8+cff) + tl_Bio(i,k,aCDOM(nb))=(tl_Bio(i,k,aCDOM(nb))- & + & tl_cff*Bio(i,k,aCDOM(nb)))/ & + & (1.0_r8+cff) + END DO + END DO + END DO + + END DO ITER_LOOP +! +!----------------------------------------------------------------------- +! Update global tracer variables: Add increment due to BGC processes +! to tracer array in time index "nnew". Index "nnew" is solution after +! advection and mixing and has transport units (m Tunits) hence the +! increment is multiplied by Hz. Notice that we need to subtract +! original values "Bio_old" at the top of the routine to just account +! for the concentractions affected by BGC processes. This also takes +! into account any constraints (non-negative concentrations, carbon +! concentration range) specified before entering BGC kernel. If "Bio" +! were unchanged by BGC processes, the increment would be exactly +! zero. Notice that final tracer values, t(:,:,:,nnew,:) are not +! bounded >=0 so that we can preserve total inventory of nutrients +! when advection causes tracer concentration to go negative. +!----------------------------------------------------------------------- +! + DO itrc=1,NBT + ibio=idbio(itrc) + DO k=1,N(ng) + DO i=Istr,Iend + cff=Bio(i,k,ibio)-Bio_old(i,k,ibio) + tl_cff=tl_Bio(i,k,ibio)-tl_Bio_old(i,k,ibio) +!^ t(i,j,k,nnew,ibio)=t(i,j,k,nnew,ibio)+cff*Hz(i,j,k) +!^ + tl_t(i,j,k,nnew,ibio)=tl_t(i,j,k,nnew,ibio)+ & + & tl_cff*Hz(i,j,k)+cff*tl_Hz(i,j,k) + END DO + END DO + END DO + + END DO J_LOOP + + RETURN + END SUBROUTINE tl_biology_tile diff --git a/ROMS/Utility/checkdefs.F b/ROMS/Utility/checkdefs.F index 9fd9355f..cb8f3b01 100644 --- a/ROMS/Utility/checkdefs.F +++ b/ROMS/Utility/checkdefs.F @@ -1500,6 +1500,14 @@ SUBROUTINE checkdefs Coptions(is:is+15)=' INNER_PRODUCT,' idriver=idriver+1 #endif +#ifdef IOP_CDOM +! + IF (Master) WRITE (stdout,20) 'IOP_CDOM', & + & 'IOP-based CDOM ecosystem model' + is=LEN_TRIM(Coptions)+1 + Coptions(is:is+10)=' IOP_CDOM,' + ibiology=ibiology+1 +#endif #if defined I4DVAR && !defined SPLIT_4DVAR ! IF (Master) WRITE (stdout,20) 'I4DVAR', & @@ -1872,6 +1880,14 @@ SUBROUTINE checkdefs Coptions(is:is+13)=' NPZD_FRANKS,' ibiology=ibiology+1 #endif +#ifdef NPZD_IOP +! + IF (Master) WRITE (stdout,20) 'NPZD_IOP', & + 'IOP-based NPZD ecosystem model' + is=LEN_TRIM(Coptions)+1 + Coptions(is:is+10)=' NPZD_IOP,' + ibiology=ibiology+1 +#endif #ifdef NPZD_IRON ! IF (Master) WRITE (stdout,20) 'NPZD_IRON', & diff --git a/ROMS/Utility/def_info.F b/ROMS/Utility/def_info.F index 52bcb056..935c65bf 100644 --- a/ROMS/Utility/def_info.F +++ b/ROMS/Utility/def_info.F @@ -2948,10 +2948,14 @@ SUBROUTINE def_info_nf90 (ng, model, ncid, ncname, DimIDs) # include # elif defined HYPOXIA_SRM # include +# elif defined IOP_CDOM +# include # elif defined NEMURO # include # elif defined NPZD_FRANKS # include +# elif defined NPZD_IOP +# include # elif defined NPZD_IRON # include # elif defined NPZD_POWELL @@ -6422,10 +6426,14 @@ SUBROUTINE def_info_pio (ng, model, pioFile, ncname, DimIDs) # include # elif defined HYPOXIA_SRM # include +# elif defined IOP_CDOM +# include # elif defined NEMURO # include # elif defined NPZD_FRANKS # include +# elif defined NPZD_IOP +# include # elif defined NPZD_IRON # include # elif defined NPZD_POWELL diff --git a/ROMS/Utility/read_biopar.F b/ROMS/Utility/read_biopar.F index 1acf013b..3d5de8f0 100644 --- a/ROMS/Utility/read_biopar.F +++ b/ROMS/Utility/read_biopar.F @@ -19,10 +19,14 @@ # include # elif defined HYPOXIA_SRM # include +# elif defined IOP_CDOM +# include # elif defined NEMURO # include # elif defined NPZD_FRANKS # include +# elif defined NPZD_IOP +# include # elif defined NPZD_IRON # include # elif defined NPZD_POWELL diff --git a/ROMS/Utility/wrt_info.F b/ROMS/Utility/wrt_info.F index f23db49b..1182c438 100644 --- a/ROMS/Utility/wrt_info.F +++ b/ROMS/Utility/wrt_info.F @@ -1354,10 +1354,14 @@ SUBROUTINE wrt_info_nf90 (ng, model, ncid, ncname) # include # elif defined HYPOXIA_SRM # include +# elif defined IOP_CDOM +# include # elif defined NEMURO # include # elif defined NPZD_FRANKS # include +# elif defined NPZD_IOP +# include # elif defined NPZD_IRON # include # elif defined NPZD_POWELL @@ -4692,10 +4696,14 @@ SUBROUTINE wrt_info_pio (ng, model, pioFile, ncname) # include # elif defined HYPOXIA_SRM # include +# elif defined IOP_CDOM +# include # elif defined NEMURO # include # elif defined NPZD_FRANKS # include +# elif defined NPZD_IOP +# include # elif defined NPZD_IRON # include # elif defined NPZD_POWELL diff --git a/User/External/iop_cdom.in b/User/External/iop_cdom.in new file mode 100644 index 00000000..e9c9e803 --- /dev/null +++ b/User/External/iop_cdom.in @@ -0,0 +1,307 @@ +! IOP-based, CDOM Ecosystem Model Parameters. +! +!git $Id$ +!========================================================= Hernan G. Arango === +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!============================================================================== +! ! +! Input parameters can be entered in ANY order, provided that the parameter ! +! KEYWORD (usually, upper case) is typed correctly followed by "=" or "==" ! +! symbols. Any comment lines are allowed and must begin with an exclamation ! +! mark (!) in column one. Comments may appear to the right of a parameter ! +! specification to improve documentation. Comments will be ignored during ! +! reading. Blank lines are also allowed and ignored. Continuation lines in ! +! a parameter specification are allowed and must be preceded by a backslash ! +! (\). In some instances, more than one value is required for a parameter. ! +! If fewer values are provided, the last value is assigned for the entire ! +! parameter array. The multiplication symbol (*), without blank spaces in ! +! between, is allowed for a parameter specification. For example, in a two ! +! grids nested application: ! +! ! +! AKT_BAK == 2*1.0d-6 2*5.0d-6 ! m2/s ! +! ! +! indicates that the first two entries of array AKT_BAK, in fortran column- ! +! major order, will have the same value of "1.0d-6" for grid 1, whereas the ! +! next two entries will have the same value of "5.0d-6" for grid 2. ! +! ! +! In multiple levels of nesting and/or multiple connected domains step-ups, ! +! "Ngrids" entries are expected for some of these parameters. In such case, ! +! the order of the entries for a parameter is extremely important. It must ! +! follow the same order (1:Ngrids) as in the state variable declaration. The ! +! USER may follow the above guidelines for specifying his/her values. These ! +! parameters are marked by "==" plural symbol after the KEYWORD. ! +! ! +!============================================================================== +! +! NOTICE: Input parameter units are specified within brackets and default +! ****** values are specified within braces. +! +! Switch to control the computation of biology within nested and/or multiple +! connected grids. + + Lbiology == T + +! Maximum number of iterations to achieve convergence of the nonlinear +! solution. + + BioIter == 1 + +! Initial concentration for analytical uniform initial conditions for +! aCDOM (Colored Dissolved Organic Matter aborption) [1/meter]. + +BioIni(i440n) == 1.0d0 ! aCDOM at 440nm +BioIni(i510n) == 1.0d0 ! aCDOM at 510nm + +! Fraction of shortwave radiation that is photosynthetically active +! (nondimensional), {0.43d0}. + + PARfrac == 0.43d0 + +! Light attenuation due to seawater [1/m], {0.04d0}. + + AttSW == 0.04d0 + +! Light attenuation factor due to CDOM absorption [nondimensional]. + +CDOM_LightAtt == 0.8d0 + +! Light-dependent degradation rate for CDOM absorption [1/(Watt m-2 day)]. + + CDOM_sigma == 0.0005d0 + +! Harmonic/biharmonic horizontal diffusion of biological tracer for +! nonlinear model and adjoint-based algorithms: [1:NBT,Ngrids]. + + TNU2 == 20.0d0 20.0d0 ! m2/s + TNU4 == 2.0d+8 2.0d+8 ! m4/s + + ad_TNU2 == 20.0d0 20.0d0 ! m2/s + ad_TNU4 == 2.0d+8 2.0d+8 ! m4/s + +! Vertical mixing coefficients for biological tracers for nonlinear +! model and basic state scale factor in adjoint-based algorithms: +! [1:NBT,Ngrids]. + + AKT_BAK == 2*5.0d-6 ! m2/s + + ad_AKT_fac == 2*1.0d0 ! nondimensional + +! Nudging/relaxation time scales, inverse scales will be computed +! internally: [1:NBT,Ngrids]. + + TNUDG == 2*0.5d0 ! days + +! Logical switches (TRUE/FALSE) to specify which variables to consider on +! tracers point Sources/Sinks (like river runoff): [NBT,Ngrids] values are +! expected. See glossary below for details. + + LtracerSrc == 2*F + +! Logical switches (TRUE/FALSE) to activate writing of biological tracers +! into HISTORY/AVERAGE output files: [1:NBT,Ngrids]. + + Hout(idTvar) == 2*T ! biological tracer + Hout(idTsur) == 2*F ! surface tracer flux + +! Logical switches (TRUE/FALSE) to activate writing of time-averaged fields +! into AVERAGE output file: [1:NBT,Ngrids]. + + Aout(idTvar) == 6*T ! biological tracer + +! Logical switches (TRUE/FALSE) to activate writing of time-averaged, +! biological tracer diagnostic terms into DIAGNOSTIC output file: +! [1:NBT,Ngrids]. + + Dout(iTrate) == 6*T ! time rate of change + Dout(iThadv) == 6*T ! horizontal total advection + Dout(iTxadv) == 6*T ! horizontal XI-advection + Dout(iTyadv) == 6*T ! horizontal ETA-advection + Dout(iTvadv) == 6*T ! vertical advection + Dout(iThdif) == 6*T ! horizontal total diffusion + Dout(iTxdif) == 6*T ! horizontal XI-diffusion + Dout(iTydif) == 6*T ! horizontal ETA-diffusion + Dout(iTsdif) == 6*T ! horizontal S-diffusion + Dout(iTvdif) == 6*T ! vertical diffusion + +! +! GLOSSARY: +! ========= +! +!------------------------------------------------------------------------------ +! IOP-based, CDOM (Colored Dissolved Organic Matter) Ecosystem Model +! Parameters. Currently, it is configured with 2 biological tracers: +! +! idbio(1) CDOM absorption at 440nm +! idbio(2) CDOM absorption at 510nm +! +!------------------------------------------------------------------------------ +! +! Lbiology Switch to control the computation of a particular module +! within nested and/or multiple connected grids. By default +! this switch is set to TRUE in "mod_scalars" for all grids. +! Ngrids values are expected. The USER has the option, for +! example, to compute the biology in just one of the nested +! grids. If so, this switch needs to be consistent with the +! dimension parameter NBT in "mod_param". In order to make +! the model more efficient in memory usage, NBT(:) should +! be zero in such grids. +! +! BioIter Maximum number of iterations to achieve convergence of +! the nonlinear implicit solution. +! +! BioIni Initial concentration for analytical uniform initial +! conditions, [1/meter]. It is only used when +! ANA_BIOLOGY is activated. +! +! BioIni(i440n) CDOM absorption at 440nm +! BioIni(i510n) CDOM absorption at 510nm +! +! PARfrac Fraction of shortwave radiation that is photosynthetically +! active (nondimensional). +! +! AttSW Light attenuation due to seawater [1/m]. +! +! CDOM_LightAtt Light attenuation factor due to CDOM absorption +! [nondimensional]. +! +! CDOM_sigma Light-dependent degradation rate for CDOM absorption +! [1/(Watt m-2 day)]. +! +!------------------------------------------------------------------------------ +! Physical Parameters, [1:NBT,1:Ngrids] values are expected. +!------------------------------------------------------------------------------ +! +! TNU2 Nonlinear model lateral, harmonic, constant, mixing +! coefficient (m2/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, TNU2 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! TNU4 Nonlinear model lateral, biharmonic, constant, mixing +! coefficient (m4/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, TNU4 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! ad_TNU2 Adjoint-based algorithms lateral, harmonic, constant, +! mixing coefficient (m2/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, ad_TNU2 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! ad_TNU4 Adjoint-based algorithms lateral, biharmonic, constant, +! mixing coefficient (m4/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, ad_TNU4 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! AKT_BAK Background vertical mixing coefficient (m2/s) for biological +! tracer variables, [1:NBT,1:Ngrids] values are expected. +! +! +! ad_AKT_fac Adjoint-based algorithms vertical mixing, basic state, +! scale factor (nondimensional) for biological tracer +! variables; [1:NBT,1:Ngrids] values are expected. In +! some applications, a smaller/larger values of vertical +! mixing are necessary for stability. It is only used +! when FORWARD_MIXING is activated. +! +! TNUDG Nudging time scale (days), [1:NBT,1:Ngrids]. Inverse scale +! will be computed internally. +! +! +!------------------------------------------------------------------------------ +! Tracer point Sources/Sink sources switches. +!------------------------------------------------------------------------------ +! +! LtracerSrc Logical switches (T/F) to specify which tracer variables +! to consider when the option TS_PSOURCE is activated; +! [1:NBT,1:Ngrids] values are expected. +! +! LtracerSrc(idbio(1),ng) CDOM absorption at 440nm +! LtracerSrc(idbio(2),ng) CDOM absorption at 510nm +! +! Recall that TS_PSOURCE is usually activated to add river +! runoff as a point source. At minimum, it is necessary to +! specify both temperature and salinity for all rivers. The +! other tracers are optional. The user needs to know the +! correspondence between biological variables and indices +! idbio(1:NBT) when activating one or more of these switches. +! +! This logical switch REPLACES and ELIMINATES the need to +! have or read the variable "river_flag(river)" in the input +! rivers forcing NetCDF file: +! +! double river_flag(river) +! river_flag:long_name = "river runoff tracer flag" +! river_flag:option_0 = "all tracers are off" +! river_flag:option_1 = "only temperature" +! river_flag:option_2 = "only salinity" +! river_flag:option_3 = "both temperature and salinity" +! river_flag:units = "nondimensional" +! +! This logic was too cumbersome and complicated when +! additional tracers are considered. However, this change +! is backward compatible. +! +! The LtracerSrc switch will be used to activate the reading +! of respective tracer variable from input river forcing +! NetCDF file. If you want to add other tracer variables +! (other than temperature and salinity) as a source for a +! particular river(s), you just need to specify such values +! on those river(s). Then, set the values to ZERO on the +! other river(s) that do NOT require such river forcing for +! that tracer. Recall that you need to specify the tracer +! values for all rivers, even if their values are zero. +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of fields into HISTORY files. +!------------------------------------------------------------------------------ +! +! Hout Logical switches (T/F) to write out biological data into +! output HISTORY NetCDF file, [1:NBT,1:Ngrids] values are +! expected: +! +! Hout(idTvar) biological tracers +! Hout(idTsur) biological tracers surface flux +! +! idTvar(idbio(1))=aCDOM(i440n) CDOM absorption at 440nm +! idTvar(idbio(2))=aCDOM(i510n) CDOM absorption at 510nm +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of fields into AVERAGE file. +!------------------------------------------------------------------------------ +! +! Aout Logical switches to write out biological fields into +! output AVERAGE NetCDF file, [1:NBT,1:Ngrids] values +! are expected: +! +! Aout(idTvar) biological tracers +! +! The idTvar(idbio(:)) are the same to those in the HISTORY +! file. +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of time-averaged fields into +! DIAGNOSTIC file. +!------------------------------------------------------------------------------ +! +! Time-averaged, biological tracers diagnostic terms, [1:NBT,Ngrids] values +! expected: (if DIAGNOSTICS_TS) +! +! Dout(idDtrc(idbio(1:NBT),iT....),1:Ngrids) +! +! Dout(iTrate) Write out time rate of change. +! Dout(iThadv) Write out horizontal total advection. +! Dout(iTxadv) Write out horizontal XI-advection. +! Dout(iTyadv) Write out horizontal ETA-advection. +! Dout(iTvadv) Write out vertical advection. +! Dout(iThdif) Write out horizontal total diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTxdif) Write out horizonta1 XI-diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTydif) Write out horizontal ETA-diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTsdif) Write out horizontal S-diffusion, if TS_DIF2 or TS_DIF4 and +! rotated tensor (MIX_GEO_TS or MIX_ISO_TS). +! Dout(iTvdif) Write out vertical diffusion. +! diff --git a/User/External/npzd_iop.in b/User/External/npzd_iop.in new file mode 100644 index 00000000..18c5efef --- /dev/null +++ b/User/External/npzd_iop.in @@ -0,0 +1,417 @@ +! IOP-based, NPZD Ecosystem Model Parameters. +! +!svn $Id$ +!========================================================= Hernan G. Arango === +! Copyright (c) 2002-2024 The ROMS/TOMS Group ! +! Licensed under a MIT/X style license ! +! See License_ROMS.md ! +!============================================================================== +! ! +! Input parameters can be entered in ANY order, provided that the parameter ! +! KEYWORD (usually, upper case) is typed correctly followed by "=" or "==" ! +! symbols. Any comment lines are allowed and must begin with an exclamation ! +! mark (!) in column one. Comments may appear to the right of a parameter ! +! specification to improve documentation. Comments will be ignored during ! +! reading. Blank lines are also allowed and ignored. Continuation lines in ! +! a parameter specification are allowed and must be preceded by a backslash ! +! (\). In some instances, more than one value is required for a parameter. ! +! If fewer values are provided, the last value is assigned for the entire ! +! parameter array. The multiplication symbol (*), without blank spaces in ! +! between, is allowed for a parameter specification. For example, in a two ! +! grids nested application: ! +! ! +! AKT_BAK == 2*1.0d-6 2*5.0d-6 ! m2/s ! +! ! +! indicates that the first two entries of array AKT_BAK, in fortran column- ! +! major order, will have the same value of "1.0d-6" for grid 1, whereas the ! +! next two entries will have the same value of "5.0d-6" for grid 2. ! +! ! +! In multiple levels of nesting and/or multiple connected domains step-ups, ! +! "Ngrids" entries are expected for some of these parameters. In such case, ! +! the order of the entries for a parameter is extremely important. It must ! +! follow the same order (1:Ngrids) as in the state variable declaration. The ! +! USER may follow the above guidelines for specifying his/her values. These ! +! parameters are marked by "==" plural symbol after the KEYWORD. ! +! ! +!============================================================================== +! +! NOTICE: Input parameter units are specified within brackets and default +! ****** values are specified within braces. +! +! Switch to control the computation of biology within nested and/or multiple +! connected grids. + + Lbiology == T + +! Maximum number of iterations to achieve convergence of the nonlinear +! solution. + + BioIter == 1 + +! Initial concentration for analytical uniform initial conditions for +! ecosystem tracers. Except for DIN, two values are expected for two +! spectral bands: 410nm and 510nm. + +BioIni(iDIN_) == 1.0d0 ! Dissolved Inorganic Nitrogen +BioIni(iAphy) == 1.0d0 1.0d0 ! Phytoplankton absorption at 440, 510nm +BioIni(iBphy) == 1.0d0 1.0d0 ! Phytoplankton scattering at 440, 510nm +BioIni(aCDOM) == 1.0d0 1.0d0 ! CDOM absorption at 440, 510nm +BioIni(iBdet) == 1.0d0 1.0d0 ! Detritus scatteing at 440, 510 nm + +! Fraction of shortwave radiation that is photosynthetically active +! (nondimensional), {0.43d0}. + + PARfrac == 0.43d0 + +! Light attenuation due to seawater [1/m], {0.04d0}. + + AttSW == 0.04d0 + +! Light attenuation factor due to CDOM absorption at 440nm +! [nondimensional]. + +CDOM_LightAtt == 0.8d0 + +! Light-dependent degradation rate for CDOM absorption at 440nm +! [1/(Watt m-2 day)]. + + CDOM_sigma == 0.01d0 + +! Half-saturation for phytoplankton nitrogen uptake [millimole_N m-3]. + + K_DIN == 0.5d0 + +! Phytoplankton, initial slope of the P-I curve [m2/Watt]. + + PhyIS == 0.025d0 + +! Phytoplankton mortality rate to the Detritus pool [1/day]. + + PhyMRD == 0.0d0 + +! Phytoplankton loss rate to the Nitrogen pool [1/day]. + + PhyMRN == 0.0d0 + +! Nitrogen uptake rate [1/day]. + + Vm_DIN == 1.0d0 + +! Detritus remineraliztion rate [1/day]. + + DetRR == 0.0d0 + +! Maximum photosynthetic rate [1/day]. + + PhotoRmax == 1.0d0 + +! Maximum ratio of phytoplankton backscatter to absorption +! [nondimensional]. + + ThetaM == 1.0d0 + +! Mapping from phytoplankton backscatter to Nitrogen biomass at 440 nm +! [millimole_N/m2]. + + BphyMap == 50.0d0 + +! Mapping from detritus backscatter to Nitrogen biomass at 440 nm +! [millimole_N/m2]. + + BdetMap == 8.0d0 + +! Phytoplankton sinking rate [m/day]. + + wPhy == 0.d0 + +! Detrital sinking rate [m/day]. + + wDet == 0.d0 + +! Harmonic/biharmonic horizontal diffusion of biological tracer for +! nonlinear model and adjoint-based algorithms: [1:NBT,Ngrids]. + + TNU2 == 9*20.0d0 ! m2/s + TNU4 == 9*2.0d8 ! m4/s + + ad_TNU2 == 9*0.0d0 ! m2/s + ad_TNU4 == 9*0.0d0 ! m4/s + +! Vertical mixing coefficients for biological tracers for nonlinear +! model and basic state scale factor in adjoint-based algorithms: +! [1:NBT,Ngrids]. + + AKT_BAK == 9*1.0d-6 ! m2/s + + ad_AKT_fac == 9*1.0d0 ! nondimensional + +! Nudging/relaxation time scales, inverse scales will be computed +! internally: [1:NBT,Ngrids]. + + TNUDG == 9*0.5d0 ! days + +! Logical switches (TRUE/FALSE) to specify which variables to consider on +! tracers point Sources/Sinks (like river runoff): [NBT,Ngrids] values are +! expected. See glossary below for details. + + LtracerSrc == 9*F + +! Logical switches (TRUE/FALSE) to activate writing of biological tracers +! into HISTORY/AVERAGE output files: [1:NBT,Ngrids]. + + Hout(idTvar) == 9*T ! biological tracer + Hout(idTsur) == 9*F ! surface tracer flux + +! Logical switches (TRUE/FALSE) to activate writing of time-averaged fields +! into AVERAGE output file: [1:NBT,Ngrids]. + + Aout(idTvar) == 9*T ! biological tracer + +! Logical switches (TRUE/FALSE) to activate writing of time-averaged, +! biological tracer diagnostic terms into DIAGNOSTIC output file: +! [1:NBT,Ngrids]. + + Dout(iTrate) == 9*T ! time rate of change + Dout(iThadv) == 9*T ! horizontal total advection + Dout(iTxadv) == 9*T ! horizontal XI-advection + Dout(iTyadv) == 9*T ! horizontal ETA-advection + Dout(iTvadv) == 9*T ! vertical advection + Dout(iThdif) == 9*T ! horizontal total diffusion + Dout(iTxdif) == 9*T ! horizontal XI-diffusion + Dout(iTydif) == 9*T ! horizontal ETA-diffusion + Dout(iTsdif) == 9*T ! horizontal S-diffusion + Dout(iTvdif) == 9*T ! vertical diffusion + +! +! GLOSSARY: +! ========= +! +!------------------------------------------------------------------------------ +! IOP-based, NPZD Ecosystem Model Parameters. Currently, it is configured with +! 9 biological tracers: +! +! idbio(1) Dissolved inorganic nitrogen +! idbio(2) Phytoplankton absorption at 440nm +! idbio(3) Phytoplankton backscattering at 440nm +! idbio(4) CDOM absorption at 440nm +! idbio(5) Detritus backscattering at 440nm +! idbio(6) Phytoplankton absorption at 510nm +! idbio(7) Phytoplankton backscattering at 510nm +! idbio(8) CDOM absorption at 510nm +! idbio(9) Detritus backscattering at 510nm +! +!------------------------------------------------------------------------------ +! +! Lbiology Switch to control the computation of a particular module +! within nested and/or multiple connected grids. By default +! this switch is set to TRUE in "mod_scalars" for all grids. +! Ngrids values are expected. The USER has the option, for +! example, to compute the biology in just one of the nested +! grids. If so, this switch needs to be consistent with the +! dimension parameter NBT in "mod_param". In order to make +! the model more efficient in memory usage, NBT(:) should +! be zero in such grids. +! +! BioIter Maximum number of iterations to achieve convergence of +! the nonlinear implicit solution. +! +! BioIni Initial concentration for analytical uniform initial +! conditions, [1/meter]. It is only used when +! ANA_BIOLOGY is activated. Except for DIN, two values are +! expected for two spectral bands: 410nm and 510nm. +! +! BioIni(iDIN_) Dissolved Inorganic Nitrogen +! BioIni(iAphy) Phytoplankton absorption at 440, 510nm +! BioIni(iBphy) Phytoplankton scattering at 440, 510nm +! BioIni(iBdet) Detritus absorption at 440, 510 nm +! BioIni(aCDOM) CDOM absorption at 440, 510nm +! +! PARfrac Fraction of shortwave radiation that is photosynthetically +! active (nondimensional). +! +! AttSW Light attenuation due to seawater [1/m]. +! +! CDOM_LightAtt Light attenuation factor due to CDOM absorption +! [nondimensional]. +! +! CDOM_sigma Light-dependent degradation rate for CDOM absorption +! [1/(Watt m-2 day)]. +! +! K_DIN Half-saturation for phytoplankton nitrogen uptake +! [millimole_N m-3]. +! +! PhyIS Phytoplankton, initial slope of the P-I curve [m2/Watt]. +! +! PhyMRD Phytoplankton mortality rate to the Detritus pool [1/day]. +! +! PhyMRN Phytoplankton loss rate to the Nitrogen pool [1/day]. +! +! Vm_DIN Nitrogen uptake rate [1/day]. +! +! DetRR Detritus remineraliztion rate [1/day]. +! +! PhotoRmax Maximum photosynthetic rate [1/day]. +! +! ThetaM Maximum ratio of phytoplankton backscatter to absorption +! [nondimensional]. +! +! BphyMap Mapping from phytoplankton backscatter to Nitrogen biomass +! at 440 nm [millimole_N/m2]. +! +! BdetMap Mapping from detritus backscatter to Nitrogen biomass +! at 440 nm [millimole_N/m2]. +! +! wPhy Phytoplankton sinking rate [m/day]. +! +! wDet Detrital sinking rate [m/day]. +! +!------------------------------------------------------------------------------ +! Physical Parameters, [1:NBT,1:Ngrids] values are expected. +!------------------------------------------------------------------------------ +! +! TNU2 Nonlinear model lateral, harmonic, constant, mixing +! coefficient (m2/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, TNU2 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! TNU4 Nonlinear model lateral, biharmonic, constant, mixing +! coefficient (m4/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, TNU4 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! ad_TNU2 Adjoint-based algorithms lateral, harmonic, constant, +! mixing coefficient (m2/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, ad_TNU2 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! ad_TNU4 Adjoint-based algorithms lateral, biharmonic, constant, +! mixing coefficient (m4/s) for biological tracer variables; +! [1:NBT,1:Ngrids] values are expected. If variable +! horizontal diffusion is activated, ad_TNU4 is the mixing +! coefficient for the largest grid-cell in the domain. +! +! AKT_BAK Background vertical mixing coefficient (m2/s) for biological +! tracer variables, [1:NBT,1:Ngrids] values are expected. +! +! +! ad_AKT_fac Adjoint-based algorithms vertical mixing, basic state, +! scale factor (nondimensional) for biological tracer +! variables; [1:NBT,1:Ngrids] values are expected. In +! some applications, a smaller/larger values of vertical +! mixing are necessary for stability. It is only used +! when FORWARD_MIXING is activated. +! +! TNUDG Nudging time scale (days), [1:NBT,1:Ngrids]. Inverse scale +! will be computed internally. +! +! +!------------------------------------------------------------------------------ +! Tracer point Sources/Sink sources switches. +!------------------------------------------------------------------------------ +! +! LtracerSrc Logical switches (T/F) to specify which tracer variables +! to consider when the option TS_PSOURCE is activated; +! [1:NBT,1:Ngrids] values are expected. +! +! LtracerSrc(idbio(1),ng) Dissolved inorganic Nitrogen +! LtracerSrc(idbio(2),ng) Phy absorption at 440nm +! LtracerSrc(idbio(3),ng) Phy backscattering at 440nm +! LtracerSrc(idbio(4),ng) CDOM absorption at 440nm +! LtracerSrc(idbio(5),ng) Det backscattering at 440nm +! LtracerSrc(idbio(6),ng) Phy absorption at 510nm +! LtracerSrc(idbio(7),ng) Phy backscattering at 510nm +! LtracerSrc(idbio(8),ng) CDOM absorption at 510nm +! LtracerSrc(idbio(9),ng) Det backscattering at 510nm +! +! Recall that TS_PSOURCE is usually activated to add river +! runoff as a point source. At minimum, it is necessary to +! specify both temperature and salinity for all rivers. The +! other tracers are optional. The user needs to know the +! correspondence between biological variables and indices +! idbio(1:NBT) when activating one or more of these switches. +! +! This logical switch REPLACES and ELIMINATES the need to +! have or read the variable "river_flag(river)" in the input +! rivers forcing NetCDF file: +! +! double river_flag(river) +! river_flag:long_name = "river runoff tracer flag" +! river_flag:option_0 = "all tracers are off" +! river_flag:option_1 = "only temperature" +! river_flag:option_2 = "only salinity" +! river_flag:option_3 = "both temperature and salinity" +! river_flag:units = "nondimensional" +! +! This logic was too cumbersome and complicated when +! additional tracers are considered. However, this change +! is backward compatible. +! +! The LtracerSrc switch will be used to activate the reading +! of respective tracer variable from input river forcing +! NetCDF file. If you want to add other tracer variables +! (other than temperature and salinity) as a source for a +! particular river(s), you just need to specify such values +! on those river(s). Then, set the values to ZERO on the +! other river(s) that do NOT require such river forcing for +! that tracer. Recall that you need to specify the tracer +! values for all rivers, even if their values are zero. +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of fields into HISTORY files. +!------------------------------------------------------------------------------ +! +! Hout Logical switches (T/F) to write out biological data into +! output HISTORY NetCDF file, [1:NBT,1:Ngrids] values are +! expected: +! +! Hout(idTvar) biological tracers +! Hout(idTsur) biological tracers surface flux +! +! idTvar(idbio(1))=iDIN_ dissolved Inorganic Nitrogen +! idTvar(idbio(2))=iAphy(i440n) Phy absorption at 440nm +! idTvar(idbio(3))=iBphy(i440n) Phy backscattering at 440nm +! idTvar(idbio(4))=aCDOM(i440n) CDOM absorption at 440nm +! idTvar(idbio(5))=iBdet(i440n) Det backscattering at 440nm +! idTvar(idbio(6))=iAphy(i510n) Phy absorption at 510nm +! idTvar(idbio(7))=iBphy(i510n) Phy backscattering at 510nm +! idTvar(idbio(8))=aCDOM(i510n) CDOM absorption at 510nm +! idTvar(idbio(9))=iBdet(i510n) Det backscattering at 510nm +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of fields into AVERAGE file. +!------------------------------------------------------------------------------ +! +! Aout Logical switches to write out biological fields into +! output AVERAGE NetCDF file, [1:NBT,1:Ngrids] values +! are expected: +! +! Aout(idTvar) biological tracers +! +! The idTvar(idbio(:)) are the same to those in the HISTORY +! file. +! +!------------------------------------------------------------------------------ +! Logical switches (T/F) to activate writing of time-averaged fields into +! DIAGNOSTIC file. +!------------------------------------------------------------------------------ +! +! Time-averaged, biological tracers diagnostic terms, [1:NBT,Ngrids] values +! expected: (if DIAGNOSTICS_TS) +! +! Dout(idDtrc(idbio(1:NBT),iT....),1:Ngrids) +! +! Dout(iTrate) Write out time rate of change. +! Dout(iThadv) Write out horizontal total advection. +! Dout(iTxadv) Write out horizontal XI-advection. +! Dout(iTyadv) Write out horizontal ETA-advection. +! Dout(iTvadv) Write out vertical advection. +! Dout(iThdif) Write out horizontal total diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTxdif) Write out horizonta1 XI-diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTydif) Write out horizontal ETA-diffusion, if TS_DIF2 or TS_DIF4. +! Dout(iTsdif) Write out horizontal S-diffusion, if TS_DIF2 or TS_DIF4 and +! rotated tensor (MIX_GEO_TS or MIX_ISO_TS). +! Dout(iTvdif) Write out vertical diffusion. +! diff --git a/User/Functionals/ana_biology.h b/User/Functionals/ana_biology.h index d01a0775..a1e0ae07 100644 --- a/User/Functionals/ana_biology.h +++ b/User/Functionals/ana_biology.h @@ -172,6 +172,38 @@ END DO END DO +#elif defined IOP_CDOM +! +!----------------------------------------------------------------------- +! IOP-based, CDOM (Colored Dissolver Organic Matter) ecosystem model. +!----------------------------------------------------------------------- +! + DO itrc=1,NBT + DO k=1,N(ng) + DO j=JstrT,JendT + DO i=IstrT,IendT + t(i,j,k,1,idbio(itrc))=BioIni(idbio(itrc),ng) + END DO + END DO + END DO + END DO + +#elif defined NPZD_IOP +! +!----------------------------------------------------------------------- +! IOP-based, NPZD ecosystem model. +!----------------------------------------------------------------------- +! + DO itrc=1,NBT + DO k=1,N(ng) + DO j=JstrT,JendT + DO i=IstrT,IendT + t(i,j,k,1,idbio(itrc))=BioIni(idbio(itrc),ng) + END DO + END DO + END DO + END DO + #elif defined NPZD_FRANKS || defined NPZD_POWELL ! !-----------------------------------------------------------------------