78 use fms_mod,
only : lowercase, &
139 character(len=32) :: tracer_name, tracer_units
140 character(len=128) :: tracer_longname
141 integer :: num_methods, model, instances
142 logical :: is_prognostic, instances_set
143 logical :: needs_init
146 logical :: needs_mass_adjust
147 logical :: needs_positive_adjust
151 character(len=32) :: model_name, tracer_name, tracer_units
152 character(len=128) :: tracer_longname
157 character(len=128) :: name
165 #include<file_version.h> 190 integer :: model, num_tracers, num_prog, num_diag
195 call write_version_number (
"TRACER_MANAGER_MOD", version)
213 integer,
intent(in) :: model
214 integer,
intent(out) :: num_tracers, num_prog, num_diag
215 character(len=256) :: warnmesg
217 character(len=32) :: name_type,
type, name
218 integer :: n, m, mod, num_tracer_methods, nfields, swop
219 integer :: j, log_unit, num_methods
221 type(method_type),
dimension(MAX_TRACER_METHOD) :: methods
222 integer :: instances, siz_inst,i
223 character(len = 32) :: digit,suffnam
225 character(len=128) :: list_name , control
226 integer :: index_list_name
227 logical :: fm_success
250 num_tracers = 0; num_prog = 0; num_diag = 0
258 if (nfields == 0 )
then 259 if (mpp_pe() == mpp_root_pe()) &
260 call mpp_error(note,
'tracer_manager_init : No tracers are available to be registered.')
270 if (mod == model .and.
type ==
'tracer') then
288 if (name ==
'cld_amt')
then 291 if (name ==
'cld_amt' .or. name ==
'liq_wat' .or. name ==
'ice_wat')
then 295 num_tracer_methods = 0
299 select case (methods(j)%method_type)
306 siz_inst =
parse(methods(j)%method_name,
"",instances)
310 if (methods(j)%method_name ==
"false")
then 313 case (
'adjust_positive_def')
314 if (methods(j)%method_name ==
"false")
then 318 num_tracer_methods = num_tracer_methods+1
325 if (flag_type .and. name_type ==
'diagnostic')
then 331 num_prog = num_prog+1
333 num_diag = num_diag+1
343 if ( model ==
tracers(n)%model .and.
tracers(n)%instances_set )
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
360 write (suffnam,
'(''suffix'',i1)') i
361 siz_inst =
parse(control, suffnam,digit)
362 if (siz_inst == 0 )
then 363 write (digit,
'(''_'',i1)') i
365 digit =
"_"//trim(digit)
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
373 digit =
"_"//trim(digit)
376 call mpp_error(fatal,
'tracer_manager_init: MULTIPLE_TRACER_SET_UP exceeds 100 for '//
tracers(n)%tracer_name )
394 if (mpp_pe() == mpp_root_pe() )
write (*,*)
"Creating list name = ",trim(list_name)//trim(digit)
401 num_prog = num_prog+1
403 num_diag = num_diag+1
408 siz_inst =
parse(control,
"suffix1",digit)
409 if (siz_inst > 0 )
then 410 digit =
"_"//trim(digit)
413 tracers(n)%tracer_name = trim(
tracers(n)%tracer_name)//trim(digit)
421 if ( mod == model .and.
type ==
'instances' ) then
426 call mpp_error(fatal,
'tracer_manager_init: The instances keyword was found for undefined tracer '&
427 //trim(methods(j)%method_type))
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
435 ' will have '//trim(methods(j)%method_name)//
' instances')
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
444 if (instances .eq. 1)
then 445 siz_inst =
parse(methods(j)%method_control,
'suffix1',digit)
446 if (siz_inst == 0 )
then 449 digit =
"_"//trim(digit)
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
464 digit =
"_"//trim(digit)
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
472 digit =
"_"//trim(digit)
475 call mpp_error(fatal,
'tracer_manager_init: MULTIPLE_TRACER_SET_UP exceeds 100 for '&
494 if (mpp_pe() == mpp_root_pe() )
write (*,*)
"Creating list name = ",trim(list_name)
500 num_prog = num_prog+1
502 num_diag = num_diag+1
506 siz_inst =
parse(methods(j)%method_control,
'suffix1',digit)
507 if (siz_inst == 0 )
then 510 digit =
"_"//trim(digit)
513 tracers(m)%tracer_name = trim(
tracers(m)%tracer_name)//trim(digit)
518 num_tracers = num_prog + num_diag
531 do m = n, num_tracers
547 if ( mpp_pe() == mpp_root_pe() )
then 551 15
format (
'Number of tracers in field table for ',a,
' model = ',i4)
558 integer,
intent(in) :: model, n
602 subroutine register_tracers(model, num_tracers, num_prog, num_diag, num_family)
603 integer,
intent(in) :: model
604 integer,
intent(out) :: num_tracers, num_prog, num_diag
605 integer,
intent(out),
optional :: num_family
642 integer,
intent(in) :: model
643 integer,
intent(out),
optional :: num_tracers, num_prog, num_diag, num_family
653 call mpp_error(fatal,
"get_number_tracers : Model number is invalid.")
658 if (
present(num_family)) num_family = 0
698 integer,
intent(in) :: model
699 integer,
intent(out),
dimension(:),
optional :: ind, prog_ind, diag_ind, fam_ind
701 integer :: i, j, np, nd, n
709 if (
PRESENT(prog_ind)) prog_ind =
no_tracer 710 if (
PRESENT(diag_ind)) diag_ind =
no_tracer 711 if (
PRESENT(fam_ind)) fam_ind =
no_tracer 716 if ( model ==
tracers(j)%model)
then 717 if (
PRESENT(ind))
then 722 if (n >
size(ind(:)))
call mpp_error(fatal,
'get_tracer_indices : index array size too small in get_tracer_indices')
726 if (
tracers(j)%is_prognostic.and.
PRESENT(prog_ind))
then 731 if ( np >
size( prog_ind(:)))
call mpp_error(fatal,&
732 'get_tracer_indices : prognostic array size too small in get_tracer_indices')
734 else if (.not.
tracers(j)%is_prognostic .and.
PRESENT(diag_ind))
then 739 if (nd >
size(diag_ind(:)))
call mpp_error(fatal,&
740 'get_tracer_indices : diagnostic array size too small in get_tracer_indices')
791 integer,
intent(in) :: model
792 character(len=*),
intent(in) :: name
793 integer,
intent(in),
dimension(:),
optional :: indices
794 logical,
intent(in),
optional :: verbose
803 if (
PRESENT(indices))
then 804 do i = 1,
size(indices(:))
805 if (model ==
tracers(indices(i))%model .and. lowercase(trim(name)) == trim(
tracers(indices(i))%tracer_name))
then 826 call mpp_error(note,
'get_tracer_index : tracer with this name not found: '//trim(name))
838 integer,
intent(in) :: model
839 character(len=*),
intent(in) :: name
840 integer,
intent(out) :: index
841 integer,
intent(in),
dimension(:),
optional :: indices
842 logical,
intent(in),
optional :: verbose
871 if ( mpp_pe() == mpp_root_pe() )
then 872 write (log_unit,
'(/,(a))')
'Exiting tracer_manager, have a nice day ...' 892 integer,
intent(in) :: model,n
893 integer :: i,log_unit
897 if(mpp_pe()==mpp_root_pe() .and.
tracer_array(model,n)> 0 )
then 900 write(log_unit, *)
'----------------------------------------------------' 901 write(log_unit, *)
'Contents of tracer entry ', i
902 write(log_unit, *)
'Model type and field name' 903 write(log_unit, *)
'Model : ',
tracers(i)%model
904 write(log_unit, *)
'Field name : ', trim(
tracers(i)%tracer_name)
905 write(log_unit, *)
'Tracer units : ', trim(
tracers(i)%tracer_units)
906 write(log_unit, *)
'Tracer longname : ', trim(
tracers(i)%tracer_longname)
907 write(log_unit, *)
'Tracer is_prognostic : ',
tracers(i)%is_prognostic
908 write(log_unit, *)
'----------------------------------------------------' 911 900
FORMAT(a,2(1x,e12.6))
912 901
FORMAT(e12.6,1x,e12.6)
949 integer,
intent(in) :: model, n
950 character (len=*),
intent(out) :: name
951 character (len=*),
intent(out),
optional :: longname, units, err_msg
952 character (len=128) :: err_msg_local
954 character(len=11) :: chn
959 write(chn,
'(i11)') n
960 err_msg_local =
' Invalid tracer index. Model name = '//trim(
model_names(model))//
', Index='//trim(chn)
961 if(
error_handler(
'get_tracer_names', err_msg_local, err_msg))
return 965 name = trim(
tracers(n1)%tracer_name)
966 if (
PRESENT(longname)) longname = trim(
tracers(n1)%tracer_longname)
967 if (
PRESENT(units)) units = trim(
tracers(n1)%tracer_units)
1016 integer,
intent(in) :: model, n
1017 character (len=*),
intent(out) :: name
1018 character (len=*),
intent(out),
optional :: longname, units, err_msg
1019 character (len=128) :: err_msg_local
1021 character(len=11) :: chn
1026 write(chn,
'(i11)') n
1027 err_msg_local =
' Invalid tracer index. Model name = '//trim(
model_names(model))//
', Index='//trim(chn)
1028 if(
error_handler(
'get_tracer_name', err_msg_local, err_msg))
then 1037 name = trim(
tracers(n1)%tracer_name)
1038 if (
PRESENT(longname)) longname = trim(
tracers(n1)%tracer_longname)
1039 if (
PRESENT(units)) units = trim(
tracers(n1)%tracer_units)
1072 integer,
intent(in) :: model, n
1074 character(len=*),
intent(out),
optional :: err_msg
1075 character(len=128) :: err_msg_local
1076 character(len=11) :: chn
1081 write(chn,
'(i11)') n
1082 err_msg_local =
' Invalid tracer index. Model name = '//trim(
model_names(model))//
', Index='//trim(chn)
1084 if(
error_handler(
'check_if_prognostic', err_msg_local, err_msg))
return 1099 integer,
intent(in) :: model, n
1101 character(len=*),
intent(out),
optional :: err_msg
1102 character(len=128) :: err_msg_local
1103 character(len=11) :: chn
1108 write(chn,
'(i11)') n
1109 err_msg_local =
' Invalid tracer index. Model name = '//trim(
model_names(model))//
', Index='//trim(chn)
1111 if(
error_handler(
'adjust_mass', err_msg_local, err_msg))
return 1123 integer,
intent(in) :: model, n
1125 character(len=*),
intent(out),
optional :: err_msg
1126 character(len=128) :: err_msg_local
1127 character(len=11) :: chn
1132 write(chn,
'(i11)') n
1133 err_msg_local =
' Invalid tracer index. Model name = '//trim(
model_names(model))//
', Index='//trim(chn)
1135 if(
error_handler(
'adjust_positive_def', err_msg_local, err_msg))
return 1192 integer,
intent(in) :: model, n
1193 real,
intent(inout),
dimension(:,:,:) :: tracer
1194 character(len=*),
intent(out),
optional :: err_msg
1196 real :: surf_value, multiplier
1197 integer :: numlevels, k, n1, flag
1198 real :: top_value, bottom_value
1199 character(len=80) :: scheme, control,profile_type
1200 character(len=128) :: err_msg_local
1201 character(len=11) :: chn
1206 write(chn,
'(i11)') n
1207 err_msg_local =
' Invalid tracer index. Model name = '//trim(
model_names(model))//
', Index='//trim(chn)
1208 if(
error_handler(
'set_tracer_profile', err_msg_local, err_msg))
return 1213 profile_type =
'Fixed' 1214 surf_value = 0.0e+00
1215 top_value = surf_value
1216 bottom_value = surf_value
1221 if (
query_method(
'profile_type',model,n,scheme,control))
then 1224 if(lowercase(trim(scheme(1:5))).eq.
'fixed')
then 1225 profile_type =
'Fixed' 1226 flag =
parse(control,
'surface_value',surf_value)
1231 if(lowercase(trim(scheme(1:7))).eq.
'profile')
then 1232 profile_type =
'Profile' 1233 flag=
parse(control,
'surface_value',surf_value)
1234 if (surf_value .eq. 0.0) &
1235 call mpp_error(fatal,
'set_tracer_profile : Cannot have a zero surface value for an exponential profile. Tracer '&
1236 //
tracers(n1)%tracer_name//
" "//control//
" "//scheme)
1237 select case (
tracers(n1)%model)
1239 flag=
parse(control,
'top_value',top_value)
1240 if(mpp_pe()==mpp_root_pe() .and. flag == 0) &
1241 call mpp_error(note,
'set_tracer_profile : Parameter top_value needs to be defined for the tracer profile.')
1243 flag =
parse(control,
'bottom_value',bottom_value)
1244 if(mpp_pe() == mpp_root_pe() .and. flag == 0) &
1245 call mpp_error(note,
'set_tracer_profile : Parameter bottom_value needs to be defined for the tracer profile.')
1257 numlevels =
size(tracer,3) -1
1258 select case (
tracers(n1)%model)
1260 multiplier = exp( log(top_value/surf_value) /numlevels)
1261 tracer(:,:,1) = surf_value
1262 do k = 2,
size(tracer,3)
1263 tracer(:,:,k) = tracer(:,:,k-1) * multiplier
1266 multiplier = exp( log(bottom_value/surf_value) /numlevels)
1267 tracer(:,:,
size(tracer,3)) = surf_value
1268 do k =
size(tracer,3) - 1, 1, -1
1269 tracer(:,:,k) = tracer(:,:,k+1) * multiplier
1275 if (mpp_pe() == mpp_root_pe() )
write(*,700)
'Tracer ',trim(
tracers(n1)%tracer_name), &
1276 ' initialized with surface value of ',surf_value, &
1277 ' and vertical multiplier of ',multiplier
1278 700
FORMAT (3a,e12.6,a,f10.6)
1346 function query_method (method_type, model, n, name, control, err_msg)
1366 integer ,
intent(in) :: model, n
1367 character(len=*),
intent(out) :: name
1368 character(len=*),
intent(out),
optional :: control, err_msg
1372 character(len=256) :: list_name
1373 character(len=1024):: control_tr
1374 character(len=16) :: chn,chn1
1375 character(len=128) :: err_msg_local
1382 write(chn,
'(i11)') n
1383 err_msg_local =
' Invalid tracer index. Model name = '//trim(
model_names(model))//
', Index='//trim(chn)
1384 if(
error_handler(
'query_method', err_msg_local, err_msg))
return 1391 list_name =
"/coupler_mod/tracer/"//trim(
tracers(n1)%tracer_name)//
"/"//trim(
method_type)
1393 list_name =
"/atmos_mod/tracer/"//trim(
tracers(n1)%tracer_name)//
"/"//trim(
method_type)
1395 list_name =
"/ocean_mod/tracer/"//trim(
tracers(n1)%tracer_name)//
"/"//trim(
method_type)
1397 list_name =
"/ice_mod/tracer/"//trim(
tracers(n1)%tracer_name)//
"/"//trim(
method_type)
1399 list_name =
"/land_mod/tracer/"//trim(
tracers(n1)%tracer_name)//
"/"//trim(
method_type)
1401 list_name =
"/default/tracer/"//trim(
tracers(n1)%tracer_name)//
"/"//trim(
method_type)
1408 if (
present(control) )
then 1409 if ( len_trim(control_tr)>len(control) )
then 1410 write(chn,*)len(control)
1411 write(chn1,*)len_trim(control_tr)
1413 ' Output string length ('//trim(adjustl(chn)) &
1414 //
') is not enough to return all "control" parameters ("'//trim(control_tr) &
1415 //
'", length='//trim(adjustl(chn1))//
')', &
1418 control = trim(control_tr)
1454 integer,
intent(in) :: model
1455 character(len=*),
intent(in) :: name
1456 character(len=*),
intent(in),
optional :: longname, units
1460 character(len=128) :: list_name
1467 list_name =
"/coupler_mod/tracer/"//trim(name)
1469 list_name =
"/atmos_mod/tracer/"//trim(name)
1471 list_name =
"/ocean_mod/tracer/"//trim(name)
1473 list_name =
"/land_mod/tracer/"//trim(name)
1475 list_name =
"/ice_mod/tracer/"//trim(name)
1477 list_name =
"/"//trim(name)
1484 if (
present(longname) )
then 1485 if ( longname .ne.
"" ) index =
fm_new_value(
'longname',longname)
1487 if (
present(units) )
then 1488 if (units .ne.
"" ) index =
fm_new_value(
'units',units)
1493 call mpp_error(note,
'set_tracer_atts : Trying to set longname and/or units for non-existent tracer : '//trim(name))
1526 subroutine set_tracer_method(model, name, method_type, method_name, method_control)
1528 integer,
intent(in) :: model
1529 character(len=*),
intent(in) :: name
1530 character(len=*),
intent(in) :: method_type
1531 character(len=*),
intent(in) :: method_name
1532 character(len=*),
intent(in) :: method_control
1534 integer :: n, num_method, index
1536 character(len=128) :: list_name
1540 num_method =
tracers(n)%num_methods
1544 list_name =
"/coupler_mod/tracer/"//trim(name)
1546 list_name =
"/atmos_mod/tracer/"//trim(name)
1548 list_name =
"/ocean_mod/tracer/"//trim(name)
1550 list_name =
"/land_mod/tracer/"//trim(name)
1552 list_name =
"/ice_mod/tracer/"//trim(name)
1554 list_name =
"/"//trim(name)
1557 if ( method_control .ne.
"" )
then 1559 list_name = trim(list_name)//
"/"//trim(
method_type)
1565 call mpp_error(note,
'set_tracer_method : Trying to set a method for non-existent tracer : '//trim(name))
1574 character(len=*),
intent(in) :: routine, err_msg_local
1575 character(len=*),
intent(out),
optional :: err_msg
1577 if(
present(err_msg))
then 1578 err_msg = err_msg_local
1581 call mpp_error(fatal,trim(routine)//
': '//trim(err_msg_local))
integer, parameter, public model_ice
subroutine print_tracer_info(model, n)
integer, parameter, public model_atmos
logical function, public get_tracer_name(model, n, name, longname, units, err_msg)
subroutine get_tracer_meta_data(model, num_tracers, num_prog, num_diag)
void error_handler(const char *msg)
subroutine set_tracer_method(model, name, method_type, method_name, method_control)
integer, dimension(num_models) total_tracers
logical function, public adjust_positive_def(model, n, err_msg)
integer, parameter, public model_ocean
integer, parameter, public max_tracer_fields
subroutine, public get_tracer_indices(model, ind, prog_ind, diag_ind, fam_ind)
integer, dimension(num_models) prog_tracers
subroutine, public get_field_info(n, fld_type, fld_name, model, num_methods)
subroutine, public create(self, geom, vars)
Linked list implementation.
integer, parameter, public model_land
logical function, public fm_change_list(name)
logical, dimension(num_models) model_registered
subroutine, public get_number_tracers(model, num_tracers, num_prog, num_diag, num_family)
logical module_is_initialized
type(method_type), public default_method
logical function, public query_method(method_type, model, n, name, control, err_msg)
subroutine, public tracer_manager_end
subroutine, public set_tracer_atts(model, name, longname, units)
logical function, public adjust_mass(model, n, err_msg)
subroutine, public set_tracer_profile(model, n, tracer, err_msg)
type(inst_type), dimension(max_tracer_fields), save instantiations
integer function get_tracer_index_integer(model, name, indices, verbose)
integer, dimension(num_models) diag_tracers
integer num_tracer_fields
logical function, public check_if_prognostic(model, n, err_msg)
integer, parameter notracer
logical function, public fm_exists(name)
logical function, public fm_query_method(name, method_name, method_control)
integer, parameter max_tracer_method
logical function get_tracer_index_logical(model, name, index, indices, verbose)
character(len=11), dimension(num_models), parameter, public model_names
logical function, public fm_modify_name(oldname, newname)
integer, parameter, public num_models
type(tracer_type), dimension(max_tracer_fields), save tracers
integer, dimension(num_models, max_tracer_fields) tracer_array
subroutine, public get_tracer_names(model, n, name, longname, units, err_msg)
subroutine, public tracer_manager_init
integer function, public fm_copy_list(list_name, suffix, create)
integer, parameter, public model_coupler
integer, parameter, public no_tracer
integer function model_tracer_number(model, n)
subroutine, public get_field_methods(n, methods)
subroutine, public field_manager_init(nfields, table_name)
subroutine, public register_tracers(model, num_tracers, num_prog, num_diag, num_family)