FMS  2024.03
Flexible Modeling System
fms.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 fms_mod fms_mod
20 !> @ingroup fms
21 !! @brief The fms module provides routines that are commonly used
22 !! by most FMS modules.
23 !> @author Bruce Wyman
24 !!
25 !> Here is a summary of the functions performed by routines
26 !! in the fms module.
27 !!
28 !! 1. Output module version numbers to a common (<TT>log</TT>) file
29 !! using a common format.<BR/>
30 !! 2. Open specific types of files common to many FMS modules.
31 !! These include namelist files, restart files, and 32-bit IEEE
32 !! data files. There also is a matching interface to close the files.
33 !! If other file types are needed the <TT>mpp_open</TT> and <TT>mpp_close</TT>
34 !! interfaces in module @ref mpp_io_mod must be used.<BR/>
35 !! 3. Read and write distributed data to simple native unformatted files.
36 !! This type of file (called a restart file) is used to checkpoint
37 !! model integrations for a subsequent restart of the run.<BR/>
38 !! 4. For convenience there are several routines published from
39 !! the @ref mpp module. These are routines for getting processor
40 !! numbers, commonly used I/O unit numbers, error handling, and timing sections of code.
41 
42 !> @addtogroup fms_mod
43 !> @{
44 module fms_mod
45 
46 !-----------------------------------------------------------------------
47 !
48 ! A collection of commonly used routines.
49 !
50 ! The routines are primarily I/O related, however, there also
51 ! exists several simple miscellaneous utility routines.
52 !
53 !-----------------------------------------------------------------------
54 !
55 ! file_exist Checks the existence of the given file name.
56 !
57 ! check_nml_error Checks the iostat argument that is returned after
58 ! reading a namelist and determines if the error
59 ! code is valid.
60 !
61 ! write_version_number Prints to the log file (or a specified unit)
62 ! the (cvs) version id string and (cvs) tag name.
63 !
64 ! error_mesg Print notes, warnings and error messages,
65 ! terminates program for error messages.
66 ! (use error levels NOTE,WARNING,FATAL)
67 !
68 ! open_namelist_file Opens namelist file for reading only.
69 !
70 ! open_restart_file Opens a file that will be used for reading or writing
71 ! restart files with native unformatted data.
72 !
73 ! open_ieee32_file Opens a file that will be used for reading or writing
74 ! unformatted 32-bit ieee data.
75 !
76 ! close_file Closes a file that was opened using
77 ! open_namelist_file, open_restart_file, or
78 ! open_ieee32_file.
79 !
80 ! set_domain Call this routine to internally store in fms_mod the
81 ! domain2d data type prior to calling the distributed
82 ! data I/O routines read_data and write_data.
83 !
84 ! read_data Reads distributed data from a single threaded file.
85 !
86 ! write_data Writes distributed data to a single threaded file.
87 !
88 ! fms_init Initializes the fms module and also the
89 ! mpp_io module (which initializes all mpp mods).
90 ! Will be called automatically if the user does
91 ! not call it.
92 !
93 ! fms_end Calls mpp exit routines.
94 !
95 ! lowercase Convert character strings to all lower case
96 !
97 ! uppercase Convert character strings to all upper case
98 !
99 ! monotonic_array Determines if the real input array has strictly
100 ! monotonically increasing or decreasing values.
101 !
102 ! string_array_index Match the input character string to a string
103 ! in an array/list of character strings.
104 !
105 !-----------------------------------------------------------------------
106 !---- published routines from mpp_mod ----
107 !
108 ! mpp_error, NOTE, WARNING, FATAL
109 ! mpp_error_state
110 ! mpp_pe, mpp_npes, mpp_root_pe
111 ! stdin, stdout, stderr, stdlog
112 ! mpp_chksum
113 !
114 ! mpp_clock_id, mpp_clock_begin , mpp_clock_end
115 ! MPP_CLOCK_SYNC, MPP_CLOCK_DETAILED
116 ! CLOCK_COMPONENT, CLOCK_SUBCOMPONENT, CLOCK_MODULE_DRIVER,
117 ! CLOCK_MODULE, CLOCK_ROUTINE, CLOCK_LOOP, CLOCK_INFRA
118 !
119 !-----------------------------------------------------------------------
120 
121 use mpp_mod, only: mpp_error, note, warning, fatal, &
122  mpp_set_warn_level, &
123  mpp_transmit, all_pes, &
124  mpp_pe, mpp_npes, mpp_root_pe, &
125  mpp_sync, mpp_chksum, &
126  mpp_clock_begin, mpp_clock_end, &
128  mpp_clock_sync, mpp_clock_detailed, &
129  clock_component, clock_subcomponent,&
130  clock_module_driver, clock_module, &
131  clock_routine, clock_loop, &
132  clock_infra, mpp_clock_set_grain, &
134  stdin, stdout, stderr, stdlog, &
135  mpp_error_state, lowercase, &
136  uppercase, mpp_broadcast, input_nml_file, &
137  get_unit, read_input_nml
138 
139 use mpp_domains_mod, only: domain2d, mpp_define_domains, &
140  mpp_update_domains, global_data_domain, &
145 
146 #ifdef use_deprecated_io
147 use mpp_io_mod, only: mpp_io_init, mpp_open, mpp_close, &
148  mpp_ascii, mpp_native, mpp_ieee32, mpp_netcdf, &
149  mpp_rdonly, mpp_wronly, mpp_append, mpp_overwr, &
150  mpp_sequential, mpp_direct, &
151  mpp_single, mpp_multi, mpp_delete, mpp_io_exit, &
153  do_cf_compliance
154 
155 use fms_io_mod, only : fms_io_init, fms_io_exit, field_size, &
156  read_data, write_data, read_compressed, read_distributed, &
157  open_namelist_file, open_restart_file, open_ieee32_file, close_file, &
158  get_domain_decomp, &
159  open_file, open_direct_file, get_mosaic_tile_grid, &
160  get_mosaic_tile_file, get_global_att_value, file_exist, field_exist, &
161  set_domain, nullify_domain
162 #endif
163 use fms2_io_mod, only: fms2_io_init
164 use memutils_mod, only: print_memuse_stats, memutils_init
165 use grid2_mod, only: grid_init, grid_end
166 use fms_string_utils_mod, only: fms_c2f_string, fms_cstring2cpointer, string
167 use platform_mod, only: r4_kind, r8_kind
168 
169 use, intrinsic :: iso_c_binding
170 
171 implicit none
172 private
173 
174 ! routines for initialization and termination of module
175 public :: fms_init, fms_end
176 
177 ! routines for opening/closing specific types of file
178 #ifdef use_deprecated_io
179 public :: open_namelist_file, open_restart_file, &
180  open_ieee32_file, close_file, &
181  open_file, open_direct_file
182 
183 ! routines for reading/writing distributed data
184 public :: read_data, write_data, read_compressed, read_distributed
185 public :: get_domain_decomp, field_size
186 public :: get_global_att_value
187 
188 ! routines for get mosaic information
189 public :: get_mosaic_tile_grid, get_mosaic_tile_file
190 
191 ! miscellaneous i/o routines
192 public :: file_exist, field_exist
193 #endif
195 
196 ! version logging routine (originally from fms_io)
197 public :: write_version_number
198 
199 ! miscellaneous utilities (non i/o)
200 public :: lowercase, uppercase, &
202 #ifdef use_deprecated_io
203 public :: set_domain, nullify_domain
204 #endif
205 
206 ! public mpp interfaces
207 public :: mpp_error, note, warning, fatal, &
208  mpp_error_state, &
209  mpp_pe, mpp_npes, mpp_root_pe, &
210  stdin, stdout, stderr, stdlog, &
211  mpp_chksum, get_unit, read_input_nml
212 public :: input_nml_file
213 public :: mpp_clock_id, mpp_clock_begin, mpp_clock_end
214 public :: mpp_clock_sync, mpp_clock_detailed
215 public :: clock_component, clock_subcomponent, &
216  clock_module_driver, clock_module, &
217  clock_routine, clock_loop, clock_infra
219 !public from the old fms_io but not exists here
220 public :: string
221 
222 ! public mpp-io interfaces
223 #ifdef use_deprecated_io
224 public :: do_cf_compliance
225 #endif
226 
228  module procedure :: monotonic_array_r4, monotonic_array_r8
229 end interface monotonic_array
230 
231 !Balaji
232 !this is published by fms and applied to any initialized clocks
233 !of course you can go and set the flag to SYNC or DETAILED by hand
234 integer, public :: clock_flag_default
235 !> @}
236  !> Namelist read error values
237  !> @ingroup fms_mod
239  INTEGER :: multipleNMLSinFile
240  INTEGER :: badType1
241  INTEGER :: badType2
242  INTEGER :: missingVar
243  INTEGER :: NotInFile
244  END TYPE nml_errors_type
245  TYPE(nml_errors_type), SAVE :: nml_errors
246 !> @addtogroup fms_mod
247 !> @{
248 
249 !------ namelist interface -------
250 !------ adjustable severity level for warnings ------
251 
252  logical :: read_all_pe = .true. !< Read global data on all processors extracting local
253  !! part needed (TRUE) or read global data on PE0 and broadcast to all
254  !! PEs(FALSE).
255  character(len=16) :: clock_grain = 'NONE' !< The level of clock granularity used for performance
256  !! timing sections of code. Possible values in order of increasing detail
257  !! are: 'NONE', 'COMPONENT', 'SUBCOMPONENT', 'MODULE_DRIVER', 'MODULE',
258  !! 'ROUTINE', 'LOOP', and 'INFRA'. Code sections are defined using routines
259  !! in MPP module: mpp_clock_id, mpp_clock_begin, and mpp_clock_end. The fms
260  !! module makes these routines public. A list of timed code sections will be
261  !! printed to STDOUT. See the @ref mpp_mod module for more details.
262  character(len=16) :: clock_flags='NONE' !< Possible values are 'NONE', 'SYNC', or 'DETAILED'.
263  !! SYNC will give accurate information on load balance of the clocked
264  !! portion of code. DETAILED also turns on detailed message-passing
265  !! performance diagnosis. Both SYNC and DETAILED will work correctly on
266  !! innermost clock nest and distort outer clocks, and possibly the overall
267  !! code time. See the @ref mpp_mod module for more details.
268  character(len=8) :: warning_level = 'warning' !< Sets the termination condition for the WARNING
269  !! flag to interfaces error_mesg/mpp_error. set warning_level = 'fatal'
270  !! (program crashes for warning messages) or 'warning' (prints warning
271  !! message and continues).
272  integer :: stack_size = 0 !< The size in words of the MPP user stack. If stack_size > 0,
273  !! the following MPP routine is called: call mpp_set_stack_size (stack_size).
274  !! If stack_size = 0 (default) then the default size set by mpp_mod is used.
275  integer :: domains_stack_size = 0 !< The size in words of the MPP_DOMAINS user stack. If
276  !! domains_stack_size > 0, the following MPP_DOMAINS routine is called:
277  !! call mpp_domains_set_stack_size (domains_stack_size). If
278  !! domains_stack_size = 0 (default) then the default size set by
279  !! @ref mpp_domains_mod is used.
280  logical, public :: print_memory_usage = .false. !< If set to .TRUE., memory usage statistics
281  !! will be printed at various points in the code. It is used to study memory
282  !! usage, e.g to detect memory leaks.
283 
284 !------ namelist interface -------
285 
286  namelist /fms_nml/ read_all_pe, clock_grain, clock_flags, &
289 
290 ! ---- private data for check_nml_error ----
291 
292  integer, private :: num_nml_error_codes, nml_error_codes(20)
293  logical, private :: do_nml_error_init = .true.
294  private nml_error_init
295 
296 
297 ! ---- version number -----
298 
299 ! Include variable "version" to be written to log file.
300 #include<file_version.h>
301 
302  logical :: module_is_initialized = .false.
303 
304  logical, private :: fms_io_initialized = .false.!> used to make sure fms_io version is only
305  !! written to log once
306 
307 !> @}
308 
309 !> @addtogroup fms_mod
310 !> @{
311 contains
312 
313 !#######################################################################
314 
315 !> @brief Initializes the FMS module and also calls the initialization routines for all
316 !! modules in the MPP package. Will be called automatically if the user does
317 !! not call it.
318 !! @details Initialization routine for the fms module. It also calls initialization routines
319 !! for the mpp, mpp_domains, and mpp_io modules. Although this routine
320 !! will be called automatically by other fms_mod routines, users should
321 !! explicitly call fms_init. If this routine is called more than once it will
322 !! return silently. There are no arguments.
323 !!
324 !> @throws FATAL, invalid entry for namelist variable warning_level
325 !! The namelist variable warning_level must be either 'fatal' or 'warning'(case-insensitive)
326 !!
327 !> @throws FATAL, invalid entry for namelist variable clock_grain
328 !! The namelist variable clock_grain must be one of the following values:
329 !! 'NONE', 'COMPONENT', 'SUBCOMPONENT', 'MODULE_DRIVER', 'MODULE', 'ROUTINE',
330 !! 'LOOP', or 'INFRA' (case-insensitive).
331 subroutine fms_init (localcomm, alt_input_nml_path)
332 
333 !--- needed to output the version number of constants_mod to the logfile ---
334  use constants_mod, only: constants_version=>version !pjp: PI not computed
335 #ifdef use_deprecated_io
336  use fms_io_mod, only: fms_io_version
337 #endif
338 
339  interface
340  subroutine maximize_system_stacksize_limit() bind(C)
341  end subroutine
342  end interface
343 
344  integer, intent(in), optional :: localcomm
345  character(len=*), intent(in), optional :: alt_input_nml_path
346  integer :: ierr, io
347  integer :: logunitnum
348  integer :: stdout_unit !< Unit number for the stdout file
349 
350  if (module_is_initialized) return ! return silently if already called
351  module_is_initialized = .true.
352 
353 !---- Raise the system stack size limit to its maximum permissible value ----
354  call maximize_system_stacksize_limit
355 
356 !---- initialize mpp routines ----
357  if(present(localcomm)) then
358  if(present(alt_input_nml_path)) then
359  call mpp_init(localcomm=localcomm, alt_input_nml_path=alt_input_nml_path)
360  else
361  call mpp_init(localcomm=localcomm)
362  endif
363  else
364  if(present(alt_input_nml_path)) then
365  call mpp_init(alt_input_nml_path=alt_input_nml_path)
366  else
367  call mpp_init()
368  endif
369  endif
370  call mpp_domains_init()
371 #ifdef use_deprecated_io
372  call fms_io_init()
373 #endif
374  !! write_version_number is inaccesible from fms_io_mod so write it from here if not written
375  if(.not.fms_io_initialized) then
376 #ifdef use_deprecated_io
377  call write_version_number("FMS_IO_MOD", fms_io_version)
378 #endif
379  fms_io_initialized = .true.
380  endif
381  call fms2_io_init()
382  logunitnum = stdlog()
383 !---- read namelist input ----
384 
385  call nml_error_init() ! first initialize namelist iostat error codes
386 
387  read (input_nml_file, fms_nml, iostat=io)
388  ierr = check_nml_error(io,'fms_nml')
389 
390 !---- define mpp stack sizes if non-zero -----
391 
392  if ( stack_size > 0) call mpp_set_stack_size ( stack_size)
394 
395 !---- set severity level for warnings ----
396 
397  select case( trim(lowercase(warning_level)) )
398  case( 'fatal' )
399  call mpp_set_warn_level ( fatal )
400  case( 'warning' )
401  call mpp_set_warn_level ( warning )
402  case default
403  call error_mesg ( 'fms_init', &
404  'invalid entry for namelist variable warning_level', fatal )
405  end select
406 
407 !--- set granularity for timing code sections ---
408 
409  select case( trim(uppercase(clock_grain)) )
410  case( 'NONE' )
411  call mpp_clock_set_grain (0)
412  case( 'COMPONENT' )
413  call mpp_clock_set_grain (clock_component)
414  case( 'SUBCOMPONENT' )
415  call mpp_clock_set_grain (clock_subcomponent)
416  case( 'MODULE_DRIVER' )
417  call mpp_clock_set_grain (clock_module_driver)
418  case( 'MODULE' )
419  call mpp_clock_set_grain (clock_module)
420  case( 'ROUTINE' )
421  call mpp_clock_set_grain (clock_routine)
422  case( 'LOOP' )
423  call mpp_clock_set_grain (clock_loop)
424  case( 'INFRA' )
425  call mpp_clock_set_grain (clock_infra)
426  case default
427  call error_mesg ( 'fms_init', &
428  'invalid entry for namelist variable clock_grain', fatal )
429  end select
430 !Balaji
431  select case( trim(uppercase(clock_flags)) )
432  case( 'NONE' )
433  clock_flag_default = 0
434  case( 'SYNC' )
435  clock_flag_default = mpp_clock_sync
436  case( 'DETAILED' )
437  clock_flag_default = mpp_clock_detailed
438  case default
439  call error_mesg ( 'fms_init', &
440  'invalid entry for namelist variable clock_flags', fatal )
441  end select
442 
443 !--- write version info and namelist to logfile ---
444 
445  call write_version_number("FMS_MOD", version)
446  if (mpp_pe() == mpp_root_pe()) then
447  stdout_unit = stdlog()
448  write (stdout_unit, nml=fms_nml)
449  write (stdout_unit,*) 'nml_error_codes=', nml_error_codes(1:num_nml_error_codes)
450  endif
451 
453  call print_memuse_stats('fms_init')
454 
455 !--- output version information constants to the logfile
456  call write_version_number("CONSTANTS_MOD", constants_version)
457  call grid_init
458 
459 end subroutine fms_init
460 
461 !#######################################################################
462 
463 !> @brief Calls the termination routines for all modules in the MPP package.
464 !!
465 !> Termination routine for the fms module. It also calls destructor routines
466 !! for the mpp, mpp_domains, and mpp_io modules. If this routine is called
467 !! more than once it will return silently. There are no arguments.
468 subroutine fms_end ( )
469 
470  if (.not.module_is_initialized) return ! return silently
471 ! call fms_io_exit ! now called from coupler_end
472  call grid_end
473 #ifdef use_deprecated_io
474  call mpp_io_exit
475 #endif
476  call mpp_domains_exit
477  call mpp_exit
478  module_is_initialized =.false.
479 
480 end subroutine fms_end
481 
482 !#######################################################################
483 
484  !> @brief Print notes, warnings and error messages; terminates program for warning
485  !! and error messages. Usage of @ref mpp_error is preferable. (use error levels NOTE,WARNING,FATAL, see example below)
486  !! @details Print notes, warnings and error messages; and terminates the program for
487  !! error messages. This routine is a wrapper around mpp_error, and is provided
488  !! for backward compatibility. This module also publishes mpp_error,
489  !! <B>users should try to use the mpp_error interface</B>.
490  !!
491  !! <br>Example usage:
492  !! @code{.F90}
493  !! use fms_mod, only: error_mesg, FATAL, NOTE
494  !! call error_mesg ('fms_mod', 'initialization not called', FATAL)
495  !! call error_mesg ('fms_mod', 'fms_mod message', NOTE)
496  !! @endcode
497  subroutine error_mesg (routine, message, level)
498  character(len=*), intent(in) :: routine !< Routine name where the warning or error has occurred.
499  character(len=*), intent(in) :: message !< Warning or error message to be printed.
500  integer, intent(in) :: level !< Level of severity; set to NOTE, WARNING, or FATAL Termination always occurs
501  !! for FATAL, never for NOTE, and is settable for WARNING (see namelist).
502 
503 ! input:
504 ! routine name of the calling routine (character string)
505 ! message message written to output (character string)
506 ! level set to NOTE, MESSAGE, or FATAL (integer)
507 
508  if (.not.module_is_initialized) call fms_init ( )
509  call mpp_error ( routine, message, level )
510 
511  end subroutine error_mesg
512 
513 !#######################################################################
514 
515  !> @brief Facilitates the control of fatal error conditions
516  !! @details When err_msg is present, message is copied into err_msg
517  !! and the function returns a value of .true.
518  !! Otherwise calls mpp_error to terminate execution.
519  !! The intended use is as shown below.
520  !! @returns true when err_msg is present
521  !! @code{.F90}
522  !! if(fms_error_handler(routine, message, err_msg)) return
523  !! @endcode
524  function fms_error_handler(routine, message, err_msg)
525 
526  logical :: fms_error_handler
527  character(len=*), intent(in) :: routine !< Routine name where the fatal error has occurred.
528  character(len=*), intent(in) :: message !< fatal error message to be printed.
529  character(len=*), intent(out), optional :: err_msg !< When err_msg is present: err_msg = message
530 
531  fms_error_handler = .false.
532  if(present(err_msg)) then
533  err_msg = message
534  fms_error_handler = .true.
535  else
536  call mpp_error(trim(routine),trim(message),fatal)
537  endif
538 
539  end function fms_error_handler
540 
541 ! used to check the iostat argument that is
542 ! returned after reading a namelist
543 ! see the online documentation for how this routine might be used
544 
545  !> @brief Checks the iostat argument that is returned after reading a namelist
546  !! and determines if the error code is valid.
547  !! @return This function returns the input iostat value (integer) if it is an
548  !! allowable error code. If the iostat error code is not
549  !! allowable, an error message is printed and the program terminated.
550  !! @details The FMS allows multiple namelist records to reside in the same file.
551  !! Use this interface to check the iostat argument that is returned after
552  !! reading a record from the namelist file. If an invalid iostat value
553  !! is detected this routine will produce a fatal error. See the NOTE below.
554  !!
555  !! Some compilers will return non-zero iostat values when reading through
556  !! files with multiple namelist. This routine
557  !! will try skip these errors and only terminate for true namelist errors.
558  !!
559  !! <br>Examples<br>
560  !!
561  !! The following example checks if a file exists, reads a namelist input
562  !! from that file, and checks for errors in that
563  !! namelist. When the correct namelist is read and it has no errors the
564  !! routine check_nml_error will return zero and the while loop will exit.
565  !! This code segment should be used to read namelist files.
566  !! @code{.F90}
567  !! integer :: ierr, io
568  !!
569  !! read (input_nml_file, fms_nml, iostat=io)
570  !! ierr = check_nml_error(io,'fms_nml')
571  !! @endcode
572  !! @throws FATAL, Unknown error while reading namelist ...., (IOSTAT = ####)
573  !! There was an error reading the namelist specified. Carefully examine all namelist and variables
574  !! for anything incorrect (e.g. malformed, hidden characters).
575  !!
576  !! @throws FATAL, Unknown namelist, or mistyped namelist variable in namelist ...., (IOSTAT = ####)
577  !! The name list given doesn't exist in the namelist file, or a variable in the namelist is
578  !! mistyped or isn't a namelist variable.
579  INTEGER FUNCTION check_nml_error(IOSTAT, NML_NAME)
580  INTEGER, INTENT(in) :: iostat !< The iostat value returned when reading a namelist record.
581  CHARACTER(len=*), INTENT(in) :: nml_name !< The name of the namelist. This name will be printed if an error is
582  !! encountered, otherwise the name is not used.
583 
584  CHARACTER(len=256) :: err_str
585 
586  IF ( .NOT.module_is_initialized) CALL fms_init()
587 
588  check_nml_error = iostat
589 
590  ! Return on valid IOSTAT values
591  IF ( iostat <= 0 .OR.&
592  & iostat == nml_errors%multipleNMLSinFile .OR.&
593  & iostat == nml_errors%NotInFile) RETURN
594 
595  ! Everything else is a FATAL
596  IF ( (iostat == nml_errors%badType1 .OR. iostat == nml_errors%badType2) .OR. iostat == nml_errors%missingVar ) THEN
597  WRITE (err_str,*) 'Unknown namelist, or mistyped namelist variable in namelist ',trim(nml_name),', &
598  & (IOSTAT = ',iostat,')'
599  CALL error_mesg ('check_nml_error in fms_mod', err_str, fatal)
600  CALL mpp_sync()
601  ELSE
602  WRITE (err_str,*) 'Unknown error while reading namelist ',trim(nml_name),', (IOSTAT = ',iostat,')'
603  CALL error_mesg ('check_nml_error in fms_mod', err_str, fatal)
604  CALL mpp_sync()
605  END IF
606  END FUNCTION check_nml_error
607 
608 !-----------------------------------------------------------------------
609 ! private routine for initializing allowable error codes
610 
611  !> @brief Determines the IOSTAT error value for some common Namelist errors.
612  !! Also checks if the compiler returns a non-zero status if there are
613  !! multiple namelist records in a single file.
614  SUBROUTINE nml_error_init
615  ! Determines the IOSTAT error value for some common Namelist errors.
616  ! Also checks if the compiler returns a non-zero status if there are
617  ! multiple namelist records in a single file.
618  INTEGER, PARAMETER :: unit_begin = 20, unit_end = 1024
619  INTEGER :: fileunit, io_stat
620  INTEGER, DIMENSION(5) :: nml_iostats
621  LOGICAL :: opened
622 
623  ! Variables for sample namelists
624  INTEGER :: i1 !< Variables for sample namelists
625  INTEGER :: i2 !< Variables for sample namelists
626  REAL :: r1, r2
627  LOGICAL :: l1
628  namelist /a_nml/ i1, r1
629  namelist /b_nml/ i2, r2, l1
630  namelist /badtype1_nml/ i1, r1
631  namelist /badtype2_nml/ i1, r1
632  namelist /missingvar_nml/ i2, r2
633  namelist /not_in_file_nml/ i2, r2
634 
635  ! Initialize the sample namelist variables
636  i1 = 1
637  i2 = 2
638  r1 = 1.0
639  r2 = 2.0
640  l1 = .false.
641 
642  ! Create a dummy namelist file
643  IF ( mpp_pe() == mpp_root_pe() ) THEN
644  ! Find a free file unit for a scratch file
645  file_opened: DO fileunit = unit_begin, unit_end
646  INQUIRE(unit=fileunit, opened=opened)
647  IF ( .NOT.opened ) EXIT file_opened
648  END DO file_opened
649 
650 #if defined(__PGI) || defined(_CRAYFTN)
651  OPEN (unit=fileunit, file='_read_error.nml', iostat=io_stat)
652 #else
653  OPEN (unit=fileunit, status='SCRATCH', iostat=io_stat)
654 #endif
655 
656  ! Write sample namelist to the SCRATCH file.
657  WRITE (unit=fileunit, nml=a_nml, iostat=io_stat)
658  WRITE (unit=fileunit, nml=b_nml, iostat=io_stat)
659  WRITE (unit=fileunit, iostat=io_stat, fmt='(/,"&badType1_nml i1=1, r1=''bad'' /",/)')
660  WRITE (unit=fileunit, iostat=io_stat, fmt='(/,"&badType2_nml i1=1, r1=.true. /",/)')
661  WRITE (unit=fileunit, iostat=io_stat, fmt='(/,"&missingVar_nml i2=1, r2=1.0e0, l1=.true. /",/)')
662 
663  ! Rewind for reading
664  rewind(unit=fileunit)
665 
666  ! Read the second namelist from the file -- check for namelist bug
667  READ (unit=fileunit, nml=b_nml, iostat=nml_iostats(1))
668  rewind(unit=fileunit)
669 
670  ! Read in bad type 1 --- Some compilers treat the string cast differently
671  READ (unit=fileunit, nml=badtype1_nml, iostat=nml_iostats(2))
672  rewind(unit=fileunit)
673 
674  ! Read in bad type 2
675  READ (unit=fileunit, nml=badtype2_nml, iostat=nml_iostats(3))
676  rewind(unit=fileunit)
677 
678  ! Read in missing variable/misstyped
679  READ (unit=fileunit, nml=missingvar_nml, iostat=nml_iostats(4))
680  rewind(unit=fileunit)
681 
682  ! Code for namelist not in file
683  READ (unit=fileunit, nml=not_in_file_nml, iostat=nml_iostats(5))
684 
685  ! Done, close file
686  CLOSE (unit=fileunit)
687 
688  ! Some compilers don't handle the type casting as well as we would like.
689  IF ( nml_iostats(2) * nml_iostats(3) .EQ. 0 ) THEN
690  IF ( nml_iostats(2) .NE. 0 .AND. nml_iostats(3) .EQ. 0 ) THEN
691  nml_iostats(3) = nml_iostats(2)
692  ELSE IF ( nml_iostats(2) .EQ. 0 .AND. nml_iostats(3) .NE.0 ) THEN
693  nml_iostats(2) = nml_iostats(3)
694  ELSE
695  nml_iostats(2) = nml_iostats(4)
696  nml_iostats(2) = nml_iostats(4)
697  END IF
698  END IF
699  END IF
700 
701  ! Broadcast nml_errors
702  CALL mpp_broadcast(nml_iostats,5,mpp_root_pe())
703  nml_errors%multipleNMLSinFile = nml_iostats(1)
704  nml_errors%badType1 = nml_iostats(2)
705  nml_errors%badType2 = nml_iostats(3)
706  nml_errors%missingVar = nml_iostats(4)
707  nml_errors%NotInFile = nml_iostats(5)
708 
709  do_nml_error_init = .false.
710  END SUBROUTINE nml_error_init
711 
712 !#######################################################################
713 
714 !> @brief match the input character string to a string
715 !! in an array/list of character strings
716 !! @return If an exact match was found then true is returned, otherwise false is returned.
717 !! @details Tries to find a match for a character string in a list of character strings.
718 !! The match is case sensitive and disregards blank characters to the right of
719 !! the string.
720 !!
721 !! <br>Examples<br>
722 !! @code{.F90}
723 !! string = "def"
724 !! string_array = (/ "abcd", "def ", "fghi" /)
725 !!
726 !! string_array_index ( string, string_array, index )
727 !! @endcode
728 !! Returns: TRUE, index = 2
729 function string_array_index ( string, string_array, index ) result (found)
730 character(len=*), intent(in) :: string !< Character string of arbitrary length.
731 character(len=*), intent(in) :: string_array(:) !< Array/list of character strings.
732 integer, optional, intent(out) :: index !< The index of string_array where the first match was found. If
733  !! no match was found then index = 0.
734 logical :: found !< If an exact match was found then TRUE is returned, otherwise FALSE is returned.
735 integer :: i
736 
737 ! initialize this function to false
738 ! loop thru string_array and exit when a match is found
739 
740  found = .false.
741  if (present(index)) index = 0
742 
743  do i = 1, size(string_array(:))
744  ! found a string match ?
745  if ( trim(string) == trim(string_array(i)) ) then
746  found = .true.
747  if (present(index)) index = i
748  exit
749  endif
750  enddo
751 
752 end function string_array_index
753 
754 !#######################################################################
755 !> @brief Prints to the log file (or a specified unit) the version id string and
756 !! tag name.
757 subroutine write_version_number (version, tag, unit)
758  character(len=*), intent(in) :: version !> string that contains routine name
759  character(len=*), intent(in), optional :: tag !> tag name that code was checked out with
760  integer, intent(in), optional :: unit !> alternate unit number to direct output,
761  !! defaults to stdlog
762  integer :: logunit
763 
764  if (.not.module_is_initialized) call fms_init ( )
765 
766  logunit = stdlog()
767 
768  if (present(unit)) then
769  logunit = unit
770  else
771  ! only allow stdlog messages on root pe
772  if ( mpp_pe() /= mpp_root_pe() ) return
773  endif
774 
775  if (present(tag)) then
776  write (logunit,'(/,80("="),/(a))') trim(version), trim(tag)
777  else
778  write (logunit,'(/,80("="),/(a))') trim(version)
779  endif
780 
781 end subroutine write_version_number
782 
783 #include "fms_r4.fh"
784 #include "fms_r8.fh"
785 
786 end module fms_mod
787 ! <INFO>
788 ! <BUG>
789 ! Namelist error checking may not work correctly with some compilers.
790 !
791 ! Users should beware when mixing Fortran reads and read_data calls. If a
792 ! Fortran read follows read_data and namelist variable read_all_pe = FALSE
793 ! (not the default), then the code will fail. It is safest if Fortran reads
794 ! precede calls to read_data.
795 ! </BUG>
796 ! <ERROR MSG="unexpected EOF" STATUS="FATAL">
797 ! An unexpected end-of-file was encountered in a read_data call.
798 ! You may want to use the optional end argument to detect the EOF.
799 ! </ERROR>
800 ! <NOTE>
801 ! 1) If the <B>MPP</B> or <B>MPP_DOMAINS</B> stack size is exceeded the
802 ! program will terminate after printing the required size.
803 !
804 ! 2) When running on a very small number of processors or for high
805 ! resolution models the default domains_stack_size will
806 ! probably be insufficient.
807 !
808 ! 3) The following performance routines in the <B>MPP</B> module are published by this module.
809 !<PRE>
810 ! mpp_clock_id, mpp_clock_begin, mpp_clock_end
811 !</PRE>
812 ! and associated parameters that are published:
813 !<PRE>
814 ! MPP_CLOCK_SYNC, MPP_CLOCK_DETAILED, CLOCK_COMPONENT, CLOCK_SUBCOMPONENT,
815 ! CLOCK_MODULE_DRIVER, CLOCK_MODULE, CLOCK_ROUTINE, CLOCK_LOOP, CLOCK_INFRA
816 !</PRE>
817 !
818 ! 4) Here is an example of how to time a section of code.<BR/>
819 !<PRE>
820 ! use fms_mod, only: mpp_clock_id, mpp_clock_begin, &
821 ! mpp_clock_end. MPP_CLOCK_SYNC, &
822 ! CLOCK_MODULE_DRIVER
823 ! integer :: id_mycode
824 !
825 ! id_mycode = mpp_clock_id ('mycode loop', flags=MPP_CLOCK_SYNC, grain=CLOCK_MODULE_DRIVER)
826 ! call mpp_clock_begin (id_mycode)
827 ! :
828 ! :
829 ! ~~ this code will be timed ~~
830 ! :
831 ! :
832 ! call mpp_clock_end (id_mycode)
833 ! </PRE>
834 ! Note: <TT>CLOCK_MODULE_DRIVER</TT> can be replaced with
835 ! CLOCK_COMPONENT, CLOCK_SUBCOMPONENT, CLOCK_MODULE_DRIVER, CLOCK_MODULE, CLOCK_ROUTINE,
836 ! CLOCK_LOOP, or CLOCK_INFRA.
837 !
838 ! </NOTE>
839 ! <FUTURE>
840 ! NetCDF facilities for reading and writing restart files and (IEEE32)
841 ! data files.
842 ! </FUTURE>
843 ! <FUTURE>
844 ! May possible split the FMS module into two modules.
845 !
846 ! i.general utilities (FMS_MOD) <BR/>
847 ! ii.I/O utilities (FMS_IO_MOD)
848 ! </FUTURE>
849 ! </INFO>
850 !> @}
851 ! close documentation grouping
subroutine, public fms2_io_init()
Reads the fms2_io_nml.
Definition: fms2_io.F90:396
Close a netcdf or domain file opened with open_file or open_virtual_file.
Definition: fms2_io.F90:166
Opens a given netcdf or domain file.
Definition: fms2_io.F90:122
Read data from a defined field in a file.
Definition: fms2_io.F90:292
Write data to a defined field within a file Example usage:
Definition: fms2_io.F90:262
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...
Definition: fms.F90:580
subroutine, public write_version_number(version, tag, unit)
Prints to the log file (or a specified unit) the version id string and tag name.
Definition: fms.F90:758
subroutine, private nml_error_init
Determines the IOSTAT error value for some common Namelist errors. Also checks if the compiler return...
Definition: fms.F90:615
character(len=8) warning_level
Sets the termination condition for the WARNING flag to interfaces error_mesg/mpp_error....
Definition: fms.F90:268
logical function, public string_array_index(string, string_array, index)
match the input character string to a string in an array/list of character strings
Definition: fms.F90:730
logical read_all_pe
Read global data on all processors extracting local part needed (TRUE) or read global data on PE0 and...
Definition: fms.F90:252
subroutine, public fms_end()
Calls the termination routines for all modules in the MPP package.
Definition: fms.F90:469
character(len=16) clock_grain
The level of clock granularity used for performance timing sections of code. Possible values in order...
Definition: fms.F90:255
logical function, public fms_error_handler(routine, message, err_msg)
Facilitates the control of fatal error conditions.
Definition: fms.F90:525
integer domains_stack_size
The size in words of the MPP_DOMAINS user stack. If domains_stack_size > 0, the following MPP_DOMAINS...
Definition: fms.F90:275
subroutine, public fms_init(localcomm, alt_input_nml_path)
Initializes the FMS module and also calls the initialization routines for all modules in the MPP pack...
Definition: fms.F90:332
logical, public print_memory_usage
If set to .TRUE., memory usage statistics will be printed at various points in the code....
Definition: fms.F90:280
character(len=16) clock_flags
Possible values are 'NONE', 'SYNC', or 'DETAILED'. SYNC will give accurate information on load balanc...
Definition: fms.F90:262
subroutine, public error_mesg(routine, message, level)
Print notes, warnings and error messages; terminates program for warning and error messages....
Definition: fms.F90:498
integer stack_size
The size in words of the MPP user stack. If stack_size > 0, the following MPP routine is called: call...
Definition: fms.F90:272
Converts a C string to a Fortran string.
Namelist read error values.
Definition: fms.F90:238
character(:) function, allocatable, public string(v, fmt)
Converts a number or a Boolean value to a string.
subroutine, public grid_end
Shutdown the grid2 module.
Definition: grid2.F90:162
subroutine, public grid_init
Initialize the grid2 module.
Definition: grid2.F90:146
subroutine, public memutils_init(print_flag)
Initialize the memutils module.
Definition: memutils.F90:55
subroutine, public print_memuse_stats(text, unit, always)
Print memory usage stats to stdout, or a particular file.
Definition: memutils.F90:71
subroutine mpp_domains_init(flags)
Initialize domain decomp package.
subroutine mpp_domains_exit()
Exit mpp_domains_mod. Serves no particular purpose, but is provided should you require to re-initiali...
subroutine mpp_domains_set_stack_size(n)
Set user stack size.
Set up a domain decomposition.
These routines retrieve the axis specifications associated with the compute domains....
These routines retrieve the axis specifications associated with the data domains. The domain is a der...
These routines retrieve the axis specifications associated with the global domains....
Fill in a global array from domain-decomposed arrays.
Performs halo updates for a given domain.
The domain2D type contains all the necessary information to define the global, compute and data domai...
subroutine mpp_get_info(unit, ndim, nvar, natt, ntime)
Get some general information about a file.
Definition: mpp_io_util.inc:33
subroutine mpp_get_fields(unit, variables)
Copy variable information from file (excluding data)
Get file global metadata.
Definition: mpp_io.F90:522
integer function stdout()
This function returns the current standard fortran unit numbers for output.
Definition: mpp_util.inc:43
subroutine mpp_init(flags, localcomm, test_level, alt_input_nml_path)
Initialize the mpp_mod module. Must be called before any usage.
integer function stderr()
This function returns the current standard fortran unit numbers for error messages.
Definition: mpp_util.inc:51
subroutine read_input_nml(pelist_name_in, alt_input_nml_path)
Reads an existing input nml file into a character array and broadcasts it to the non-root mpi-tasks....
Definition: mpp_util.inc:1219
subroutine mpp_clock_set_grain(grain)
Set the level of granularity of timing measurements.
Definition: mpp_util.inc:641
subroutine mpp_exit()
Finalizes process termination. To be called at the end of a run. Certain mpi implementations(openmpi)...
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
Definition: mpp_util.inc:59
integer function mpp_npes()
Returns processor count for current pelist.
Definition: mpp_util.inc:421
subroutine mpp_set_stack_size(n)
Set the mpp_stack variable to be at least n LONG words long.
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:407
subroutine mpp_sync(pelist, do_self)
Synchronize PEs in list.
integer function mpp_clock_id(name, flags, grain)
Return an ID for a new or existing clock.
Definition: mpp_util.inc:705
integer function stdin()
This function returns the current standard fortran unit numbers for input.
Definition: mpp_util.inc:36
Perform parallel broadcasts.
Definition: mpp.F90:1091
Calculate parallel checksums.
Definition: mpp.F90:1200
Error handler.
Definition: mpp.F90:382
Basic message-passing call.
Definition: mpp.F90:872
converts a kind=c_char to type c_ptr