FMS 2025.01-dev
Flexible Modeling System
Loading...
Searching...
No Matches
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
42module tracer_manager_mod
43
44!----------------------------------------------------------------------
45
46use mpp_mod, only : mpp_error, &
47 mpp_pe, &
48 mpp_root_pe, &
49 fatal, &
50 warning, &
51 note, &
52 stdlog
53use fms_mod, only : lowercase, &
54 write_version_number
55
56use field_manager_mod, only : field_manager_init, &
60 model_land, &
62 model_ice, &
64 num_models, &
66 default_method, &
67 parse, &
73 fm_exists, &
75use platform_mod, only : r4_kind, &
76 r8_kind
77
78implicit none
79private
80
81!-----------------------------------------------------------------------
82
83public tracer_manager_init, &
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
128end interface
129
131 module procedure set_tracer_profile_r4
132 module procedure set_tracer_profile_r8
133end interface set_tracer_profile
134
135!> Private type to hold metadata for a tracer
136!> @ingroup tracer_manager_mod
137type, 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
147end type tracer_type
148
149!> Private type to holds string data for a tracer
150!> @ingroup tracer_manager_mod
151type, private :: tracer_name_type
152 character(len=32) :: model_name, tracer_name, tracer_units
153 character(len=128) :: tracer_longname
154end type tracer_name_type
155
156!> Private type to represent named instances
157!> @ingroup tracer_manager_mod
158type, private :: inst_type
159 character(len=128) :: name
160 integer :: instances
161end type inst_type
162
163!> @addtogroup tracer_manager_mod
164!> @{
165
166integer :: num_tracer_fields = 0
167integer, parameter :: MAX_TRACER_FIELDS = 250
168integer, parameter :: MAX_TRACER_METHOD = 20
169integer, parameter :: NO_TRACER = 1-huge(1)
170integer, parameter :: NOTRACER = -huge(1)
171
172type(tracer_type), save :: tracers(MAX_TRACER_FIELDS)
173type(inst_type) , save :: instantiations(MAX_TRACER_FIELDS)
174
175integer :: total_tracers(NUM_MODELS), prog_tracers(NUM_MODELS), diag_tracers(NUM_MODELS)
176logical :: model_registered(NUM_MODELS) = .false.
177
178! Include variable "version" to be written to log file.
179#include<file_version.h>
180
181logical :: module_is_initialized = .false.
182
183logical :: verbose_local
184integer :: TRACER_ARRAY(NUM_MODELS,MAX_TRACER_FIELDS)
185
186contains
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
194integer :: 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
206end subroutine tracer_manager_init
207
208!> @brief Read in tracer table and store tracer information associated with "model" in "tracers"
209!! array.
210subroutine get_tracer_meta_data(model, num_tracers,num_prog,num_diag)
211
212integer, intent(in) :: model !< model being used
213integer, intent(out) :: num_tracers, num_prog, num_diag
214character(len=256) :: warnmesg
215
216character(len=32) :: name_type, type, name
217integer :: n, m, mod, num_tracer_methods, nfields, swop
218integer :: j, log_unit, num_methods
219logical :: flag_type
220type(method_type), dimension(MAX_TRACER_METHOD) :: methods
221integer :: instances, siz_inst,i
222character(len = 32) :: digit,suffnam
223
224character(len=128) :: list_name , control
225integer :: index_list_name
226logical :: fm_success
227
228! <ERROR MSG="invalid model type" STATUS="FATAL">
229! The index for the model type is invalid.
230! </ERROR>
231if (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
239if ( 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
246endif
247
248! Initialize the number of tracers to zero.
249num_tracers = 0; num_prog = 0; num_diag = 0
250
251call 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>
257if (nfields == 0 ) then
258if (mpp_pe() == mpp_root_pe()) &
259 call mpp_error(note,'tracer_manager_init : No tracers are available to be registered.')
260 return
261endif
262
263! search through field entries for model tracers
264total_tracers(model) = 0
265
266do 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
336enddo
337
338! Now cycle through the tracers and add additional instances of the tracers.
339
340do 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 !}
416enddo !}
417
418! Find any field entries with the instances keyword.
419do 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
517enddo
518
519num_tracers = num_prog + num_diag
520! Make the number of tracers available publicly.
521total_tracers(model) = num_tracers
522prog_tracers(model) = num_prog
523diag_tracers(model) = num_diag
524model_registered(model) = .true.
525
526! Now sort through the tracer fields and sort them so that the
527! prognostic tracers are first.
528
529do 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
541enddo
542
543do n=1, num_tracer_fields
544 call print_tracer_info(model,n)
545enddo
546
547log_unit = stdlog()
548if ( mpp_pe() == mpp_root_pe() ) then
549 write (log_unit,15) trim(model_names(model)),total_tracers(model)
550endif
551
55215 format ('Number of tracers in field table for ',a,' model = ',i4)
553
554end subroutine get_tracer_meta_data
555
556function model_tracer_number(model,n)
557integer, intent(in) :: model, n
558integer model_tracer_number
559
560integer :: i
561
562model_tracer_number = no_tracer
563
564do i = 1, max_tracer_fields
565 if ( tracer_array(model,i) == n ) then
566 model_tracer_number = i
567 return
568 endif
569enddo
570
571end 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.
578subroutine register_tracers(model, num_tracers, num_prog, num_diag, num_family)
579integer, intent(in) :: model !< A parameter to identify which model is being used.
580integer, intent(out) :: num_tracers !< The total number of valid tracers within the component model.
581integer, intent(out) :: num_prog !< The number of prognostic tracers within the component model.
582integer, intent(out) :: num_diag !< The number of diagnostic tracers within the component model.
583integer, intent(out), optional :: num_family
584
585if(.not.module_is_initialized) call tracer_manager_init
586
587call get_number_tracers(model, num_tracers, num_prog, num_diag, num_family)
588
589end 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
597subroutine get_number_tracers(model, num_tracers, num_prog, num_diag, num_family)
598
599integer, intent(in) :: model !< A parameter to identify which model is being used
600integer, intent(out), optional :: num_tracers !< The total number of valid tracers within
601 !! the component model
602integer, intent(out), optional :: num_prog !< The number of prognostic tracers within the
603 !! component model.
604integer, intent(out), optional :: num_diag !< The number of diagnostic tracers within the
605 !! component model
606integer, intent(out), optional :: num_family
607
608if(.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>
613if (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
618if (present(num_tracers)) num_tracers = total_tracers(model)
619if (present(num_prog)) num_prog = prog_tracers(model)
620if (present(num_diag)) num_diag = diag_tracers(model)
621if (present(num_family)) num_family = 0 ! Needed only for backward compatability with lima
622
623end 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.
640subroutine get_tracer_indices(model, ind, prog_ind, diag_ind, fam_ind)
641
642integer, intent(in) :: model
643integer, intent(out), dimension(:), optional :: ind, prog_ind, diag_ind, fam_ind
644
645integer :: i, j, np, nd, n
646
647if(.not.module_is_initialized) call tracer_manager_init
648
649nd=0;np=0;n=0
650
651! Initialize arrays with dummy values
652if (PRESENT(ind)) ind = no_tracer
653if (PRESENT(prog_ind)) prog_ind = no_tracer
654if (PRESENT(diag_ind)) diag_ind = no_tracer
655if (PRESENT(fam_ind)) fam_ind = no_tracer
656
657do i = 1, max_tracer_fields
658j = 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
690enddo
691
692return
693end 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
738function get_tracer_index_integer(model, name, indices, verbose)
739
740integer, intent(in) :: model !< Parameter to identify which model is used
741character(len=*), intent(in) :: name !< name of the tracer
742integer, intent(in), dimension(:), optional :: indices !< An array of indices, limits search to tracers
743 !! whose indices are within the array.
744logical, intent(in), optional :: verbose !< debug flag
746
747integer :: i
748
749if(.not.module_is_initialized) call tracer_manager_init
750
751get_tracer_index_integer = no_tracer
752
753if (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
760else
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
768end if
769
770verbose_local=.false.
771if (present(verbose)) verbose_local=verbose
772
773if (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>
779endif
780
781return
782
783end function get_tracer_index_integer
784
785!#######################################################################
786!> @brief Checks if tracer is present, and returns it's position in index
787function get_tracer_index_logical(model, name, index, indices, verbose)
788
789integer, intent(in) :: model !< Parameter for which model is used
790character(len=*), intent(in) :: name !< name of given drifter
791integer, intent(out) :: index !< returned drifter index
792integer, intent(in), dimension(:), optional :: indices !< optional list of indices to limit results to
793logical, intent(in), optional :: verbose !< debug flag
795
796index = get_tracer_index_integer(model, name, indices, verbose)
797if(index == no_tracer) then
799else
801endif
802
803end function get_tracer_index_logical
804
805!#######################################################################
806
807!> @brief Uninitializes module and writes exit to logfile.
809
810integer :: log_unit
811
812log_unit = stdlog()
813if ( mpp_pe() == mpp_root_pe() ) then
814 write (log_unit,'(/,(a))') 'Exiting tracer_manager, have a nice day ...'
815endif
816
817module_is_initialized = .false.
818
819end 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.
826subroutine print_tracer_info(model,n)
827integer, intent(in) :: model
828integer, intent(in) :: n !< index of the tracer that is being printed
829integer :: i, log_unit
830
831if(.not.module_is_initialized) call tracer_manager_init
832
833if(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, *)'----------------------------------------------------'
845endif
846
847end 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.
855subroutine get_tracer_names(model,n,name,longname, units, err_msg)
856
857integer, intent(in) :: model !< A parameter representing component model in use
858integer, intent(in) :: n !< Tracer number
859character (len=*),intent(out) :: name !< Field name associate with tracer number
860character (len=*), intent(out), optional :: longname !< Long name associated with tracer number
861character (len=*), intent(out), optional :: units !< Tracer associated units
862character (len=*), intent(out), optional :: err_msg
863character (len=128) :: err_msg_local
864integer :: n1
865character(len=11) :: chn
866
867if(.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
876name = trim(tracers(n1)%tracer_name)
877if (PRESENT(longname)) longname = trim(tracers(n1)%tracer_longname)
878if (PRESENT(units)) units = trim(tracers(n1)%tracer_units)
879
880end 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.
889function get_tracer_name(model,n,name,longname, units, err_msg)
890
891integer, intent(in) :: model !< A parameter representing component model in use
892integer, intent(in) :: n !< Tracer number
893character (len=*),intent(out) :: name !< Field name associate with tracer number
894character (len=*), intent(out), optional :: longname !< Long name associated with tracer number
895character (len=*), intent(out), optional :: units !< Tracer associated units
896character (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
905logical :: get_tracer_name
906character (len=128) :: err_msg_local
907integer :: n1
908character(len=11) :: chn
909
910if(.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
924name = trim(tracers(n1)%tracer_name)
925if (PRESENT(longname)) longname = trim(tracers(n1)%tracer_longname)
926if (PRESENT(units)) units = trim(tracers(n1)%tracer_units)
927
928end 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.
940function check_if_prognostic(model, n, err_msg)
941
942integer, intent(in) :: model !< Parameter representing component model in use
943integer, intent(in) :: n !< Tracer number
944logical :: check_if_prognostic
945character(len=*), intent(out), optional :: err_msg
946character(len=128) :: err_msg_local
947character(len=11) :: chn
948
949if(.not.module_is_initialized) call tracer_manager_init
950
951if (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
956endif
957
958!Convert local model index to tracer_manager index
959
960check_if_prognostic = tracers(tracer_array(model,n))%is_prognostic
961
962end 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
967function adjust_mass(model, n, err_msg)
968
969integer, intent(in) :: model, n
970logical :: adjust_mass
971character(len=*), intent(out), optional :: err_msg
972character(len=128) :: err_msg_local
973character(len=11) :: chn
974
975if(.not.module_is_initialized) call tracer_manager_init
976
977if (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
982endif
983
984!Convert local model index to tracer_manager index
985
986adjust_mass = tracers(tracer_array(model,n))%needs_mass_adjust
987
988end function adjust_mass
989
990! Function to check whether tracer should be adjusted to remain positive definite
991function adjust_positive_def(model, n, err_msg)
992
993integer, intent(in) :: model, n
994logical :: adjust_positive_def
995character(len=*), intent(out), optional :: err_msg
996character(len=128) :: err_msg_local
997character(len=11) :: chn
998
999if(.not.module_is_initialized) call tracer_manager_init
1000
1001if (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
1006endif
1007
1008!Convert local model index to tracer_manager index
1009
1010adjust_positive_def = tracers(tracer_array(model,n))%needs_positive_adjust
1011
1012end 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.
1114subroutine set_tracer_atts(model, name, longname, units)
1115
1116integer, intent(in) :: model !< A parameter representing component model in use
1117character(len=*), intent(in) :: name !< Tracer name
1118character(len=*), intent(in), optional :: longname !< Long name of the tracer
1119character(len=*), intent(in), optional :: units !< Units for the tracer
1120
1121integer :: n, index
1122logical :: success
1123character(len=128) :: list_name
1124
1125if ( 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
1155else
1156 call mpp_error(note,'set_tracer_atts : Trying to set longname and/or units for non-existent tracer : '//trim(name))
1157endif
1158
1159end subroutine set_tracer_atts
1160
1161!> @brief A subroutine to allow the user to set some tracer specific methods.
1162subroutine set_tracer_method(model, name, method_type, method_name, method_control)
1163
1164integer, intent(in) :: model !< A parameter representing component model in use
1165character(len=*), intent(in) :: name !< Tracer name
1166character(len=*), intent(in) :: method_type !< type of method to be set
1167character(len=*), intent(in) :: method_name !< name of method to be set
1168character(len=*), intent(in) :: method_control !< control parameters of the given method
1169
1170integer :: n, num_method, index
1171logical :: success
1172character(len=128) :: list_name
1173
1174if ( 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
1203endif
1204
1205end subroutine set_tracer_method
1206
1207function error_handler(routine, err_msg_local, err_msg)
1208logical :: error_handler
1209character(len=*), intent(in) :: routine, err_msg_local
1210character(len=*), intent(out), optional :: err_msg
1211
1212if(present(err_msg)) then
1213 err_msg = err_msg_local
1214 error_handler = .true.
1215else
1216 call mpp_error(fatal,trim(routine)//': '//trim(err_msg_local))
1217endif
1218
1219end function error_handler
1220
1221#include "tracer_manager_r4.fh"
1222#include "tracer_manager_r8.fh"
1223
1224end module tracer_manager_mod
1225!> @}
1226! close documentation grouping
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_land
Land model.
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.
integer, parameter, public model_coupler
Ice model.
subroutine, public get_field_methods(n, methods)
A routine to obtain all the methods associated with a field.
integer, parameter, public model_ocean
Ocean model.
integer, parameter, public model_ice
Ice model.
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...
recursive logical function query_method(list_p, recursive, name, method_name, method_control)
A private function that can recursively recover values for parameters associated with a field.
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.
logical function, public fm_exists(name)
A function to test whether a named field exists.
integer, parameter, public model_atmos
Atmospheric model.
integer, parameter, public num_models
Number of models (ATMOS, OCEAN, LAND, ICE, COUPLER).
subroutine, public field_manager_init(nfields, table_name)
Routine to initialize the field manager.
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...
Error handler.
Definition mpp.F90:382
logical function, public check_if_prognostic(model, n, err_msg)
Function to see if a tracer is prognostic or diagnostic.
subroutine, public tracer_manager_init
Not necessary to call, only needed for backward compatability.
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.
logical function get_tracer_index_logical(model, name, index, indices, verbose)
Checks if tracer is present, and returns it's position in index.
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.
logical function, public adjust_mass(model, n, err_msg)
Function to check whether tracer should have its mass adjusted.
subroutine, public get_tracer_names(model, n, name, longname, units, err_msg)
Routine to find the names associated with a tracer number.
subroutine, public register_tracers(model, num_tracers, num_prog, num_diag, num_family)
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.
subroutine print_tracer_info(model, n)
Routine to print out the components of the tracer. This is useful for informational purposes....
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...
integer function get_tracer_index_integer(model, name, indices, verbose)
Function which returns the number assigned to the tracer name.
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.
logical function, public get_tracer_name(model, n, name, longname, units, err_msg)
Routine to find the names associated with a tracer number.
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.