MOM6
MOM_generic_tracer.F90
1 module mom_generic_tracer
2 
3 ! This file is part of MOM6. See LICENSE.md for the license.
4 
5 #include <MOM_memory.h>
6 
7 #ifdef _USE_GENERIC_TRACER
8 #include <fms_platform.h>
9 
10  use mpp_mod, only: stdout, mpp_error, fatal,warning,note
11  use field_manager_mod, only: fm_get_index,fm_string_len
12 
13  use generic_tracer, only: generic_tracer_register, generic_tracer_get_diag_list
14  use generic_tracer, only: generic_tracer_init, generic_tracer_source, generic_tracer_register_diag
15  use generic_tracer, only: generic_tracer_coupler_get, generic_tracer_coupler_set
16  use generic_tracer, only: generic_tracer_end, generic_tracer_get_list, do_generic_tracer
17  use generic_tracer, only: generic_tracer_update_from_bottom,generic_tracer_vertdiff_g
18  use generic_tracer, only: generic_tracer_coupler_accumulate
19 
20  use g_tracer_utils, only: g_tracer_get_name,g_tracer_set_values,g_tracer_set_common,g_tracer_get_common
21  use g_tracer_utils, only: g_tracer_get_next,g_tracer_type,g_tracer_is_prog,g_tracer_flux_init
22  use g_tracer_utils, only: g_tracer_send_diag,g_tracer_get_values
23  use g_tracer_utils, only: g_tracer_get_pointer,g_tracer_get_alias,g_tracer_set_csdiag
24 
25  use mom_diag_mediator, only : post_data, register_diag_field, safe_alloc_ptr
26  use mom_diag_mediator, only : diag_ctrl, get_diag_time_end
27  use mom_error_handler, only : mom_error, fatal, warning, note, is_root_pe
29  use mom_forcing_type, only : forcing, optics_type
30  use mom_grid, only : ocean_grid_type
31  use mom_hor_index, only : hor_index_type
32  use mom_io, only : file_exists, mom_read_data, slasher
34  use mom_spatial_means, only : global_area_mean
35  use mom_sponge, only : set_up_sponge_field, sponge_cs
37  use mom_time_manager, only : time_type, set_time
38  use mom_tracer_diabatic, only : tracer_vertdiff, applytracerboundaryfluxesinout
39  use mom_tracer_registry, only : register_tracer, tracer_registry_type
40  use mom_tracer_z_init, only : tracer_z_init
41  use mom_tracer_initialization_from_z, only : mom_initialize_tracer_from_z
46 
47 
48  implicit none ; private
49  logical :: g_registered = .false.
50 
51  public register_mom_generic_tracer, initialize_mom_generic_tracer
52  public mom_generic_tracer_column_physics, mom_generic_tracer_surface_state
53  public end_mom_generic_tracer, mom_generic_tracer_get
54  public mom_generic_tracer_stock
55  public mom_generic_flux_init
56  public mom_generic_tracer_min_max
57  public mom_generic_tracer_fluxes_accumulate
58 
59  type, public :: mom_generic_tracer_cs ; private
60  character(len = 200) :: IC_file ! The file in which the generic tracer initial values can
61  ! be found, or an empty string for internal initialization.
62  logical :: Z_IC_file ! If true, the generic_tracer IC_file is in Z-space. The default is false.
63  real :: tracer_IC_val = 0.0 ! The initial value assigned to tracers.
64  real :: tracer_land_val = -1.0 ! The values of tracers used where land is masked out.
65  logical :: tracers_may_reinit ! If true, tracers may go through the
66  ! initialization code if they are not found in the
67  ! restart files.
68 
69  type(diag_ctrl), pointer :: diag => null() ! A structure that is used to
70  ! regulate the timing of diagnostic output.
71  type(MOM_restart_CS), pointer :: restart_CSp => null()
72 
73  ! The following pointer will be directed to the first element of the
74  ! linked list of generic tracers.
75  type(g_tracer_type), pointer :: g_tracer_list => null()
76 
77  integer :: H_to_m !Auxiliary to access GV%H_to_m in routines that do not have access to GV
78 
79  end type mom_generic_tracer_cs
80 
81 ! This include declares and sets the variable "version".
82 #include "version_variable.h"
83 
84 contains
85 
86  !> Initializes the generic tracer packages and adds their tracers to the list
87  !! Adds the tracers in the list of generic tracers to the set of MOM tracers (i.e., MOM-register them)
88  !! Register these tracers for restart
89  function register_mom_generic_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
90  type(hor_index_type), intent(in) :: HI !< Horizontal index ranges
91  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
92  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
93  type(MOM_generic_tracer_CS), pointer :: CS !< Pointer to the control structure for this module
94  type(tracer_registry_type), pointer :: tr_Reg !< Pointer to the control structure for the tracer
95  !! advection and diffusion module.
96  type(MOM_restart_CS), pointer :: restart_CS !< Pointer to the restart control structure.
97 
98 ! Local variables
99  logical :: register_MOM_generic_tracer
100 
101  character(len=fm_string_len), parameter :: sub_name = 'register_MOM_generic_tracer'
102  character(len=200) :: inputdir ! The directory where NetCDF input files are.
103  ! These can be overridden later in via the field manager?
104 
105  integer :: ntau, k,i,j,axes(3)
106  type(g_tracer_type), pointer :: g_tracer,g_tracer_next
107  character(len=fm_string_len) :: g_tracer_name,longname,units
108  real, dimension(:,:,:,:), pointer :: tr_field
109  real, dimension(:,:,:), pointer :: tr_ptr
110  real, dimension(HI%isd:HI%ied, HI%jsd:HI%jed,GV%ke) :: grid_tmask
111  integer, dimension(HI%isd:HI%ied, HI%jsd:HI%jed) :: grid_kmt
112 
113  register_mom_generic_tracer = .false.
114  if (associated(cs)) then
115  call mpp_error(warning, "register_MOM_generic_tracer called with an "// &
116  "associated control structure.")
117  return
118  endif
119  allocate(cs)
120 
121 
122  !Register all the generic tracers used and create the list of them.
123  !This can be called by ALL PE's. No array fields allocated.
124  if (.not. g_registered) then
125  call generic_tracer_register
126  g_registered = .true.
127  endif
128 
129 
130  ! Read all relevant parameters and write them to the model log.
131  call log_version(param_file, sub_name, version, "")
132  call get_param(param_file, sub_name, "GENERIC_TRACER_IC_FILE", cs%IC_file, &
133  "The file in which the generic trcer initial values can "//&
134  "be found, or an empty string for internal initialization.", &
135  default=" ")
136  if ((len_trim(cs%IC_file) > 0) .and. (scan(cs%IC_file,'/') == 0)) then
137  ! Add the directory if CS%IC_file is not already a complete path.
138  call get_param(param_file, sub_name, "INPUTDIR", inputdir, default=".")
139  cs%IC_file = trim(slasher(inputdir))//trim(cs%IC_file)
140  call log_param(param_file, sub_name, "INPUTDIR/GENERIC_TRACER_IC_FILE", cs%IC_file)
141  endif
142  call get_param(param_file, sub_name, "GENERIC_TRACER_IC_FILE_IS_Z", cs%Z_IC_file, &
143  "If true, GENERIC_TRACER_IC_FILE is in depth space, not "//&
144  "layer space.",default=.false.)
145  call get_param(param_file, sub_name, "TRACERS_MAY_REINIT", cs%tracers_may_reinit, &
146  "If true, tracers may go through the initialization code "//&
147  "if they are not found in the restart files. Otherwise "//&
148  "it is a fatal error if tracers are not found in the "//&
149  "restart files of a restarted run.", default=.false.)
150 
151  cs%restart_CSp => restart_cs
152 
153 
154  ntau=1 ! MOM needs the fields at only one time step
155 
156 
157  ! At this point G%mask2dT and CS%diag%axesTL are not allocated.
158  ! postpone diag_registeration to initialize_MOM_generic_tracer
159 
160  !Fields cannot be diag registered as they are allocated and have to registered later.
161  grid_tmask(:,:,:) = 0.0
162  grid_kmt(:,:) = 0.0
163  axes(:) = -1
164 
165  !
166  ! Initialize all generic tracers
167  !
168  call generic_tracer_init(hi%isc,hi%iec,hi%jsc,hi%jec,hi%isd,hi%ied,hi%jsd,hi%jed,&
169  gv%ke,ntau,axes,grid_tmask,grid_kmt,set_time(0,0))
170 
171 
172  !
173  ! MOM-register the generic tracers
174  !
175 
176  !Get the tracer list
177  call generic_tracer_get_list(cs%g_tracer_list)
178  if (.NOT. associated(cs%g_tracer_list)) call mpp_error(fatal, trim(sub_name)//&
179  ": No tracer in the list.")
180  ! For each tracer name get its T_prog index and get its fields
181 
182  g_tracer=>cs%g_tracer_list
183  do
184  call g_tracer_get_alias(g_tracer,g_tracer_name)
185 
186  call g_tracer_get_pointer(g_tracer,g_tracer_name,'field',tr_field)
187  call g_tracer_get_values(g_tracer,g_tracer_name,'longname', longname)
188  call g_tracer_get_values(g_tracer,g_tracer_name,'units',units )
189 
190  !!nnz: MOM field is 3D. Does this affect performance? Need it be override field?
191  tr_ptr => tr_field(:,:,:,1)
192  ! Register prognastic tracer for horizontal advection, diffusion, and restarts.
193  if (g_tracer_is_prog(g_tracer)) then
194  call register_tracer(tr_ptr, tr_reg, param_file, hi, gv, &
195  name=g_tracer_name, longname=longname, units=units, &
196  registry_diags=.false., & !### CHANGE TO TRUE?
197  restart_cs=restart_cs, mandatory=.not.cs%tracers_may_reinit)
198  else
199  call register_restart_field(tr_ptr, g_tracer_name, .not.cs%tracers_may_reinit, &
200  restart_cs, longname=longname, units=units)
201  endif
202 
203  !traverse the linked list till hit NULL
204  call g_tracer_get_next(g_tracer, g_tracer_next)
205  if (.NOT. associated(g_tracer_next)) exit
206  g_tracer=>g_tracer_next
207 
208  enddo
209 
210  register_mom_generic_tracer = .true.
211  end function register_mom_generic_tracer
212 
213  !> Initialize phase II: Initialize required variables for generic tracers
214  !! There are some steps of initialization that cannot be done in register_MOM_generic_tracer
215  !! This is the place and time to do them:
216  !! Set the grid mask and initial time for all generic tracers.
217  !! Diag_register them.
218  !! Z_diag_register them.
219  !!
220  !! This subroutine initializes the NTR tracer fields in tr(:,:,:,:)
221  !! and it sets up the tracer output.
222  subroutine initialize_mom_generic_tracer(restart, day, G, GV, US, h, param_file, diag, OBC, CS, &
223  sponge_CSp, ALE_sponge_CSp)
224  logical, intent(in) :: restart !< .true. if the fields have already been
225  !! read from a restart file.
226  type(time_type), target, intent(in) :: day !< Time of the start of the run.
227  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure
228  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
229  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
230  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
231  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
232  type(diag_ctrl), target, intent(in) :: diag !< Regulates diagnostic output.
233  type(ocean_OBC_type), pointer :: OBC !< This open boundary condition type specifies whether,
234  !! where, and what open boundary conditions are used.
235  type(MOM_generic_tracer_CS), pointer :: CS !< Pointer to the control structure for this module.
236  type(sponge_CS), pointer :: sponge_CSp !< Pointer to the control structure for the sponges.
237  type(ALE_sponge_CS), pointer :: ALE_sponge_CSp !< Pointer to the control structure for the
238  !! ALE sponges.
239 
240  character(len=fm_string_len), parameter :: sub_name = 'initialize_MOM_generic_tracer'
241  logical :: OK
242  integer :: i, j, k, isc, iec, jsc, jec, nk
243  type(g_tracer_type), pointer :: g_tracer,g_tracer_next
244  character(len=fm_string_len) :: g_tracer_name
245  real, dimension(:,:,:,:), pointer :: tr_field
246  real, dimension(:,:,:), pointer :: tr_ptr
247  real, dimension(G%isd:G%ied, G%jsd:G%jed,1:G%ke) :: grid_tmask
248  integer, dimension(G%isd:G%ied, G%jsd:G%jed) :: grid_kmt
249 
250  !! 2010/02/04 Add code to re-initialize Generic Tracers if needed during a model simulation
251  !! By default, restart cpio should not contain a Generic Tracer IC file and step below will be skipped.
252  !! Ideally, the generic tracer IC file should have the tracers on Z levels.
253 
254  isc = g%isc ; iec = g%iec ; jsc = g%jsc ; jec = g%jec ; nk = g%ke
255 
256  cs%diag=>diag
257  !Get the tracer list
258  if (.NOT. associated(cs%g_tracer_list)) call mpp_error(fatal, trim(sub_name)//&
259  ": No tracer in the list.")
260  !For each tracer name get its fields
261  g_tracer=>cs%g_tracer_list
262 
263  do
264  if (index(cs%IC_file, '_NULL_') /= 0) then
265  call mom_error(warning,"The name of the IC_file "//trim(cs%IC_file)//&
266  " indicates no MOM initialization was asked for the generic tracers."//&
267  "Bypassing the MOM initialization of ALL generic tracers!")
268  exit
269  endif
270  call g_tracer_get_alias(g_tracer,g_tracer_name)
271  call g_tracer_get_pointer(g_tracer,g_tracer_name,'field',tr_field)
272  tr_ptr => tr_field(:,:,:,1)
273 
274  if (.not.restart .or. (cs%tracers_may_reinit .and. &
275  .not.query_initialized(tr_ptr, g_tracer_name, cs%restart_CSp))) then
276 
277  if (g_tracer%requires_src_info ) then
278  call mom_error(note,"initialize_MOM_generic_tracer: "//&
279  "initializing generic tracer "//trim(g_tracer_name)//&
280  " using MOM_initialize_tracer_from_Z ")
281 
282  call mom_initialize_tracer_from_z(h, tr_ptr, g, gv, us, param_file, &
283  src_file = g_tracer%src_file, &
284  src_var_nam = g_tracer%src_var_name, &
285  src_var_unit_conversion = g_tracer%src_var_unit_conversion,&
286  src_var_record = g_tracer%src_var_record, &
287  src_var_gridspec = g_tracer%src_var_gridspec )
288 
289  !Check/apply the bounds for each g_tracer
290  do k=1,nk ; do j=jsc,jec ; do i=isc,iec
291  if (tr_ptr(i,j,k) /= cs%tracer_land_val) then
292  if (tr_ptr(i,j,k) < g_tracer%src_var_valid_min) tr_ptr(i,j,k) = g_tracer%src_var_valid_min
293  !Jasmin does not want to apply the maximum for now
294  !if (tr_ptr(i,j,k) > g_tracer%src_var_valid_max) tr_ptr(i,j,k) = g_tracer%src_var_valid_max
295  endif
296  enddo ; enddo ; enddo
297 
298  !jgj: Reset CASED to 0 below K=1
299  if ( (trim(g_tracer_name) == 'cased') .or. (trim(g_tracer_name) == 'ca13csed') ) then
300  do k=2,nk ; do j=jsc,jec ; do i=isc,iec
301  if (tr_ptr(i,j,k) /= cs%tracer_land_val) then
302  tr_ptr(i,j,k) = 0.0
303  endif
304  enddo ; enddo ; enddo
305  endif
306  elseif(.not. g_tracer%requires_restart) then
307  !Do nothing for this tracer, it is initialized by the tracer package
308  call mom_error(note,"initialize_MOM_generic_tracer: "//&
309  "skip initialization of generic tracer "//trim(g_tracer_name))
310  else !Do it old way if the tracer is not registered to start from a specific source file.
311  !This path should be deprecated if all generic tracers are required to start from specified sources.
312  if (len_trim(cs%IC_file) > 0) then
313  ! Read the tracer concentrations from a netcdf file.
314  if (.not.file_exists(cs%IC_file)) call mom_error(fatal, &
315  "initialize_MOM_Generic_tracer: Unable to open "//cs%IC_file)
316  if (cs%Z_IC_file) then
317  ok = tracer_z_init(tr_ptr, h, cs%IC_file, g_tracer_name, g, us)
318  if (.not.ok) then
319  ok = tracer_z_init(tr_ptr, h, cs%IC_file, trim(g_tracer_name), g, us)
320  if (.not.ok) call mom_error(fatal,"initialize_MOM_Generic_tracer: "//&
321  "Unable to read "//trim(g_tracer_name)//" from "//&
322  trim(cs%IC_file)//".")
323  endif
324  call mom_error(note,"initialize_MOM_generic_tracer: "//&
325  "initialized generic tracer "//trim(g_tracer_name)//&
326  " using Generic Tracer File on Z: "//cs%IC_file)
327  else
328  ! native grid
329  call mom_error(note,"initialize_MOM_generic_tracer: "//&
330  "Using Generic Tracer IC file on native grid "//trim(cs%IC_file)//&
331  " for tracer "//trim(g_tracer_name))
332  call mom_read_data(cs%IC_file, trim(g_tracer_name), tr_ptr, g%Domain)
333  endif
334  else
335  call mom_error(fatal,"initialize_MOM_generic_tracer: "//&
336  "check Generic Tracer IC filename "//trim(cs%IC_file)//&
337  " for tracer "//trim(g_tracer_name))
338  endif
339 
340  endif
341  endif
342 
343  !traverse the linked list till hit NULL
344  call g_tracer_get_next(g_tracer, g_tracer_next)
345  if (.NOT. associated(g_tracer_next)) exit
346  g_tracer=>g_tracer_next
347  enddo
348  !! end section to re-initialize generic tracers
349 
350 
351  !Now we can reset the grid mask, axes and time to their true values
352  !Note that grid_tmask must be set correctly on the data domain boundary
353  !so that coast mask can be deduced from it.
354  grid_tmask(:,:,:) = 0.0
355  grid_kmt(:,:) = 0
356  do j = g%jsd, g%jed ; do i = g%isd, g%ied
357  if (g%mask2dT(i,j) > 0) then
358  grid_tmask(i,j,:) = 1.0
359  grid_kmt(i,j) = g%ke ! Tell the code that a layer thicker than 1m is the bottom layer.
360  endif
361  enddo ; enddo
362  call g_tracer_set_common(g%isc,g%iec,g%jsc,g%jec,g%isd,g%ied,g%jsd,g%jed,&
363  gv%ke,1,cs%diag%axesTL%handles,grid_tmask,grid_kmt,day)
364 
365  ! Register generic tracer modules diagnostics
366 
367 #ifdef _USE_MOM6_DIAG
368  call g_tracer_set_csdiag(cs%diag)
369 #endif
370  call generic_tracer_register_diag()
371 #ifdef _USE_MOM6_DIAG
372  call g_tracer_set_csdiag(cs%diag)
373 #endif
374 
375  cs%H_to_m = gv%H_to_m
376 
377  end subroutine initialize_mom_generic_tracer
378 
379  !> Column physics for generic tracers.
380  !! Get the coupler values for generic tracers that exchange with atmosphere
381  !! Update generic tracer concentration fields from sources and sinks.
382  !! Vertically diffuse generic tracer concentration fields.
383  !! Update generic tracers from bottom and their bottom reservoir.
384  !!
385  !! This subroutine applies diapycnal diffusion and any other column
386  !! tracer physics or chemistry to the tracers from this file.
387  !! CFCs are relatively simple, as they are passive tracers. with only a surface
388  !! flux as a source.
389  subroutine mom_generic_tracer_column_physics(h_old, h_new, ea, eb, fluxes, Hml, dt, G, GV, CS, tv, optics, &
390  evap_CFL_limit, minimum_forcing_depth)
391  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
392  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
393  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
394  intent(in) :: h_old !< Layer thickness before entrainment [H ~> m or kg m-2].
395  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
396  intent(in) :: h_new !< Layer thickness after entrainment [H ~> m or kg m-2].
397  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
398  intent(in) :: ea !< The amount of fluid entrained from the layer
399  !! above during this call [H ~> m or kg m-2].
400  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
401  intent(in) :: eb !< The amount of fluid entrained from the layer
402  !! below during this call [H ~> m or kg m-2].
403  type(forcing), intent(in) :: fluxes !< A structure containing pointers to thermodynamic
404  !! and tracer forcing fields.
405  real, dimension(SZI_(G),SZJ_(G)), intent(in) :: Hml !< Mixed layer depth [H ~> m or kg m-2]
406  real, intent(in) :: dt !< The amount of time covered by this call [s]
407  type(MOM_generic_tracer_CS), pointer :: CS !< Pointer to the control structure for this module.
408  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables
409  type(optics_type), intent(in) :: optics !< The structure containing optical properties.
410  real, optional, intent(in) :: evap_CFL_limit !< Limits how much water can be fluxed out of
411  !! the top layer Stored previously in diabatic CS.
412  real, optional, intent(in) :: minimum_forcing_depth !< The smallest depth over which fluxes
413  !! can be applied Stored previously in diabatic CS.
414  ! The arguments to this subroutine are redundant in that
415  ! h_new(k) = h_old(k) + ea(k) - eb(k-1) + eb(k) - ea(k+1)
416 
417  ! Local variables
418  character(len=fm_string_len), parameter :: sub_name = 'MOM_generic_tracer_column_physics'
419 
420  type(g_tracer_type), pointer :: g_tracer, g_tracer_next
421  character(len=fm_string_len) :: g_tracer_name
422  real, dimension(:,:), pointer :: stf_array,trunoff_array,runoff_tracer_flux_array
423 
424  real :: surface_field(SZI_(G),SZJ_(G))
425  real :: sosga
426 
427  real, dimension(G%isd:G%ied,G%jsd:G%jed,G%ke) :: rho_dzt, dzt
428  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_work
429  integer :: i, j, k, isc, iec, jsc, jec, nk
430 
431  isc = g%isc ; iec = g%iec ; jsc = g%jsc ; jec = g%jec ; nk = g%ke
432 
433  !Get the tracer list
434  if (.NOT. associated(cs%g_tracer_list)) call mpp_error(fatal,&
435  trim(sub_name)//": No tracer in the list.")
436 
437 #ifdef _USE_MOM6_DIAG
438  call g_tracer_set_csdiag(cs%diag)
439 #endif
440 
441  !
442  !Extract the tracer surface fields from coupler and update tracer fields from sources
443  !
444  !call generic_tracer_coupler_get(fluxes%tr_fluxes)
445  !Niki: This is moved out to ocean_model_MOM.F90 because if dt_therm>dt_cpld we need to average
446  ! the fluxes without coming into this subroutine.
447  ! MOM5 has to modified to conform.
448 
449  !
450  !Add contribution of river to surface flux
451  !
452  g_tracer=>cs%g_tracer_list
453  do
454  if (_allocated(g_tracer%trunoff)) then
455  call g_tracer_get_alias(g_tracer,g_tracer_name)
456  call g_tracer_get_pointer(g_tracer,g_tracer_name,'stf', stf_array)
457  call g_tracer_get_pointer(g_tracer,g_tracer_name,'trunoff',trunoff_array)
458  call g_tracer_get_pointer(g_tracer,g_tracer_name,'runoff_tracer_flux',runoff_tracer_flux_array)
459  !nnz: Why is fluxes%river = 0?
460  runoff_tracer_flux_array = trunoff_array * fluxes%lrunoff
461  stf_array = stf_array + runoff_tracer_flux_array
462  endif
463 
464  !traverse the linked list till hit NULL
465  call g_tracer_get_next(g_tracer, g_tracer_next)
466  if (.NOT. associated(g_tracer_next)) exit
467  g_tracer=>g_tracer_next
468 
469  enddo
470 
471  !
472  !Prepare input arrays for source update
473  !
474 
475  rho_dzt(:,:,:) = gv%H_to_kg_m2 * gv%Angstrom_H
476  do k = 1, nk ; do j = jsc, jec ; do i = isc, iec !{
477  rho_dzt(i,j,k) = gv%H_to_kg_m2 * h_old(i,j,k)
478  enddo ; enddo ; enddo !}
479 
480  dzt(:,:,:) = 1.0
481  do k = 1, nk ; do j = jsc, jec ; do i = isc, iec !{
482  dzt(i,j,k) = gv%H_to_m * h_old(i,j,k)
483  enddo ; enddo ; enddo !}
484 
485  do j=jsc,jec ; do i=isc,iec
486  surface_field(i,j) = tv%S(i,j,1)
487  enddo ; enddo
488  sosga = global_area_mean(surface_field, g)
489 
490  !
491  !Calculate tendencies (i.e., field changes at dt) from the sources / sinks
492  !
493 
494  call generic_tracer_source(tv%T,tv%S,rho_dzt,dzt,hml,g%isd,g%jsd,1,dt,&
495  g%areaT,get_diag_time_end(cs%diag),&
496  optics%nbands, optics%max_wavelength_band, optics%sw_pen_band, optics%opacity_band, &
497  internal_heat=tv%internal_heat, frunoff=fluxes%frunoff, sosga=sosga)
498 
499  ! This uses applyTracerBoundaryFluxesInOut to handle the change in tracer due to freshwater fluxes
500  ! usually in ALE mode
501  if (present(evap_cfl_limit) .and. present(minimum_forcing_depth)) then
502  g_tracer=>cs%g_tracer_list
503  do
504  if (g_tracer_is_prog(g_tracer)) then
505  do k=1,nk ;do j=jsc,jec ; do i=isc,iec
506  h_work(i,j,k) = h_old(i,j,k)
507  enddo ; enddo ; enddo
508  call applytracerboundaryfluxesinout(g, gv, g_tracer%field(:,:,:,1), dt, fluxes, h_work, &
509  evap_cfl_limit, minimum_forcing_depth)
510  endif
511 
512  !traverse the linked list till hit NULL
513  call g_tracer_get_next(g_tracer, g_tracer_next)
514  if (.NOT. associated(g_tracer_next)) exit
515  g_tracer=>g_tracer_next
516  enddo
517  endif
518 
519  !
520  !Update Tr(n)%field from explicit vertical diffusion
521  !
522  ! Use a tridiagonal solver to determine the concentrations after the
523  ! surface source is applied and diapycnal advection and diffusion occurs.
524  if (present(evap_cfl_limit) .and. present(minimum_forcing_depth)) then
525  ! Last arg is tau which is always 1 for MOM6
526  call generic_tracer_vertdiff_g(h_work, ea, eb, dt, gv%kg_m2_to_H, gv%m_to_H, 1)
527  else
528  ! Last arg is tau which is always 1 for MOM6
529  call generic_tracer_vertdiff_g(h_old, ea, eb, dt, gv%kg_m2_to_H, gv%m_to_H, 1)
530  endif
531 
532  ! Update bottom fields after vertical processes
533 
534  ! Second arg is tau which is always 1 for MOM6
535  call generic_tracer_update_from_bottom(dt, 1, get_diag_time_end(cs%diag))
536 
537  !Output diagnostics via diag_manager for all generic tracers and their fluxes
538  call g_tracer_send_diag(cs%g_tracer_list, get_diag_time_end(cs%diag), tau=1)
539 #ifdef _USE_MOM6_DIAG
540  call g_tracer_set_csdiag(cs%diag)
541 #endif
542 
543 
544  end subroutine mom_generic_tracer_column_physics
545 
546  !> This subroutine calculates mass-weighted integral on the PE either
547  !! of all available tracer concentrations, or of a tracer that is
548  !! being requested specifically, returning the number of stocks it has
549  !! calculated. If the stock_index is present, only the stock corresponding
550  !! to that coded index is returned.
551  function mom_generic_tracer_stock(h, stocks, G, GV, CS, names, units, stock_index)
552  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
553  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
554  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
555  real, dimension(:), intent(out) :: stocks !< The mass-weighted integrated amount of each
556  !! tracer, in kg times concentration units [kg conc].
557  type(MOM_generic_tracer_CS), pointer :: CS !< Pointer to the control structure for this module.
558  character(len=*), dimension(:), intent(out) :: names !< The names of the stocks calculated.
559  character(len=*), dimension(:), intent(out) :: units !< The units of the stocks calculated.
560  integer, optional, intent(in) :: stock_index !< The coded index of a specific stock
561  !! being sought.
562  integer :: MOM_generic_tracer_stock !< Return value, the
563  !! number of stocks calculated here.
564 
565 ! Local variables
566  type(g_tracer_type), pointer :: g_tracer, g_tracer_next
567  real, dimension(:,:,:,:), pointer :: tr_field
568  real, dimension(:,:,:), pointer :: tr_ptr
569  character(len=fm_string_len), parameter :: sub_name = 'MOM_generic_tracer_stock'
570 
571  integer :: i, j, k, is, ie, js, je, nz, m
572  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
573 
574  mom_generic_tracer_stock = 0
575  if (.not.associated(cs)) return
576 
577  if (present(stock_index)) then ; if (stock_index > 0) then
578  ! Check whether this stock is available from this routine.
579 
580  ! No stocks from this routine are being checked yet. Return 0.
581  return
582  endif ; endif
583 
584  if (.NOT. associated(cs%g_tracer_list)) return ! No stocks.
585 
586  m=1 ; g_tracer=>cs%g_tracer_list
587  do
588  call g_tracer_get_alias(g_tracer,names(m))
589  call g_tracer_get_values(g_tracer,names(m),'units',units(m))
590  units(m) = trim(units(m))//" kg"
591  call g_tracer_get_pointer(g_tracer,names(m),'field',tr_field)
592 
593  stocks(m) = 0.0
594  tr_ptr => tr_field(:,:,:,1)
595  do k=1,nz ; do j=js,je ; do i=is,ie
596  stocks(m) = stocks(m) + tr_ptr(i,j,k) * &
597  (g%mask2dT(i,j) * g%areaT(i,j) * h(i,j,k))
598  enddo ; enddo ; enddo
599  stocks(m) = gv%H_to_kg_m2 * stocks(m)
600 
601  !traverse the linked list till hit NULL
602  call g_tracer_get_next(g_tracer, g_tracer_next)
603  if (.NOT. associated(g_tracer_next)) exit
604  g_tracer=>g_tracer_next
605  m = m+1
606  enddo
607 
608  mom_generic_tracer_stock = m
609 
610  end function mom_generic_tracer_stock
611 
612  !> This subroutine find the global min and max of either of all
613  !! available tracer concentrations, or of a tracer that is being
614  !! requested specifically, returning the number of tracers it has gone through.
615  function mom_generic_tracer_min_max(ind_start, got_minmax, gmin, gmax, xgmin, ygmin, zgmin, &
616  xgmax, ygmax, zgmax , G, CS, names, units)
617  use mpp_utilities_mod, only: mpp_array_global_min_max
618  integer, intent(in) :: ind_start !< The index of the tracer to start with
619  logical, dimension(:), intent(out) :: got_minmax !< Indicates whether the global min and
620  !! max are found for each tracer
621  real, dimension(:), intent(out) :: gmin !< Global minimum of each tracer, in kg
622  !! times concentration units.
623  real, dimension(:), intent(out) :: gmax !< Global maximum of each tracer, in kg
624  !! times concentration units.
625  real, dimension(:), intent(out) :: xgmin !< The x-position of the global minimum
626  real, dimension(:), intent(out) :: ygmin !< The y-position of the global minimum
627  real, dimension(:), intent(out) :: zgmin !< The z-position of the global minimum
628  real, dimension(:), intent(out) :: xgmax !< The x-position of the global maximum
629  real, dimension(:), intent(out) :: ygmax !< The y-position of the global maximum
630  real, dimension(:), intent(out) :: zgmax !< The z-position of the global maximum
631  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
632  type(MOM_generic_tracer_CS), pointer :: CS !< Pointer to the control structure for this module.
633  character(len=*), dimension(:), intent(out) :: names !< The names of the stocks calculated.
634  character(len=*), dimension(:), intent(out) :: units !< The units of the stocks calculated.
635  integer :: MOM_generic_tracer_min_max !< Return value, the
636  !! number of tracers done here.
637 
638 ! Local variables
639  type(g_tracer_type), pointer :: g_tracer, g_tracer_next
640  real, dimension(:,:,:,:), pointer :: tr_field
641  real, dimension(:,:,:), pointer :: tr_ptr
642  character(len=fm_string_len), parameter :: sub_name = 'MOM_generic_tracer_min_max'
643 
644  real, dimension(:,:,:),pointer :: grid_tmask
645  integer :: isc,iec,jsc,jec,isd,ied,jsd,jed,nk,ntau
646 
647  integer :: i, j, k, is, ie, js, je, nz, m
648  real, allocatable, dimension(:) :: geo_z
649 
650  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
651 
652  mom_generic_tracer_min_max = 0
653  if (.not.associated(cs)) return
654 
655  if (.NOT. associated(cs%g_tracer_list)) return ! No stocks.
656 
657 
658  call g_tracer_get_common(isc,iec,jsc,jec,isd,ied,jsd,jed,nk,ntau,grid_tmask=grid_tmask)
659 
660  ! Because the use of a simple z-coordinate can not be assumed, simply
661  ! use the layer index as the vertical label.
662  allocate(geo_z(nk))
663  do k=1,nk ; geo_z(k) = real(k) ; enddo
664 
665  m=ind_start ; g_tracer=>cs%g_tracer_list
666  do
667  call g_tracer_get_alias(g_tracer,names(m))
668  call g_tracer_get_values(g_tracer,names(m),'units',units(m))
669  units(m) = trim(units(m))//" kg"
670  call g_tracer_get_pointer(g_tracer,names(m),'field',tr_field)
671 
672  gmin(m) = -1.0
673  gmax(m) = -1.0
674 
675  tr_ptr => tr_field(:,:,:,1)
676 
677  call mpp_array_global_min_max(tr_ptr, grid_tmask,isd,jsd,isc,iec,jsc,jec,nk , gmin(m), gmax(m), &
678  g%geoLonT,g%geoLatT,geo_z,xgmin(m), ygmin(m), zgmin(m), &
679  xgmax(m), ygmax(m), zgmax(m))
680 
681  got_minmax(m) = .true.
682 
683  !traverse the linked list till hit NULL
684  call g_tracer_get_next(g_tracer, g_tracer_next)
685  if (.NOT. associated(g_tracer_next)) exit
686  g_tracer=>g_tracer_next
687  m = m+1
688  enddo
689 
690  mom_generic_tracer_min_max = m
691 
692  end function mom_generic_tracer_min_max
693 
694 
695  !> This subroutine calculates the surface state and sets coupler values for
696  !! those generic tracers that have flux exchange with atmosphere.
697  !!
698  !! This subroutine sets up the fields that the coupler needs to calculate the
699  !! CFC fluxes between the ocean and atmosphere.
700  subroutine mom_generic_tracer_surface_state(state, h, G, CS)
701  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
702  type(surface), intent(inout) :: state !< A structure containing fields that
703  !! describe the surface state of the ocean.
704  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
705  type(MOM_generic_tracer_CS), pointer :: CS !< Pointer to the control structure for this module.
706 
707 ! Local variables
708  real :: sosga
709 
710  character(len=fm_string_len), parameter :: sub_name = 'MOM_generic_tracer_surface_state'
711  real, dimension(G%isd:G%ied,G%jsd:G%jed,1:G%ke,1) :: rho0
712  real, dimension(G%isd:G%ied,G%jsd:G%jed,1:G%ke) :: dzt
713  type(g_tracer_type), pointer :: g_tracer
714 
715  !Set coupler values
716  !nnz: fake rho0
717  rho0=1.0
718 
719  dzt(:,:,:) = cs%H_to_m * h(:,:,:)
720 
721  sosga = global_area_mean(state%SSS, g)
722 
723  call generic_tracer_coupler_set(state%tr_fields,&
724  st=state%SST,&
725  ss=state%SSS,&
726  rho=rho0,& !nnz: required for MOM5 and previous versions.
727  ilb=g%isd, jlb=g%jsd,&
728  dzt=dzt,& !This is needed for the Mocsy method of carbonate system vars
729  tau=1,sosga=sosga,model_time=get_diag_time_end(cs%diag))
730 
731  !Output diagnostics via diag_manager for all tracers in this module
732 ! if (.NOT. associated(CS%g_tracer_list)) call mpp_error(FATAL, trim(sub_name)//&
733 ! "No tracer in the list.")
734 ! call g_tracer_send_diag(CS%g_tracer_list, get_diag_time_end(CS%diag), tau=1)
735  !Niki: The problem with calling diagnostic outputs here is that this subroutine is called every dt_cpld
736  ! hence if dt_therm > dt_cpld we get output (and contribution to the mean) at times that tracers
737  ! had not been updated.
738  ! Moving this to the end of column physics subrotuine fixes this issue.
739 
740  end subroutine mom_generic_tracer_surface_state
741 
742 !ALL PE subroutine on Ocean! Due to otpm design the fluxes should be initialized like this on ALL PE's!
743  subroutine mom_generic_flux_init(verbosity)
744  integer, optional, intent(in) :: verbosity !< A 0-9 integer indicating a level of verbosity.
745 
746  integer :: ind
747  character(len=fm_string_len) :: g_tracer_name,longname, package,units,old_package,file_in,file_out
748  real :: const_init_value
749  character(len=fm_string_len), parameter :: sub_name = 'MOM_generic_flux_init'
750  type(g_tracer_type), pointer :: g_tracer_list,g_tracer,g_tracer_next
751 
752  if (.not. g_registered) then
753  call generic_tracer_register
754  g_registered = .true.
755  endif
756 
757  call generic_tracer_get_list(g_tracer_list)
758  if (.NOT. associated(g_tracer_list)) then
759  call mpp_error(warning, trim(sub_name)// ": No generic tracer in the list.")
760  return
761  endif
762 
763  g_tracer=>g_tracer_list
764  do
765 
766  call g_tracer_flux_init(g_tracer) !, verbosity=verbosity) !### Add this after ocean shared is updated.
767 
768  !traverse the linked list till hit NULL
769  call g_tracer_get_next(g_tracer, g_tracer_next)
770  if (.NOT. associated(g_tracer_next)) exit
771  g_tracer=>g_tracer_next
772 
773  enddo
774 
775  end subroutine mom_generic_flux_init
776 
777  subroutine mom_generic_tracer_fluxes_accumulate(flux_tmp, weight)
778  type(forcing), intent(in) :: flux_tmp !< A structure containing pointers to
779  !! thermodynamic and tracer forcing fields.
780  real, intent(in) :: weight !< A weight for accumulating this flux
781 
782  call generic_tracer_coupler_accumulate(flux_tmp%tr_fluxes, weight)
783 
784  end subroutine mom_generic_tracer_fluxes_accumulate
785 
786  !> Copy the requested tracer into an array.
787  subroutine mom_generic_tracer_get(name,member,array, CS)
788  character(len=*), intent(in) :: name !< Name of requested tracer.
789  character(len=*), intent(in) :: member !< The tracer element to return.
790  real, dimension(:,:,:), intent(out) :: array !< Array filled by this routine.
791  type(MOM_generic_tracer_CS), pointer :: CS !< Pointer to the control structure for this module.
792 
793  real, dimension(:,:,:), pointer :: array_ptr
794  character(len=fm_string_len), parameter :: sub_name = 'MOM_generic_tracer_get'
795 
796  call g_tracer_get_pointer(cs%g_tracer_list,name,member,array_ptr)
797  array(:,:,:) = array_ptr(:,:,:)
798 
799  end subroutine mom_generic_tracer_get
800 
801  !> This subroutine deallocates the memory owned by this module.
802  subroutine end_mom_generic_tracer(CS)
803  type(MOM_generic_tracer_CS), pointer :: CS !< Pointer to the control structure for this module.
804 
805  call generic_tracer_end
806 
807  if (associated(cs)) then
808  deallocate(cs)
809  endif
810  end subroutine end_mom_generic_tracer
811 
812 #endif /* _USE_GENERIC_TRACER */
813 !----------------------------------------------------------------
814 ! <CONTACT EMAIL="Niki.Zadeh@noaa.gov"> Niki Zadeh
815 ! </CONTACT>
816 !
817 ! <REVIEWER EMAIL="William.Cooke@noaa.gov"> William Cooke
818 ! </REVIEWER>
819 !
820 ! <OVERVIEW>
821 ! This module drives the generic version of tracers TOPAZ and CFC
822 ! </OVERVIEW>
823 !----------------------------------------------------------------
824 
825 end module mom_generic_tracer
mom_time_manager
Wraps the FMS time manager functions.
Definition: MOM_time_manager.F90:2
mom_variables::surface
Pointers to various fields which may be used describe the surface state of MOM, and which will be ret...
Definition: MOM_variables.F90:38
mom_spatial_means
Functions and routines to take area, volume, mass-weighted, layerwise, zonal or meridional means.
Definition: MOM_spatial_means.F90:2
mom_verticalgrid
Provides a transparent vertical ocean grid type and supporting routines.
Definition: MOM_verticalGrid.F90:2
mom_file_parser::log_version
An overloaded interface to log version information about modules.
Definition: MOM_file_parser.F90:109
mom_diag_mediator
The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional d...
Definition: MOM_diag_mediator.F90:3
mom_variables::thermo_var_ptrs
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Definition: MOM_variables.F90:82
mom_ale_sponge::ale_sponge_cs
ALE sponge control structure.
Definition: MOM_ALE_sponge.F90:85
mom_tracer_registry
This module contains the tracer_registry_type and the subroutines that handle registration of tracers...
Definition: MOM_tracer_registry.F90:5
mom_file_parser::param_file_type
A structure that can be parsed to read and document run-time parameters.
Definition: MOM_file_parser.F90:54
mom_file_parser::get_param
An overloaded interface to read and log the values of various types of parameters.
Definition: MOM_file_parser.F90:102
mom_hor_index
Defines the horizontal index type (hor_index_type) used for providing index ranges.
Definition: MOM_hor_index.F90:2
mom_tracer_initialization_from_z
Initializes hydrography from z-coordinate climatology files.
Definition: MOM_tracer_initialization_from_Z.F90:2
mom_ale_sponge
This module contains the routines used to apply sponge layers when using the ALE mode.
Definition: MOM_ALE_sponge.F90:11
mom_io
This module contains I/O framework code.
Definition: MOM_io.F90:2
mom_restart::mom_restart_cs
A restart registry and the control structure for restarts.
Definition: MOM_restart.F90:72
mom_tracer_z_init
Used to initialize tracers from a depth- (or z*-) space file.
Definition: MOM_tracer_Z_init.F90:2
mom_unit_scaling::unit_scale_type
Describes various unit conversion factors.
Definition: MOM_unit_scaling.F90:14
mom_tracer_diabatic
This module contains routines that implement physical fluxes of tracers (e.g. due to surface fluxes o...
Definition: MOM_tracer_diabatic.F90:4
mom_diag_mediator::post_data
Make a diagnostic available for averaging or output.
Definition: MOM_diag_mediator.F90:70
mom_forcing_type
This module implements boundary forcing for MOM6.
Definition: MOM_forcing_type.F90:2
mom_ale_sponge::set_up_ale_sponge_field
Store the reference profile at h points for a variable.
Definition: MOM_ALE_sponge.F90:34
mom_verticalgrid::verticalgrid_type
Describes the vertical ocean grid, including unit conversion factors.
Definition: MOM_verticalGrid.F90:24
mom_restart
The MOM6 facility for reading and writing restart files, and querying what has been read.
Definition: MOM_restart.F90:2
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.F90:2
mom_io::mom_read_data
Read a data field from a file.
Definition: MOM_io.F90:74
mom_open_boundary
Controls where open boundary conditions are applied.
Definition: MOM_open_boundary.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_sponge
Implements sponge regions in isopycnal mode.
Definition: MOM_sponge.F90:2
mom_tracer_registry::tracer_registry_type
Type to carry basic tracer information.
Definition: MOM_tracer_registry.F90:122
mom_hor_index::hor_index_type
Container for horizontal index ranges for data, computational and global domains.
Definition: MOM_hor_index.F90:15
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
mom_open_boundary::ocean_obc_type
Open-boundary data.
Definition: MOM_open_boundary.F90:186
mom_sponge::sponge_cs
This control structure holds memory and parameters for the MOM_sponge module.
Definition: MOM_sponge.F90:40
mom_restart::register_restart_field
Register fields for restarts.
Definition: MOM_restart.F90:107
mom_unit_scaling
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Definition: MOM_unit_scaling.F90:2
mom_forcing_type::forcing
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Definition: MOM_forcing_type.F90:49
mom_io::file_exists
Indicate whether a file exists, perhaps with domain decomposition.
Definition: MOM_io.F90:68
mom_file_parser::log_param
An overloaded interface to log the values of various types of parameters.
Definition: MOM_file_parser.F90:96
mom_restart::query_initialized
Indicate whether a field has been read from a restart file.
Definition: MOM_restart.F90:116
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_grid::ocean_grid_type
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:25
mom_diag_mediator::diag_ctrl
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Definition: MOM_diag_mediator.F90:239