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