FMS  2025.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 use fms2_io_mod, only: fms2_io_init
147 use memutils_mod, only: print_memuse_stats, memutils_init
148 use grid2_mod, only: grid_init, grid_end
149 use fms_string_utils_mod, only: fms_c2f_string, fms_cstring2cpointer, string
150 use platform_mod, only: r4_kind, r8_kind
151 
152 use, intrinsic :: iso_c_binding
153 
154 implicit none
155 private
156 
157 ! routines for initialization and termination of module
158 public :: fms_init, fms_end
159 
161 
162 ! version logging routine (originally from fms_io)
163 public :: write_version_number
164 
165 ! miscellaneous utilities (non i/o)
166 public :: lowercase, uppercase, &
168 
169 ! public mpp interfaces
170 public :: mpp_error, note, warning, fatal, &
171  mpp_error_state, &
172  mpp_pe, mpp_npes, mpp_root_pe, &
173  stdin, stdout, stderr, stdlog, &
174  mpp_chksum, get_unit, read_input_nml
175 public :: input_nml_file
176 public :: mpp_clock_id, mpp_clock_begin, mpp_clock_end
177 public :: mpp_clock_sync, mpp_clock_detailed
178 public :: clock_component, clock_subcomponent, &
179  clock_module_driver, clock_module, &
180  clock_routine, clock_loop, clock_infra
182 !public from the old fms_io but not exists here
183 public :: string
184 
186  module procedure :: monotonic_array_r4, monotonic_array_r8
187 end interface monotonic_array
188 
189 !Balaji
190 !this is published by fms and applied to any initialized clocks
191 !of course you can go and set the flag to SYNC or DETAILED by hand
192 integer, public :: clock_flag_default
193 !> @}
194  !> Namelist read error values
195  !> @ingroup fms_mod
197  INTEGER :: multipleNMLSinFile
198  INTEGER :: badType1
199  INTEGER :: badType2
200  INTEGER :: missingVar
201  INTEGER :: NotInFile
202  END TYPE nml_errors_type
203  TYPE(nml_errors_type), SAVE :: nml_errors
204 !> @addtogroup fms_mod
205 !> @{
206 
207 !------ namelist interface -------
208 !------ adjustable severity level for warnings ------
209 
210  logical :: read_all_pe = .true. !< Read global data on all processors extracting local
211  !! part needed (TRUE) or read global data on PE0 and broadcast to all
212  !! PEs(FALSE).
213  character(len=16) :: clock_grain = 'NONE' !< The level of clock granularity used for performance
214  !! timing sections of code. Possible values in order of increasing detail
215  !! are: 'NONE', 'COMPONENT', 'SUBCOMPONENT', 'MODULE_DRIVER', 'MODULE',
216  !! 'ROUTINE', 'LOOP', and 'INFRA'. Code sections are defined using routines
217  !! in MPP module: mpp_clock_id, mpp_clock_begin, and mpp_clock_end. The fms
218  !! module makes these routines public. A list of timed code sections will be
219  !! printed to STDOUT. See the @ref mpp_mod module for more details.
220  character(len=16) :: clock_flags='NONE' !< Possible values are 'NONE', 'SYNC', or 'DETAILED'.
221  !! SYNC will give accurate information on load balance of the clocked
222  !! portion of code. DETAILED also turns on detailed message-passing
223  !! performance diagnosis. Both SYNC and DETAILED will work correctly on
224  !! innermost clock nest and distort outer clocks, and possibly the overall
225  !! code time. See the @ref mpp_mod module for more details.
226  character(len=8) :: warning_level = 'warning' !< Sets the termination condition for the WARNING
227  !! flag to interfaces error_mesg/mpp_error. set warning_level = 'fatal'
228  !! (program crashes for warning messages) or 'warning' (prints warning
229  !! message and continues).
230  integer :: stack_size = 0 !< The size in words of the MPP user stack. If stack_size > 0,
231  !! the following MPP routine is called: call mpp_set_stack_size (stack_size).
232  !! If stack_size = 0 (default) then the default size set by mpp_mod is used.
233  integer :: domains_stack_size = 0 !< The size in words of the MPP_DOMAINS user stack. If
234  !! domains_stack_size > 0, the following MPP_DOMAINS routine is called:
235  !! call mpp_domains_set_stack_size (domains_stack_size). If
236  !! domains_stack_size = 0 (default) then the default size set by
237  !! @ref mpp_domains_mod is used.
238  logical, public :: print_memory_usage = .false. !< If set to .TRUE., memory usage statistics
239  !! will be printed at various points in the code. It is used to study memory
240  !! usage, e.g to detect memory leaks.
241 
242 !------ namelist interface -------
243 
244  namelist /fms_nml/ read_all_pe, clock_grain, clock_flags, &
247 
248 ! ---- private data for check_nml_error ----
249 
250  integer, private :: num_nml_error_codes, nml_error_codes(20)
251  logical, private :: do_nml_error_init = .true.
252  private nml_error_init
253 
254 
255 ! ---- version number -----
256 
257 ! Include variable "version" to be written to log file.
258 #include<file_version.h>
259 
260  logical :: module_is_initialized = .false.
261 
262 !> @}
263 
264 !> @addtogroup fms_mod
265 !> @{
266 contains
267 
268 !#######################################################################
269 
270 !> @brief Initializes the FMS module and also calls the initialization routines for all
271 !! modules in the MPP package. Will be called automatically if the user does
272 !! not call it.
273 !! @details Initialization routine for the fms module. It also calls initialization routines
274 !! for the mpp, mpp_domains, and mpp_io modules. Although this routine
275 !! will be called automatically by other fms_mod routines, users should
276 !! explicitly call fms_init. If this routine is called more than once it will
277 !! return silently. There are no arguments.
278 !!
279 !> @throws FATAL, invalid entry for namelist variable warning_level
280 !! The namelist variable warning_level must be either 'fatal' or 'warning'(case-insensitive)
281 !!
282 !> @throws FATAL, invalid entry for namelist variable clock_grain
283 !! The namelist variable clock_grain must be one of the following values:
284 !! 'NONE', 'COMPONENT', 'SUBCOMPONENT', 'MODULE_DRIVER', 'MODULE', 'ROUTINE',
285 !! 'LOOP', or 'INFRA' (case-insensitive).
286 subroutine fms_init (localcomm, alt_input_nml_path)
287 
288 !--- needed to output the version number of constants_mod to the logfile ---
289  use constants_mod, only: constants_version=>version !pjp: PI not computed
290  interface
291  subroutine maximize_system_stacksize_limit() bind(C)
292  end subroutine
293  end interface
294 
295  integer, intent(in), optional :: localcomm
296  character(len=*), intent(in), optional :: alt_input_nml_path
297  integer :: ierr, io
298  integer :: logunitnum
299  integer :: stdout_unit !< Unit number for the stdout file
300 
301  if (module_is_initialized) return ! return silently if already called
302  module_is_initialized = .true.
303 
304 !---- Raise the system stack size limit to its maximum permissible value ----
305  call maximize_system_stacksize_limit
306 
307 !---- initialize mpp routines ----
308  if(present(localcomm)) then
309  if(present(alt_input_nml_path)) then
310  call mpp_init(localcomm=localcomm, alt_input_nml_path=alt_input_nml_path)
311  else
312  call mpp_init(localcomm=localcomm)
313  endif
314  else
315  if(present(alt_input_nml_path)) then
316  call mpp_init(alt_input_nml_path=alt_input_nml_path)
317  else
318  call mpp_init()
319  endif
320  endif
321  call mpp_domains_init()
322  call fms2_io_init()
323 #ifdef use_deprecated_io
324  call mpp_error(note, "fms_io_init: fms_io HAS BEEN DEPRECATED! "//&
325  "PLEASE REMOVE -Duse_deprecated_io FROM YOUR COMPILE FLAGS "// &
326  "AND MOVE TO FMS2_IO. CONTACT YOUR MODEL LIASISON IF YOU NEED "// &
327  "ASSISTANCE")
328 #endif
329  logunitnum = stdlog()
330 !---- read namelist input ----
331 
332  call nml_error_init() ! first initialize namelist iostat error codes
333 
334  read (input_nml_file, fms_nml, iostat=io)
335  ierr = check_nml_error(io,'fms_nml')
336 
337 !---- define mpp stack sizes if non-zero -----
338 
339  if ( stack_size > 0) call mpp_set_stack_size ( stack_size)
341 
342 !---- set severity level for warnings ----
343 
344  select case( trim(lowercase(warning_level)) )
345  case( 'fatal' )
346  call mpp_set_warn_level ( fatal )
347  case( 'warning' )
348  call mpp_set_warn_level ( warning )
349  case default
350  call error_mesg ( 'fms_init', &
351  'invalid entry for namelist variable warning_level', fatal )
352  end select
353 
354 !--- set granularity for timing code sections ---
355 
356  select case( trim(uppercase(clock_grain)) )
357  case( 'NONE' )
358  call mpp_clock_set_grain (0)
359  case( 'COMPONENT' )
360  call mpp_clock_set_grain (clock_component)
361  case( 'SUBCOMPONENT' )
362  call mpp_clock_set_grain (clock_subcomponent)
363  case( 'MODULE_DRIVER' )
364  call mpp_clock_set_grain (clock_module_driver)
365  case( 'MODULE' )
366  call mpp_clock_set_grain (clock_module)
367  case( 'ROUTINE' )
368  call mpp_clock_set_grain (clock_routine)
369  case( 'LOOP' )
370  call mpp_clock_set_grain (clock_loop)
371  case( 'INFRA' )
372  call mpp_clock_set_grain (clock_infra)
373  case default
374  call error_mesg ( 'fms_init', &
375  'invalid entry for namelist variable clock_grain', fatal )
376  end select
377 !Balaji
378  select case( trim(uppercase(clock_flags)) )
379  case( 'NONE' )
380  clock_flag_default = 0
381  case( 'SYNC' )
382  clock_flag_default = mpp_clock_sync
383  case( 'DETAILED' )
384  clock_flag_default = mpp_clock_detailed
385  case default
386  call error_mesg ( 'fms_init', &
387  'invalid entry for namelist variable clock_flags', fatal )
388  end select
389 
390 !--- write version info and namelist to logfile ---
391 
392  call write_version_number("FMS_MOD", version)
393  if (mpp_pe() == mpp_root_pe()) then
394  stdout_unit = stdlog()
395  write (stdout_unit, nml=fms_nml)
396  write (stdout_unit,*) 'nml_error_codes=', nml_error_codes(1:num_nml_error_codes)
397  endif
398 
400  call print_memuse_stats('fms_init')
401 
402 !--- output version information constants to the logfile
403  call write_version_number("CONSTANTS_MOD", constants_version)
404  call grid_init
405 
406 end subroutine fms_init
407 
408 !#######################################################################
409 
410 !> @brief Calls the termination routines for all modules in the MPP package.
411 !!
412 !> Termination routine for the fms module. It also calls destructor routines
413 !! for the mpp, mpp_domains, and mpp_io modules. If this routine is called
414 !! more than once it will return silently. There are no arguments.
415 subroutine fms_end ( )
416 
417  if (.not.module_is_initialized) return ! return silently
418 ! call fms_io_exit ! now called from coupler_end
419  call grid_end
420  call mpp_domains_exit
421  call mpp_exit
422  module_is_initialized =.false.
423 
424 end subroutine fms_end
425 
426 !#######################################################################
427 
428  !> @brief Print notes, warnings and error messages; terminates program for warning
429  !! and error messages. Usage of @ref mpp_error is preferable. (use error levels NOTE,WARNING,FATAL, see example below)
430  !! @details Print notes, warnings and error messages; and terminates the program for
431  !! error messages. This routine is a wrapper around mpp_error, and is provided
432  !! for backward compatibility. This module also publishes mpp_error,
433  !! <B>users should try to use the mpp_error interface</B>.
434  !!
435  !! <br>Example usage:
436  !! @code{.F90}
437  !! use fms_mod, only: error_mesg, FATAL, NOTE
438  !! call error_mesg ('fms_mod', 'initialization not called', FATAL)
439  !! call error_mesg ('fms_mod', 'fms_mod message', NOTE)
440  !! @endcode
441  subroutine error_mesg (routine, message, level)
442  character(len=*), intent(in) :: routine !< Routine name where the warning or error has occurred.
443  character(len=*), intent(in) :: message !< Warning or error message to be printed.
444  integer, intent(in) :: level !< Level of severity; set to NOTE, WARNING, or FATAL Termination always occurs
445  !! for FATAL, never for NOTE, and is settable for WARNING (see namelist).
446 
447 ! input:
448 ! routine name of the calling routine (character string)
449 ! message message written to output (character string)
450 ! level set to NOTE, MESSAGE, or FATAL (integer)
451 
452  if (.not.module_is_initialized) call fms_init ( )
453  call mpp_error ( routine, message, level )
454 
455  end subroutine error_mesg
456 
457 !#######################################################################
458 
459  !> @brief Facilitates the control of fatal error conditions
460  !! @details When err_msg is present, message is copied into err_msg
461  !! and the function returns a value of .true.
462  !! Otherwise calls mpp_error to terminate execution.
463  !! The intended use is as shown below.
464  !! @returns true when err_msg is present
465  !! @code{.F90}
466  !! if(fms_error_handler(routine, message, err_msg)) return
467  !! @endcode
468  function fms_error_handler(routine, message, err_msg)
469 
470  logical :: fms_error_handler
471  character(len=*), intent(in) :: routine !< Routine name where the fatal error has occurred.
472  character(len=*), intent(in) :: message !< fatal error message to be printed.
473  character(len=*), intent(out), optional :: err_msg !< When err_msg is present: err_msg = message
474 
475  fms_error_handler = .false.
476  if(present(err_msg)) then
477  err_msg = message
478  fms_error_handler = .true.
479  else
480  call mpp_error(trim(routine),trim(message),fatal)
481  endif
482 
483  end function fms_error_handler
484 
485 ! used to check the iostat argument that is
486 ! returned after reading a namelist
487 ! see the online documentation for how this routine might be used
488 
489  !> @brief Checks the iostat argument that is returned after reading a namelist
490  !! and determines if the error code is valid.
491  !! @return This function returns the input iostat value (integer) if it is an
492  !! allowable error code. If the iostat error code is not
493  !! allowable, an error message is printed and the program terminated.
494  !! @details The FMS allows multiple namelist records to reside in the same file.
495  !! Use this interface to check the iostat argument that is returned after
496  !! reading a record from the namelist file. If an invalid iostat value
497  !! is detected this routine will produce a fatal error. See the NOTE below.
498  !!
499  !! Some compilers will return non-zero iostat values when reading through
500  !! files with multiple namelist. This routine
501  !! will try skip these errors and only terminate for true namelist errors.
502  !!
503  !! <br>Examples<br>
504  !!
505  !! The following example checks if a file exists, reads a namelist input
506  !! from that file, and checks for errors in that
507  !! namelist. When the correct namelist is read and it has no errors the
508  !! routine check_nml_error will return zero and the while loop will exit.
509  !! This code segment should be used to read namelist files.
510  !! @code{.F90}
511  !! integer :: ierr, io
512  !!
513  !! read (input_nml_file, fms_nml, iostat=io)
514  !! ierr = check_nml_error(io,'fms_nml')
515  !! @endcode
516  !! @throws FATAL, Unknown error while reading namelist ...., (IOSTAT = ####)
517  !! There was an error reading the namelist specified. Carefully examine all namelist and variables
518  !! for anything incorrect (e.g. malformed, hidden characters).
519  !!
520  !! @throws FATAL, Unknown namelist, or mistyped namelist variable in namelist ...., (IOSTAT = ####)
521  !! The name list given doesn't exist in the namelist file, or a variable in the namelist is
522  !! mistyped or isn't a namelist variable.
523  INTEGER FUNCTION check_nml_error(IOSTAT, NML_NAME)
524  INTEGER, INTENT(in) :: iostat !< The iostat value returned when reading a namelist record.
525  CHARACTER(len=*), INTENT(in) :: nml_name !< The name of the namelist. This name will be printed if an error is
526  !! encountered, otherwise the name is not used.
527 
528  CHARACTER(len=256) :: err_str
529 
530  IF ( .NOT.module_is_initialized) CALL fms_init()
531 
532  check_nml_error = iostat
533 
534  ! Return on valid IOSTAT values
535  IF ( iostat <= 0 .OR.&
536  & iostat == nml_errors%multipleNMLSinFile .OR.&
537  & iostat == nml_errors%NotInFile) RETURN
538 
539  ! Everything else is a FATAL
540  IF ( (iostat == nml_errors%badType1 .OR. iostat == nml_errors%badType2) .OR. iostat == nml_errors%missingVar ) THEN
541  WRITE (err_str,*) 'Unknown namelist, or mistyped namelist variable in namelist ',trim(nml_name),', &
542  & (IOSTAT = ',iostat,')'
543  CALL error_mesg ('check_nml_error in fms_mod', err_str, fatal)
544  CALL mpp_sync()
545  ELSE
546  WRITE (err_str,*) 'Unknown error while reading namelist ',trim(nml_name),', (IOSTAT = ',iostat,')'
547  CALL error_mesg ('check_nml_error in fms_mod', err_str, fatal)
548  CALL mpp_sync()
549  END IF
550  END FUNCTION check_nml_error
551 
552 !-----------------------------------------------------------------------
553 ! private routine for initializing allowable error codes
554 
555  !> @brief Determines the IOSTAT error value for some common Namelist errors.
556  !! Also checks if the compiler returns a non-zero status if there are
557  !! multiple namelist records in a single file.
558  SUBROUTINE nml_error_init
559  ! Determines the IOSTAT error value for some common Namelist errors.
560  ! Also checks if the compiler returns a non-zero status if there are
561  ! multiple namelist records in a single file.
562  INTEGER, PARAMETER :: unit_begin = 20, unit_end = 1024
563  INTEGER :: fileunit, io_stat
564  INTEGER, DIMENSION(5) :: nml_iostats
565  LOGICAL :: opened
566 
567  ! Variables for sample namelists
568  INTEGER :: i1 !< Variables for sample namelists
569  INTEGER :: i2 !< Variables for sample namelists
570  REAL :: r1, r2
571  LOGICAL :: l1
572  namelist /a_nml/ i1, r1
573  namelist /b_nml/ i2, r2, l1
574  namelist /badtype1_nml/ i1, r1
575  namelist /badtype2_nml/ i1, r1
576  namelist /missingvar_nml/ i2, r2
577  namelist /not_in_file_nml/ i2, r2
578 
579  ! Initialize the sample namelist variables
580  i1 = 1
581  i2 = 2
582  r1 = 1.0
583  r2 = 2.0
584  l1 = .false.
585 
586  ! Create a dummy namelist file
587  IF ( mpp_pe() == mpp_root_pe() ) THEN
588  ! Find a free file unit for a scratch file
589  file_opened: DO fileunit = unit_begin, unit_end
590  INQUIRE(unit=fileunit, opened=opened)
591  IF ( .NOT.opened ) EXIT file_opened
592  END DO file_opened
593 
594 #if defined(__PGI) || defined(_CRAYFTN)
595  OPEN (unit=fileunit, file='_read_error.nml', iostat=io_stat)
596 #else
597  OPEN (unit=fileunit, status='SCRATCH', iostat=io_stat)
598 #endif
599 
600  ! Write sample namelist to the SCRATCH file.
601  WRITE (unit=fileunit, nml=a_nml, iostat=io_stat)
602  WRITE (unit=fileunit, nml=b_nml, iostat=io_stat)
603  WRITE (unit=fileunit, iostat=io_stat, fmt='(/,"&badType1_nml i1=1, r1=''bad'' /",/)')
604  WRITE (unit=fileunit, iostat=io_stat, fmt='(/,"&badType2_nml i1=1, r1=.true. /",/)')
605  WRITE (unit=fileunit, iostat=io_stat, fmt='(/,"&missingVar_nml i2=1, r2=1.0e0, l1=.true. /",/)')
606 
607  ! Rewind for reading
608  rewind(unit=fileunit)
609 
610  ! Read the second namelist from the file -- check for namelist bug
611  READ (unit=fileunit, nml=b_nml, iostat=nml_iostats(1))
612  rewind(unit=fileunit)
613 
614  ! Read in bad type 1 --- Some compilers treat the string cast differently
615  READ (unit=fileunit, nml=badtype1_nml, iostat=nml_iostats(2))
616  rewind(unit=fileunit)
617 
618  ! Read in bad type 2
619  READ (unit=fileunit, nml=badtype2_nml, iostat=nml_iostats(3))
620  rewind(unit=fileunit)
621 
622  ! Read in missing variable/misstyped
623  READ (unit=fileunit, nml=missingvar_nml, iostat=nml_iostats(4))
624  rewind(unit=fileunit)
625 
626  ! Code for namelist not in file
627  READ (unit=fileunit, nml=not_in_file_nml, iostat=nml_iostats(5))
628 
629  ! Done, close file
630  CLOSE (unit=fileunit)
631 
632  ! Some compilers don't handle the type casting as well as we would like.
633  IF ( nml_iostats(2) * nml_iostats(3) .EQ. 0 ) THEN
634  IF ( nml_iostats(2) .NE. 0 .AND. nml_iostats(3) .EQ. 0 ) THEN
635  nml_iostats(3) = nml_iostats(2)
636  ELSE IF ( nml_iostats(2) .EQ. 0 .AND. nml_iostats(3) .NE.0 ) THEN
637  nml_iostats(2) = nml_iostats(3)
638  ELSE
639  nml_iostats(2) = nml_iostats(4)
640  nml_iostats(2) = nml_iostats(4)
641  END IF
642  END IF
643  END IF
644 
645  ! Broadcast nml_errors
646  CALL mpp_broadcast(nml_iostats,5,mpp_root_pe())
647  nml_errors%multipleNMLSinFile = nml_iostats(1)
648  nml_errors%badType1 = nml_iostats(2)
649  nml_errors%badType2 = nml_iostats(3)
650  nml_errors%missingVar = nml_iostats(4)
651  nml_errors%NotInFile = nml_iostats(5)
652 
653  do_nml_error_init = .false.
654  END SUBROUTINE nml_error_init
655 
656 !#######################################################################
657 
658 !> @brief match the input character string to a string
659 !! in an array/list of character strings
660 !! @return If an exact match was found then true is returned, otherwise false is returned.
661 !! @details Tries to find a match for a character string in a list of character strings.
662 !! The match is case sensitive and disregards blank characters to the right of
663 !! the string.
664 !!
665 !! <br>Examples<br>
666 !! @code{.F90}
667 !! string = "def"
668 !! string_array = (/ "abcd", "def ", "fghi" /)
669 !!
670 !! string_array_index ( string, string_array, index )
671 !! @endcode
672 !! Returns: TRUE, index = 2
673 function string_array_index ( string, string_array, index ) result (found)
674 character(len=*), intent(in) :: string !< Character string of arbitrary length.
675 character(len=*), intent(in) :: string_array(:) !< Array/list of character strings.
676 integer, optional, intent(out) :: index !< The index of string_array where the first match was found. If
677  !! no match was found then index = 0.
678 logical :: found !< If an exact match was found then TRUE is returned, otherwise FALSE is returned.
679 integer :: i
680 
681 ! initialize this function to false
682 ! loop thru string_array and exit when a match is found
683 
684  found = .false.
685  if (present(index)) index = 0
686 
687  do i = 1, size(string_array(:))
688  ! found a string match ?
689  if ( trim(string) == trim(string_array(i)) ) then
690  found = .true.
691  if (present(index)) index = i
692  exit
693  endif
694  enddo
695 
696 end function string_array_index
697 
698 !#######################################################################
699 !> @brief Prints to the log file (or a specified unit) the version id string and
700 !! tag name.
701 subroutine write_version_number (version, tag, unit)
702  character(len=*), intent(in) :: version !> string that contains routine name
703  character(len=*), intent(in), optional :: tag !> tag name that code was checked out with
704  integer, intent(in), optional :: unit !> alternate unit number to direct output,
705  !! defaults to stdlog
706  integer :: logunit
707 
708  if (.not.module_is_initialized) call fms_init ( )
709 
710  logunit = stdlog()
711 
712  if (present(unit)) then
713  logunit = unit
714  else
715  ! only allow stdlog messages on root pe
716  if ( mpp_pe() /= mpp_root_pe() ) return
717  endif
718 
719  if (present(tag)) then
720  write (logunit,'(/,80("="),/(a))') trim(version), trim(tag)
721  else
722  write (logunit,'(/,80("="),/(a))') trim(version)
723  endif
724 
725 end subroutine write_version_number
726 
727 #include "fms_r4.fh"
728 #include "fms_r8.fh"
729 
730 end module fms_mod
731 ! <INFO>
732 ! <BUG>
733 ! Namelist error checking may not work correctly with some compilers.
734 !
735 ! Users should beware when mixing Fortran reads and read_data calls. If a
736 ! Fortran read follows read_data and namelist variable read_all_pe = FALSE
737 ! (not the default), then the code will fail. It is safest if Fortran reads
738 ! precede calls to read_data.
739 ! </BUG>
740 ! <ERROR MSG="unexpected EOF" STATUS="FATAL">
741 ! An unexpected end-of-file was encountered in a read_data call.
742 ! You may want to use the optional end argument to detect the EOF.
743 ! </ERROR>
744 ! <NOTE>
745 ! 1) If the <B>MPP</B> or <B>MPP_DOMAINS</B> stack size is exceeded the
746 ! program will terminate after printing the required size.
747 !
748 ! 2) When running on a very small number of processors or for high
749 ! resolution models the default domains_stack_size will
750 ! probably be insufficient.
751 !
752 ! 3) The following performance routines in the <B>MPP</B> module are published by this module.
753 !<PRE>
754 ! mpp_clock_id, mpp_clock_begin, mpp_clock_end
755 !</PRE>
756 ! and associated parameters that are published:
757 !<PRE>
758 ! MPP_CLOCK_SYNC, MPP_CLOCK_DETAILED, CLOCK_COMPONENT, CLOCK_SUBCOMPONENT,
759 ! CLOCK_MODULE_DRIVER, CLOCK_MODULE, CLOCK_ROUTINE, CLOCK_LOOP, CLOCK_INFRA
760 !</PRE>
761 !
762 ! 4) Here is an example of how to time a section of code.<BR/>
763 !<PRE>
764 ! use fms_mod, only: mpp_clock_id, mpp_clock_begin, &
765 ! mpp_clock_end. MPP_CLOCK_SYNC, &
766 ! CLOCK_MODULE_DRIVER
767 ! integer :: id_mycode
768 !
769 ! id_mycode = mpp_clock_id ('mycode loop', flags=MPP_CLOCK_SYNC, grain=CLOCK_MODULE_DRIVER)
770 ! call mpp_clock_begin (id_mycode)
771 ! :
772 ! :
773 ! ~~ this code will be timed ~~
774 ! :
775 ! :
776 ! call mpp_clock_end (id_mycode)
777 ! </PRE>
778 ! Note: <TT>CLOCK_MODULE_DRIVER</TT> can be replaced with
779 ! CLOCK_COMPONENT, CLOCK_SUBCOMPONENT, CLOCK_MODULE_DRIVER, CLOCK_MODULE, CLOCK_ROUTINE,
780 ! CLOCK_LOOP, or CLOCK_INFRA.
781 !
782 ! </NOTE>
783 ! <FUTURE>
784 ! NetCDF facilities for reading and writing restart files and (IEEE32)
785 ! data files.
786 ! </FUTURE>
787 ! <FUTURE>
788 ! May possible split the FMS module into two modules.
789 !
790 ! i.general utilities (FMS_MOD) <BR/>
791 ! ii.I/O utilities (FMS_IO_MOD)
792 ! </FUTURE>
793 ! </INFO>
794 !> @}
795 ! close documentation grouping
subroutine, public fms2_io_init()
Reads the fms2_io_nml.
Definition: fms2_io.F90:396
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:524
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:702
subroutine, private nml_error_init
Determines the IOSTAT error value for some common Namelist errors. Also checks if the compiler return...
Definition: fms.F90:559
character(len=8) warning_level
Sets the termination condition for the WARNING flag to interfaces error_mesg/mpp_error....
Definition: fms.F90:226
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:674
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:210
subroutine, public fms_end()
Calls the termination routines for all modules in the MPP package.
Definition: fms.F90:416
character(len=16) clock_grain
The level of clock granularity used for performance timing sections of code. Possible values in order...
Definition: fms.F90:213
logical function, public fms_error_handler(routine, message, err_msg)
Facilitates the control of fatal error conditions.
Definition: fms.F90:469
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:233
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:287
logical, public print_memory_usage
If set to .TRUE., memory usage statistics will be printed at various points in the code....
Definition: fms.F90:238
character(len=16) clock_flags
Possible values are 'NONE', 'SYNC', or 'DETAILED'. SYNC will give accurate information on load balanc...
Definition: fms.F90:220
subroutine, public error_mesg(routine, message, level)
Print notes, warnings and error messages; terminates program for warning and error messages....
Definition: fms.F90:442
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:230
Converts a C string to a Fortran string.
Namelist read error values.
Definition: fms.F90:196
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...
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:1228
subroutine mpp_clock_set_grain(grain)
Set the level of granularity of timing measurements.
Definition: mpp_util.inc:650
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:714
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:1105
Calculate parallel checksums.
Definition: mpp.F90:1214
Error handler.
Definition: mpp.F90:382
Basic message-passing call.
Definition: mpp.F90:886
converts a kind=c_char to type c_ptr