MOM6
MOM_checksum_packages.F90
Go to the documentation of this file.
2 
3 !***********************************************************************
4 !* GNU General Public License *
5 !* This file is a part of MOM. *
6 !* *
7 !* MOM is free software; you can redistribute it and/or modify it and *
8 !* are expected to follow the terms of the GNU General Public License *
9 !* as published by the Free Software Foundation; either version 2 of *
10 !* the License, or (at your option) any later version. *
11 !* *
12 !* MOM is distributed in the hope that it will be useful, but WITHOUT *
13 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
14 !* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public *
15 !* License for more details. *
16 !* *
17 !* For the full text of the GNU General Public License, *
18 !* write to: Free Software Foundation, Inc., *
19 !* 675 Mass Ave, Cambridge, MA 02139, USA. *
20 !* or see: http://www.gnu.org/licenses/gpl.html *
21 !***********************************************************************
22 
23 ! This module provdes a several routines that do check-sums of groups
24 ! of variables in the various dynamic solver routines.
25 
26 use mom_debugging, only : hchksum, uvchksum
27 use mom_domains, only : sum_across_pes, min_across_pes, max_across_pes
29 use mom_grid, only : ocean_grid_type
32 
33 implicit none ; private
34 
36 public mom_state_stats
37 
39  module procedure mom_state_chksum_5arg
40  module procedure mom_state_chksum_3arg
41 end interface
42 
43 #include <MOM_memory.h>
44 
45 type :: stats
46  private
47  real :: minimum = 1.e34, maximum = -1.e34, average = 0.
48 end type stats
49 
50 contains
51 
52 ! =============================================================================
53 
54 subroutine mom_state_chksum_5arg(mesg, u, v, h, uh, vh, G, GV, haloshift, symmetric)
55  character(len=*), &
56  intent(in) :: mesg !< A message that appears on the chksum lines.
57  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
58  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
59  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
60  intent(in) :: u !< The zonal velocity, in m s-1.
61  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
62  intent(in) :: v !< The meridional velocity, in m s-1.
63  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
64  intent(in) :: h !< Layer thicknesses, in H (usually m or kg m-2).
65  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
66  intent(in) :: uh !< Volume flux through zonal faces = u*h*dy, m3 s-1.
67  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
68  intent(in) :: vh !< Volume flux through meridional
69  !! faces = v*h*dx, in m3 s-1.
70  integer, optional, intent(in) :: haloshift
71  logical, optional, intent(in) :: symmetric
72 ! This subroutine writes out chksums for the model's basic state variables.
73 ! Arguments: mesg - A message that appears on the chksum lines.
74 ! (in) u - Zonal velocity, in m s-1.
75 ! (in) v - Meridional velocity, in m s-1.
76 ! (in) h - Layer thickness, in m.
77 ! (in) uh - Volume flux through zonal faces = u*h*dy, m3 s-1.
78 ! (in) vh - Volume flux through meridional faces = v*h*dx, in m3 s-1.
79 ! (in) G - The ocean's grid structure.
80 ! (in) GV - The ocean's vertical grid structure.
81  integer :: is, ie, js, je, nz, hs
82  logical :: sym
83  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
84 
85  ! Note that for the chksum calls to be useful for reproducing across PE
86  ! counts, there must be no redundant points, so all variables use is..ie
87  ! and js...je as their extent.
88  hs=1; if (present(haloshift)) hs=haloshift
89  sym=.false.; if (present(symmetric)) sym=symmetric
90  call uvchksum(mesg//" [uv]", u, v, g%HI, haloshift=hs, symmetric=sym)
91  call hchksum(h, mesg//" h", g%HI, haloshift=hs, scale=gv%H_to_m)
92  call uvchksum(mesg//" [uv]h", uh, vh, g%HI, haloshift=hs, &
93  symmetric=sym, scale=gv%H_to_m)
94 end subroutine mom_state_chksum_5arg
95 
96 ! =============================================================================
97 
98 subroutine mom_state_chksum_3arg(mesg, u, v, h, G, GV, haloshift, symmetric)
99  character(len=*), intent(in) :: mesg !< A message that appears on the chksum lines.
100  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
101  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
102  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
103  intent(in) :: u !< Zonal velocity, in m s-1.
104  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
105  intent(in) :: v !< Meridional velocity, in m s-1.
106  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
107  intent(in) :: h !< Layer thicknesses, in H (usually m or kg m-2).
108  integer, optional, intent(in) :: haloshift
109  logical, optional, intent(in) :: symmetric
110 ! This subroutine writes out chksums for the model's basic state variables.
111 ! Arguments: mesg - A message that appears on the chksum lines.
112 ! (in) u - Zonal velocity, in m s-1.
113 ! (in) v - Meridional velocity, in m s-1.
114 ! (in) h - Layer thickness, in m.
115 ! (in) uh - Volume flux through zonal faces = u*h*dy, m3 s-1.
116 ! (in) vh - Volume flux through meridional faces = v*h*dx, in m3 s-1.
117 ! (in) G - The ocean's grid structure.
118 ! (in) GV - The ocean's vertical grid structure.
119  integer :: is, ie, js, je, nz, hs
120  logical :: sym
121  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
122 
123  ! Note that for the chksum calls to be useful for reproducing across PE
124  ! counts, there must be no redundant points, so all variables use is..ie
125  ! and js...je as their extent.
126  hs=1; if (present(haloshift)) hs=haloshift
127  sym=.false.; if (present(symmetric)) sym=symmetric
128  call uvchksum(mesg//" u", u, v, g%HI,haloshift=hs, symmetric=sym)
129  call hchksum(h, mesg//" h",g%HI, haloshift=hs, scale=gv%H_to_m)
130 end subroutine mom_state_chksum_3arg
131 
132 ! =============================================================================
133 
134 subroutine mom_thermo_chksum(mesg, tv, G, haloshift)
135  character(len=*), intent(in) :: mesg !< A message that appears on the chksum lines.
136  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various
137  !! thermodynamic variables.
138  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
139  integer, optional, intent(in) :: haloshift
140 ! This subroutine writes out chksums for the model's thermodynamic state
141 ! variables.
142 ! Arguments: mesg - A message that appears on the chksum lines.
143 ! (in) tv - A structure containing pointers to any thermodynamic
144 ! fields that are in use.
145 ! (in) G - The ocean's grid structure.
146  integer :: is, ie, js, je, nz, hs
147  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
148  hs=1; if (present(haloshift)) hs=haloshift
149 
150  if (associated(tv%T)) call hchksum(tv%T, mesg//" T",g%HI,haloshift=hs)
151  if (associated(tv%S)) call hchksum(tv%S, mesg//" S",g%HI,haloshift=hs)
152  if (associated(tv%frazil)) call hchksum(tv%frazil, mesg//" frazil",g%HI,haloshift=hs)
153  if (associated(tv%salt_deficit)) call hchksum(tv%salt_deficit, mesg//" salt deficit",g%HI,haloshift=hs)
154 
155 end subroutine mom_thermo_chksum
156 
157 ! =============================================================================
158 
159 subroutine mom_accel_chksum(mesg, CAu, CAv, PFu, PFv, diffu, diffv, G, GV, pbce, &
160  u_accel_bt, v_accel_bt, symmetric)
161  character(len=*), intent(in) :: mesg !< A message that appears on the chksum lines.
162  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
163  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
164  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
165  intent(in) :: CAu !< Zonal acceleration due to Coriolis
166  !! and momentum advection terms, in m s-2.
167  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
168  intent(in) :: CAv !< Meridional acceleration due to Coriolis
169  !! and momentum advection terms, in m s-2.
170  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
171  intent(in) :: PFu !< Zonal acceleration due to pressure gradients
172  !! (equal to -dM/dx) in m s-2.
173  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
174  intent(in) :: PFv !< Meridional acceleration due to pressure gradients
175  !! (equal to -dM/dy) in m s-2.
176  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
177  intent(in) :: diffu !< Zonal acceleration due to convergence of the
178  !! along-isopycnal stress tensor, in m s-2.
179  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
180  intent(in) :: diffv !< Meridional acceleration due to convergence of
181  !! the along-isopycnal stress tensor, in m s-2.
182  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
183  optional, intent(in) :: pbce !< The baroclinic pressure anomaly in each layer
184  !! due to free surface height anomalies, in
185  !! m2 s-2 H-1. !! NULL.
186  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
187  optional, intent(in) :: u_accel_bt !< The zonal acceleration from terms in the
188  !! barotropic solver,in m s-2.
189  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
190  optional, intent(in) :: v_accel_bt !< The meridional acceleration from terms in
191  !! the barotropic solver,in m s-2.
192  logical, optional, intent(in) :: symmetric
193 
194 ! This subroutine writes out chksums for the model's accelerations.
195 ! Arguments: mesg - A message that appears on the chksum lines.
196 ! (in) CAu - Zonal acceleration due to Coriolis and momentum
197 ! advection terms, in m s-2.
198 ! (in) CAv - Meridional acceleration due to Coriolis and
199 ! momentum advection terms, in m s-2.
200 ! (in) PFu - Zonal acceleration due to pressure gradients
201 ! (equal to -dM/dx) in m s-2.
202 ! (in) PFv - Meridional acceleration due to pressure
203 ! gradients (equal to -dM/dy) in m s-2.
204 ! (in) diffu - Zonal acceleration due to convergence of the
205 ! along-isopycnal stress tensor, in m s-2.
206 ! (in) diffv - Meridional acceleration due to convergence of
207 ! the along-isopycnal stress tensor, in m s-2.
208 ! (in) G - The ocean's grid structure.
209 ! (in) GV - The ocean's vertical grid structure.
210 ! (in) pbce - the baroclinic pressure anomaly in each layer
211 ! due to free surface height anomalies, in m2 s-2 H-1.
212 ! pbce points to a space with nz layers or NULL.
213 ! (in) u_accel_bt - The zonal acceleration from terms in the barotropic
214 ! solver, in m s-2.
215 ! (in) v_accel_bt - The meridional acceleration from terms in the
216 ! barotropic solver, in m s-2.
217  integer :: is, ie, js, je, nz
218  logical :: sym
219 
220  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
221  sym=.false.; if (present(symmetric)) sym=symmetric
222 
223  ! Note that for the chksum calls to be useful for reproducing across PE
224  ! counts, there must be no redundant points, so all variables use is..ie
225  ! and js...je as their extent.
226  call uvchksum(mesg//" CA[uv]", cau, cav, g%HI, haloshift=0, symmetric=sym)
227  call uvchksum(mesg//" PF[uv]", pfu, pfv, g%HI, haloshift=0, symmetric=sym)
228  call uvchksum(mesg//" diffu", diffu, diffv, g%HI,haloshift=0, symmetric=sym)
229  if (present(pbce)) &
230  call hchksum(pbce, mesg//" pbce",g%HI,haloshift=0, scale=gv%m_to_H)
231  if (present(u_accel_bt) .and. present(v_accel_bt)) &
232  call uvchksum(mesg//" [uv]_accel_bt", u_accel_bt, v_accel_bt, g%HI,haloshift=0, symmetric=sym)
233 end subroutine mom_accel_chksum
234 
235 ! =============================================================================
236 
237 subroutine mom_state_stats(mesg, u, v, h, Temp, Salt, G, allowChange, permitDiminishing)
238  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
239  character(len=*), intent(in) :: mesg !< A message that appears on the chksum lines.
240  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
241  intent(in) :: u !< The zonal velocity, in m s-1.
242  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
243  intent(in) :: v !< The meridional velocity, in m s-1.
244  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
245  intent(in) :: h !< Layer thicknesses, in H (usually m or kg m-2).
246  real, pointer, dimension(:,:,:), &
247  intent(in) :: Temp !< Temperature in degree C.
248  real, pointer, dimension(:,:,:), &
249  intent(in) :: Salt !< Salinity, in ppt.
250 
251  logical, optional, intent(in) :: allowChange !< do not flag an error
252  !! if the statistics change.
253  logical, optional, &
254  intent(in) :: permitDiminishing !< do not flag error
255  !!if the extrema are diminishing.
256 ! This subroutine monitors statistics for the model's state variables.
257 ! Arguments: mesg - A message that appears on the chksum lines.
258 ! (in) u - Zonal velocity, in m s-1.
259 ! (in) v - Meridional velocity, in m s-1.
260 ! (in) h - Layer thickness, in m.
261 ! (in) T - Temperature, in degree C.
262 ! (in) S - Salinity, in ppt.
263 ! (in) G - The ocean's grid structure.
264 ! (in) allowChange - do not flag an error if the statistics change
265 ! (in) permitDiminishing - do not flag an error if the extrema are diminishing
266  integer :: is, ie, js, je, nz, i, j, k
267  real :: Vol, dV, Area, h_minimum
268  type(stats) :: T, S, delT, delS
269  type(stats), save :: oldT, oldS ! NOTE: save data is not normally allowed but
270  logical, save :: firstCall = .true. ! we use it for debugging purposes here on the
271  logical :: do_TS
272  real, save :: oldVol ! assumption we will not turn this on with threads
273  character(len=80) :: lMsg
274  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
275 
276  do_ts = associated(temp) .and. associated(salt)
277 
278  ! First collect local stats
279  area = 0. ; vol = 0.
280  do j = js, je ; do i = is, ie
281  area = area + g%areaT(i,j)
282  enddo ; enddo
283  t%minimum = 1.e34 ; t%maximum = -1.e34 ; t%average = 0.
284  s%minimum = 1.e34 ; s%maximum = -1.e34 ; s%average = 0.
285  h_minimum = 1.e34
286  do k = 1, nz ; do j = js, je ; do i = is, ie
287  if (g%mask2dT(i,j)>0.) then
288  dv = g%areaT(i,j)*h(i,j,k) ; vol = vol + dv
289  if (do_ts .and. h(i,j,k)>0.) then
290  t%minimum = min( t%minimum, temp(i,j,k) ) ; t%maximum = max( t%maximum, temp(i,j,k) )
291  t%average = t%average + dv*temp(i,j,k)
292  s%minimum = min( s%minimum, salt(i,j,k) ) ; s%maximum = max( s%maximum, salt(i,j,k) )
293  s%average = s%average + dv*salt(i,j,k)
294  endif
295  if (h_minimum > h(i,j,k)) h_minimum = h(i,j,k)
296  endif
297  enddo ; enddo ; enddo
298  call sum_across_pes( area ) ; call sum_across_pes( vol )
299  if (do_ts) then
300  call min_across_pes( t%minimum ) ; call max_across_pes( t%maximum ) ; call sum_across_pes( t%average )
301  call min_across_pes( s%minimum ) ; call max_across_pes( s%maximum ) ; call sum_across_pes( s%average )
302  t%average = t%average / vol ; s%average = s%average / vol
303  endif
304  if (is_root_pe()) then
305  if (.not.firstcall) then
306  dv = vol - oldvol
307  delt%minimum = t%minimum - oldt%minimum ; delt%maximum = t%maximum - oldt%maximum
308  delt%average = t%average - oldt%average
309  dels%minimum = s%minimum - olds%minimum ; dels%maximum = s%maximum - olds%maximum
310  dels%average = s%average - olds%average
311  write(lmsg(1:80),'(2(a,es12.4))') 'Mean thickness =',vol/area,' frac. delta=',dv/vol
312  call mom_mesg(lmsg//trim(mesg))
313  if (do_ts) then
314  write(lmsg(1:80),'(a,3es12.4)') 'Temp min/mean/max =',t%minimum,t%average,t%maximum
315  call mom_mesg(lmsg//trim(mesg))
316  write(lmsg(1:80),'(a,3es12.4)') 'delT min/mean/max =',delt%minimum,delt%average,delt%maximum
317  call mom_mesg(lmsg//trim(mesg))
318  write(lmsg(1:80),'(a,3es12.4)') 'Salt min/mean/max =',s%minimum,s%average,s%maximum
319  call mom_mesg(lmsg//trim(mesg))
320  write(lmsg(1:80),'(a,3es12.4)') 'delS min/mean/max =',dels%minimum,dels%average,dels%maximum
321  call mom_mesg(lmsg//trim(mesg))
322  endif
323  else
324  write(lmsg(1:80),'(a,es12.4)') 'Mean thickness =',vol/area
325  call mom_mesg(lmsg//trim(mesg))
326  if (do_ts) then
327  write(lmsg(1:80),'(a,3es12.4)') 'Temp min/mean/max =',t%minimum,t%average,t%maximum
328  call mom_mesg(lmsg//trim(mesg))
329  write(lmsg(1:80),'(a,3es12.4)') 'Salt min/mean/max =',s%minimum,s%average,s%maximum
330  call mom_mesg(lmsg//trim(mesg))
331  endif
332  endif
333  endif
334  firstcall = .false. ; oldvol = vol
335  oldt%minimum = t%minimum ; oldt%maximum = t%maximum ; oldt%average = t%average
336  olds%minimum = s%minimum ; olds%maximum = s%maximum ; olds%average = s%average
337 
338  if (do_ts .and. t%minimum<-5.0) then
339  do j = js, je ; do i = is, ie
340  if (minval(temp(i,j,:)) == t%minimum) then
341  write(0,'(a,2f12.5)') 'x,y=',g%geoLonT(i,j),g%geoLatT(i,j)
342  write(0,'(a3,3a12)') 'k','h','Temp','Salt'
343  do k = 1, nz
344  write(0,'(i3,3es12.4)') k,h(i,j,k),temp(i,j,k),salt(i,j,k)
345  enddo
346  stop 'Extremum detected'
347  endif
348  enddo ; enddo
349  endif
350 
351  if (h_minimum<0.0) then
352  do j = js, je ; do i = is, ie
353  if (minval(h(i,j,:)) == h_minimum) then
354  write(0,'(a,2f12.5)') 'x,y=',g%geoLonT(i,j),g%geoLatT(i,j)
355  write(0,'(a3,3a12)') 'k','h','Temp','Salt'
356  do k = 1, nz
357  write(0,'(i3,3es12.4)') k,h(i,j,k),temp(i,j,k),salt(i,j,k)
358  enddo
359  stop 'Negative thickness detected'
360  endif
361  enddo ; enddo
362  endif
363 
364 end subroutine mom_state_stats
365 
366 end module mom_checksum_packages
subroutine, public mom_thermo_chksum(mesg, tv, G, haloshift)
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
Provides the ocean grid type.
Definition: MOM_grid.F90:2
subroutine, public mom_accel_chksum(mesg, CAu, CAv, PFu, PFv, diffu, diffv, G, GV, pbce, u_accel_bt, v_accel_bt, symmetric)
subroutine, public mom_state_stats(mesg, u, v, h, Temp, Salt, G, allowChange, permitDiminishing)
logical function, public is_root_pe()
subroutine, public mom_mesg(message, verb, all_print)
subroutine mom_state_chksum_3arg(mesg, u, v, h, G, GV, haloshift, symmetric)
The thermo_var_ptrs structure contains pointers to an assortment of thermodynamic fields that may be ...
subroutine mom_state_chksum_5arg(mesg, u, v, h, uh, vh, G, GV, haloshift, symmetric)