ROMS
Loading...
Searching...
No Matches
diag.F
Go to the documentation of this file.
1#include "cppdefs.h"
2 MODULE diag_mod
3!
4!git $Id$
5!================================================== Hernan G. Arango ===
6! Copyright (c) 2002-2025 The ROMS Group !
7! Licensed under a MIT/X style license !
8! See License_ROMS.md !
9!=======================================================================
10! !
11! This routine computes various diagnostic fields. !
12! !
13!=======================================================================
14!
15 implicit none
16!
17 PRIVATE
18 PUBLIC :: diag
19!
20 CONTAINS
21!
22!***********************************************************************
23 SUBROUTINE diag (ng, tile)
24!***********************************************************************
25!
26 USE mod_param
27 USE mod_grid
28 USE mod_ocean
29 USE mod_stepping
30!
31#ifdef ANA_DIAG
32 USE analytical_mod, ONLY : ana_diag
33#endif
34!
35! Imported variable declarations.
36!
37 integer, intent(in) :: ng, tile
38!
39! Local variable declarations.
40!
41 character (len=*), parameter :: myfile = &
42 & __FILE__
43!
44#include "tile.h"
45!
46#ifdef PROFILE
47 CALL wclock_on (ng, inlm, 7, __line__, myfile)
48#endif
49 CALL diag_tile (ng, tile, &
50 & lbi, ubi, lbj, ubj, &
51 & imins, imaxs, jmins, jmaxs, &
52#ifdef STEP2D_FB_LF_AM3
53 & nstp(ng), kstp(ng), &
54#else
55 & nstp(ng), krhs(ng), &
56#endif
57 & grid(ng) % h, &
58 & grid(ng) % pm, &
59 & grid(ng) % pn, &
60 & grid(ng) % omn, &
61#ifdef SOLVE3D
62 & grid(ng) % Hz, &
63 & grid(ng) % z_r, &
64 & grid(ng) % z_w, &
65 & ocean(ng) % rho, &
66 & ocean(ng) % u, &
67 & ocean(ng) % v, &
68 & ocean(ng) % wvel, &
69#endif
70 & ocean(ng) % ubar, &
71 & ocean(ng) % vbar, &
72 & ocean(ng) % zeta)
73#ifdef ANA_DIAG
74 CALL ana_diag (ng, tile, inlm)
75#endif
76#ifdef PROFILE
77 CALL wclock_off (ng, inlm, 7, __line__, myfile)
78#endif
79!
80 RETURN
81 END SUBROUTINE diag
82!
83!***********************************************************************
84 SUBROUTINE diag_tile (ng, tile, &
85 & LBi, UBi, LBj, UBj, &
86 & IminS, ImaxS, JminS, JmaxS, &
87 & nstp, krhs, &
88 & h, pm, pn, omn, &
89#ifdef SOLVE3D
90 & Hz, z_r, z_w, &
91 & rho, u, v, wvel, &
92#endif
93 & ubar, vbar, zeta)
94!***********************************************************************
95!
96 USE mod_param
97 USE mod_parallel
98 USE mod_iounits
99 USE mod_scalars
100
101#ifdef DISTRIBUTE
102!
103 USE distribute_mod, ONLY : mp_reduce
104 USE distribute_mod, ONLY : mp_reduce2
105#endif
106!
107 implicit none
108!
109! Imported variable declarations.
110!
111 integer, intent(in) :: ng, tile
112 integer, intent(in) :: LBi, UBi, LBj, UBj
113 integer, intent(in) :: IminS, ImaxS, JminS, JmaxS
114 integer, intent(in) :: nstp, krhs
115
116#ifdef ASSUMED_SHAPE
117 real(r8), intent(in) :: h(LBi:,LBj:)
118 real(r8), intent(in) :: pm(LBi:,LBj:)
119 real(r8), intent(in) :: pn(LBi:,LBj:)
120 real(r8), intent(in) :: omn(LBi:,LBj:)
121# ifdef SOLVE3D
122 real(r8), intent(in) :: Hz(LBi:,LBj:,:)
123 real(r8), intent(in) :: z_r(LBi:,LBj:,:)
124 real(r8), intent(in) :: z_w(LBi:,LBj:,0:)
125 real(r8), intent(in) :: rho(LBi:,LBj:,:)
126 real(r8), intent(in) :: u(LBi:,LBj:,:,:)
127 real(r8), intent(in) :: v(LBi:,LBj:,:,:)
128 real(r8), intent(in) :: wvel(LBi:,LBj:,0:)
129# endif
130 real(r8), intent(in) :: ubar(LBi:,LBj:,:)
131 real(r8), intent(in) :: vbar(LBi:,LBj:,:)
132 real(r8), intent(in) :: zeta(LBi:,LBj:,:)
133#else
134 real(r8), intent(in) :: h(LBi:UBi,LBj:UBj)
135 real(r8), intent(in) :: pm(LBi:UBi,LBj:UBj)
136 real(r8), intent(in) :: pn(LBi:UBi,LBj:UBj)
137 real(r8), intent(in) :: omn(LBi:UBi,LBj:UBj)
138# ifdef SOLVE3D
139 real(r8), intent(in) :: Hz(LBi:UBi,LBj:UBj,N(ng))
140 real(r8), intent(in) :: z_r(LBi:UBi,LBj:UBj,N(ng))
141 real(r8), intent(in) :: z_w(LBi:UBi,LBj:UBj,0:N(ng))
142 real(r8), intent(in) :: rho(LBi:UBi,LBj:UBj,N(ng))
143 real(r8), intent(in) :: u(LBi:UBi,LBj:UBj,N(ng),2)
144 real(r8), intent(in) :: v(LBi:UBi,LBj:UBj,N(ng),2)
145 real(r8), intent(in) :: wvel(LBi:UBi,LBj:UBj,0:N(ng))
146# endif
147 real(r8), intent(in) :: ubar(LBi:UBi,LBj:UBj,:)
148 real(r8), intent(in) :: vbar(LBi:UBi,LBj:UBj,:)
149 real(r8), intent(in) :: zeta(LBi:UBi,LBj:UBj,:)
150#endif
151!
152! Local variable declarations.
153!
154 integer :: NSUB, i, ispace, j, k, trd
155 integer :: idia, istep
156 integer :: my_max_Ci, my_max_Cj, my_max_Ck
157#ifdef DISTRIBUTE
158# ifdef SOLVE3D
159 integer, parameter :: Nreduce = 5
160 integer, parameter :: Ncourant = 7
161# else
162 integer, parameter :: Nreduce = 4
163 integer, parameter :: Ncourant = 5
164# endif
165 real(r8), dimension(Nreduce) :: rbuffer
166 real(r8), dimension(Ncourant) :: Courant
167 character (len=3), dimension(Nreduce) :: op_handle
168 character (len=6), dimension(Nreduce) :: C_handle
169#else
170 integer :: my_threadnum
171#endif
172!
173 real(r8) :: cff, my_avgke, my_avgpe, my_volume
174 real(r8) :: my_C , my_max_C
175 real(r8) :: my_Cu, my_max_Cu
176 real(r8) :: my_Cv, my_max_Cv
177#ifdef SOLVE3D
178 real(r8) :: my_Cw, my_max_Cw
179#endif
180 real(r8) :: my_maxspeed, u2v2
181#ifdef SOLVE3D
182 real(r8) :: my_maxrho
183#endif
184 real(r8), dimension(IminS:ImaxS,JminS:JmaxS) :: ke2d
185 real(r8), dimension(IminS:ImaxS,JminS:JmaxS) :: pe2d
186!
187 character (len=8 ) :: kechar, pechar, maxvalchar
188 character (len=22) :: DateTime
189 character (len=60) :: frmt
190
191#include "set_bounds.h"
192!
193!-----------------------------------------------------------------------
194! Compute and report out volume averaged kinetic, potential
195! total energy, volume, Courant numbers.
196!-----------------------------------------------------------------------
197!
198! Set time timestep counter and time level indices to process. Restart
199! counter after 10 billion steps.
200!
201 istep=int(mod(real(iic(ng)-1,r8),1.0e+10_r8))
202#ifdef SOLVE3D
203 idia=nstp
204#else
205 idia=krhs
206#endif
207 datetime=time_code(ng)
208!
209! Compute kinetic and potential energy.
210!
211 IF (mod(iic(ng)-1,ninfo(ng)).eq.0) THEN
212 my_max_c =0.0_r8
213 my_max_cu=0.0_r8
214 my_max_cv=0.0_r8
215#ifdef SOLVE3D
216 my_max_cw=0.0_r8
217#endif
218 my_max_ci=0
219 my_max_cj=0
220 my_max_ck=0
221 my_maxspeed=0.0_r8
222#ifdef SOLVE3D
223 my_maxrho=-spval
224#endif
225 DO j=jstr,jend
226#ifdef SOLVE3D
227 DO i=istr,iend
228 ke2d(i,j)=0.0_r8
229 pe2d(i,j)=0.5_r8*g*z_w(i,j,n(ng))*z_w(i,j,n(ng))
230 END DO
231 cff=g/rho0
232 DO k=n(ng),1,-1
233 DO i=istr,iend
234 u2v2=u(i ,j,k,idia)*u(i ,j,k,idia)+ &
235 & u(i+1,j,k,idia)*u(i+1,j,k,idia)+ &
236 & v(i,j ,k,idia)*v(i,j ,k,idia)+ &
237 & v(i,j+1,k,idia)*v(i,j+1,k,idia)
238 ke2d(i,j)=ke2d(i,j)+ &
239 & hz(i,j,k)*0.25_r8*u2v2
240 pe2d(i,j)=pe2d(i,j)+ &
241 & cff*hz(i,j,k)*(rho(i,j,k)+1000.0_r8)* &
242 & (z_r(i,j,k)-z_w(i,j,0))
243 my_cu=0.5_r8*abs(u(i,j,k,idia)+u(i+1,j,k,idia))* &
244 & dt(ng)*pm(i,j)
245 my_cv=0.5_r8*abs(v(i,j,k,idia)+v(i,j+1,k,idia))* &
246 & dt(ng)*pn(i,j)
247 my_cw=0.5_r8*abs(wvel(i,j,k-1)+wvel(i,j,k))* &
248 & dt(ng)/hz(i,j,k)
249 my_c=my_cu+my_cv+my_cw
250 IF (my_c.gt.my_max_c) THEN
251 my_max_c =my_c
252 my_max_cu=my_cu
253 my_max_cv=my_cv
254 my_max_cw=my_cw
255 my_max_ci=i
256 my_max_cj=j
257 my_max_ck=k
258 END IF
259 my_maxspeed=max(my_maxspeed,sqrt(0.5_r8*u2v2))
260 my_maxrho=max(my_maxrho,rho(i,j,k))
261 END DO
262 END DO
263#else
264 cff=0.5_r8*g
265 DO i=istr,iend
266 u2v2=ubar(i ,j,idia)*ubar(i ,j,idia)+ &
267 & ubar(i+1,j,idia)*ubar(i+1,j,idia)+ &
268 & vbar(i,j ,idia)*vbar(i,j ,idia)+ &
269 & vbar(i,j+1,idia)*vbar(i,j+1,idia)
270 ke2d(i,j)=(zeta(i,j,idia)+h(i,j))*0.25_r8*u2v2
271 pe2d(i,j)=cff*zeta(i,j,idia)*zeta(i,j,idia)
272 my_cu=0.5_r8*abs(ubar(i,j,idia)+ubar(i+1,j,idia))* &
273 & dt(ng)*pn(i,j)
274 my_cv=0.5_r8*abs(vbar(i,j,idia)+vbar(i,j+1,idia))* &
275 & dt(ng)*pn(i,j)
276 my_c=my_cu+my_cv
277 IF (my_c.gt.my_max_c) THEN
278 my_max_c =my_c
279 my_max_cu=my_cu
280 my_max_cv=my_cv
281 my_max_ci=i
282 my_max_cj=j
283 END IF
284 my_maxspeed=max(my_maxspeed,sqrt(0.5_r8*u2v2))
285 END DO
286#endif
287 END DO
288!
289! Integrate horizontally within one tile. In order to reduce the
290! round-off errors, the summation is performed in two stages. First,
291! the index j is collapsed and then the accumulation is carried out
292! along index i. In this order, the partial sums consist on much
293! fewer number of terms than in a straightforward two-dimensional
294! summation. Thus, adding numbers which are orders of magnitude
295! apart is avoided.
296!
297 DO i=istr,iend
298 pe2d(i,jend+1)=0.0_r8
299 pe2d(i,jstr-1)=0.0_r8
300 ke2d(i,jstr-1)=0.0_r8
301 END DO
302 DO j=jstr,jend
303 DO i=istr,iend
304#ifdef SOLVE3D
305 pe2d(i,jend+1)=pe2d(i,jend+1)+ &
306 & omn(i,j)*(z_w(i,j,n(ng))-z_w(i,j,0))
307#else
308 pe2d(i,jend+1)=pe2d(i,jend+1)+ &
309 & omn(i,j)*(zeta(i,j,idia)+h(i,j))
310#endif
311 pe2d(i,jstr-1)=pe2d(i,jstr-1)+omn(i,j)*pe2d(i,j)
312 ke2d(i,jstr-1)=ke2d(i,jstr-1)+omn(i,j)*ke2d(i,j)
313 END DO
314 END DO
315 my_volume=0.0_r8
316 my_avgpe=0.0_r8
317 my_avgke=0.0_r8
318 DO i=istr,iend
319 my_volume=my_volume+pe2d(i,jend+1)
320 my_avgpe =my_avgpe +pe2d(i,jstr-1)
321 my_avgke =my_avgke +ke2d(i,jstr-1)
322 END DO
323!
324! Perform global summation: whoever gets first to the critical region
325! resets global sums before global summation starts; after the global
326! summation is completed, thread, which is the last one to enter the
327! critical region, finalizes the computation of diagnostics and prints
328! them out.
329!
330#ifdef DISTRIBUTE
331 nsub=1 ! distributed-memory
332#else
333 IF (domain(ng)%SouthWest_Corner(tile).and. &
334 & domain(ng)%NorthEast_Corner(tile)) THEN
335 nsub=1 ! non-tiled application
336 ELSE
337 nsub=ntilex(ng)*ntilee(ng) ! tiled application
338 END IF
339#endif
340!$OMP CRITICAL (NL_DIAGNOSTICS)
341!! IF (tile_count.eq.0) THEN
342!! volume=0.0_r8
343!! avgke=0.0_r8
344!! avgpe=0.0_r8
345!! maxspeed(ng)=0.0_r8
346#ifdef SOLVE3D
347!! maxrho(ng)=-spval
348#endif
349!! max_C =0.0_r8
350!! max_Cu=0.0_r8
351!! max_Cv=0.0_r8
352#ifdef SOLVE3D
353!! max_Cw=0.0_r8
354#endif
355!! max_Ci=0
356!! max_Cj=0
357#ifdef SOLVE3D
358!! max_Ck=0
359#endif
360!! END IF
361 volume=volume+my_volume
362 avgke=avgke+my_avgke
363 avgpe=avgpe+my_avgpe
364 maxspeed(ng)=max(maxspeed(ng),my_maxspeed)
365#ifdef SOLVE3D
366 maxrho(ng)=max(maxrho(ng),my_maxrho)
367#endif
368 IF (my_max_c.eq.max_c) THEN
369 max_ci=min(max_ci,my_max_ci)
370 max_cj=min(max_cj,my_max_cj)
371#ifdef SOLVE3D
372 max_ck=min(max_ck,my_max_ck)
373#endif
374 ELSE IF (my_max_c.gt.max_c) THEN
375 max_c =my_max_c
376 max_cu=my_max_cu
377 max_cv=my_max_cv
378#ifdef SOLVE3D
379 max_cw=my_max_cw
380#endif
381 max_ci=my_max_ci
382 max_cj=my_max_cj
383#ifdef SOLVE3D
384 max_ck=my_max_ck
385#endif
386 END IF
388 IF (tile_count.eq.nsub) THEN
389 tile_count=0
390#ifdef DISTRIBUTE
391 rbuffer(1)=volume
392 rbuffer(2)=avgke
393 rbuffer(3)=avgpe
394 rbuffer(4)=maxspeed(ng)
395# ifdef SOLVE3D
396 rbuffer(5)=maxrho(ng)
397# endif
398 op_handle(1)='SUM'
399 op_handle(2)='SUM'
400 op_handle(3)='SUM'
401 op_handle(4)='MAX'
402# ifdef SOLVE3D
403 op_handle(5)='MAX'
404# endif
405 CALL mp_reduce (ng, inlm, nreduce, rbuffer, op_handle)
406 volume=rbuffer(1)
407 avgke=rbuffer(2)
408 avgpe=rbuffer(3)
409 maxspeed(ng)=rbuffer(4)
410# ifdef SOLVE3D
411 maxrho(ng)=rbuffer(5)
412# endif
413!
414 courant(1)=max_c
415 courant(2)=max_cu
416 courant(3)=max_cv
417 courant(4)=real(max_ci,r8)
418 courant(5)=real(max_cj,r8)
419# ifdef SOLVE3D
420 courant(6)=max_cw
421 courant(7)=real(max_ck,r8)
422# endif
423 c_handle(1)='MAXLOC'
424 CALL mp_reduce2 (ng, inlm, ncourant, 1, courant, c_handle)
425 max_c =courant(1)
426 max_cu=courant(2)
427 max_cv=courant(3)
428 max_ci=int(courant(4))
429 max_cj=int(courant(5))
430# ifdef SOLVE3D
431 max_cw=courant(6)
432 max_ck=int(courant(7))
433# endif
434!
435 trd=mymaster
436#else
437 trd=my_threadnum()
438#endif
442!
443! Report global run diagnotics values for the nonlinear kernel.
444!
445 IF (first_time(ng).eq.0) THEN
446 first_time(ng)=1
447 IF (master.and.(ng.eq.1)) THEN
448 WRITE (stdout,10) 'TIME-STEP', 'YYYY-MM-DD hh:mm:ss.ss', &
449 & 'KINETIC_ENRG', 'POTEN_ENRG', &
450#ifdef NESTING
451 & 'TOTAL_ENRG', 'NET_VOLUME', 'Grid'
452#else
453 & 'TOTAL_ENRG', 'NET_VOLUME'
454#endif
455#ifdef SOLVE3D
456 WRITE (stdout,20) 'C => (i,j,k)', 'Cu', 'Cv', &
457 & ' Cw ', 'Max Speed'
458#else
459 WRITE (stdout,20) ' C => (i,j)', 'Cu', 'Cv', &
460 & ' C Max', 'Max Speed'
461#endif
462#ifdef NESTING
463 10 FORMAT (/,1x,a,1x,a,2x,a,3x,a,4x,a,4x,a,2x,a)
464#else
465 10 FORMAT (/,1x,a,1x,a,2x,a,3x,a,4x,a,4x,a)
466#endif
467 20 FORMAT (21x,a,7x,a,12x,a,10x,a,7x,a,/)
468 END IF
469 END IF
470!
471 IF (master) THEN
472 WRITE (stdout,30) istep, datetime, &
473#ifdef NESTING
474 & avgke, avgpe, avgkp, volume, ng
475#else
477#endif
478#ifdef SOLVE3D
479 ispace=35-(6+idigits(ng)+jdigits(ng)+kdigits(ng))
480 WRITE (frmt,40) ispace, &
481 & '"("', idigits(ng), idigits(ng), &
482 & '","', jdigits(ng), jdigits(ng), &
483 & '","', kdigits(ng), kdigits(ng), '")"'
484 WRITE (stdout,frmt) max_ci, max_cj, &
485 & max_ck, max_cu, max_cv, max_cw, &
486 & maxspeed(ng)
487#else
488 ispace=35-(5+idigits(ng)+jdigits(ng))
489 WRITE (frmt,40) ispace, &
490 & '"("', idigits(ng), idigits(ng), &
491 & '","', jdigits(ng), jdigits(ng), '")"'
492 WRITE (stdout,frmt) max_ci, max_cj, &
493 & max_cu, max_cv, max_c, &
494 & maxspeed(ng)
495#endif
496 FLUSH (stdout)
497#ifdef NESTING
498 30 FORMAT (i10,1x,a,4(1pe14.6),2x,i2.2)
499#else
500 30 FORMAT (i10,1x,a,4(1pe14.6))
501#endif
502 40 FORMAT ('(',i2.2,'x,',a,',i',i1,'.',i1,',', &
503 & a,',i',i1,'.',i1,',', &
504#ifdef SOLVE3D
505 & a,',i',i1,'.',i1,',', &
506#endif
507 & a,',t35,4(1pe13.6,1x))')
508 END IF
509!
510! If blowing-up, set exit_flag to stop computations.
511!
512 WRITE (kechar,'(1pe8.1)') avgke
513 WRITE (pechar,'(1pe8.1)') avgpe
514 DO i=1,8
515 IF ((kechar(i:i).eq.'N').or.(pechar(i:i).eq.'N').or. &
516 & (kechar(i:i).eq.'n').or.(pechar(i:i).eq.'n').or. &
517 & (kechar(i:i).eq.'*').or.(pechar(i:i).eq.'*')) THEN
518 exit_flag=1
519 blowup_string='KEchar = '//kechar//', PEchar = '//pechar
520 END IF
521 END DO
522!
523! Stop computations if exceeding maximum speed allowed. This will be
524! useful during debugging to avoid NaNs in output NetCDF files.
525!
526 IF (maxspeed(ng).gt.max_speed) THEN
527 exit_flag=1
528 WRITE (maxvalchar,'(1pe8.1)') maxspeed(ng)
529 blowup_string='MaxSpeed = '//maxvalchar
530 END IF
531#ifdef SOLVE3D
532!
533! Stop computation if exceeding maximum density anomaly allowed.
534! Recall that density is computed from potential temperature and
535! salinity. This is a good way to screen for very bad values which
536! indicates that the model is blowing-up.
537!
538 IF (maxrho(ng).gt.max_rho) THEN
539 exit_flag=1
540 WRITE (maxvalchar,'(1pe8.1)') maxrho(ng)
541 blowup_string='MaxDensity = '//maxvalchar
542 END IF
543#endif
544!
545! Reset global reduction variables for the next call.
546!
547 volume=0.0_r8
548 avgke=0.0_r8
549 avgpe=0.0_r8
550 maxspeed(ng)=-large
551#ifdef SOLVE3D
552 maxrho(ng)=-large
553#endif
554 max_c =0.0_r8
555 max_cu=0.0_r8
556 max_cv=0.0_r8
557#ifdef SOLVE3D
558 max_cw=0.0_r8
559#endif
560 max_ci=0
561 max_cj=0
562#ifdef SOLVE3D
563 max_ck=0
564#endif
565 END IF
566!$OMP END CRITICAL (NL_DIAGNOSTICS)
567 END IF
568!
569 RETURN
570 END SUBROUTINE diag_tile
571 END MODULE diag_mod
subroutine ana_diag(ng, tile, model)
Definition ana_diag.h:3
Definition diag.F:2
subroutine diag_tile(ng, tile, lbi, ubi, lbj, ubj, imins, imaxs, jmins, jmaxs, nstp, krhs, h, pm, pn, omn, hz, z_r, z_w, rho, u, v, wvel, ubar, vbar, zeta)
Definition diag.F:94
subroutine, public diag(ng, tile)
Definition diag.F:24
subroutine mp_reduce2(ng, model, isize, jsize, a, handle_op, inpcomm)
type(t_grid), dimension(:), allocatable grid
Definition mod_grid.F:365
integer stdout
type(t_ocean), dimension(:), allocatable ocean
Definition mod_ocean.F:351
logical master
integer mymaster
integer tile_count
integer, parameter inlm
Definition mod_param.F:662
integer, dimension(:), allocatable ntilex
Definition mod_param.F:685
type(t_domain), dimension(:), allocatable domain
Definition mod_param.F:329
integer, dimension(:), allocatable ntilee
Definition mod_param.F:686
integer, dimension(:), allocatable ninfo
real(dp), parameter spval
integer, dimension(:), allocatable iic
real(dp), dimension(:), allocatable dt
real(dp), dimension(:), allocatable maxrho
real(dp), parameter large
real(dp) avgke
real(dp) avgpe
integer max_cj
integer, dimension(:), allocatable idigits
real(r8) max_cu
integer max_ci
real(dp) volume
integer, dimension(:), allocatable first_time
character(len=22), dimension(:), allocatable time_code
integer exit_flag
integer, dimension(:), allocatable kdigits
real(r8) max_cw
integer max_ck
real(dp) avgkp
real(r8) max_cv
real(dp) max_rho
real(dp) g
real(r8) max_c
character(len=80) blowup_string
real(dp) rho0
integer, dimension(:), allocatable jdigits
real(dp) max_speed
real(dp), dimension(:), allocatable maxspeed
integer, dimension(:), allocatable kstp
integer, dimension(:), allocatable krhs
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