ROMS
Loading...
Searching...
No Matches
red_tide.h
Go to the documentation of this file.
1#undef NEWMAN
2#define LIMIT_INTERIOR
3
4 MODULE biology_mod
5!
6!git $Id$
7!======================================================== Ruoying He ===
8! Copyright (c) 2002-2025 The ROMS Group !
9! Licensed under a MIT/X style license !
10! See License_ROMS.md Hernan G. Arango !
11!========================================== Alexander F. Shchepetkin ===
12! !
13! Red Tide Biological Model: Alexandrium fundyense !
14! !
15! This routine computes the biological sources and sinks and !
16! updates the global tracer array for dinoflagellates !
17! !
18! References: !
19! !
20! Stock, C.A., D.J. McGillicudy, A.R. Solow, and D.M. Anderson, !
21! 2005: Evaluating hypotheses for the initiation and development !
22! of Alexandrium fundyense blooms in the western Gulf of Maine !
23! using a coupled physical-biological model, Deep-Sea Research II,!
24! 52, 2715-2744. !
25! !
26! He, R., D.J. McGillicuddy, B.A. Keafer, and D.M. Anderson, 2008: !
27! Historic 2005 toxic bloom of Alexandrium fundyense in the !
28! western Gulf of Maine: 2, Coupled biophysical modeling, J. !
29! Geophys. Res., 113, C07040, doi:10.1029/2007JC004602. !
30! !
31!=======================================================================
32!
33 implicit none
34!
35 PRIVATE
36 PUBLIC :: biology
37!
38 CONTAINS
39!
40!***********************************************************************
41 SUBROUTINE biology (ng,tile)
42!***********************************************************************
43!
44 USE mod_param
45 USE mod_forces
46 USE mod_grid
47 USE mod_ncparam
48 USE mod_ocean
49 USE mod_stepping
50!
51! Imported variable declarations.
52!
53 integer, intent(in) :: ng, tile
54!
55! Local variable declarations.
56!
57 character (len=*), parameter :: MyFile = &
58 & __FILE__
59!
60#include "tile.h"
61!
62! Set header file name.
63!
64#ifdef DISTRIBUTE
65 IF (lbiofile(inlm)) THEN
66#else
67 IF (lbiofile(inlm).and.(tile.eq.0)) THEN
68#endif
69 lbiofile(inlm)=.false.
70 bioname(inlm)=myfile
71 END IF
72!
73#ifdef PROFILE
74 CALL wclock_on (ng, inlm, 15, __line__, myfile)
75#endif
76 CALL red_tide_tile (ng, tile, &
77 & lbi, ubi, lbj, ubj, n(ng), nt(ng), &
78 & imins, imaxs, jmins, jmaxs, &
79 & nstp(ng), nnew(ng), &
80#ifdef MASKING
81 & grid(ng) % rmask, &
82#endif
83 & grid(ng) % Hz, &
84 & grid(ng) % z_r, &
85 & grid(ng) % z_w, &
86#ifdef DAILY_SHORTWAVE
87 & forces(ng) % srflx_avg, &
88#endif
89 & forces(ng) % srflx, &
90 & ocean(ng) % CystIni, &
91 & ocean(ng) % DIN_obs, &
92 & ocean(ng) % t)
93
94#ifdef PROFILE
95 CALL wclock_off (ng, inlm, 15, __line__, myfile)
96#endif
97!
98 RETURN
99 END SUBROUTINE biology
100!
101!-----------------------------------------------------------------------
102 SUBROUTINE red_tide_tile (ng, tile, &
103 & LBi, UBi, LBj, UBj, UBk, UBt, &
104 & IminS, ImaxS, JminS, JmaxS, &
105 & nstp, nnew, &
106#ifdef MASKING
107 & rmask, &
108#endif
109 & Hz, z_r, z_w, &
110#ifdef DAILY_SHORTWAVE
111 & srflx_avg, &
112#endif
113 & srflx, CystIni, DIN_obs, &
114 & t)
115!-----------------------------------------------------------------------
116!
117 USE mod_param
118 USE mod_biology
119 USE mod_ncparam
120 USE mod_scalars
121!
122 USE dateclock_mod, ONLY : caldate
123!
124! Imported variable declarations.
125!
126 integer, intent(in) :: ng, tile
127 integer, intent(in) :: LBi, UBi, LBj, UBj, UBk, UBt
128 integer, intent(in) :: IminS, ImaxS, JminS, JmaxS
129 integer, intent(in) :: nstp, nnew
130
131#ifdef ASSUMED_SHAPE
132# ifdef MASKING
133 real(r8), intent(in) :: rmask(LBi:,LBj:)
134# endif
135 real(r8), intent(in) :: Hz(LBi:,LBj:,:)
136 real(r8), intent(in) :: z_r(LBi:,LBj:,:)
137 real(r8), intent(in) :: z_w(LBi:,LBj:,0:)
138 real(r8), intent(in) :: CystIni(LBi:,LBj:)
139 real(r8), intent(in) :: DIN_obs(LBi:,LBj:,:)
140# ifdef DAILY_SHORTWAVE
141 real(r8), intent(in) :: srflx_avg(LBi:,LBj:)
142# endif
143 real(r8), intent(in) :: srflx(LBi:,LBj:)
144 real(r8), intent(inout) :: t(LBi:,LBj:,:,:,:)
145#else
146# ifdef MASKING
147 real(r8), intent(in) :: rmask(LBi:UBi,LBj:UBj)
148# endif
149 real(r8), intent(in) :: Hz(LBi:UBi,LBj:UBj,UBk)
150 real(r8), intent(in) :: z_r(LBi:UBi,LBj:UBj,UBk)
151 real(r8), intent(in) :: z_w(LBi:UBi,LBj:UBj,0:UBk)
152 real(r8), intent(in) :: CystIni(LBi:UBi,LBj:UBj)
153# ifdef DAILY_SHORTWAVE
154 real(r8), intent(in) :: srflx_avg(LBi:UBi,LBj:UBj)
155# endif
156 real(r8), intent(in) :: srflx(LBi:UBi,LBj:UBj)
157 real(r8), intent(in) :: DIN_ob(LBi:UBi,LBj:UBj,UBk)
158 real(r8), intent(inout) :: t(LBi:UBi,LBj:UBj,UBk,3,UBt)
159#endif
160!
161! Local variable declarations.
162!
163 integer, parameter :: Nswim = 1
164
165 integer, parameter :: NsedLayers = 10
166
167 integer :: Iter, i, ibio, iswim, itrc, j, k, ks, ksed
168
169 integer, dimension(Nswim) :: idswim
170
171 real(r8) :: Cell_Flux, C_depth, DIN, E_flux, EndoScale
172 real(r8) :: Rad, RadScale
173 real(r8) :: GermD, GermL, G_DIN, G_light, G_rate, M_rate
174 real(r8) :: G_fac, S_fac, T_fac
175 real(r8) :: dtdays, oNsedLayers, salt, temp, wmig
176 real(dp) :: yday
177
178 real(r8) :: alpha, cff, cffL, cffR, deltaL, deltaR, dz, wdt
179
180 real(r8), parameter :: eps = 1.0e-8_r8
181
182 real(r8), dimension(Nswim) :: Wbio
183
184 integer, dimension(IminS:ImaxS,N(ng)) :: ksource
185
186 real(r8), dimension(IminS:ImaxS) :: Germ
187
188 real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio
189 real(r8), dimension(IminS:ImaxS,N(ng),NT(ng)) :: Bio_old
190
191 real(r8), dimension(IminS:ImaxS,0:N(ng)) :: FC
192 real(r8), dimension(IminS:ImaxS,0:N(ng)) :: aL
193 real(r8), dimension(IminS:ImaxS,0:N(ng)) :: aR
194 real(r8), dimension(IminS:ImaxS,0:N(ng)) :: dL
195 real(r8), dimension(IminS:ImaxS,0:N(ng)) :: dR
196 real(r8), dimension(IminS:ImaxS,0:N(ng)) :: r
197
198 real(r8), dimension(IminS:ImaxS,N(ng)) :: Hz_inv
199 real(r8), dimension(IminS:ImaxS,N(ng)) :: Light
200!
201! Temperature dependent grow factor polynomial coefficients.
202!
203!! real(r8), parameter :: TC0 = 0.382_r8 ! Stock el al, 2005
204!! real(r8), parameter :: TC1 =-0.0867_r8 ! Eq. 5a
205!! real(r8), parameter :: TC2 = 0.0160_r8
206!! real(r8), parameter :: TC3 =-0.000513_r8
207!!
208 real(r8), parameter :: TC0 = 0.379_r8 ! Revised
209 real(r8), parameter :: TC1 =-0.0961_r8 ! Stock 8/15/2006
210 real(r8), parameter :: TC2 = 0.0169_r8
211 real(r8), parameter :: TC3 =-0.000536_r8
212!
213! Salinity dependent grow factor polynomial coefficients.
214!
215!! real(r8), parameter :: SC0 =-0.872_r8 ! Stock el al, 2005
216!! real(r8), parameter :: SC1 = 0.220_r8 ! Eq. 6
217!! real(r8), parameter :: SC2 =-0.00808_r8
218!! real(r8), parameter :: SC3 = 0.0000882_r8
219!!
220 real(r8), parameter :: SC0 =-0.693_r8 ! Revised
221 real(r8), parameter :: SC1 = 0.186_r8 ! Stock 8/15/2006
222 real(r8), parameter :: SC2 =-0.00622_r8
223 real(r8), parameter :: SC3 = 0.0000557_r8
224
225#include "set_bounds.h"
226!
227!-----------------------------------------------------------------------
228! Add biological Source/Sink terms.
229!-----------------------------------------------------------------------
230!
231! Avoid computing source/sink terms if no biological iterations.
232!
233 IF (bioiter(ng).le.0) RETURN
234!
235! Set time-stepping size (days) according to the number of iterations.
236!
237 dtdays=dt(ng)*sec2day/real(bioiter(ng),r8)
238!
239! Set shortwave radiation scale. In ROMS all the fluxes are kinematic.
240!
241 radscale=rho0*cp ! Celsius m/s to Watts/m2
242!
243! Set critical depth (m; negative) used in the growth function.
244!
245 c_depth=(log(g_r(ng)/(g_eff(ng)*srad_cdepth(ng))))/attw(ng)
246!
247! Set vertical swimming identification vector.
248!
249 idswim(1)=idino ! Dinoflagellate
250!
251! Set vertical swimming velocity vector in the same order as the
252! identification vector, IDSWIM.
253!
254 wbio(1)=wdino(ng) ! Dinoflagellate
255!
256! Set scale for germination term.
257!
258 onsedlayers=1.0_r8/real(nsedlayers,r8)
259!
260! Compute inverse thickness to avoid repeated divisions.
261!
262 j_loop : DO j=jstr,jend
263 DO k=1,n(ng)
264 DO i=istr,iend
265 hz_inv(i,k)=1.0_r8/hz(i,j,k)
266 END DO
267 END DO
268!
269! Extract biological variables from tracer arrays, place them into
270! scratch arrays, and restrict their values to be positive definite.
271! At input, all tracers (index nnew) from predictor step have
272! transport units (m Tunits) since we do not have yet the new
273! values for zeta and Hz. These are known after the 2D barotropic
274! time-stepping.
275!
276 DO itrc=1,nbt
277 ibio=idbio(itrc)
278 DO k=1,n(ng)
279 DO i=istr,iend
280 bio_old(i,k,ibio)=max(0.0_r8,t(i,j,k,nstp,ibio))
281 bio(i,k,ibio)=bio_old(i,k,ibio)
282 END DO
283 END DO
284 END DO
285!
286! Extract potential temperature and salinity.
287!
288 DO k=1,n(ng)
289 DO i=istr,iend
290 bio(i,k,itemp)=min(t(i,j,k,nstp,itemp),36.0_r8)
291 bio(i,k,isalt)=max(0.0_r8,t(i,j,k,nstp,isalt))
292 END DO
293 END DO
294!
295! Calculate endogenous clock scale used in the cysts germination
296! term. The cysts germination rates are regulated by an endogenous
297! circannual clock.
298!
299 CALL caldate (tdays(ng), yd_dp=yday)
300!
301 IF (yday.lt.month_midday(1)) THEN
302 cff=(365.0_r8-month_midday(12)+yday)/ &
303 & (365.0_r8-month_midday(12)+month_midday(1))
304 endoscale=gpn(12)+cff*(gpn(1)-gpn(12))
305 ELSE IF (yday.ge.month_midday(12)) THEN
306 cff=(yday-month_midday(12))/ &
307 (365.0_r8-month_midday(12)+month_midday(1))
308 endoscale=gpn(12)+cff*(gpn(1)-gpn(12))
309 ELSE
310 DO i=1,11
311 IF ((yday.ge.month_midday(i)).and. &
312 & (yday.lt.month_midday(i+1))) THEN
313 cff=(yday-month_midday(i))/ &
314 & (month_midday(i+1)-month_midday(i))
315 endoscale=gpn(i)+cff*(gpn(i+1)-gpn(i))
316 END IF
317 END DO
318 END IF
319!
320!=======================================================================
321! Start internal iterations to achieve convergence of the nonlinear
322! backward-implicit solution.
323!=======================================================================
324!
325! The iterative loop below is to iterate toward an universal Backward-
326! Euler treatment of all terms. So if there are oscillations in the
327! system, they are only physical oscillations. These iterations,
328! however, do not improve the accuaracy of the solution.
329!
330 iter_loop: DO iter=1,bioiter(ng)
331!
332!-----------------------------------------------------------------------
333! Add Cyst germination flux at the bottom layer
334!-----------------------------------------------------------------------
335!
336! Calculate Cyst germination rate at the top of the sediment layer
337! as a function of bottom water temperature and non-spectral
338! irradiance.
339!
340 DO i=istr,iend
341!
342! Calculate "light" and "dark" cyst germination rates as a function
343! of bottom temperature.
344!
345 temp=bio(i,1,itemp) ! bottom, k=1
346 germl=(1.50_r8+ &
347 & (8.72_r8-1.50_r8)*0.5_r8* &
348 & (tanh(0.790_r8*temp-6.27_r8)+1.0_r8))*onsedlayers
349 germd=(1.04_r8+ &
350 & (4.26_r8-1.04_r8)*0.5_r8* &
351 & (tanh(0.394_r8*temp-3.33_r8)+1.0_r8))*onsedlayers
352!
353! Compute non-spectral irradiance flux at each sediment layer. Then,
354! compute cyst germination rate according to the light regime.
355!
356 germ(i)=0.0_r8 ! initialize
357 DO ksed=1,nsedlayers
358# ifdef DAILY_SHORTWAVE
359 e_flux=radscale*srflx_avg(i,j)* &
360 & exp( attw(ng)*z_w(i,j,0)- &
361 & atts(ng)*dg(ng)*(real(ksed,r8)-0.5) )
362# else
363 e_flux=radscale*srflx(i,j)* &
364 & exp( attw(ng)*z_w(i,j,0)- &
365 & atts(ng)*dg(ng)*(real(ksed,r8)-0.5) )
366# endif
367 IF (e_flux.gt.e_light(ng)) THEN
368 germ(i)=germ(i)+germl
369 ELSE IF (e_flux.lt.e_dark(ng)) THEN
370 germ(i)=germ(i)+germd
371 ELSE
372 germ(i)=germ(i)+ &
373 & (germd+ &
374 & (germl-germd)* &
375 & ((e_flux-e_dark(ng))/ &
376 & (e_light(ng)-e_dark(ng))))
377 END IF
378 END DO
379!
380! Multiply by endogenous clock factor. The cyst germination are
381! regulated by an endogenous circannual clock. The 100 factor here
382! is because "Dg" is meters and we need centimeters.
383!
384 germ(i)=germ(i)*dg(ng)*100.0_r8*endoscale
385!
386! Convert percentage cysts/day into decimal fraction of cysts.
387!
388 germ(i)=germ(i)*0.01_r8
389!
390! Calculate the flux of cells away from the bottom. It is referenced
391! to the initial number of cysts to be consistent with laboratory
392! experiments.
393!
394 cell_flux=cystini(i,j)* &
395 & germ(i)*hz_inv(i,1) ! cells/m3
396!
397! Add cell flux at the bottom layer (k=1).
398!
399 bio(i,1,idino)=bio(i,1,idino)+cell_flux*dtdays
400 END DO
401!
402!-----------------------------------------------------------------------
403! Compute growth term.
404!-----------------------------------------------------------------------
405!
406! The growth is dependent on temperature, salinity, non-spectral
407! irradiance (light), and nutrient (Dissolved Inorganic Nutrient, DIN).
408!
409 DO k=1,n(ng)
410 DO i=istr,iend
411 temp=bio(i,k,itemp)
412 salt=bio(i,k,isalt)
413!
414! Compute Alexandrium fundyense temperature dependent growth factor
415! using a cubic polynomial fitted to available data.
416!
417 IF (temp.ge.tmin_growth(ng)) THEN
418 t_fac=tc0+temp*(tc1+temp*(tc2+temp*tc3))
419 ELSE ! linear extrapolation
420!! T_fac=TC0+temp*(TC1+temp*(TC22+temp*TC3))- &
421!! & 0.0343_r8*(5.0_r8-temp) ! Stock el al, 2005
422!! ! Eq. 5b
423 t_fac=0.254_r8-0.0327_r8*(5.0_r8-temp) ! Stock 8/15/2006
424 END IF
425!
426! Compute Alexandrium fundyense salinity dependent growth factor
427! using a cubic polynomial to fit to available data.
428!
429 s_fac=sc0+salt*(sc1+salt*(sc2+salt*sc3))
430!
431! Compute temperature and salinity growth factor.
432!
433 g_fac=t_fac*s_fac
434!
435! Compute light dependency factor (Platt and Jassby, 1976).
436!
437# ifdef DAILY_SHORTWAVE
438 rad=srflx_avg(i,j)*radscale*exp(attw(ng)*z_r(i,j,k))
439# else
440 rad=srflx(i,j)*radscale*exp(attw(ng)*z_r(i,j,k))
441# endif
442 IF (z_r(i,j,k).gt.c_depth) THEN
443 cff=gmax(ng)*g_fac+g_r(ng)
444 g_light=max(0.0_r8,cff*tanh(g_eff(ng)*rad/cff)-g_r(ng))
445 ELSE
446 g_light=0.0_r8
447 END IF
448!
449! Compute dissolved inorganic nutrient (DIN) dependency.
450! [JWilkin: This ELSE block below appears redundant because if
451! z_r(i,j,k).le.C_depth then G_light=0.0_r8 (see above) and
452! therefore G_rate will be set to zero (see below) regardless of
453! the calculated value of G_DIN].
454!
455 IF (z_r(i,j,k).gt.c_depth) THEN
456 din=din_obs(i,j,k)
457 ELSE
458 din=din_cdepth(ng)
459 END IF
460!
461! The nutrient dependence is modeled by the Monod formulation with
462! half-saturation Kn.
463!
464 g_din=gmax(ng)*g_fac*din/(max(kn(ng),0.0_r8)+din)
465!
466! Compute growth term (implicit). The growth rate is either limited
467! by the nutrient or light. The rate is capped to be positive.
468!
469 g_rate=max(min(g_light,g_din),0.0_r8)
470 bio(i,k,idino)=bio(i,k,idino)/(1.0_r8-g_rate*dtdays)
471 END DO
472 END DO
473!
474!-----------------------------------------------------------------------
475! Compute mortality term.
476!-----------------------------------------------------------------------
477!
478! The mortality is modeled as function dependent on temperature
479! (implicit). Use a Q10 mortality rate equation.
480!
481 DO k=1,n(ng)
482 DO i=istr,iend
483 temp=bio(i,k,itemp)
484 m_rate=mor_a(ng)* &
485 & mor_q10(ng)**((temp-mor_t0(ng))*0.1_r8)+ &
486 & mor_b(ng)
487 bio(i,k,idino)=bio(i,k,idino)/(1.0_r8+m_rate*dtdays)
488 END DO
489 END DO
490!
491!-----------------------------------------------------------------------
492! Vertical sinking/ascending term: dinoflagellate swimming
493!-----------------------------------------------------------------------
494!
495! Reconstruct vertical profile of selected biological constituents
496! "Bio(:,:,iswim)" in terms of a set of parabolic segments within each
497! grid box. Then, compute semi-Lagrangian flux due to vertical motion.
498! Many thanks to Sasha Shchepetkin for the updated algorithm.
499!
500 swim_loop: DO iswim=1,nswim
501 ibio=idswim(iswim)
502 DO k=n(ng)-1,1,-1
503 DO i=istr,iend
504 fc(i,k)=(bio(i,k+1,ibio)-bio(i,k,ibio))/ &
505 & (hz(i,j,k+1)+hz(i,j,k))
506 END DO
507 END DO
508!
509 DO k=2,n(ng)-1
510 DO i=istr,iend
511 deltar=hz(i,j,k)*fc(i,k )
512 deltal=hz(i,j,k)*fc(i,k-1)
513 IF (deltar*deltal.lt.0.0_r8) THEN
514 deltar=0.0_r8
515 deltal=0.0_r8
516 END IF
517 cff=hz(i,j,k-1)+2.0_r8*hz(i,j,k)+hz(i,j,k+1)
518 cffr=cff*fc(i,k )
519 cffl=cff*fc(i,k-1)
520 IF (abs(deltar).gt.abs(cffl)) deltar=cffl
521 IF (abs(deltal).gt.abs(cffr)) deltal=cffr
522 cff=(deltar-deltal)/(hz(i,j,k-1)+hz(i,j,k)+hz(i,j,k+1))
523 deltar=deltar-cff*hz(i,j,k+1)
524 deltal=deltal+cff*hz(i,j,k-1)
525!
526 ar(i,k)=bio(i,k,ibio)+deltar
527 al(i,k)=bio(i,k,ibio)-deltal
528!
529 dr(i,k)=(2.0_r8*deltar-deltal)**2
530 dl(i,k)=(2.0_r8*deltal-deltar)**2
531 END DO
532 END DO
533
534#ifdef LIMIT_INTERIOR
535!
536! Apply boundary conditions for strictly monotonic option. The only way
537! to avoid extrapolation toward the boundary is to assume that field is
538! simply constant within topmost and bottommost grid boxes.
539!
540
541 DO i=istr,iend
542 ar(i,n(ng))=bio(i,n(ng),ibio)
543 al(i,n(ng))=bio(i,n(ng),ibio)
544 dr(i,n(ng))=0.0_r8
545 dl(i,n(ng))=0.0_r8
546!
547 ar(i,1)=bio(i,1,ibio)
548 al(i,1)=bio(i,1,ibio)
549 dr(i,1)=0.0_r8
550 dl(i,1)=0.0_r8
551 END DO
552#else
553!
554! Apply Neumann or linear continuation boundary conditions. Notice that
555! for Neumann conditions, the extrapolate values aR(i,N(ng)) and aL(i,0)
556! exceed corresponding box values.
557!
558 DO i=istr,iend
559 al(i,n(ng))=ar(i,n(ng)-1)
560# ifdef NEUMANN
561 ar(i,n(ng))=1.5_r8*bio(i,n(ng),ibio)-0.5_r8*al(i,n(ng))
562# else
563 ar(i,n(ng))=2.0_r8*bio(i,n(ng),ibio)-al(i,n(ng))
564# endif
565 dr(i,n(ng))=(2.0_r8*ar(i,n(ng))+al(i,n(ng))- &
566 & 3.0_r8*bio(i,n(ng),ibio))**2
567 dl(i,n(ng))=(3.0_r8*bio(i,n(ng),ibio)- &
568 & 2.0_r8*al(i,n(ng))-ar(i,n(ng)))**2
569!
570 ar(i,1)=al(i,2)
571# ifdef NEUMANN
572 al(i,1)=1.5_r8*bio(i,1,ibio)-0.5_r8*ar(i,1)
573# else
574 al(i,1)=2.0_r8*bio(i,1,ibio)-ar(i,1)
575# endif
576 dr(i,1)=(2.0_r8*ar(i,1)+al(i,1)- &
577 & 3.0_r8*bio(i,1,ibio))**2
578 dl(i,1)=(3.0_r8*bio(i,1,ibio)- &
579 & 2.0_r8*al(i,1)-ar(i,1))**2
580 END DO
581#endif
582!
583! Reconcile interfacial values aR and aL using Weighted Essentially
584! Non-Oscillatory (WENO) procedure.
585!
586 DO k=1,n(ng)-1
587 DO i=istr,iend
588 deltal=max(dl(i,k ),eps)
589 deltar=max(dr(i,k+1),eps)
590 r(i,k)=(deltar*ar(i,k)+deltal*al(i,k+1))/ &
591 & (deltar+deltal)
592 END DO
593 END DO
594 DO i=istr,iend
595#ifdef NEUMANN
596 r(i,n(ng))=1.5_r8*bio(i,n(ng),ibio)-0.5_r8*r(i,n(ng)-1)
597 r(i,0 )=1.5_r8*bio(i,1 ,ibio)-0.5_r8*r(i,1 )
598#else
599 r(i,n(ng))=2.0_r8*bio(i,n(ng),ibio)-r(i,n(ng)-1)
600 r(i,0 )=2.0_r8*bio(i,1 ,ibio)-r(i,1 )
601#endif
602 END DO
603!
604! Remapping step: This operation consists essentially of three stages:
605!---------------- (1) within each grid box compute averaged slope
606! (stored as dR) and curvature (stored as dL); then (2) compute
607! interfacial fluxes FC; and (3) apply these fluxes to complete
608! remapping step.
609!
610 DO k=1,n(ng)
611 DO i=istr,iend
612#ifdef LIMIT_INTERIOR
613 deltar=r(i,k)-bio(i,k,ibio) ! Constrain parabolic
614 deltal=bio(i,k,ibio)-r(i,k-1) ! segment monotonicity
615 cffr=2.0_r8*deltar ! like in PPM
616 cffl=2.0_r8*deltal
617 IF (deltar*deltal.lt.0.0_r8) THEN
618 deltar=0.0_r8
619 deltal=0.0_r8
620 ELSE IF (abs(deltar).gt.abs(cffl)) THEN
621 deltar=cffl
622 ELSE IF (abs(deltal).gt.abs(cffr)) THEN
623 deltal=cffr
624 END IF
625 ar(i,k)=bio(i,k,ibio)+deltar
626 al(i,k)=bio(i,k,ibio)-deltal
627#else
628 ar(i,k)=r(i,k )
629 al(i,k)=r(i,k-1)
630#endif
631 dl(i,k)=0.5_r8*(ar(i,k)-al(i,k))
632 dr(i,k)=0.5_r8*(ar(i,k)+al(i,k))-bio(i,k,ibio)
633 END DO
634 END DO
635!
636! Compute interfacial fluxes. The convention is that Wbio is positive
637! for upward motion (swimming, floating) and negative for downward motion
638! (sinking).
639!
640 wdt=-wbio(iswim)*dtdays
641 DO k=1,n(ng)-1
642 DO i=istr,iend
643 IF (wdt.gt.0.0_r8) THEN ! downward vertical
644 alpha=hz(i,j,k+1) ! motion (sinking)
645 cff =al(i,k+1)
646 cffl=dl(i,k+1)
647 cffr=dr(i,k+1)
648 dz=wdt
649 ELSE ! upward vertical
650 alpha=-hz(i,j,k) ! motion (swimming,
651 cff =ar(i,k) ! migration)
652 cffl=-dl(i,k)
653 cffr=dr(i,k)
654 dz=wdt
655!! IF (ABS(z_w(i,j,k)).lt.21.0_r8) THEN
656!! dz=wdt*(1.0_r8-TANH((21.0_r8+z_w(i,j,k))*0.1_r8))
657!! ELSE
658!! dz=wdt
659!! END IF
660 END IF
661 alpha=dz/alpha ! Courant number
662 fc(i,k)=dz*(cff+alpha*(cffl-cffr*(3.0_r8-2.0_r8*alpha)))
663 END DO
664 END DO
665 DO i=istr,iend
666 fc(i,0 )=0.0_r8
667 fc(i,n(ng))=0.0_r8
668 END DO
669!
670! Add semi-Lagrangian vertical flux.
671!
672 DO k=1,n(ng)
673 DO i=istr,iend
674 cff=(fc(i,k)-fc(i,k-1))*hz_inv(i,k)
675 bio(i,k,ibio)=bio(i,k,ibio)+cff
676 END DO
677 END DO
678
679 END DO swim_loop
680 END DO iter_loop
681!
682!-----------------------------------------------------------------------
683! Update global tracer variables: Add increment due to BGC processes
684! to tracer array in time index "nnew". Index "nnew" is solution after
685! advection and mixing and has transport units (m Tunits) hence the
686! increment is multiplied by Hz. Notice that we need to subtract
687! original values "Bio_old" at the top of the routine to just account
688! for the concentrations affected by BGC processes. This also takes
689! into account any constraints (non-negative concentrations, carbon
690! concentration range) specified before entering BGC kernel. If "Bio"
691! were unchanged by BGC processes, the increment would be exactly
692! zero. Notice that final tracer values, t(:,:,:,nnew,:) are not
693! bounded >=0 so that we can preserve total inventory of nutrients
694! when advection causes tracer concentration to go negative.
695!-----------------------------------------------------------------------
696!
697 DO itrc=1,nbt
698 ibio=idbio(itrc)
699 DO k=1,n(ng)
700 DO i=istr,iend
701 cff=bio(i,k,ibio)-bio_old(i,k,ibio)
702 t(i,j,k,nnew,ibio)=t(i,j,k,nnew,ibio)+cff*hz(i,j,k)
703 END DO
704 END DO
705 END DO
706
707 END DO j_loop
708!
709 RETURN
710 END SUBROUTINE red_tide_tile
711
712 END MODULE biology_mod
subroutine, public biology(ng, tile)
Definition ecosim.h:57
subroutine red_tide_tile(ng, tile, lbi, ubi, lbj, ubj, ubk, ubt, imins, imaxs, jmins, jmaxs, nstp, nnew, rmask, hz, z_r, z_w, srflx_avg, srflx, cystini, din_obs, t)
Definition red_tide.h:115
subroutine, public caldate(currenttime, yy_i, yd_i, mm_i, dd_i, h_i, m_i, s_i, yd_dp, dd_dp, h_dp, m_dp, s_dp)
Definition dateclock.F:76
real(r8), dimension(:), allocatable mor_t0
real(dp), dimension(12) month_midday
integer, dimension(:), allocatable bioiter
Definition ecosim_mod.h:343
real(r8), dimension(:), allocatable e_dark
real(r8), dimension(:), allocatable srad_cdepth
real(r8), dimension(:), allocatable din_cdepth
real(r8), dimension(:), allocatable wdino
real(r8), dimension(:), allocatable mor_q10
real(r8), dimension(:), allocatable dg
real(r8), dimension(:), allocatable g_eff
real(r8), dimension(:), allocatable mor_b
real(r8), dimension(:), allocatable e_light
real(r8), dimension(:), allocatable mor_a
integer idino
real(r8), dimension(:), allocatable attw
real(r8), dimension(:), allocatable atts
integer, dimension(:), allocatable idbio
Definition ecosim_mod.h:256
real(r8), dimension(:), allocatable g_r
real(r8), dimension(:), allocatable kn
real(r8), dimension(:), allocatable tmin_growth
real(r8), dimension(12) gpn
real(r8), dimension(:), allocatable gmax
type(t_forces), dimension(:), allocatable forces
Definition mod_forces.F:554
type(t_grid), dimension(:), allocatable grid
Definition mod_grid.F:365
type(t_ocean), dimension(:), allocatable ocean
Definition mod_ocean.F:351
integer, parameter inlm
Definition mod_param.F:662
integer, dimension(:), allocatable n
Definition mod_param.F:479
integer nbt
Definition mod_param.F:509
integer, dimension(:), allocatable nt
Definition mod_param.F:489
real(dp), dimension(:), allocatable dt
real(dp) cp
real(dp), dimension(:), allocatable tdays
real(dp), parameter sec2day
integer isalt
integer itemp
real(dp) rho0
integer, dimension(:), allocatable nnew
integer, dimension(:), allocatable nstp
recursive subroutine wclock_off(ng, model, region, line, routine)
Definition timers.F:148
recursive subroutine wclock_on(ng, model, region, line, routine)
Definition timers.F:3