FMS  2024.03
Flexible Modeling System
tracer_manager.F90
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 !> @defgroup tracer_manager_mod tracer_manager_mod
20 !> @ingroup tracer_manager
21 !> @brief Code to manage the simple addition of tracers to the FMS code.
22 !! This code keeps track of the numbers and names of tracers included
23 !! in a tracer table.
24 !!
25 !> @author William Cooke
26 !!
27 !> This code is a grouping of calls which will allow the simple
28 !! introduction of tracers into the FMS framework. It is designed to
29 !! allow users of a variety of component models interact easily with
30 !! the dynamical core of the model.
31 !!
32 !! In calling the tracer manager routines the user must provide a
33 !! parameter identifying the model that the user is working with. This
34 !! parameter is defined within field_manager as MODEL_X
35 !! where X is one of [ATMOS, OCEAN, LAND, ICE].
36 !!
37 !! In many of these calls the argument list includes model and tracer_index. These
38 !! are the parameter corresponding to the component model and the tracer_index N is
39 !! the Nth tracer within the component model. Therefore a call with MODEL_ATMOS and 5
40 !! is different from a call with MODEL_OCEAN and 5.
41 
42 module tracer_manager_mod
43 
44 !----------------------------------------------------------------------
45 
46 use mpp_mod, only : mpp_error, &
47  mpp_pe, &
48  mpp_root_pe, &
49  fatal, &
50  warning, &
51  note, &
52  stdlog
53 use fms_mod, only : lowercase, &
55 
56 use field_manager_mod, only : field_manager_init, &
59  model_atmos, &
60  model_land, &
61  model_ocean, &
62  model_ice, &
63  model_coupler, &
64  num_models, &
65  method_type, &
66  default_method, &
67  parse, &
68  fm_copy_list, &
72  fm_new_value, &
73  fm_exists, &
75 use platform_mod, only : r4_kind, &
76  r8_kind
77 
78 implicit none
79 private
80 
81 !-----------------------------------------------------------------------
82 
83 public tracer_manager_init, &
90  query_method, &
95  adjust_mass, &
96  adjust_positive_def, &
97  no_tracer, &
98  max_tracer_fields, &
100 
101 !> @brief Function which returns the number assigned to the tracer name.
102 !!
103 !> This is a function which returns the index, as implied within the component model.
104 !! There are two overloaded interfaces: one of type integer, one logical.
105 !!
106 !! @param model A integer parameter to identify which model is being used
107 !! @param name The name of the tracer (as assigned in the field table).
108 !! @param indices An array indices. When present, the returned index will limit the search for the
109 !! tracer to thos tracers whose indices are among those in array 'indices'. This would be useful
110 !! when it is desired to limit the search to a subset of the tracers. Such a subset might be the
111 !! diagnostic or prognostic tracers.(note that @ref get_tracer_indices returns these subsets)
112 !! @param verbose Optional flag for debugging
113 !! @param[out] index Holds the returned index if given
114 !! @returns The integer function returns the index of the tracer named "name". If no tracer by that
115 !! name exists then the returned value is NO_TRACER. The logical function returns false if no
116 !! tracer by the given name exists and true otherwise, and stores the returned value in index.
117 !!
118 !! <br>Example usage:
119 !! @code{.F90}
120 !! integer:
121 !! index = get_tracer_index(model, name, indices, verbose)
122 !! logical:
123 !! if ( get_tracer_index(model, name, index, indices, verbose) ) then
124 !! @endcode
125 !> @ingroup tracer_manager_mod
128 end interface
129 
131  module procedure set_tracer_profile_r4
132  module procedure set_tracer_profile_r8
133 end interface set_tracer_profile
134 
135 !> Private type to hold metadata for a tracer
136 !> @ingroup tracer_manager_mod
137 type, private :: tracer_type
138  character(len=32) :: tracer_name, tracer_units
139  character(len=128) :: tracer_longname
140  integer :: num_methods, model, instances
141  logical :: is_prognostic, instances_set
142  logical :: needs_init
143 ! Does tracer need mass or positive definite adjustment?
144 ! (true by default for both)
145  logical :: needs_mass_adjust
146  logical :: needs_positive_adjust
147 end type tracer_type
148 
149 !> Private type to holds string data for a tracer
150 !> @ingroup tracer_manager_mod
151 type, private :: tracer_name_type
152  character(len=32) :: model_name, tracer_name, tracer_units
153  character(len=128) :: tracer_longname
154 end type tracer_name_type
155 
156 !> Private type to represent named instances
157 !> @ingroup tracer_manager_mod
158 type, private :: inst_type
159  character(len=128) :: name
160  integer :: instances
161 end type inst_type
162 
163 !> @addtogroup tracer_manager_mod
164 !> @{
165 
166 integer :: num_tracer_fields = 0
167 integer, parameter :: MAX_TRACER_FIELDS = 250
168 integer, parameter :: MAX_TRACER_METHOD = 20
169 integer, parameter :: NO_TRACER = 1-huge(1)
170 integer, parameter :: NOTRACER = -huge(1)
171 
172 type(tracer_type), save :: tracers(MAX_TRACER_FIELDS)
173 type(inst_type) , save :: instantiations(MAX_TRACER_FIELDS)
174 
175 integer :: total_tracers(NUM_MODELS), prog_tracers(NUM_MODELS), diag_tracers(NUM_MODELS)
176 logical :: model_registered(NUM_MODELS) = .false.
177 
178 ! Include variable "version" to be written to log file.
179 #include<file_version.h>
180 
181 logical :: module_is_initialized = .false.
182 
183 logical :: verbose_local
184 integer :: TRACER_ARRAY(NUM_MODELS,MAX_TRACER_FIELDS)
185 
186 contains
187 
188 !#######################################################################
189 
190 !> @brief Not necessary to call, only needed for backward compatability.
191 !!
192 !> Writes version to logfile and sets init flag for this module
194 integer :: model, num_tracers, num_prog, num_diag
195 
196  if(module_is_initialized) return
197  module_is_initialized = .true.
198 
199  call write_version_number ("TRACER_MANAGER_MOD", version)
200  call field_manager_init()
201  tracer_array = notracer
202  do model=1,num_models
203  call get_tracer_meta_data(model, num_tracers, num_prog, num_diag)
204  enddo
205 
206 end subroutine tracer_manager_init
207 
208 !> @brief Read in tracer table and store tracer information associated with "model" in "tracers"
209 !! array.
210 subroutine get_tracer_meta_data(model, num_tracers,num_prog,num_diag)
211 
212 integer, intent(in) :: model !< model being used
213 integer, intent(out) :: num_tracers, num_prog, num_diag
214 character(len=256) :: warnmesg
215 
216 character(len=32) :: name_type, type, name
217 integer :: n, m, mod, num_tracer_methods, nfields, swop
218 integer :: j, log_unit, num_methods
219 logical :: flag_type
220 type(method_type), dimension(MAX_TRACER_METHOD) :: methods
221 integer :: instances, siz_inst,i
222 character(len = 32) :: digit,suffnam
223 
224 character(len=128) :: list_name , control
225 integer :: index_list_name
226 logical :: fm_success
227 
228 ! <ERROR MSG="invalid model type" STATUS="FATAL">
229 ! The index for the model type is invalid.
230 ! </ERROR>
231 if (model .ne. model_atmos .and. model .ne. model_land .and. &
232  model .ne. model_ocean .and. model .ne. model_ice .and. &
233  model .ne. model_coupler) call mpp_error(fatal,'tracer_manager_init : invalid model type')
234 
235 ! One should only call get_tracer_meta_data once for each model type
236 ! Therefore need to set up an array to stop the subroutine being
237 ! unnecssarily called multiple times.
238 
239 if ( model_registered(model) ) then
240 ! This routine has already been called for the component model.
241 ! Fill in the values from the previous registration and return.
242  num_tracers = total_tracers(model)
243  num_prog = prog_tracers(model)
244  num_diag = diag_tracers(model)
245  return
246 endif
247 
248 ! Initialize the number of tracers to zero.
249 num_tracers = 0; num_prog = 0; num_diag = 0
250 
251 call field_manager_init(nfields=nfields)
252 
253 ! <ERROR MSG="No tracers are available to be registered." STATUS="NOTE">
254 ! No tracers are available to be registered. This means that the field
255 ! table does not exist or is empty.
256 ! </ERROR>
257 if (nfields == 0 ) then
258 if (mpp_pe() == mpp_root_pe()) &
259  call mpp_error(note,'tracer_manager_init : No tracers are available to be registered.')
260  return
261 endif
262 
263 ! search through field entries for model tracers
264 total_tracers(model) = 0
265 
266 do n=1,nfields
267  call get_field_info(n,type,name,mod,num_methods)
268 
269  if (mod == model .and. type == 'tracer') then
270  num_tracer_fields = num_tracer_fields + 1
271  total_tracers(model) = total_tracers(model) + 1
272 ! <ERROR MSG="MAX_TRACER_FIELDS exceeded" STATUS="FATAL">
273 ! The maximum number of tracer fields has been exceeded.
274 ! </ERROR>
275  if(num_tracer_fields > max_tracer_fields) call mpp_error(fatal, &
276  & 'tracer_manager_init: MAX_TRACER_FIELDS exceeded')
277  tracer_array(model,total_tracers(model)) = num_tracer_fields
278  tracers(num_tracer_fields)%model = model
279  tracers(num_tracer_fields)%tracer_name = name
280  tracers(num_tracer_fields)%tracer_units = 'none'
281  tracers(num_tracer_fields)%tracer_longname = tracers(num_tracer_fields)%tracer_name
282  tracers(num_tracer_fields)%instances_set = .false.
283 ! By default, tracers need mass and positive definite adjustments.
284 ! We hardwire exceptions for compatibility with existing field_tables
285 ! This should ideally be cleaned up.
286  tracers(num_tracer_fields)%needs_mass_adjust = .true.
287  tracers(num_tracer_fields)%needs_positive_adjust = .true.
288  if (name == 'cld_amt') then
289  tracers(num_tracer_fields)%needs_mass_adjust = .false.
290  endif
291  if (name == 'cld_amt' .or. name == 'liq_wat' .or. name == 'ice_wat') then
292  tracers(num_tracer_fields)%needs_positive_adjust = .false.
293  endif
294 
295  num_tracer_methods = 0
296  methods = default_method ! initialize methods array
297  call get_field_methods(n,methods)
298  do j=1,num_methods
299  select case (methods(j)%method_type)
300  case ('units')
301  tracers(num_tracer_fields)%tracer_units = methods(j)%method_name
302  case ('longname')
303  tracers(num_tracer_fields)%tracer_longname = methods(j)%method_name
304  case ('instances')
305 ! tracers(num_tracer_fields)%instances = methods(j)%method_name
306  siz_inst = parse(methods(j)%method_name,"",instances)
307  tracers(num_tracer_fields)%instances = instances
308  tracers(num_tracer_fields)%instances_set = .true.
309  case ('adjust_mass')
310  if (methods(j)%method_name == "false") then
311  tracers(num_tracer_fields)%needs_mass_adjust = .false.
312  endif
313  case ('adjust_positive_def')
314  if (methods(j)%method_name == "false") then
315  tracers(num_tracer_fields)%needs_positive_adjust = .false.
316  endif
317  case default
318  num_tracer_methods = num_tracer_methods+1
319 ! tracers(num_tracer_fields)%methods(num_tracer_methods) = methods(j)
320  end select
321  enddo
322  tracers(num_tracer_fields)%num_methods = num_tracer_methods
323  tracers(num_tracer_fields)%needs_init = .false.
324  flag_type = query_method('tracer_type',model,total_tracers(model),name_type)
325  if (flag_type .and. name_type == 'diagnostic') then
326  tracers(num_tracer_fields)%is_prognostic = .false.
327  else
328  tracers(num_tracer_fields)%is_prognostic = .true.
329  endif
330  if (tracers(num_tracer_fields)%is_prognostic) then
331  num_prog = num_prog+1
332  else
333  num_diag = num_diag+1
334  endif
335  endif
336 enddo
337 
338 ! Now cycle through the tracers and add additional instances of the tracers.
339 
340 do n = 1, num_tracer_fields !{
341 ! call get_field_info(n,type,name,mod,num_methods)
342 
343  if ( model == tracers(n)%model .and. tracers(n)%instances_set ) then !{ We have multiple instances of this tracer
344 
345  if ( num_tracer_fields + tracers(n)%instances > max_tracer_fields ) then
346  write(warnmesg, '("tracer_manager_init: Number of tracers will exceed MAX_TRACER_FIELDS with &
347  &multiple (",I3," instances) setup of tracer ",A)') tracers(n)%instances,tracers(n)%tracer_name
348  call mpp_error(fatal, warnmesg)
349  endif
350 
351  do i = 2, tracers(n)%instances !{
352  num_tracer_fields = num_tracer_fields + 1
353  total_tracers(model) = total_tracers(model) + 1
354  tracer_array(model,total_tracers(model)) = num_tracer_fields
355  ! Copy the original tracer type to the multiple instances.
356  tracers(num_tracer_fields) = tracers(n)
357  if ( query_method('instances', model,model_tracer_number(model,n),name, control)) then !{
358 
359  if (i .lt. 10) then !{
360  write (suffnam,'(''suffix'',i1)') i
361  siz_inst = parse(control, suffnam,digit)
362  if (siz_inst == 0 ) then
363  write (digit,'(''_'',i1)') i
364  else
365  digit = "_"//trim(digit)
366  endif
367  elseif (i .lt. 100) then !}{
368  write (suffnam,'(''suffix'',i2)') i
369  siz_inst = parse(control, suffnam,digit)
370  if (siz_inst == 0 ) then
371  write (digit,'(''_'',i2)') i
372  else
373  digit = "_"//trim(digit)
374  endif
375  else !}{
376  call mpp_error(fatal, 'tracer_manager_init: MULTIPLE_TRACER_SET_UP exceeds 100 for '// &
377  & tracers(n)%tracer_name )
378  endif !}
379 
380  select case(model)
381  case (model_coupler)
382  list_name = "/coupler_mod/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
383  case (model_atmos)
384  list_name = "/atmos_mod/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
385  case (model_ocean)
386  list_name = "/ocean_mod/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
387  case (model_ice )
388  list_name = "/ice_mod/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
389  case (model_land )
390  list_name = "/land_mod/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
391  case default
392  list_name = "/default/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
393  end select
394 
395  if (mpp_pe() == mpp_root_pe() ) write (*,*) "Creating list name = ",trim(list_name)//trim(digit)
396 
397  index_list_name = fm_copy_list(trim(list_name),digit, create = .true.)
398  tracers(num_tracer_fields)%tracer_name = trim(tracers(num_tracer_fields)%tracer_name)//trim(digit)
399  endif !}
400 
401  if (tracers(num_tracer_fields)%is_prognostic) then !{
402  num_prog = num_prog+1
403  else !}{
404  num_diag = num_diag+1
405  endif !}
406  enddo !}
407  ! Multiple instances of tracers were found so need to rename the original tracer.
408  digit = "_1"
409  siz_inst = parse(control, "suffix1",digit)
410  if (siz_inst > 0 ) then !{
411  digit = "_"//trim(digit)
412  endif !}
413  fm_success = fm_modify_name(trim(list_name), trim(tracers(n)%tracer_name)//trim(digit))
414  tracers(n)%tracer_name = trim(tracers(n)%tracer_name)//trim(digit)
415  endif !}
416 enddo !}
417 
418 ! Find any field entries with the instances keyword.
419 do n=1,nfields
420  call get_field_info(n,type,name,mod,num_methods)
421 
422  if ( mod == model .and. type == 'instances' ) then
423  call get_field_methods(n,methods)
424  do j=1,num_methods
425 
426  if (.not.get_tracer_index(mod,methods(j)%method_type,m)) then
427  call mpp_error(fatal,'tracer_manager_init: The instances keyword was found for undefined tracer '&
428  //trim(methods(j)%method_type))
429  else
430  if ( tracers(m)%instances_set ) &
431  call mpp_error(fatal,'tracer_manager_init: The instances keyword was found for '&
432  //trim(methods(j)%method_type)//' but has previously been defined in the tracer entry')
433  siz_inst = parse(methods(j)%method_name,"",instances)
434  tracers(m)%instances = instances
435  call mpp_error(note,'tracer_manager_init: '//trim(instantiations(j)%name)// &
436  ' will have '//trim(methods(j)%method_name)//' instances')
437  endif
438  if ( num_tracer_fields + instances > max_tracer_fields ) then
439  write(warnmesg, '("tracer_manager_init: Number of tracers will exceed MAX_TRACER_FIELDS with &
440  &multiple (",I3," instances) setup of tracer ",A)') tracers(m)%instances,tracers(m)%tracer_name
441  call mpp_error(fatal, warnmesg)
442  endif
443 ! We have found a valid tracer that has more than one instantiation.
444 ! We need to modify that tracer name to tracer_1 and add extra tracers for the extra instantiations.
445  if (instances .eq. 1) then
446  siz_inst = parse(methods(j)%method_control, 'suffix1',digit)
447  if (siz_inst == 0 ) then
448  digit = '_1'
449  else
450  digit = "_"//trim(digit)
451  endif
452  endif
453  do i = 2, instances
454  num_tracer_fields = num_tracer_fields + 1
455  total_tracers(model) = total_tracers(model) + 1
456  tracer_array(model,total_tracers(model)) = num_tracer_fields
457  tracers(num_tracer_fields) = tracers(m)
458 
459  if (i .lt. 10) then !{
460  write (suffnam,'(''suffix'',i1)') i
461  siz_inst = parse(methods(j)%method_control, suffnam,digit)
462  if (siz_inst == 0 ) then
463  write (digit,'(''_'',i1)') i
464  else
465  digit = "_"//trim(digit)
466  endif
467  elseif (i .lt. 100) then !}{
468  write (suffnam,'(''suffix'',i2)') i
469  siz_inst = parse(methods(j)%method_control, suffnam,digit)
470  if (siz_inst == 0 ) then
471  write (digit,'(''_'',i2)') i
472  else
473  digit = "_"//trim(digit)
474  endif
475  else !}{
476  call mpp_error(fatal, 'tracer_manager_init: MULTIPLE_TRACER_SET_UP exceeds 100 for '&
477  //tracers(num_tracer_fields)%tracer_name )
478  endif !}
479 
480  select case(model)
481  case (model_coupler)
482  list_name = "/coupler_mod/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
483  case (model_atmos)
484  list_name = "/atmos_mod/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
485  case (model_ocean)
486  list_name = "/ocean_mod/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
487  case (model_ice )
488  list_name = "/ice_mod/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
489  case (model_land )
490  list_name = "/land_mod/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
491  case default
492  list_name = "/default/tracer/"//trim(tracers(num_tracer_fields)%tracer_name)
493  end select
494 
495  if (mpp_pe() == mpp_root_pe() ) write (*,*) "Creating list name = ",trim(list_name)
496 
497  index_list_name = fm_copy_list(trim(list_name),digit, create = .true.)
498 
499  tracers(num_tracer_fields)%tracer_name = trim(tracers(num_tracer_fields)%tracer_name)//digit
500  if (tracers(num_tracer_fields)%is_prognostic) then
501  num_prog = num_prog+1
502  else
503  num_diag = num_diag+1
504  endif
505  enddo
506 !Now rename the original tracer to tracer_1 (or if suffix1 present to tracer_'value_of_suffix1')
507  siz_inst = parse(methods(j)%method_control, 'suffix1',digit)
508  if (siz_inst == 0 ) then
509  digit = '_1'
510  else
511  digit = "_"//trim(digit)
512  endif
513  fm_success = fm_modify_name(trim(list_name), trim(tracers(m)%tracer_name)//trim(digit))
514  tracers(m)%tracer_name = trim(tracers(m)%tracer_name)//trim(digit)
515  enddo
516  endif
517 enddo
518 
519 num_tracers = num_prog + num_diag
520 ! Make the number of tracers available publicly.
521 total_tracers(model) = num_tracers
522 prog_tracers(model) = num_prog
523 diag_tracers(model) = num_diag
524 model_registered(model) = .true.
525 
526 ! Now sort through the tracer fields and sort them so that the
527 ! prognostic tracers are first.
528 
529 do n=1, num_tracers
530  if (.not.check_if_prognostic(model,n) .and. n.le.num_prog) then
531  ! This is a diagnostic tracer so find a prognostic tracer to swop with
532  do m = n, num_tracers
533  if (check_if_prognostic(model,m) .and. .not.check_if_prognostic(model,n)) then
534  swop = tracer_array(model,n)
535  tracer_array(model,n) = tracer_array(model,m)
536  tracer_array(model,m) = swop
537  cycle
538  endif
539  enddo
540  endif
541 enddo
542 
543 do n=1, num_tracer_fields
544  call print_tracer_info(model,n)
545 enddo
546 
547 log_unit = stdlog()
548 if ( mpp_pe() == mpp_root_pe() ) then
549  write (log_unit,15) trim(model_names(model)),total_tracers(model)
550 endif
551 
552 15 format ('Number of tracers in field table for ',a,' model = ',i4)
553 
554 end subroutine get_tracer_meta_data
555 
556 function model_tracer_number(model,n)
557 integer, intent(in) :: model, n
558 integer model_tracer_number
559 
560 integer :: i
561 
562 model_tracer_number = no_tracer
563 
564 do i = 1, max_tracer_fields
565  if ( tracer_array(model,i) == n ) then
566  model_tracer_number = i
567  return
568  endif
569 enddo
570 
571 end function model_tracer_number
572 
573 !#######################################################################
574 
575 !> @brief Not necessary to call, only needed for backward compatability.
576 !!
577 !> Returns the total number of valid, prognostic and diagnostic tracers.
578 subroutine register_tracers(model, num_tracers, num_prog, num_diag, num_family)
579 integer, intent(in) :: model !< A parameter to identify which model is being used.
580 integer, intent(out) :: num_tracers !< The total number of valid tracers within the component model.
581 integer, intent(out) :: num_prog !< The number of prognostic tracers within the component model.
582 integer, intent(out) :: num_diag !< The number of diagnostic tracers within the component model.
583 integer, intent(out), optional :: num_family
584 
585 if(.not.module_is_initialized) call tracer_manager_init
586 
587 call get_number_tracers(model, num_tracers, num_prog, num_diag, num_family)
588 
589 end subroutine register_tracers
590 
591 !#######################################################################
592 
593 !> @brief A routine to return the number of tracers included in a component model.
594 !!
595 !> This routine returns the total number of valid tracers,
596 !! the number of prognostic and diagnostic tracers
597 subroutine get_number_tracers(model, num_tracers, num_prog, num_diag, num_family)
598 
599 integer, intent(in) :: model !< A parameter to identify which model is being used
600 integer, intent(out), optional :: num_tracers !< The total number of valid tracers within
601  !! the component model
602 integer, intent(out), optional :: num_prog !< The number of prognostic tracers within the
603  !! component model.
604 integer, intent(out), optional :: num_diag !< The number of diagnostic tracers within the
605  !! component model
606 integer, intent(out), optional :: num_family
607 
608 if(.not.module_is_initialized) call tracer_manager_init
609 
610 ! <ERROR MSG="Model number is invalid." STATUS="FATAL">
611 ! The index of the component model is invalid.
612 ! </ERROR>
613 if (model .ne. model_atmos .and. model .ne. model_land .and. &
614  model .ne. model_ocean .and. model .ne. model_ice .and. &
615  model .ne. model_coupler) &
616  call mpp_error(fatal,"get_number_tracers : Model number is invalid.")
617 
618 if (present(num_tracers)) num_tracers = total_tracers(model)
619 if (present(num_prog)) num_prog = prog_tracers(model)
620 if (present(num_diag)) num_diag = diag_tracers(model)
621 if (present(num_family)) num_family = 0 ! Needed only for backward compatability with lima
622 
623 end subroutine get_number_tracers
624 
625 !> @brief Routine to return the component model tracer indices as defined within
626 !! the tracer manager.
627 !!
628 !> If several models are being used or redundant tracers have been written to
629 !! the tracer_table, then the indices in the component model and the tracer
630 !! manager may not have a one to one correspondence. Therefore the component
631 !! model needs to know what index to pass to calls to tracer_manager routines in
632 !! order that the correct tracer information be accessed.
633 !> @param model A parameter to identify which model is being used.
634 !> @param ind An array containing the tracer manager defined indices for
635 !! all the tracers within the component model.
636 !> @param prog_ind An array containing the tracer manager defined indices for
637 !! the prognostic tracers within the component model.
638 !> @param diag_ind An array containing the tracer manager defined indices for
639 !! the diagnostic tracers within the component model.
640 subroutine get_tracer_indices(model, ind, prog_ind, diag_ind, fam_ind)
641 
642 integer, intent(in) :: model
643 integer, intent(out), dimension(:), optional :: ind, prog_ind, diag_ind, fam_ind
644 
645 integer :: i, j, np, nd, n
646 
647 if(.not.module_is_initialized) call tracer_manager_init
648 
649 nd=0;np=0;n=0
650 
651 ! Initialize arrays with dummy values
652 if (PRESENT(ind)) ind = no_tracer
653 if (PRESENT(prog_ind)) prog_ind = no_tracer
654 if (PRESENT(diag_ind)) diag_ind = no_tracer
655 if (PRESENT(fam_ind)) fam_ind = no_tracer
656 
657 do i = 1, max_tracer_fields
658 j = tracer_array(model,i)
659  if ( j /= notracer) then
660  if ( model == tracers(j)%model) then
661  if (PRESENT(ind)) then
662  n=n+1
663 ! <ERROR MSG="index array size too small in get_tracer_indices" STATUS="FATAL">
664 ! The global index array is too small and cannot contain all the tracer numbers.
665 ! </ERROR>
666  if (n > size(ind(:))) call mpp_error(fatal, &
667  & 'get_tracer_indices : index array size too small in get_tracer_indices')
668  ind(n) = i
669  endif
670 
671  if (tracers(j)%is_prognostic.and.PRESENT(prog_ind)) then
672  np=np+1
673 ! <ERROR MSG="prognostic array size too small in get_tracer_indices" STATUS="FATAL">
674 ! The prognostic index array is too small and cannot contain all the tracer numbers.
675 ! </ERROR>
676  if ( np > size( prog_ind(:)))call mpp_error(fatal,&
677  'get_tracer_indices : prognostic array size too small in get_tracer_indices')
678  prog_ind(np) = i
679  else if (.not.tracers(j)%is_prognostic .and. PRESENT(diag_ind)) then
680  nd = nd+1
681 ! <ERROR MSG="diagnostic array size too small in get_tracer_indices" STATUS="FATAL">
682 ! The diagnostic index array is too small and cannot contain all the tracer numbers.
683 ! </ERROR>
684  if (nd > size(diag_ind(:))) call mpp_error(fatal,&
685  'get_tracer_indices : diagnostic array size too small in get_tracer_indices')
686  diag_ind(nd) = i
687  endif
688  endif
689  endif
690 enddo
691 
692 return
693 end subroutine get_tracer_indices
694 
695 !<FUNCTION NAME= "get_tracer_index">
696 ! <OVERVIEW>
697 ! Function which returns the number assigned to the tracer name.
698 ! </OVERVIEW>
699 ! <DESCRIPTION>
700 ! This is a function which returns the index, as implied within the component model.
701 ! There are two overloaded interfaces: one of type integer, one logical.
702 ! </DESCRIPTION>
703 ! <TEMPLATE>
704 ! integer: index = get_tracer_index(model, name, indices, verbose)
705 ! logical: if ( get_tracer_index(model, name, index, indices, verbose) ) then
706 ! </TEMPLATE>
707 ! <IN NAME="model" TYPE="integer">
708 ! A parameter to identify which model is being used.
709 ! </IN>
710 ! <IN NAME="name" TYPE="character">
711 ! The name of the tracer (as assigned in the field table).
712 ! </IN>
713 ! <IN NAME="indices" TYPE="integer, optional" DIM="(:)">
714 ! An array indices.
715 ! When present, the returned index will limit the search for the tracer
716 ! to those tracers whos indices are amoung those in array "indices".
717 ! This would be useful when it is desired to limit the search to a subset
718 ! of the tracers. Such a subset might be the diagnostic or prognostic tracers.
719 ! (Note that subroutine get_tracer_indices returns these subsets)
720 ! </IN>
721 ! <IN NAME="verbose" TYPE="logical, optional">
722 ! A flag to allow the message saying that a tracer with this name has not
723 ! been found. This should only be used for debugging purposes.
724 ! </IN>
725 ! <OUT NAME="get_tracer_index" TYPE="integer">
726 ! integer function:
727 ! The index of the tracer named "name".
728 ! If no tracer by that name exists then the returned value is NO_TRACER.
729 ! logical function:
730 ! If no tracer by that name exists then the returned value is .false.,
731 ! otherwise the returned value is .true.
732 ! </OUT>
733 
734 !> @brief Function which returns the number assigned to the tracer name.
735 !!
736 !> See @ref get_tracer_index Interface for more information.
737 !! @returns index of given tracer name if present, otherwise returns NO_TRACER
738 function get_tracer_index_integer(model, name, indices, verbose)
739 
740 integer, intent(in) :: model !< Parameter to identify which model is used
741 character(len=*), intent(in) :: name !< name of the tracer
742 integer, intent(in), dimension(:), optional :: indices !< An array of indices, limits search to tracers
743  !! whose indices are within the array.
744 logical, intent(in), optional :: verbose !< debug flag
745 integer :: get_tracer_index_integer
746 
747 integer :: i
748 
749 if(.not.module_is_initialized) call tracer_manager_init
750 
751 get_tracer_index_integer = no_tracer
752 
753 if (PRESENT(indices)) then
754  do i = 1, size(indices(:))
755  if (model == tracers(indices(i))%model .and. lowercase(trim(name)) == trim(tracers(indices(i))%tracer_name))then
757  exit
758  endif
759  enddo
760 else
761  do i=1, num_tracer_fields
762  if(tracer_array(model,i) == notracer) cycle
763  if (lowercase(trim(name)) == trim(tracers(tracer_array(model,i))%tracer_name)) then
764  get_tracer_index_integer = i!TRACER_ARRAY(model,i)
765  exit
766  endif
767  enddo
768 end if
769 
770 verbose_local=.false.
771 if (present(verbose)) verbose_local=verbose
772 
773 if (verbose_local) then
774 ! <ERROR MSG="tracer with this name not found: X" STATUS="NOTE">
775  if (get_tracer_index_integer == no_tracer ) then
776  call mpp_error(note,'get_tracer_index : tracer with this name not found: '//trim(name))
777  endif
778 ! </ERROR>
779 endif
780 
781 return
782 
783 end function get_tracer_index_integer
784 
785 !#######################################################################
786 !> @brief Checks if tracer is present, and returns it's position in index
787 function get_tracer_index_logical(model, name, index, indices, verbose)
788 
789 integer, intent(in) :: model !< Parameter for which model is used
790 character(len=*), intent(in) :: name !< name of given drifter
791 integer, intent(out) :: index !< returned drifter index
792 integer, intent(in), dimension(:), optional :: indices !< optional list of indices to limit results to
793 logical, intent(in), optional :: verbose !< debug flag
794 logical :: get_tracer_index_logical
795 
796 index = get_tracer_index_integer(model, name, indices, verbose)
797 if(index == no_tracer) then
798  get_tracer_index_logical = .false.
799 else
800  get_tracer_index_logical = .true.
801 endif
802 
803 end function get_tracer_index_logical
804 
805 !#######################################################################
806 
807 !> @brief Uninitializes module and writes exit to logfile.
809 
810 integer :: log_unit
811 
812 log_unit = stdlog()
813 if ( mpp_pe() == mpp_root_pe() ) then
814  write (log_unit,'(/,(a))') 'Exiting tracer_manager, have a nice day ...'
815 endif
816 
817 module_is_initialized = .false.
818 
819 end subroutine tracer_manager_end
820 
821 !#######################################################################
822 
823 !> @brief Routine to print out the components of the tracer.
824 !! This is useful for informational purposes.
825 !! Used in get_tracer_meta_data.
826 subroutine print_tracer_info(model,n)
827 integer, intent(in) :: model
828 integer, intent(in) :: n !< index of the tracer that is being printed
829 integer :: i, log_unit
830 
831 if(.not.module_is_initialized) call tracer_manager_init
832 
833 if(mpp_pe()==mpp_root_pe() .and. tracer_array(model,n)> 0 ) then
834  i = tracer_array(model,n)
835  log_unit = stdlog()
836  write(log_unit, *)'----------------------------------------------------'
837  write(log_unit, *) 'Contents of tracer entry ', i
838  write(log_unit, *) 'Model type and field name'
839  write(log_unit, *) 'Model : ', tracers(i)%model
840  write(log_unit, *) 'Field name : ', trim(tracers(i)%tracer_name)
841  write(log_unit, *) 'Tracer units : ', trim(tracers(i)%tracer_units)
842  write(log_unit, *) 'Tracer longname : ', trim(tracers(i)%tracer_longname)
843  write(log_unit, *) 'Tracer is_prognostic : ', tracers(i)%is_prognostic
844  write(log_unit, *)'----------------------------------------------------'
845 endif
846 
847 end subroutine print_tracer_info
848 
849 !#######################################################################
850 
851 !> @brief Routine to find the names associated with a tracer number.
852 !!
853 !> This routine can return the name, long name and units associated
854 !! with a tracer.
855 subroutine get_tracer_names(model,n,name,longname, units, err_msg)
856 
857 integer, intent(in) :: model !< A parameter representing component model in use
858 integer, intent(in) :: n !< Tracer number
859 character (len=*),intent(out) :: name !< Field name associate with tracer number
860 character (len=*), intent(out), optional :: longname !< Long name associated with tracer number
861 character (len=*), intent(out), optional :: units !< Tracer associated units
862 character (len=*), intent(out), optional :: err_msg
863 character (len=128) :: err_msg_local
864 integer :: n1
865 character(len=11) :: chn
866 
867 if(.not.module_is_initialized) call tracer_manager_init
868 
869  if (n < 1 .or. n > total_tracers(model)) then
870  write(chn, '(i11)') n
871  err_msg_local = ' Invalid tracer index. Model name = '//trim(model_names(model))//', Index='//trim(chn)
872  if(error_handler('get_tracer_names', err_msg_local, err_msg)) return
873  endif
874  n1 = tracer_array(model,n)
875 
876 name = trim(tracers(n1)%tracer_name)
877 if (PRESENT(longname)) longname = trim(tracers(n1)%tracer_longname)
878 if (PRESENT(units)) units = trim(tracers(n1)%tracer_units)
879 
880 end subroutine get_tracer_names
881 
882 !#######################################################################
883 
884 !> @brief Routine to find the names associated with a tracer number.
885 !!
886 !> This routine can return the name, long name and units associated with a tracer.
887 !! The return value of get_tracer_name is .false. when a FATAL error condition is
888 !! detected, otherwise the return value is .true.
889 function get_tracer_name(model,n,name,longname, units, err_msg)
890 
891 integer, intent(in) :: model !< A parameter representing component model in use
892 integer, intent(in) :: n !< Tracer number
893 character (len=*),intent(out) :: name !< Field name associate with tracer number
894 character (len=*), intent(out), optional :: longname !< Long name associated with tracer number
895 character (len=*), intent(out), optional :: units !< Tracer associated units
896 character (len=*), intent(out), optional :: err_msg !< When present: If a FATAL error condition is
897  !! detected then err_msg will contain an error message
898  !! and the return value of get_tracer_name will be .false.
899  !! If no FATAL error is detected err_msg will be filled with space characters and
900  !! and the return value of get_tracer_name will be .true.
901  !! When not present:
902  !! A FATAL error will result in termination inside get_tracer_name without returning.
903  !! If no FATAL error is detected the return value of get_tracer_name will be .true.
904 
905 logical :: get_tracer_name
906 character (len=128) :: err_msg_local
907 integer :: n1
908 character(len=11) :: chn
909 
910 if(.not.module_is_initialized) call tracer_manager_init
911 
912  if (n < 1 .or. n > total_tracers(model)) then
913  write(chn, '(i11)') n
914  err_msg_local = ' Invalid tracer index. Model name = '//trim(model_names(model))//', Index='//trim(chn)
915  if(error_handler('get_tracer_name', err_msg_local, err_msg)) then
916  get_tracer_name = .false.
917  return
918  endif
919  else
920  get_tracer_name = .true.
921  endif
922  n1 = tracer_array(model,n)
923 
924 name = trim(tracers(n1)%tracer_name)
925 if (PRESENT(longname)) longname = trim(tracers(n1)%tracer_longname)
926 if (PRESENT(units)) units = trim(tracers(n1)%tracer_units)
927 
928 end function get_tracer_name
929 
930 !#######################################################################
931 
932 !> @brief Function to see if a tracer is prognostic or diagnostic.
933 !!
934 !> All tracers are assumed to be prognostic when read in from the field_table
935 !! However a tracer can be changed to a diagnostic tracer by adding the line
936 !! "tracer_type","diagnostic"
937 !! to the tracer description in field_table.
938 !!
939 !! @returns A logical flag set TRUE if the tracer is prognostic.
940 function check_if_prognostic(model, n, err_msg)
941 
942 integer, intent(in) :: model !< Parameter representing component model in use
943 integer, intent(in) :: n !< Tracer number
944 logical :: check_if_prognostic
945 character(len=*), intent(out), optional :: err_msg
946 character(len=128) :: err_msg_local
947 character(len=11) :: chn
948 
949 if(.not.module_is_initialized) call tracer_manager_init
950 
951 if (n < 1 .or. n > total_tracers(model)) then
952  write(chn, '(i11)') n
953  err_msg_local = ' Invalid tracer index. Model name = '//trim(model_names(model))//', Index='//trim(chn)
954  check_if_prognostic = .true.
955  if(error_handler('check_if_prognostic', err_msg_local, err_msg)) return
956 endif
957 
958 !Convert local model index to tracer_manager index
959 
960 check_if_prognostic = tracers(tracer_array(model,n))%is_prognostic
961 
962 end function check_if_prognostic
963 
964 ! Does tracer need mass or positive definite adjustments?
965 !#######################################################################
966 !> Function to check whether tracer should have its mass adjusted
967 function adjust_mass(model, n, err_msg)
968 
969 integer, intent(in) :: model, n
970 logical :: adjust_mass
971 character(len=*), intent(out), optional :: err_msg
972 character(len=128) :: err_msg_local
973 character(len=11) :: chn
974 
975 if(.not.module_is_initialized) call tracer_manager_init
976 
977 if (n < 1 .or. n > total_tracers(model)) then
978  write(chn, '(i11)') n
979  err_msg_local = ' Invalid tracer index. Model name = '//trim(model_names(model))//', Index='//trim(chn)
980  adjust_mass = .true.
981  if(error_handler('adjust_mass', err_msg_local, err_msg)) return
982 endif
983 
984 !Convert local model index to tracer_manager index
985 
986 adjust_mass = tracers(tracer_array(model,n))%needs_mass_adjust
987 
988 end function adjust_mass
989 
990 ! Function to check whether tracer should be adjusted to remain positive definite
991 function adjust_positive_def(model, n, err_msg)
992 
993 integer, intent(in) :: model, n
994 logical :: adjust_positive_def
995 character(len=*), intent(out), optional :: err_msg
996 character(len=128) :: err_msg_local
997 character(len=11) :: chn
998 
999 if(.not.module_is_initialized) call tracer_manager_init
1000 
1001 if (n < 1 .or. n > total_tracers(model)) then
1002  write(chn, '(i11)') n
1003  err_msg_local = ' Invalid tracer index. Model name = '//trim(model_names(model))//', Index='//trim(chn)
1004  adjust_positive_def = .true.
1005  if(error_handler('adjust_positive_def', err_msg_local, err_msg)) return
1006 endif
1007 
1008 !Convert local model index to tracer_manager index
1009 
1010 adjust_positive_def = tracers(tracer_array(model,n))%needs_positive_adjust
1011 
1012 end function adjust_positive_def
1013 
1014 !#######################################################################
1015 
1016 !> @brief A function to query the schemes associated with each tracer.
1017 !!
1018 !> A function to query the "methods" associated with each tracer. The
1019 !! "methods" are the parameters of the component model that can be
1020 !! adjusted by user by placing formatted strings, associated with a
1021 !! particular tracer, within the field table.
1022 !! These methods can control the advection, wet deposition, dry
1023 !! deposition or initial profile of the tracer in question. Any
1024 !! parametrization can use this function as long as a routine for parsing
1025 !!
1026 !! @returns A flag to show whether method_type exists with regard to tracer n. If method_type is not
1027 !! present then one must have default values. the name and control strings are provided by that routine.
1028 !!
1029 !! @note At present the tracer manager module allows the initialization of a tracer
1030 !! profile if a restart does not exist for that tracer.
1031 !! Options for this routine are as follows
1032 !!
1033 !! Tracer profile setup
1034 !! ==================================================================
1035 !! |method_type |method_name |method_control |
1036 !! ==================================================================
1037 !! |profile_type |fixed |surface_value = X |
1038 !! |profile_type |profile |surface_value = X, top_value = Y |(atmosphere)
1039 !! |profile_type |profile |surface_value = X, bottom_value = Y |(ocean)
1040 !! ==================================================================
1041  function query_method (method_type, model, n, name, control, err_msg)
1042 
1043  character(len=*), intent(in) :: method_type !< The requested method
1044  integer , intent(in) :: model !< Model the function is being called from
1045  integer , intent(in) :: n !< Tracer number
1046  character(len=*), intent(out) :: name !< A string containing the modified name to be used
1047  !! with method_type. i.e. "2nd_order" might be the default
1048  !! advection. One could use "4th_order" to modify behaviour
1049  character(len=*), intent(out), optional :: control !< A string containing the modified parameters
1050  !! that are associated with method_type and name.
1051  character(len=*), intent(out), optional :: err_msg
1052  logical :: query_method
1053 
1054  integer :: n1
1055  character(len=256) :: list_name
1056  character(len=1024):: control_tr
1057  character(len=16) :: chn,chn1
1058  character(len=128) :: err_msg_local
1059 
1060  if(.not.module_is_initialized) call tracer_manager_init
1061 
1062 !Convert the local model tracer number to the tracer_manager version.
1063 
1064  if (n < 1 .or. n > total_tracers(model)) then
1065  write(chn, '(i11)') n
1066  err_msg_local = ' Invalid tracer index. Model name = '//trim(model_names(model))//', Index='//trim(chn)
1067  if(error_handler('query_method', err_msg_local, err_msg)) return
1068  endif
1069 
1070  n1 = tracer_array(model,n)
1071 
1072  select case(model)
1073  case (model_coupler)
1074  list_name = "/coupler_mod/tracer/"//trim(tracers(n1)%tracer_name)//"/"//trim(method_type)
1075  case (model_atmos)
1076  list_name = "/atmos_mod/tracer/"//trim(tracers(n1)%tracer_name)//"/"//trim(method_type)
1077  case (model_ocean)
1078  list_name = "/ocean_mod/tracer/"//trim(tracers(n1)%tracer_name)//"/"//trim(method_type)
1079  case (model_ice )
1080  list_name = "/ice_mod/tracer/"//trim(tracers(n1)%tracer_name)//"/"//trim(method_type)
1081  case (model_land )
1082  list_name = "/land_mod/tracer/"//trim(tracers(n1)%tracer_name)//"/"//trim(method_type)
1083  case default
1084  list_name = "/default/tracer/"//trim(tracers(n1)%tracer_name)//"/"//trim(method_type)
1085  end select
1086 
1087  name = ''
1088  control_tr = ''
1089  query_method = fm_query_method(list_name, name, control_tr)
1090 
1091  if ( present(control) ) then
1092  if ( len_trim(control_tr)>len(control) ) then
1093  write(chn,*)len(control)
1094  write(chn1,*)len_trim(control_tr)
1095  if(error_handler('query_method', &
1096  ' Output string length ('//trim(adjustl(chn)) &
1097  // ') is not enough to return all "control" parameters ("'//trim(control_tr) &
1098  // '", length='//trim(adjustl(chn1))//')', &
1099  err_msg)) return
1100  endif
1101  control = trim(control_tr)
1102  endif
1103 
1104  end function query_method
1105 
1106 !> @brief A subroutine to allow the user set the tracer longname and units from the
1107 !! tracer initialization routine.
1108 !!
1109 !> A function to allow the user set the tracer longname and units from the
1110 !! tracer initialization routine. It seems sensible that the user who is
1111 !! coding the tracer code will know what units they are working in and it
1112 !! is probably safer to set the value in the tracer code rather than in
1113 !! the field table.
1114 subroutine set_tracer_atts(model, name, longname, units)
1115 
1116 integer, intent(in) :: model !< A parameter representing component model in use
1117 character(len=*), intent(in) :: name !< Tracer name
1118 character(len=*), intent(in), optional :: longname !< Long name of the tracer
1119 character(len=*), intent(in), optional :: units !< Units for the tracer
1120 
1121 integer :: n, index
1122 logical :: success
1123 character(len=128) :: list_name
1124 
1125 if ( get_tracer_index(model,name,n) ) then
1126  tracers(tracer_array(model,n))%tracer_units = units
1127  tracers(tracer_array(model,n))%tracer_longname = longname
1128  select case(model)
1129  case(model_coupler)
1130  list_name = "/coupler_mod/tracer/"//trim(name)
1131  case(model_atmos)
1132  list_name = "/atmos_mod/tracer/"//trim(name)
1133  case(model_ocean)
1134  list_name = "/ocean_mod/tracer/"//trim(name)
1135  case(model_land)
1136  list_name = "/land_mod/tracer/"//trim(name)
1137  case(model_ice)
1138  list_name = "/ice_mod/tracer/"//trim(name)
1139  case DEFAULT
1140  list_name = "/"//trim(name)
1141  end select
1142 
1143 ! Method_type is a list, method_name is a name of a parameter and method_control has the value.
1144 ! list_name = trim(list_name)//"/longname"
1145  if ( fm_exists(list_name)) then
1146  success = fm_change_list(list_name)
1147  if ( present(longname) ) then
1148  if ( longname .ne. "" ) index = fm_new_value('longname',longname)
1149  endif
1150  if ( present(units) ) then
1151  if (units .ne. "" ) index = fm_new_value('units',units)
1152  endif
1153  endif
1154 
1155 else
1156  call mpp_error(note,'set_tracer_atts : Trying to set longname and/or units for non-existent tracer : '//trim(name))
1157 endif
1158 
1159 end subroutine set_tracer_atts
1160 
1161 !> @brief A subroutine to allow the user to set some tracer specific methods.
1162 subroutine set_tracer_method(model, name, method_type, method_name, method_control)
1163 
1164 integer, intent(in) :: model !< A parameter representing component model in use
1165 character(len=*), intent(in) :: name !< Tracer name
1166 character(len=*), intent(in) :: method_type !< type of method to be set
1167 character(len=*), intent(in) :: method_name !< name of method to be set
1168 character(len=*), intent(in) :: method_control !< control parameters of the given method
1169 
1170 integer :: n, num_method, index
1171 logical :: success
1172 character(len=128) :: list_name
1173 
1174 if ( get_tracer_index(model,name,n) ) then
1175  tracers(n)%num_methods = tracers(n)%num_methods + 1
1176  num_method = tracers(n)%num_methods
1177 
1178  select case(model)
1179  case(model_coupler)
1180  list_name = "/coupler_mod/tracer/"//trim(name)
1181  case(model_atmos)
1182  list_name = "/atmos_mod/tracer/"//trim(name)
1183  case(model_ocean)
1184  list_name = "/ocean_mod/tracer/"//trim(name)
1185  case(model_land)
1186  list_name = "/land_mod/tracer/"//trim(name)
1187  case(model_ice)
1188  list_name = "/ice_mod/tracer/"//trim(name)
1189  case DEFAULT
1190  list_name = "/"//trim(name)
1191  end select
1192 
1193  if ( method_control .ne. "" ) then
1194 ! Method_type is a list, method_name is a name of a parameter and method_control has the value.
1195  list_name = trim(list_name)//"/"//trim(method_type)
1196  if ( fm_exists(list_name)) then
1197  success = fm_change_list(list_name)
1198  index = fm_new_value(method_type,method_control)
1199  endif
1200  else
1201  call mpp_error(note,'set_tracer_method : Trying to set a method for non-existent tracer : '//trim(name))
1202  endif
1203 endif
1204 
1205 end subroutine set_tracer_method
1206 
1207 function error_handler(routine, err_msg_local, err_msg)
1208 logical :: error_handler
1209 character(len=*), intent(in) :: routine, err_msg_local
1210 character(len=*), intent(out), optional :: err_msg
1211 
1212 if(present(err_msg)) then
1213  err_msg = err_msg_local
1214  error_handler = .true.
1215 else
1216  call mpp_error(fatal,trim(routine)//': '//trim(err_msg_local))
1217 endif
1218 
1219 end function error_handler
1220 
1221 #include "tracer_manager_r4.fh"
1222 #include "tracer_manager_r8.fh"
1223 
1224 end module tracer_manager_mod
1225 !> @}
1226 ! close documentation grouping
integer function, public fm_copy_list(list_name, suffix, create)
A function that allows the user to copy a field and add a suffix to the name of the new field.
integer, parameter, public model_land
Land model.
logical function, public fm_exists(name)
A function to test whether a named field exists.
character(len=11), dimension(num_models), parameter, public model_names
Model names, e.g. MODEL_NAMES(MODEL_OCEAN) is 'oceanic'.
logical function, public fm_change_list(name)
Change the current list. Return true on success, false otherwise.
subroutine, public get_field_methods(n, methods)
A routine to obtain all the methods associated with a field.
subroutine, public field_manager_init(nfields, table_name)
Routine to initialize the field manager.
logical function, public fm_query_method(name, method_name, method_control)
This is a function that provides the capability to return parameters associated with a field in a pai...
integer, parameter, public model_coupler
Ice model.
subroutine, public get_field_info(n, fld_type, fld_name, model, num_methods)
This routine allows access to field information given an index.
logical function, public fm_modify_name(oldname, newname)
This function allows a user to rename a field without modifying the contents of the field.
integer, parameter, public model_ocean
Ocean model.
integer, parameter, public model_ice
Ice model.
integer, parameter, public model_atmos
Atmospheric model.
integer, parameter, public num_models
Number of models (ATMOS, OCEAN, LAND, ICE, COUPLER).
An overloaded function to assign a value to a field.
A function to parse an integer or an array of integers, a real or an array of reals,...
This method_type is a way to allow a component module to alter the parameters it needs for various tr...
subroutine, public write_version_number(version, tag, unit)
Prints to the log file (or a specified unit) the version id string and tag name.
Definition: fms.F90:758
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
Definition: mpp_util.inc:59
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:407
Error handler.
Definition: mpp.F90:382
subroutine, public tracer_manager_end
Uninitializes module and writes exit to logfile.
subroutine, public set_tracer_method(model, name, method_type, method_name, method_control)
A subroutine to allow the user to set some tracer specific methods.
subroutine, public get_tracer_indices(model, ind, prog_ind, diag_ind, fam_ind)
Routine to return the component model tracer indices as defined within the tracer manager.
subroutine, public get_tracer_names(model, n, name, longname, units, err_msg)
Routine to find the names associated with a tracer number.
logical function, public query_method(method_type, model, n, name, control, err_msg)
A function to query the schemes associated with each tracer.
logical function, public get_tracer_name(model, n, name, longname, units, err_msg)
Routine to find the names associated with a tracer number.
logical function, public adjust_mass(model, n, err_msg)
Function to check whether tracer should have its mass adjusted.
subroutine, public set_tracer_atts(model, name, longname, units)
A subroutine to allow the user set the tracer longname and units from the tracer initialization routi...
logical function, public check_if_prognostic(model, n, err_msg)
Function to see if a tracer is prognostic or diagnostic.
subroutine print_tracer_info(model, n)
Routine to print out the components of the tracer. This is useful for informational purposes....
subroutine get_tracer_meta_data(model, num_tracers, num_prog, num_diag)
Read in tracer table and store tracer information associated with "model" in "tracers" array.
subroutine, public register_tracers(model, num_tracers, num_prog, num_diag, num_family)
Not necessary to call, only needed for backward compatability.
integer function get_tracer_index_integer(model, name, indices, verbose)
Function which returns the number assigned to the tracer name.
logical function get_tracer_index_logical(model, name, index, indices, verbose)
Checks if tracer is present, and returns it's position in index.
subroutine, public tracer_manager_init
Not necessary to call, only needed for backward compatability.
subroutine, public get_number_tracers(model, num_tracers, num_prog, num_diag, num_family)
A routine to return the number of tracers included in a component model.
Function which returns the number assigned to the tracer name.
Private type to represent named instances.
Private type to holds string data for a tracer.
Private type to hold metadata for a tracer.