157 module field_manager_mod
160 #define MAXFIELDS_ 250
164 #ifndef MAXFIELDMETHODS_
165 #define MAXFIELDMETHODS_ 250
190 use fms_mod,
only : lowercase, &
193 use fms2_io_mod,
only: file_exists
194 use platform_mod,
only: r4_kind, r8_kind, fms_path_len, fms_file_len
202 #include<file_version.h>
203 logical :: module_is_initialized = .false.
228 public :: fm_get_value_real_r4
229 public :: fm_get_value_real_r8
238 public :: fm_new_value_real_r4
239 public :: fm_new_value_real_r8
284 character(len=11),
parameter,
public,
dimension(NUM_MODELS) :: &
285 model_names=(/
'atmospheric',
'oceanic ',
'land ',
'ice ',
'coupler '/)
305 character(len=fm_string_len) :: method_name
308 character(len=fm_string_len) :: method_control
319 character(len=fm_string_len) :: method_type
320 character(len=fm_string_len) :: method_name
329 character(len=fm_string_len) :: method_type
370 module procedure parse_real_r4
371 module procedure parse_real_r8
372 module procedure parse_reals_r4
373 module procedure parse_reals_r8
399 module procedure fm_new_value_real_r4
400 module procedure fm_new_value_real_r8
418 module procedure fm_get_value_real_r4
419 module procedure fm_get_value_real_r8
437 character(len=17),
parameter :: module_name =
'field_manager_mod'
438 character(len=33),
parameter :: error_header =
'==>Error from '//trim(module_name)//
': '
439 character(len=35),
parameter :: warn_header =
'==>Warning from '//trim(module_name)//
': '
440 character(len=32),
parameter :: note_header =
'==>Note from '//trim(module_name)//
': '
441 character(len=1),
parameter :: comma =
","
442 character(len=1),
parameter :: list_sep =
'/'
444 character(len=1),
parameter :: comment =
'#'
445 character(len=1),
parameter :: dquote =
'"'
446 character(len=1),
parameter :: equal =
'='
447 character(len=1),
parameter :: squote =
"'"
449 integer,
parameter :: null_type = 0
450 integer,
parameter :: integer_type = 1
451 integer,
parameter :: list_type = 2
452 integer,
parameter :: logical_type = 3
453 integer,
parameter :: real_type = 4
454 integer,
parameter :: string_type = 5
455 integer,
parameter :: num_types = 5
456 integer,
parameter :: array_increment = 10
458 integer,
parameter :: MAX_FIELDS = maxfields_
459 integer,
parameter :: MAX_FIELD_METHODS = maxfieldmethods_
465 character(len=fm_field_name_len) :: field_type
466 character(len=fm_string_len) :: field_name
467 integer :: model, num_methods
476 character(len=fm_field_name_len) :: fld_type
477 character(len=fm_field_name_len) :: mod_name
478 character(len=fm_string_len) :: fld_name
484 character(len=fm_field_name_len) :: fld_type
485 character(len=fm_field_name_len) :: mod_name
491 character (len=fm_field_name_len) :: name
493 type (field_def),
pointer :: parent => null()
494 integer :: field_type
498 type (field_def),
pointer :: first_field => null()
499 type (field_def),
pointer :: last_field => null()
500 integer,
allocatable,
dimension(:) :: i_value
501 logical,
allocatable,
dimension(:) :: l_value
502 real(r8_kind),
allocatable,
dimension(:) :: r_value
504 character(len=fm_string_len),
allocatable,
dimension(:) :: s_value
505 type (
field_def),
pointer :: next => null()
506 type (
field_def),
pointer :: prev => null()
514 character(len=FMS_PATH_LEN) :: loop_list
515 character(len=fm_type_name_len) :: field_type_name(num_types)
516 character(len=fm_field_name_len) :: save_root_name
518 character(len=52) :: set =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
521 character(len=50) :: set_nonexp =
"ABCDFGHIJKLMNOPQRSTUVWXYZabcdfghijklmnopqrstuvwxyz"
524 character(len=13) :: setnum =
"0123456789+-."
525 integer :: num_fields = 0
526 type (
field_def),
pointer :: loop_list_p => null()
527 type (
field_def),
pointer :: current_list_p => null()
528 type (
field_def),
pointer :: root_p => null()
529 type (
field_def),
pointer :: save_root_parent_p => null()
557 integer,
intent(out),
optional :: nfields
558 character(len=fm_string_len),
intent(in),
optional :: table_name
560 if (module_is_initialized)
then
561 if(
present(nfields)) nfields = num_fields
571 call mpp_error(fatal,
"You cannot have use_field_table_yaml=.true. without compiling with -Duse_yaml")
573 if (file_exists(
"field_table")) &
574 call mpp_error(fatal,
"You cannot have the legacy field_table if use_field_table_yaml=.true.")
576 call mpp_error(note,
"You are using the yaml version of the field_table")
580 if (file_exists(
"field_table.yaml")) &
581 call mpp_error(fatal,
"You cannot have the yaml field_table if use_field_table_yaml=.false.")
582 call mpp_error(note,
"You are using the legacy version of the field_table")
592 integer,
intent(out),
optional :: nfields
593 character(len=*),
intent(in),
optional :: table_name
595 character(len=FMS_FILE_LEN) :: tbl_name
596 character(len=fm_string_len) :: method_control
597 integer :: h, i, j, k, l, m
598 type (fmTable_t) :: my_table
600 character(len=FMS_PATH_LEN) :: list_name
601 character(len=fm_string_len) :: subparamvalue
602 character(len=fm_string_len) :: fm_yaml_null
603 integer :: current_field
604 integer :: index_list_name
605 integer :: subparamindex
606 logical :: fm_success
609 if (.not.
PRESENT(table_name))
then
610 tbl_name =
'field_table.yaml'
612 tbl_name = trim(table_name)
614 if (.not. file_exists(trim(tbl_name)))
then
615 if(
present(nfields)) nfields = 0
622 do h=1,
size(my_table%types)
623 do i=1,
size(my_table%types(h)%models)
624 do j=1,
size(my_table%types(h)%models(i)%variables)
625 num_fields = num_fields + 1
630 allocate(
fields(num_fields))
633 do h=1,
size(my_table%types)
634 do i=1,
size(my_table%types(h)%models)
635 select case (my_table%types(h)%models(i)%name)
647 call mpp_error(fatal, trim(error_header)//
'The model name is unrecognised : &
648 &'//trim(my_table%types(h)%models(i)%name))
650 do j=1,
size(my_table%types(h)%models(i)%variables)
651 current_field = current_field + 1
652 list_name = list_sep//lowercase(trim(my_table%types(h)%models(i)%name))//list_sep//&
653 lowercase(trim(my_table%types(h)%name))//list_sep//&
654 lowercase(trim(my_table%types(h)%models(i)%variables(j)%name))
655 index_list_name =
fm_new_list(list_name, create = .true.)
656 if ( index_list_name ==
no_field ) &
657 call mpp_error(fatal, trim(error_header)//
'Could not set field list for '//trim(list_name))
659 fields(current_field)%model = model
660 fields(current_field)%field_name = lowercase(trim(my_table%types(h)%models(i)%variables(j)%name))
661 fields(current_field)%field_type = lowercase(trim(my_table%types(h)%name))
662 fields(current_field)%num_methods =
size(my_table%types(h)%models(i)%variables(j)%keys)
663 allocate(
fields(current_field)%methods(
fields(current_field)%num_methods))
664 if(
fields(current_field)%num_methods.gt.0)
then
665 subparams = (
size(my_table%types(h)%models(i)%variables(j)%attributes) .gt. 0)
666 do k=1,
size(my_table%types(h)%models(i)%variables(j)%keys)
667 fields(current_field)%methods(k)%method_type = &
668 lowercase(trim(my_table%types(h)%models(i)%variables(j)%keys(k)))
669 fields(current_field)%methods(k)%method_name = &
670 lowercase(trim(my_table%types(h)%models(i)%variables(j)%values(k)))
671 if (.not.subparams)
then
672 call new_name(list_name, my_table%types(h)%models(i)%variables(j)%keys(k),&
673 my_table%types(h)%models(i)%variables(j)%values(k) )
676 do l=1,
size(my_table%types(h)%models(i)%variables(j)%attributes)
677 if(lowercase(trim(my_table%types(h)%models(i)%variables(j)%attributes(l)%paramname)).eq.&
678 lowercase(trim(
fields(current_field)%methods(k)%method_type)))
then
683 if (subparamindex.eq.-1)
then
684 call new_name(list_name, my_table%types(h)%models(i)%variables(j)%keys(k),&
685 my_table%types(h)%models(i)%variables(j)%values(k) )
687 do m=1,
size(my_table%types(h)%models(i)%variables(j)%attributes(subparamindex)%keys)
690 if (trim(my_table%types(h)%models(i)%variables(j)%values(k)).eq.
'fm_yaml_null')
then
693 fm_yaml_null = trim(my_table%types(h)%models(i)%variables(j)%values(k))//
'/'
695 method_control = trim(my_table%types(h)%models(i)%variables(j)%keys(k))//
"/"//&
696 &trim(fm_yaml_null)//&
697 &trim(my_table%types(h)%models(i)%variables(j)%attributes(subparamindex)%keys(m))
698 subparamvalue = trim(my_table%types(h)%models(i)%variables(j)%attributes(subparamindex)%values(m))
699 call new_name(list_name, method_control, subparamvalue)
709 if (
present(nfields)) nfields = num_fields
721 character(len=*),
intent(in) :: list_name
722 character(len=*),
intent(in) :: method_name_in
724 character(len=*),
intent(inout) :: val_name_in
727 character(len=fm_string_len) :: method_name
728 character(len=fm_string_len) :: val_name
729 integer,
dimension(:),
allocatable :: end_val
730 integer,
dimension(:),
allocatable :: start_val
736 logical :: append_new
738 real(r8_kind) :: val_real
742 method_name = trim(method_name_in)
752 do i = 1, len_trim(val_name_in)
753 if ( val_name_in(i:i) == comma )
then
754 num_elem = num_elem + 1
758 allocate(start_val(num_elem))
759 allocate(end_val(num_elem))
761 end_val(:) = len_trim(val_name_in)
764 do i = 1, len_trim(val_name_in)
765 if ( val_name_in(i:i) == comma )
then
766 end_val(num_elem) = i-1
767 start_val(num_elem+1) = i+1
768 num_elem = num_elem + 1
774 if ( i .gt. 1 .or. index_t .eq. 0 )
then
778 val_type = string_type
779 val_name = val_name_in(start_val(i):end_val(i))
782 if ( scan(val_name(1:1), setnum ) > 0 )
then
783 if ( scan(val_name, set_nonexp ) .le. 0 )
then
784 if ( scan(val_name,
'.') > 0 .or. scan(val_name,
'e') > 0 .or. scan(val_name,
'E') > 0)
then
785 read(val_name, *) val_real
788 read(val_name, *) val_int
789 val_type = integer_type
794 if ( len_trim(val_name) == 1 .or. len_trim(val_name) == 3)
then
795 if ( val_name ==
't' .or. val_name ==
'T' .or. val_name ==
'.t.' .or. val_name ==
'.T.' )
then
797 val_type = logical_type
799 if ( val_name ==
'f' .or. val_name ==
'F' .or. val_name ==
'.f.' .or. val_name ==
'.F.' )
then
801 val_type = logical_type
804 if ( trim(lowercase(val_name)) ==
'true' .or. trim(lowercase(val_name)) ==
'.true.' )
then
806 val_type = logical_type
808 if ( trim(lowercase(val_name)) ==
'false' .or. trim(lowercase(val_name)) ==
'.false.' )
then
810 val_type = logical_type
813 select case(val_type)
816 if (
fm_new_value( method_name, val_int, create = .true., index = index_t, append = append_new ) < 0 ) &
817 call mpp_error(fatal, trim(error_header)//
'Could not set "' // trim(val_name) //
'" for '//trim(method_name)//&
818 ' (I) for '//trim(list_name))
821 if (
fm_new_value( method_name, val_logic, create = .true., index = index_t, append = append_new) < 0 ) &
822 call mpp_error(fatal, trim(error_header)//
'Could not set "' // trim(val_name) //
'" for '//trim(method_name)//&
823 ' (L) for '//trim(list_name))
826 if (
fm_new_value( method_name, val_real, create = .true., index = index_t, append = append_new) < 0 ) &
827 call mpp_error(fatal, trim(error_header)//
'Could not set "' // trim(val_name) //
'" for '//trim(method_name)//&
828 ' (R) for '//trim(list_name))
831 if (
fm_new_value( method_name, val_name, create = .true., index = index_t, append = append_new) < 0 ) &
832 call mpp_error(fatal, trim(error_header)//
'Could not set "' // trim(val_name) //
'" for '//trim(method_name)//&
833 ' (S) for '//trim(list_name))
835 call mpp_error(fatal, trim(error_header)//
'Could not find a valid type to set the '//trim(method_name)//&
836 ' for '//trim(list_name))
841 deallocate(start_val)
856 integer,
intent(out),
optional :: nfields
857 character(len=fm_string_len),
intent(in),
optional :: table_name
860 character(len=1024) :: record
861 character(len=fm_string_len) :: control_str
862 character(len=FMS_PATH_LEN) :: list_name
863 character(len=fm_string_len) :: method_name
864 character(len=fm_string_len) :: name_str
865 character(len=fm_string_len) :: type_str
866 character(len=fm_string_len) :: val_name
867 character(len=fm_string_len) :: tbl_name
868 integer :: control_array(MAX_FIELDS,3)
871 integer :: index_list_name
881 logical :: flag_method
882 logical :: fm_success
889 if (.not.
PRESENT(table_name))
then
890 tbl_name =
'field_table'
892 tbl_name = trim(table_name)
894 if (.not. file_exists(trim(tbl_name)))
then
895 if(
present(nfields)) nfields = 0
899 allocate(
fields(max_fields))
901 open(newunit=iunit, file=trim(tbl_name), action=
'READ', iostat=io_status)
902 if(io_status/=0)
call mpp_error(fatal,
'field_manager_mod: Error in opening file '//trim(tbl_name))
907 read(iunit,
'(a)',
end=89,err=99) record
908 write( log_unit,
'(a)' )record
909 if (record(1:1) ==
"#" ) cycle
910 ltrec = len_trim(record)
911 if (ltrec .le. 0 ) cycle
916 if (record(l:l) ==
'"' )
then
920 if (icount > 6 )
then
921 call mpp_error(fatal,trim(error_header)//
'Too many fields in field table header entry.'//trim(record))
926 read(record,*,
end=79,err=79) text_names
927 text_names%fld_type = lowercase(trim(text_names%fld_type))
928 text_names%mod_name = lowercase(trim(text_names%mod_name))
929 text_names%fld_name = lowercase(trim(text_names%fld_name))
932 read(record,*,
end=79,err=79) text_names_short
933 text_names%fld_type = lowercase(trim(text_names_short%fld_type))
934 text_names%mod_name = lowercase(trim(text_names_short%mod_name))
935 text_names%fld_name = lowercase(trim(text_names_short%mod_name))
939 read(record,*,
end=79,err=79) text_names_short
940 text_names%fld_type = lowercase(trim(text_names_short%fld_type))
941 text_names%mod_name = lowercase(trim(text_names_short%mod_name))
942 text_names%fld_name = lowercase(trim(text_names_short%mod_name))
945 text_names%fld_type =
" "
946 text_names%mod_name = lowercase(trim(record))
947 text_names%fld_name =
" "
952 list_name = list_sep//trim(text_names%mod_name)//list_sep//trim(text_names%fld_type)//&
953 list_sep//trim(text_names%fld_name)
955 index_list_name =
fm_new_list(list_name, create = .true.)
956 if ( index_list_name ==
no_field ) &
957 call mpp_error(fatal, trim(error_header)//
'Could not set field list for '//trim(list_name))
960 select case (text_names%mod_name)
972 call mpp_error(fatal, trim(error_header)//
'The model name is unrecognised : '//trim(text_names%mod_name))
975 num_fields = num_fields + 1
977 if (num_fields > max_fields)
call mpp_error(fatal,trim(error_header)//
'max fields exceeded')
978 fields(num_fields)%model = model
979 fields(num_fields)%field_name = lowercase(trim(text_names%fld_name))
980 fields(num_fields)%field_type = lowercase(trim(text_names%fld_type))
981 fields(num_fields)%num_methods = 0
982 allocate(
fields(num_fields)%methods(max_field_methods))
983 call check_for_name_duplication
986 if ( record(len_trim(record):len_trim(record)) == list_sep) cycle
990 do while (flag_method)
991 read(iunit,
'(a)',
end=99,err=99) record
993 if (len_trim(record) .le. 0) cycle
995 if ( record(len_trim(record):len_trim(record)) == list_sep)
then
996 flag_method = .false.
997 if (len_trim(record) == 1) cycle
998 record = record(:len_trim(record)-1)
1001 if (len_trim(record) .le. 0) cycle
1003 if (record(1:1) == comment ) cycle
1006 do l= 1, len_trim(record)
1007 if (record(l:l) == dquote )
then
1011 if (icount > 6 )
call mpp_error(fatal,trim(error_header)//
'Too many fields in field entry.'//trim(record))
1014 call mpp_error(fatal, trim(error_header)//
'Could not change to '//trim(list_name)//
' list')
1016 select case (icount)
1018 read(record,*,
end=99,err=99) text_method
1019 fields(num_fields)%methods(m)%method_type = lowercase(trim(text_method%method_type))
1020 fields(num_fields)%methods(m)%method_name = lowercase(trim(text_method%method_name))
1021 fields(num_fields)%methods(m)%method_control = lowercase(trim(text_method%method_control))
1023 type_str = text_method%method_type
1024 name_str = text_method%method_name
1025 control_str = text_method%method_control
1029 read(record,*,
end=99,err=99) text_method_short
1030 fields(num_fields)%methods(m)%method_type =&
1031 & lowercase(trim(text_method_short%method_type))
1032 fields(num_fields)%methods(m)%method_name =&
1033 & lowercase(trim(text_method_short%method_name))
1034 fields(num_fields)%methods(m)%method_control =
" "
1036 type_str = text_method_short%method_type
1038 control_str = text_method_short%method_name
1043 read(record,*,
end=99,err=99) text_method_very_short
1044 fields(num_fields)%methods(m)%method_type = lowercase(trim(text_method_very_short%method_type))
1045 fields(num_fields)%methods(m)%method_name =
" "
1046 fields(num_fields)%methods(m)%method_control =
" "
1050 control_str = text_method_very_short%method_type
1053 read(record,
'(A)',
end=99,err=99) control_str
1058 call mpp_error(fatal,trim(error_header)//
'Unterminated field in field entry.'//trim(record))
1070 ltrec= len_trim(control_str)
1071 control_array(:,1) = 1
1072 control_array(:,2:3) = ltrec
1075 if (control_str(l:l) == equal )
then
1077 control_array(icount,2) = l
1078 elseif (control_str(l:l) == comma )
then
1079 if (icount .eq. 0)
then
1080 call mpp_error(fatal,trim(error_header) // &
1081 ' Bad format for field entry (comma without equals sign): ''' // &
1082 trim(control_str) //
'''')
1083 elseif (icount .gt. max_fields)
then
1084 call mpp_error(fatal,trim(error_header) // &
1085 ' Too many fields in field entry: ''' // &
1086 trim(control_str) //
'''')
1088 control_array(icount,3) = l-1
1089 control_array(min(max_fields,icount+1),1) = l+1
1098 if (control_str(ltrec:ltrec) .ne. comma)
then
1099 control_array(max(1,icount),3) = ltrec
1102 if ( icount == 0 )
then
1103 method_name = type_str
1104 if (len_trim(method_name) > 0 )
then
1105 method_name = trim(method_name)//list_sep// trim(name_str)
1107 method_name = trim(name_str)
1109 val_name = control_str
1111 call new_name(list_name, method_name, val_name )
1116 startcont = control_array(l,1)
1117 midcont = control_array(l,2)
1118 endcont = control_array(l,3)
1120 method_name = trim(type_str)
1121 if (len_trim(method_name) > 0 )
then
1122 method_name = trim(method_name)//list_sep// trim(name_str)
1124 method_name = trim(name_str)
1127 if (len_trim(method_name) > 0 )
then
1128 method_name = trim(method_name)//list_sep//&
1129 trim(control_str(startcont:midcont-1))
1131 method_name = trim(control_str(startcont:midcont-1))
1133 val_name = trim(control_str(midcont+1:endcont))
1135 call new_name(list_name, method_name, val_name )
1140 fields(num_fields)%num_methods =
fields(num_fields)%num_methods + 1
1141 if (
fields(num_fields)%num_methods > max_field_methods) &
1142 call mpp_error(fatal,trim(error_header)//
'Maximum number of methods for field exceeded')
1146 flag_method = .true.
1147 do while (flag_method)
1148 read(iunit,
'(A)',
end=99,err=99) record
1149 if ( record(len_trim(record):len_trim(record)) == list_sep)
then
1150 flag_method = .false.
1158 close(iunit, iostat=io_status)
1159 if(io_status/=0)
call mpp_error(fatal,
'field_manager_mod: Error in closing file '//trim(tbl_name))
1162 if(
present(nfields)) nfields = num_fields
1164 default_method%method_type =
'none'
1165 default_method%method_name =
'none'
1166 default_method%method_control =
'none'
1171 call mpp_error(fatal,trim(error_header)//
' Error reading field table. Record = '//trim(record))
1175 subroutine check_for_name_duplication
1180 if (
fields(i)%field_type ==
fields(num_fields)%field_type .and. &
1182 fields(i)%field_name ==
fields(num_fields)%field_name )
then
1183 if (
mpp_pe() .eq. mpp_root_pe())
then
1184 call mpp_error(warning,
'Error in field_manager_mod. Duplicate field name: Field type='//&
1185 trim(
fields(i)%field_type)// &
1187 ', Duplicated name='//trim(
fields(i)%field_name))
1192 end subroutine check_for_name_duplication
1202 subroutine new_name ( list_name, method_name_in , val_name_in)
1203 character(len=*),
intent(in) :: list_name
1204 character(len=*),
intent(in) :: method_name_in
1206 character(len=*),
intent(inout) :: val_name_in
1209 character(len=fm_string_len) :: method_name
1210 character(len=fm_string_len) :: val_name
1211 integer,
dimension(MAX_FIELDS) :: end_val
1212 integer,
dimension(MAX_FIELDS) :: start_val
1221 logical :: append_new
1222 logical :: val_logic
1223 real(r8_kind) :: val_real
1227 method_name = trim(method_name_in)
1232 append_new = .false.
1234 end_val(:) = len_trim(val_name_in)
1239 do i = 1, len_trim(val_name_in)
1240 if ( val_name_in(i:i) == comma )
then
1241 end_val(num_elem) = i-1
1242 start_val(num_elem+1) = i+1
1243 num_elem = num_elem + 1
1248 left_br = scan(method_name,
'[')
1249 right_br = scan(method_name,
']')
1250 if ( num_elem .eq. 1 )
then
1251 if ( left_br > 0 .and. right_br == 0 ) &
1252 call mpp_error(fatal, trim(error_header)//
"Left bracket present without right bracket in "//trim(method_name))
1253 if ( left_br== 0 .and. right_br > 0 ) &
1254 call mpp_error(fatal, trim(error_header)//
"Right bracket present without left bracket in "//trim(method_name))
1255 if ( left_br > 0 .and. right_br > 0 )
then
1256 if ( scan( method_name(left_br+1:right_br -1), set ) > 0 ) &
1257 call mpp_error(fatal, trim(error_header)//
"Using a non-numeric value for index in "//trim(method_name))
1258 read(method_name(left_br+1:right_br -1), *) index_t
1259 method_name = method_name(:left_br -1)
1263 if ( left_br > 0 .or. right_br > 0 ) &
1264 call mpp_error(fatal, &
1265 trim(error_header)//
"Using a comma delimited list with an indexed array element in "//trim(method_name))
1270 if ( i .gt. 1 .or. index_t .eq. 0 )
then
1274 val_type = string_type
1275 val_name = val_name_in(start_val(i):end_val(i))
1283 length = len_trim(val_name)
1284 if (val_name(1:1) .eq. squote)
then
1286 if (val_name(length:length) .eq. squote)
then
1287 val_name = val_name(2:length-1)//repeat(
" ",len(val_name)-length+2)
1288 val_type = string_type
1289 elseif (val_name(length:length) .eq. dquote)
then
1290 call mpp_error(fatal, trim(error_header) //
' Quotes do not match in ' // trim(val_name) // &
1291 ' for ' // trim(method_name) //
' of ' // trim(list_name))
1293 call mpp_error(fatal, trim(error_header) //
' No trailing quote in ' // trim(val_name) // &
1294 ' for ' // trim(method_name) //
' of ' // trim(list_name))
1297 elseif (val_name(1:1) .eq. dquote .or. val_name(length:length) .eq. dquote)
then
1299 call mpp_error(fatal, trim(error_header) //
' Double quotes not allowed in ' // trim(val_name) // &
1300 ' for ' // trim(method_name) //
' of ' // trim(list_name))
1302 elseif (val_name(length:length) .eq. squote)
then
1304 call mpp_error(fatal, trim(error_header) //
' No leading quote in ' // trim(val_name) // &
1305 ' for ' // trim(method_name) //
' of ' // trim(list_name))
1313 if ( scan(val_name(1:1), setnum ) > 0 )
then
1317 if ( scan(val_name, set_nonexp ) .le. 0 )
then
1319 if ( scan(val_name,
'.') > 0 .or. scan(val_name,
'e') > 0 .or. scan(val_name,
'E') > 0)
then
1320 read(val_name, *) val_real
1321 val_type = real_type
1323 read(val_name, *) val_int
1324 val_type = integer_type
1331 if ( len_trim(val_name) == 1 .or. len_trim(val_name) == 3)
then
1332 if ( val_name ==
't' .or. val_name ==
'T' .or. val_name ==
'.t.' .or. val_name ==
'.T.' )
then
1334 val_type = logical_type
1336 if ( val_name ==
'f' .or. val_name ==
'F' .or. val_name ==
'.f.' .or. val_name ==
'.F.' )
then
1338 val_type = logical_type
1341 if ( trim(lowercase(val_name)) ==
'true' .or. trim(lowercase(val_name)) ==
'.true.' )
then
1343 val_type = logical_type
1345 if ( trim(lowercase(val_name)) ==
'false' .or. trim(lowercase(val_name)) ==
'.false.' )
then
1347 val_type = logical_type
1351 select case(val_type)
1354 if (
fm_new_value( method_name, val_int, create = .true., index = index_t, append = append_new ) < 0 ) &
1355 call mpp_error(fatal, trim(error_header)//
'Could not set "' // trim(val_name) //
'" for '//trim(method_name)//&
1356 ' (I) for '//trim(list_name))
1359 if (
fm_new_value( method_name, val_logic, create = .true., index = index_t, append = append_new) < 0 ) &
1360 call mpp_error(fatal, trim(error_header)//
'Could not set "' // trim(val_name) //
'" for '//trim(method_name)//&
1361 ' (L) for '//trim(list_name))
1364 if (
fm_new_value( method_name, val_real, create = .true., index = index_t, append = append_new) < 0 ) &
1365 call mpp_error(fatal, trim(error_header)//
'Could not set "' // trim(val_name) //
'" for '//trim(method_name)//&
1366 ' (R) for '//trim(list_name))
1369 if (
fm_new_value( method_name, val_name, create = .true., index = index_t, append = append_new) < 0 ) &
1370 call mpp_error(fatal, trim(error_header)//
'Could not set "' // trim(val_name) //
'" for '//trim(method_name)//&
1371 ' (S) for '//trim(list_name))
1373 call mpp_error(fatal, trim(error_header)//
'Could not find a valid type to set the '//trim(method_name)//&
1374 ' for '//trim(list_name))
1389 module_is_initialized = .false.
1392 if(
allocated(
fields(j)%methods))
deallocate(
fields(j)%methods)
1403 character(len=*),
intent(inout) :: name
1405 name = trim(adjustl(name))
1417 integer,
intent(in) :: model
1418 character(len=*),
intent(in) :: field_name
1425 if (
fields(i)%model == model .and.
fields(i)%field_name == lowercase(field_name))
then
1437 character(len=*),
intent(in) :: field_name
1456 integer,
intent(in) :: n
1457 character (len=*),
intent(out) :: fld_type
1458 character (len=*),
intent(out) :: fld_name
1459 integer,
intent(out) :: model
1460 integer,
intent(out) :: num_methods
1462 if (n < 1 .or. n > num_fields)
call mpp_error(fatal,trim(error_header)//
'Invalid field index')
1464 fld_type =
fields(n)%field_type
1465 fld_name =
fields(n)%field_name
1467 num_methods =
fields(n)%num_methods
1477 integer,
intent(in) :: n
1478 integer,
intent(in) :: m
1481 if (n < 1 .or. n > num_fields)
call mpp_error(fatal,trim(error_header)//
'Invalid field index')
1482 if (m < 1 .or. m >
fields(n)%num_methods)
call mpp_error(fatal,trim(error_header)//
'Invalid method index')
1484 method =
fields(n)%methods(m)
1494 integer,
intent(in) :: n
1497 if (n < 1 .or. n > num_fields) &
1498 call mpp_error(fatal,trim(error_header)//
'Invalid field index')
1500 if (
size(methods(:)) <
fields(n)%num_methods) &
1501 call mpp_error(fatal,trim(error_header)//
'Method array too small')
1503 methods = default_method
1512 character(len=*),
intent(in) :: text
1513 character(len=*),
intent(in) :: label
1514 integer,
intent(out) :: values(:)
1520 character(len=*),
intent(in) :: text
1521 character(len=*),
intent(in) :: label
1522 character(len=*),
intent(out) :: values(:)
1528 character(len=*),
intent(in) :: text
1529 character(len=*),
intent(in) :: label
1530 integer,
intent(out) :: parse_ival
1533 integer :: values(1)
1536 if (
parse > 0) parse_ival = values(1)
1540 character(len=*),
intent(in) :: text
1541 character(len=*),
intent(in) :: label
1542 character(len=*),
intent(out) :: parse_sval
1545 character(len=len(parse_sval)) :: values(1)
1548 if (
parse > 0) parse_sval = values(1)
1565 character(len=*),
intent(in) :: name
1567 integer :: error, out_unit
1570 if (.not.
associated(parent_p) .or. name .eq.
' ')
then
1576 allocate(list_p, stat = error)
1577 if (error .ne. 0)
then
1578 write (out_unit,*) trim(error_header),
'Error ', error, &
1579 ' allocating memory for list ', trim(name)
1586 nullify(list_p%next)
1587 list_p%prev => parent_p%last_field
1588 nullify(list_p%first_field)
1589 nullify(list_p%last_field)
1591 list_p%field_type = null_type
1592 list_p%max_index = 0
1593 list_p%array_dim = 0
1594 if (
allocated(list_p%i_value))
deallocate(list_p%i_value)
1595 if (
allocated(list_p%l_value))
deallocate(list_p%l_value)
1596 if (
allocated(list_p%r_value))
deallocate(list_p%r_value)
1597 if (
allocated(list_p%s_value))
deallocate(list_p%s_value)
1600 if (parent_p%length .le. 0)
then
1601 parent_p%first_field => list_p
1603 parent_p%last_field%next => list_p
1606 parent_p%last_field => list_p
1608 parent_p%length = parent_p%length + 1
1610 list_p%index = parent_p%length
1612 list_p%parent => parent_p
1626 logical recursive function
dump_list(list_p,
recursive, depth, out_unit) result(success)
1629 logical,
intent(in) ::
recursive
1630 integer,
intent(in) :: depth
1632 integer,
intent(in) :: out_unit
1636 character(len=fm_field_name_len) :: num, scratch
1637 type (
field_def),
pointer :: this_field_p
1638 character(len=depth+fm_field_name_len) :: blank
1644 if (.not.
associated(list_p))
then
1646 elseif (list_p%field_type .ne. list_type)
then
1654 write (out_unit,
'(a,a,a)') blank(1:depth), trim(list_p%name), list_sep
1661 this_field_p => list_p%first_field
1663 do while (
associated(this_field_p))
1665 select case(this_field_p%field_type)
1670 success =
dump_list(this_field_p, .true., depthp1, out_unit)
1671 if (.not.success)
exit
1673 write (out_unit,
'(a,a,a)') blank(1:depthp1), trim(this_field_p%name), list_sep
1677 if (this_field_p%max_index .eq. 0)
then
1678 write (out_unit,
'(a,a,a)') blank(1:depthp1), trim(this_field_p%name),
' = NULL'
1679 elseif (this_field_p%max_index .eq. 1)
then
1680 write (scratch,*) this_field_p%i_value(1)
1681 write (out_unit,
'(a,a,a,a)') blank(1:depthp1), trim(this_field_p%name),
' = ', &
1682 trim(adjustl(scratch))
1684 do j = 1, this_field_p%max_index
1685 write (scratch,*) this_field_p%i_value(j)
1687 write (out_unit,
'(a,a,a,a,a,a)') blank(1:depthp1), trim(this_field_p%name), &
1688 '[', trim(adjustl(num)),
'] = ', trim(adjustl(scratch))
1693 if (this_field_p%max_index .eq. 0)
then
1694 write (out_unit,
'(a,a,a)') blank(1:depthp1), trim(this_field_p%name),
' = NULL'
1695 elseif (this_field_p%max_index .eq. 1)
then
1696 write (scratch,
'(l1)') this_field_p%l_value(1)
1697 write (out_unit,
'(a,a,a,a)') blank(1:depthp1), trim(this_field_p%name),
' = ', &
1698 trim(adjustl(scratch))
1700 do j = 1, this_field_p%max_index
1701 write (scratch,
'(l1)') this_field_p%l_value(j)
1703 write (out_unit,
'(a,a,a,a,a,a)') blank(1:depthp1), trim(this_field_p%name), &
1704 '[', trim(adjustl(num)),
'] = ', trim(adjustl(scratch))
1709 if (this_field_p%max_index .eq. 0)
then
1710 write (out_unit,
'(a,a,a)') blank(1:depthp1), trim(this_field_p%name),
' = NULL'
1711 elseif (this_field_p%max_index .eq. 1)
then
1712 write (scratch,*) this_field_p%r_value(1)
1713 write (out_unit,
'(a,a,a,a)') blank(1:depthp1), trim(this_field_p%name),
' = ', &
1714 trim(adjustl(scratch))
1716 do j = 1, this_field_p%max_index
1717 write (scratch,*) this_field_p%r_value(j)
1719 write (out_unit,
'(a,a,a,a,a,a)') blank(1:depthp1), trim(this_field_p%name), &
1720 '[', trim(adjustl(num)),
'] = ', trim(adjustl(scratch))
1725 if (this_field_p%max_index .eq. 0)
then
1726 write (out_unit,
'(a,a,a)') blank(1:depthp1), trim(this_field_p%name),
' = NULL'
1727 elseif (this_field_p%max_index .eq. 1)
then
1728 write (out_unit,
'(a,a,a,a)') blank(1:depthp1), trim(this_field_p%name),
' = ', &
1729 ''''//trim(this_field_p%s_value(1))//
''''
1731 do j = 1, this_field_p%max_index
1733 write (out_unit,
'(a,a,a,a,a,a)') blank(1:depthp1), trim(this_field_p%name), &
1734 '[', trim(adjustl(num)),
'] = ',
''''//trim(this_field_p%s_value(j))//
''''
1744 this_field_p => this_field_p%next
1757 character(len=*),
intent(in) :: name
1758 character(len=*),
intent(out) :: path
1759 character(len=*),
intent(out) :: base
1766 length = max(len_trim(name),0)
1767 if (length .eq. 0)
then
1774 do while (name(length:length) .eq. list_sep)
1776 if (length .eq. 0)
then
1780 if (length .eq. 0)
then
1787 i = index(name(1:length), list_sep, back = .true.)
1792 base = name(1:length)
1797 base = name(i+1:length)
1815 character(len=*),
intent(in) :: name
1816 type (
field_def),
pointer :: this_list_p
1819 type (
field_def),
pointer,
save :: temp_p
1824 if (name .eq.
'.')
then
1827 field_p => this_list_p
1828 elseif (name .eq.
'..')
then
1830 field_p => this_list_p%parent
1833 temp_p => this_list_p%first_field
1835 do while (
associated(temp_p))
1838 if (temp_p%name .eq. name)
then
1843 temp_p => temp_p%next
1859 character(len=*),
intent(in) :: name
1860 character(len=*),
intent(out) :: head
1861 character(len=*),
intent(out) :: rest
1865 i = index(name, list_sep)
1868 do while (i .le. len(name))
1869 if (name(i+1:i+1) .eq. list_sep)
then
1881 elseif (i .eq. len(name))
then
1906 character(len=*),
intent(in) :: path
1908 logical,
intent(in) :: create
1910 character(len=FMS_PATH_LEN) :: working_path
1911 character(len=FMS_PATH_LEN) :: rest
1912 character(len=fm_field_name_len) :: this_list
1913 integer :: i, out_unit
1914 type (
field_def),
pointer,
save :: working_path_p
1915 type (
field_def),
pointer,
save :: this_list_p
1920 if (path .eq.
' ')
then
1922 list_p => relative_p
1928 if (path(1:1) .eq. list_sep)
then
1929 working_path_p => root_p
1930 working_path = path(2:)
1932 working_path_p => relative_p
1936 do while (working_path .ne.
' ')
1938 call find_head(working_path, this_list, rest)
1941 if (this_list .eq.
' ')
then
1946 i = len_trim(this_list)
1947 do while (i .gt. 0 .and. this_list(i:i) .eq. list_sep)
1948 this_list(i:i) =
' '
1952 this_list_p =>
find_field(this_list, working_path_p)
1954 if (.not.
associated(this_list_p))
then
1957 this_list_p =>
make_list(working_path_p, this_list)
1958 if (.not.
associated(this_list_p))
then
1971 if (this_list_p%field_type .eq. list_type)
then
1972 working_path_p => this_list_p
1979 list_p => working_path_p
1994 character(len=*),
intent(in) :: name
1996 type (
field_def),
pointer,
save :: temp_p
1998 if (.not. module_is_initialized)
then
2002 temp_p =>
find_list(name, current_list_p, .false.)
2004 if (
associated(temp_p))
then
2005 current_list_p => temp_p
2026 character(len=*),
intent(in) :: name
2028 type (
field_def),
pointer,
save :: temp_list_p
2031 if (.not. module_is_initialized)
then
2036 if (name .eq.
' ')
then
2041 temp_list_p =>
find_list(name, current_list_p, .false.)
2043 if (
associated(temp_list_p))
then
2045 if (save_root_name .ne.
' ')
then
2046 root_p%name = save_root_name
2047 root_p%parent => save_root_parent_p
2050 root_p => temp_list_p
2052 save_root_name = root_p%name
2053 save_root_parent_p => root_p%parent
2056 nullify(root_p%parent)
2059 current_list_p => root_p
2075 character(len=*),
intent(in) :: name
2076 logical,
intent(in),
optional ::
recursive
2078 integer,
intent(in),
optional :: unit
2080 logical :: recursive_t
2081 type (
field_def),
pointer,
save :: temp_list_p
2084 if (
present(unit))
then
2090 recursive_t = .false.
2091 if (
present(
recursive)) recursive_t =
recursive
2094 if (name .eq.
' ')
then
2096 temp_list_p => current_list_p
2100 temp_list_p =>
find_list(name, current_list_p, .false.)
2101 if (
associated(temp_list_p))
then
2109 success =
dump_list(temp_list_p, recursive_t, 0, out_unit)
2121 character(len=*),
intent(in) :: name
2123 type (
field_def),
pointer,
save :: dummy_p
2125 if (.not. module_is_initialized)
then
2129 dummy_p =>
get_field(name, current_list_p)
2130 success =
associated(dummy_p)
2144 character(len=*),
intent(in) :: name
2146 type (
field_def),
pointer,
save :: temp_field_p
2151 if (.not. module_is_initialized)
then
2155 if (name .eq.
' ')
then
2160 temp_field_p =>
get_field(name, current_list_p)
2161 if (
associated(temp_field_p))
then
2163 index = temp_field_p%index
2177 character(len=FMS_PATH_LEN) :: path
2179 type (
field_def),
pointer,
save :: temp_list_p
2181 if (.not. module_is_initialized)
then
2186 temp_list_p => current_list_p
2189 do while (
associated(temp_list_p))
2192 if (temp_list_p%name .eq.
' ')
then
2196 path = list_sep // trim(temp_list_p%name) // path
2198 temp_list_p => temp_list_p%parent
2201 if (.not.
associated(temp_list_p))
then
2205 elseif (path .eq.
' ')
then
2222 character(len=*),
intent(in) :: name
2224 type (
field_def),
pointer,
save :: temp_field_p
2229 if (.not. module_is_initialized)
then
2233 if (name .eq.
' ')
then
2238 temp_field_p =>
get_field(name, current_list_p)
2240 if (
associated(temp_field_p))
then
2242 if (temp_field_p%field_type .eq. list_type)
then
2243 length = temp_field_p%length
2245 length = temp_field_p%max_index
2261 result(name_field_type)
2262 character(len=8) :: name_field_type
2263 character(len=*),
intent(in) :: name
2265 type (
field_def),
pointer,
save :: temp_field_p
2270 if (.not. module_is_initialized)
then
2274 if (name .eq.
' ')
then
2275 name_field_type =
' '
2279 temp_field_p =>
get_field(name, current_list_p)
2281 if (
associated(temp_field_p))
then
2283 name_field_type = field_type_name(temp_field_p%field_type)
2285 name_field_type =
' '
2295 character(len=*),
intent(in) :: name
2296 integer,
intent(out) :: get_ival
2297 integer,
intent(in),
optional :: index
2300 type (
field_def),
pointer,
save :: temp_field_p
2305 if (.not. module_is_initialized)
then
2309 if (name .eq.
' ')
then
2315 if (
present(index))
then
2321 temp_field_p =>
get_field(name, current_list_p)
2323 if (
associated(temp_field_p))
then
2325 if (temp_field_p%field_type .eq. integer_type)
then
2326 if (index_t .lt. 1 .or. index_t .gt. temp_field_p%max_index)
then
2332 get_ival = temp_field_p%i_value(index_t)
2352 character(len=*),
intent(in) :: name
2353 logical,
intent(out) :: get_lval
2354 integer,
intent(in),
optional :: index
2357 type (
field_def),
pointer,
save :: temp_field_p
2362 if (.not. module_is_initialized)
then
2366 if (name .eq.
' ')
then
2372 if (
present(index))
then
2378 temp_field_p =>
get_field(name, current_list_p)
2380 if (
associated(temp_field_p))
then
2382 if (temp_field_p%field_type .eq. logical_type)
then
2384 if (index_t .lt. 1 .or. index_t .gt. temp_field_p%max_index)
then
2390 get_lval = temp_field_p%l_value(index_t)
2410 character(len=*),
intent(in) :: name
2411 character(len=*),
intent(out) :: get_sval
2412 integer,
intent(in),
optional :: index
2415 type (
field_def),
pointer,
save :: temp_field_p
2420 if (.not. module_is_initialized)
then
2424 if (name .eq.
' ')
then
2430 if (
present(index))
then
2436 temp_field_p =>
get_field(name, current_list_p)
2438 if (
associated(temp_field_p))
then
2440 if (temp_field_p%field_type .eq. string_type)
then
2441 if (index_t .lt. 1 .or. index_t .gt. temp_field_p%max_index)
then
2447 get_sval = temp_field_p%s_value(index_t)
2468 character(len=*),
intent(in) :: list
2469 character(len=*),
intent(out) :: name
2470 character(len=fm_type_name_len),
intent(out) :: field_type
2471 integer,
intent(out) :: index
2477 if (.not. module_is_initialized)
then
2481 if (list .eq. loop_list .and.
associated(loop_list_p))
then
2483 loop_list_p => loop_list_p%next
2485 elseif (list .eq.
' ')
then
2488 loop_list_p => current_list_p%first_field
2493 loop_list_p =>
find_list(loop_list, current_list_p, .false.)
2494 if (
associated(loop_list_p))
then
2495 loop_list_p => loop_list_p%first_field
2515 if (
associated(loop_list_p))
then
2516 name = loop_list_p%name
2517 field_type = field_type_name(loop_list_p%field_type)
2518 index = loop_list_p%index
2535 character(len=*) ,
intent(in) :: loop_list
2540 if (loop_list==
' ')
then
2541 iter%ptr => current_list_p%first_field
2543 iter%ptr =>
find_list(loop_list,current_list_p,.false.)
2544 if (
associated(iter%ptr)) iter%ptr => iter%ptr%first_field
2552 result(success) ;
logical success
2554 character(len=*),
intent(out) :: name
2555 character(len=*),
intent(out) :: field_type
2556 integer ,
intent(out) :: index
2559 if (
associated(iter%ptr))
then
2560 name = iter%ptr%name
2561 field_type = field_type_name(iter%ptr%field_type)
2562 index = iter%ptr%index
2564 iter%ptr => iter%ptr%next
2581 character(len=*),
intent(in) :: name
2582 logical,
intent(in),
optional :: create
2583 logical,
intent(in),
optional :: keep
2587 character(len=FMS_PATH_LEN) :: path
2588 character(len=fm_field_name_len) :: base
2589 type (
field_def),
pointer,
save :: temp_list_p
2594 if (.not. module_is_initialized)
then
2598 if (name .eq.
' ')
then
2603 if (
present(create))
then
2609 if (
present(keep))
then
2617 temp_list_p =>
find_list(path, current_list_p, create_t)
2619 if (
associated(temp_list_p))
then
2621 temp_list_p =>
make_list(temp_list_p, base)
2622 if (
associated(temp_list_p))
then
2625 current_list_p => temp_list_p
2627 index = temp_list_p%index
2641 integer :: field_index
2642 character(len=*),
intent(in) :: name
2644 integer,
intent(in) :: new_ival
2646 logical,
intent(in),
optional :: create
2648 integer,
intent(in),
optional :: index
2650 logical,
intent(in),
optional :: append
2656 integer,
pointer,
dimension(:) :: temp_i_value
2657 character(len=FMS_PATH_LEN) :: path
2658 character(len=fm_field_name_len) :: base
2659 type (
field_def),
pointer,
save :: temp_list_p
2660 type (
field_def),
pointer,
save :: temp_field_p
2665 if (.not. module_is_initialized)
then
2669 if (name .eq.
' ')
then
2674 if (
present(create))
then
2680 if (
present(index) .and.
present(append))
then
2681 if (append .and. index .gt. 0)
then
2687 if (
present(index))
then
2689 if (index_t .lt. 0)
then
2699 temp_list_p =>
find_list(path, current_list_p, create_t)
2701 if (
associated(temp_list_p))
then
2702 temp_field_p =>
find_field(base, temp_list_p)
2703 if (.not.
associated(temp_field_p))
then
2707 if (
associated(temp_field_p))
then
2710 if (temp_field_p%field_type == real_type )
then
2713 field_index =
fm_new_value(name, real(new_ival,r8_kind), create, index, append)
2715 else if (temp_field_p%field_type /= integer_type )
then
2718 temp_field_p%max_index = 0
2721 temp_field_p%field_type = integer_type
2723 if (
present(append))
then
2725 index_t = temp_field_p%max_index + 1
2729 if (index_t .gt. temp_field_p%max_index + 1)
then
2734 elseif (index_t .eq. 0 .and. &
2735 temp_field_p%max_index .gt. 0)
then
2740 elseif (.not.
allocated(temp_field_p%i_value) .and. &
2741 index_t .gt. 0)
then
2743 allocate(temp_field_p%i_value(1))
2744 temp_field_p%max_index = 1
2745 temp_field_p%array_dim = 1
2746 elseif (index_t .gt. temp_field_p%array_dim)
then
2749 temp_field_p%array_dim = temp_field_p%array_dim + array_increment
2750 allocate (temp_i_value(temp_field_p%array_dim))
2751 do i = 1, temp_field_p%max_index
2752 temp_i_value(i) = temp_field_p%i_value(i)
2754 if (
allocated(temp_field_p%i_value))
deallocate(temp_field_p%i_value)
2755 temp_field_p%i_value = temp_i_value
2756 temp_field_p%max_index = index_t
2760 if (index_t .gt. 0)
then
2761 temp_field_p%i_value(index_t) = new_ival
2762 if (index_t .gt. temp_field_p%max_index)
then
2763 temp_field_p%max_index = index_t
2766 field_index = temp_field_p%index
2781 integer :: field_index
2782 character(len=*),
intent(in) :: name
2784 logical,
intent(in) :: new_lval
2786 logical,
intent(in),
optional :: create
2788 integer,
intent(in),
optional :: index
2790 logical,
intent(in),
optional :: append
2793 character(len=FMS_PATH_LEN) :: path
2794 character(len=fm_field_name_len) :: base
2798 logical,
dimension(:),
pointer :: temp_l_value
2799 type (
field_def),
pointer,
save :: temp_list_p
2800 type (
field_def),
pointer,
save :: temp_field_p
2805 if (.not. module_is_initialized)
then
2809 if (name .eq.
' ')
then
2814 if (
present(create))
then
2820 if (
present(index) .and.
present(append))
then
2821 if (append .and. index .gt. 0)
then
2827 if (
present(index))
then
2829 if (index_t .lt. 0)
then
2839 temp_list_p =>
find_list(path, current_list_p, create_t)
2841 if (
associated(temp_list_p))
then
2842 temp_field_p =>
find_field(base, temp_list_p)
2843 if (.not.
associated(temp_field_p))
then
2847 if (
associated(temp_field_p))
then
2850 if (temp_field_p%field_type /= logical_type )
then
2851 temp_field_p%max_index = 0
2854 temp_field_p%field_type = logical_type
2856 if (
present(append))
then
2858 index_t = temp_field_p%max_index + 1
2862 if (index_t .gt. temp_field_p%max_index + 1)
then
2867 elseif (index_t .eq. 0 .and. &
2868 temp_field_p%max_index .gt. 0)
then
2873 elseif (.not.
allocated(temp_field_p%l_value) .and. &
2874 index_t .gt. 0)
then
2876 allocate(temp_field_p%l_value(1))
2877 temp_field_p%max_index = 1
2878 temp_field_p%array_dim = 1
2880 elseif (index_t .gt. temp_field_p%array_dim)
then
2883 temp_field_p%array_dim = temp_field_p%array_dim + array_increment
2884 allocate (temp_l_value(temp_field_p%array_dim))
2885 do i = 1, temp_field_p%max_index
2886 temp_l_value(i) = temp_field_p%l_value(i)
2888 if (
allocated(temp_field_p%l_value))
deallocate(temp_field_p%l_value)
2889 temp_field_p%l_value = temp_l_value
2890 temp_field_p%max_index = index_t
2895 if (index_t .gt. 0)
then
2896 temp_field_p%l_value(index_t) = new_lval
2897 if (index_t .gt. temp_field_p%max_index)
then
2898 temp_field_p%max_index = index_t
2901 field_index = temp_field_p%index
2915 integer :: field_index
2916 character(len=*),
intent(in) :: name
2918 character(len=*),
intent(in) :: new_sval
2920 logical,
intent(in),
optional :: create
2922 integer,
intent(in),
optional :: index
2924 logical,
intent(in),
optional :: append
2926 character(len=fm_string_len),
dimension(:),
pointer :: temp_s_value
2927 character(len=FMS_PATH_LEN) :: path
2928 character(len=fm_field_name_len) :: base
2932 type (
field_def),
save,
pointer :: temp_list_p
2933 type (
field_def),
save,
pointer :: temp_field_p
2938 if (.not. module_is_initialized)
then
2942 if (name .eq.
' ')
then
2947 if (
present(create))
then
2953 if (
present(index) .and.
present(append))
then
2954 if (append .and. index .gt. 0)
then
2960 if (
present(index))
then
2962 if (index_t .lt. 0)
then
2972 temp_list_p =>
find_list(path, current_list_p, create_t)
2974 if (
associated(temp_list_p))
then
2975 temp_field_p =>
find_field(base, temp_list_p)
2976 if (.not.
associated(temp_field_p))
then
2980 if (
associated(temp_field_p))
then
2983 if (temp_field_p%field_type /= string_type )
then
2984 temp_field_p%max_index = 0
2987 temp_field_p%field_type = string_type
2989 if (
present(append))
then
2991 index_t = temp_field_p%max_index + 1
2995 if (index_t .gt. temp_field_p%max_index + 1)
then
3000 elseif (index_t .eq. 0 .and. &
3001 temp_field_p%max_index .gt. 0)
then
3006 elseif (.not.
allocated(temp_field_p%s_value) .and. &
3007 index_t .gt. 0)
then
3009 allocate(temp_field_p%s_value(1))
3010 temp_field_p%max_index = 1
3011 temp_field_p%array_dim = 1
3013 elseif (index_t .gt. temp_field_p%array_dim)
then
3016 temp_field_p%array_dim = temp_field_p%array_dim + array_increment
3017 allocate (temp_s_value(temp_field_p%array_dim))
3018 do i = 1, temp_field_p%max_index
3019 temp_s_value(i) = temp_field_p%s_value(i)
3021 if (
allocated(temp_field_p%s_value))
deallocate(temp_field_p%s_value)
3022 temp_field_p%s_value = temp_s_value
3023 temp_field_p%max_index = index_t
3028 if (index_t .gt. 0)
then
3029 temp_field_p%s_value(index_t) = new_sval
3030 if (index_t .gt. temp_field_p%max_index)
then
3031 temp_field_p%max_index = index_t
3034 field_index = temp_field_p%index
3050 if (.not. module_is_initialized)
then
3055 nullify(loop_list_p)
3067 if (.not. module_is_initialized)
then
3071 root_p%name = save_root_name
3072 root_p%parent => save_root_parent_p
3076 save_root_name =
' '
3077 nullify(save_root_parent_p)
3087 character(len=*),
intent(in) :: name
3088 type (
field_def),
pointer :: this_list_p
3091 character(len=FMS_PATH_LEN) :: path
3092 character(len=fm_field_name_len) :: base
3093 type (
field_def),
pointer,
save :: temp_p
3099 if (path .ne.
' ')
then
3100 temp_p =>
find_list(path, this_list_p, .false.)
3101 if (
associated(temp_p))
then
3122 character(len=*),
intent(in) :: oldname
3124 character(len=*),
intent(in) :: newname
3127 character(len=FMS_PATH_LEN) :: path
3128 character(len=fm_field_name_len) :: base
3129 type (
field_def),
pointer,
save :: list_p
3130 type (
field_def),
pointer,
save :: temp_p
3135 if (path .ne.
' ')
then
3136 temp_p =>
find_list(path, current_list_p, .false.)
3137 if (
associated(temp_p))
then
3139 if (
associated(list_p))
then
3140 list_p%name = newname
3148 if (
associated(list_p))
then
3149 list_p%name = newname
3163 if (.not. module_is_initialized)
then
3165 read (input_nml_file, nml=field_manager_nml, iostat=io)
3166 ierr = check_nml_error(io,
"field_manager_nml")
3169 if (
mpp_pe() == mpp_root_pe())
write (logunit, nml=field_manager_nml)
3173 field_type_name(integer_type) =
'integer'
3174 field_type_name(list_type) =
'list'
3175 field_type_name(logical_type) =
'logical'
3176 field_type_name(real_type) =
'real'
3177 field_type_name(string_type) =
'string'
3181 root%parent => root_p
3183 root%field_type = list_type
3186 nullify(root%first_field)
3187 nullify(root%last_field)
3190 if (
allocated(root%i_value))
deallocate(root%i_value)
3191 if (
allocated(root%l_value))
deallocate(root%l_value)
3192 if (
allocated(root%r_value))
deallocate(root%r_value)
3193 if (
allocated(root%s_value))
deallocate(root%s_value)
3198 current_list_p => root
3200 nullify(loop_list_p)
3203 nullify(save_root_parent_p)
3204 save_root_name =
' '
3206 module_is_initialized = .true.
3220 type (
field_def),
pointer :: this_list_p
3221 character(len=*),
intent(in) :: name
3223 type (
field_def),
pointer,
save :: dummy_p
3231 if (
associated(dummy_p))
then
3239 if (.not.
associated(list_p))
then
3245 list_p%field_type = list_type
3246 if (
allocated(list_p%i_value))
deallocate(list_p%i_value)
3247 if (
allocated(list_p%l_value))
deallocate(list_p%l_value)
3248 if (
allocated(list_p%r_value))
deallocate(list_p%r_value)
3249 if (
allocated(list_p%s_value))
deallocate(list_p%s_value)
3264 character(len=*),
intent(in) :: name
3265 character(len=*),
intent(out) :: method_name
3266 character(len=*),
intent(out) :: method_control
3268 character(len=FMS_PATH_LEN) :: path
3269 character(len=FMS_PATH_LEN) :: base
3270 character(len=FMS_PATH_LEN) :: name_loc
3271 logical :: recursive_t
3272 type (
field_def),
pointer,
save :: temp_list_p
3273 type (
field_def),
pointer,
save :: temp_value_p
3274 type (
field_def),
pointer,
save :: this_field_p
3279 recursive_t = .true.
3281 method_control =
" "
3284 name_loc = lowercase(name)
3287 temp_list_p =>
find_list(name_loc, current_list_p, .false.)
3289 if (
associated(temp_list_p))
then
3291 success =
query_method(temp_list_p, recursive_t, base, method_name, method_control)
3296 temp_value_p =>
find_list(path, current_list_p, .false.)
3297 if (
associated(temp_value_p))
then
3299 this_field_p => temp_value_p%first_field
3301 do while (
associated(this_field_p))
3302 if ( this_field_p%name == base )
then
3303 method_name = this_field_p%s_value(1)
3310 this_field_p => this_field_p%next
3325 recursive function query_method(list_p, recursive, name, method_name, method_control) &
3329 logical,
intent(in) ::
recursive
3330 character(len=*),
intent(in) :: name
3331 character(len=*),
intent(out) :: method_name
3332 character(len=*),
intent(out) :: method_control
3335 character(len=64) :: scratch
3336 type (
field_def),
pointer :: this_field_p
3342 if (.not.
associated(list_p) .or. list_p%field_type .ne. list_type)
then
3349 this_field_p => list_p%first_field
3351 do while (
associated(this_field_p))
3352 select case(this_field_p%field_type)
3356 if (.not.
query_method(this_field_p, .true., this_field_p%name, method_name, method_control))
then
3360 method_name = trim(method_name)//trim(this_field_p%name)
3365 write (scratch,*) this_field_p%i_value
3366 call concat_strings(method_control, comma//trim(this_field_p%name)//
' = '//trim(adjustl(scratch)))
3369 write (scratch,
'(l1)')this_field_p%l_value
3370 call concat_strings(method_control, comma//trim(this_field_p%name)//
' = '//trim(adjustl(scratch)))
3373 write (scratch,*) this_field_p%r_value
3374 call concat_strings(method_control, comma//trim(this_field_p%name)//
' = '//trim(adjustl(scratch)))
3377 call concat_strings(method_control, comma//trim(this_field_p%name)//
' = '//trim(this_field_p%s_value(1)))
3378 do i = 2, this_field_p%max_index
3379 call concat_strings(method_control, comma//trim(this_field_p%s_value(i)))
3387 this_field_p => this_field_p%next
3395 character(*),
intent(inout) :: str1
3396 character(*),
intent(in) :: str2
3398 character(64) :: n1,n2
3400 if (len_trim(str1)+len_trim(str2)>len(str1))
then
3401 write(n1,*)len(str1)
3402 write(n2,*)len_trim(str1)+len_trim(str2)
3403 call mpp_error(fatal,
'length of output string ('//trim(adjustl(n1))&
3404 //
') is not enough for the result of concatenation (len='&
3405 //trim(adjustl(n2))//
')')
3407 str1 = trim(str1)//trim(str2)
3420 character(len=*),
intent(in) :: list_name
3421 character(len=*),
intent(in) :: suffix
3423 logical,
intent(in),
optional :: create
3425 character(len=fm_string_len),
dimension(:),
allocatable :: control
3426 character(len=fm_string_len),
dimension(:),
allocatable :: method
3427 character(len=fm_string_len) :: head
3428 character(len=fm_string_len) :: list_name_new
3429 character(len=fm_string_len) :: tail
3430 character(len=fm_string_len) :: val_str
3434 logical :: found_methods
3435 logical :: got_value
3436 logical :: recursive_t
3438 logical :: val_logical
3439 real(r8_kind) :: val_real
3440 type (
field_def),
pointer,
save :: temp_field_p
3441 type (
field_def),
pointer,
save :: temp_list_p
3448 list_name_new = trim(list_name)//trim(suffix)
3449 recursive_t = .true.
3451 if (.not. module_is_initialized)
then
3455 if (list_name .eq.
' ')
then
3457 temp_list_p => current_list_p
3461 temp_list_p =>
find_list(list_name, current_list_p, .false.)
3462 if (
associated(temp_list_p))
then
3472 do n = 1,
size(method)
3473 if (len_trim(method(n)) > 0 )
then
3474 index =
fm_new_list(trim(list_name_new)//list_sep//method(n), create = create)
3476 temp_field_p =>
find_list(trim(list_name)//list_sep//head,temp_list_p, .false.)
3477 temp_field_p =>
find_field(tail,temp_field_p)
3478 select case (temp_field_p%field_type)
3480 got_value =
fm_get_value( trim(list_name)//list_sep//method(n), val_int)
3481 if (
fm_new_value( trim(list_name_new)//list_sep//method(n), val_int, &
3482 create = create, append = .true.) < 0 ) &
3483 call mpp_error(fatal, trim(error_header)//
'Could not set the '//trim(method(n))//&
3484 ' for '//trim(list_name)//trim(suffix))
3487 got_value =
fm_get_value( trim(list_name)//list_sep//method(n), val_logical)
3488 if (
fm_new_value( trim(list_name_new)//list_sep//method(n), val_logical, &
3489 create = create, append = .true.) < 0 ) &
3490 call mpp_error(fatal, trim(error_header)//
'Could not set the '//trim(method(n))//&
3491 ' for '//trim(list_name)//trim(suffix))
3494 got_value =
fm_get_value( trim(list_name)//list_sep//method(n), val_real)
3495 if (
fm_new_value( trim(list_name_new)//list_sep//method(n), val_real, &
3496 create = create, append = .true.) < 0 ) &
3497 call mpp_error(fatal, trim(error_header)//
'Could not set the '//trim(method(n))//&
3498 ' for '//trim(list_name)//trim(suffix))
3501 got_value =
fm_get_value( trim(list_name)//list_sep//method(n), val_str)
3502 if (
fm_new_value( trim(list_name_new)//list_sep//method(n), val_str, &
3503 create = create, append = .true.) < 0 ) &
3504 call mpp_error(fatal, trim(error_header)//
'Could not set the '//trim(method(n))//&
3505 ' for '//trim(list_name)//trim(suffix))
3524 character(len=*),
intent(in) :: list_name
3525 character(len=*),
intent(out),
dimension(:) :: methods
3526 character(len=*),
intent(out),
dimension(:) :: control
3529 logical :: recursive_t
3530 type (
field_def),
pointer,
save :: temp_list_p
3536 recursive_t = .true.
3538 if (.not. module_is_initialized)
then
3542 if (list_name .eq.
' ')
then
3544 temp_list_p => current_list_p
3548 temp_list_p =>
find_list(list_name, current_list_p, .false.)
3549 if (
associated(temp_list_p))
then
3558 success =
find_method(temp_list_p, recursive_t, num_meth, methods, control)
3567 recursive function find_method(list_p, recursive, num_meth, method, control) &
3571 logical,
intent(in) ::
recursive
3572 integer,
intent(inout) :: num_meth
3573 character(len=*),
intent(out),
dimension(:) :: method
3574 character(len=*),
intent(out),
dimension(:) :: control
3576 character(len=FMS_PATH_LEN) :: scratch
3579 type (
field_def),
pointer,
save :: this_field_p
3584 if (.not.
associated(list_p) .or. list_p%field_type .ne. list_type)
then
3590 this_field_p => list_p%first_field
3592 do while (
associated(this_field_p))
3593 select case(this_field_p%field_type)
3596 if ( this_field_p%length > 1)
then
3597 do n = num_meth+1, num_meth + this_field_p%length - 1
3598 write (method(n),
'(a,a,a,$)') trim(method(num_meth)), &
3599 trim(this_field_p%name), list_sep
3601 write (method(num_meth),
'(a,a,a,$)') trim(method(num_meth)), &
3602 trim(this_field_p%name), list_sep
3604 write (method(num_meth),
'(a,a,a,$)') trim(method(num_meth)), &
3605 trim(this_field_p%name), list_sep
3607 success =
find_method(this_field_p, .true., num_meth, method, control)
3610 write (scratch,*) this_field_p%i_value
3612 write (method(num_meth),
'(a,a)') trim(method(num_meth)), &
3613 trim(this_field_p%name)
3614 write (control(num_meth),
'(a)') &
3616 num_meth = num_meth + 1
3621 write (method(num_meth),
'(a,a)') trim(method(num_meth)), &
3622 trim(this_field_p%name)
3623 write (control(num_meth),
'(l1)') &
3624 this_field_p%l_value
3625 num_meth = num_meth + 1
3629 if(
allocated(this_field_p%r_value))
write (scratch,*) this_field_p%r_value
3631 write (method(num_meth),
'(a,a)') trim(method(num_meth)), &
3632 trim(this_field_p%name)
3633 write (control(num_meth),
'(a)') &
3635 num_meth = num_meth + 1
3639 write (method(num_meth),
'(a,a)') trim(method(num_meth)), &
3640 trim(this_field_p%name)
3641 write (control(num_meth),
'(a)') &
3642 trim(this_field_p%s_value(1))
3643 do i = 2, this_field_p%max_index
3644 write (control(num_meth),
'(a,a,$)') comma//trim(this_field_p%s_value(i))
3646 num_meth = num_meth + 1
3655 this_field_p => this_field_p%next
3661 #include "field_manager_r4.fh"
3662 #include "field_manager_r8.fh"
3664 end module field_manager_mod
integer function parse_integer(text, label, parse_ival)
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.
type(field_def) function, pointer, private find_list(path, relative_p, create)
Find and return a pointer to the specified list, relative to relative_p. Return a null pointer on err...
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.
subroutine, private find_base(name, path, base)
A subroutine that splits a listname into a path and a base.
integer, parameter, public fm_string_len
The length of a character string representing character values for the field.
logical function set_list_stuff()
If the the pointer matches to the right list, extract the field information. Used in fm_loop_over_lis...
type(field_def) function, pointer, private create_field(parent_p, name)
A function to create a field as a child of parent_p. This will return a pointer to a field_def type.
subroutine strip_front_blanks(name)
A routine to strip whitespace from the start of character strings.
integer, parameter, public model_land
Land model.
function parse_strings(text, label, values)
subroutine concat_strings(str1, str2)
private function: appends str2 to the end of str1, with length check
integer function, public fm_get_length(name)
A function to return how many elements are contained within the named list or entry.
character(len=8) function, public fm_get_type(name)
A function to return the type of the named field.
subroutine, public fm_reset_loop
Resets the loop variable. For use in conjunction with fm_loop_over_list.
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 read_field_table_yaml(nfields, table_name)
Routine to read and parse the field table yaml.
integer function, public fm_new_list(name, create, keep)
A function to create a new list.
type(field_mgr_type), dimension(:), allocatable, private fields
fields of field_mgr_type
integer function, public fm_new_value_string(name, new_sval, create, index, append)
Assigns a given value to a given field.
logical function, public fm_get_value_integer(name, get_ival, index)
subroutine, public get_field_methods(n, methods)
A routine to obtain all the methods associated with a field.
character(len=fms_path_len) function, public fm_get_current_list()
A function to return the full path of the current list.
subroutine, private find_head(name, head, rest)
Find the first list for a name by splitting the name into a head and the rest.
integer function, public fm_get_index(name)
A function to return the index of a named field.
integer function, public find_field_index_new(field_name)
subroutine, public field_manager_end
Destructor for field manager.
integer function, public fm_new_value_logical(name, new_lval, create, index, append)
Assigns a given value to a given field.
subroutine new_name_yaml(list_name, method_name_in, val_name_in)
Subroutine to add new values to list parameters.
type(field_def) function, pointer, private get_field(name, this_list_p)
Return a pointer to the field if it exists relative to this_list_p, null otherwise.
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 function, public find_field_index_old(model, field_name)
Function to return the index of the field.
integer, parameter, public model_coupler
Ice model.
subroutine, private initialize_module_variables
A function to initialize the values of the pointers. This will remove all fields and reset the field ...
integer, parameter, public fm_field_name_len
The length of a character string representing the field name.
type(field_def) function, pointer, private make_list(this_list_p, name)
This function creates a new field and returns a pointer to that field.
recursive logical function find_method(list_p, recursive, num_meth, method, control)
Given a field list pointer this function retrieves methods and associated parameters for the field li...
subroutine, public get_field_method(n, m, method)
A routine to get a specified method.
subroutine, public get_field_info(n, fld_type, fld_name, model, num_methods)
This routine allows access to field information given an index.
integer, parameter, public fm_type_name_len
The length of a character string representing the various types that the values of the field can take...
logical use_field_table_yaml
.True. if using the field_table.yaml, .false. if using the legacy field_table
subroutine read_field_table_legacy(nfields, table_name)
Routine to read and parse the field table yaml.
logical function, public fm_get_value_logical(name, get_lval, index)
logical function, public fm_get_value_string(name, get_sval, 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.
logical function, public fm_dump_list(name, recursive, unit)
A function to list properties associated with a field.
logical recursive function, private dump_list(list_p, recursive, depth, out_unit)
This is a function that lists the parameters of a field.
integer, parameter, public model_ocean
Ocean model.
subroutine, public fm_return_root
Return the root list to the value at initialization.
integer, parameter, public fm_path_name_len
The length of a character string representing the field path.
integer, parameter, public no_field
The value returned if a field is not defined.
subroutine, public fm_init_loop(loop_list, iter)
given a name of the list, prepares an iterator over the list content. If the name of the given list i...
function parse_integers(text, label, values)
logical function fm_loop_over_list_new(iter, name, field_type, index)
given a list iterator, returns information about curren list element and advances the iterator to the...
integer, parameter, public model_ice
Ice model.
logical function, public fm_change_root(name)
Change the root list.
subroutine new_name(list_name, method_name_in, val_name_in)
Subroutine to add new values to list parameters.
integer function parse_string(text, label, parse_sval)
integer, parameter, public model_atmos
Atmospheric model.
integer function, public fm_new_value_integer(name, new_ival, create, index, append)
Assigns a given value to a given field.
integer, parameter, public num_models
Number of models (ATMOS, OCEAN, LAND, ICE, COUPLER).
type(field_def) function, pointer, private find_field(name, this_list_p)
Find and return a pointer to the field in the specified list. Return a null pointer on error.
logical function, public fm_find_methods(list_name, methods, control)
This function retrieves all the methods associated with a field.
logical function fm_loop_over_list_old(list, name, field_type, index)
Iterates through the given list.
Returns an index corresponding to the given field name.
An overloaded function to find and extract a value for a named field.
A function for looping over a list.
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,...
Private type for internal use.
Private type for internal use.
Private type for internal use.
Private type for internal use.
Iterator over the field manager list.
This method_type is a way to allow a component module to alter the parameters it needs for various tr...
This method_type is the same as method_type except that the method_control string is not present....
This is the same as method_type except that the method_control and method_name strings are not presen...
subroutine, public build_fmtable(fmTable, filename)
Subroutine to populate an fmTable by reading a yaml file, given an optional filename.
integer function, public check_nml_error(IOSTAT, NML_NAME)
Checks the iostat argument that is returned after reading a namelist and determines if the error code...
subroutine, public write_version_number(version, tag, unit)
Prints to the log file (or a specified unit) the version id string and tag name.
integer function stdout()
This function returns the current standard fortran unit numbers for output.
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
integer function mpp_pe()
Returns processor ID.