FMS 2025.01-dev
Flexible Modeling System
Loading...
Searching...
No Matches
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!> @{
44module 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
121use 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, &
126 mpp_clock_begin, mpp_clock_end, &
127 mpp_clock_id, mpp_init, mpp_exit, &
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, &
133 mpp_set_stack_size, &
134 stdin, stdout, stderr, stdlog, &
135 mpp_error_state, lowercase, &
136 uppercase, mpp_broadcast, input_nml_file, &
137 get_unit, read_input_nml
138
139use mpp_domains_mod, only: domain2d, mpp_define_domains, &
140 mpp_update_domains, global_data_domain, &
141 mpp_domains_init, mpp_domains_exit, &
145
146#ifdef use_deprecated_io
147use 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
155use 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
163use fms2_io_mod, only: fms2_io_init
164use memutils_mod, only: print_memuse_stats, memutils_init
165use grid2_mod, only: grid_init, grid_end
166use fms_string_utils_mod, only: fms_c2f_string, fms_cstring2cpointer, string
167use platform_mod, only: r4_kind, r8_kind
168
169use, intrinsic :: iso_c_binding
170
171implicit none
172private
173
174! routines for initialization and termination of module
175public :: fms_init, fms_end
176
177! routines for opening/closing specific types of file
178#ifdef use_deprecated_io
179public :: 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
184public :: read_data, write_data, read_compressed, read_distributed
185public :: get_domain_decomp, field_size
186public :: get_global_att_value
187
188! routines for get mosaic information
189public :: get_mosaic_tile_grid, get_mosaic_tile_file
190
191! miscellaneous i/o routines
192public :: file_exist, field_exist
193#endif
194public ::check_nml_error, error_mesg, fms_error_handler
195
196! version logging routine (originally from fms_io)
197public :: write_version_number
198
199! miscellaneous utilities (non i/o)
200public :: lowercase, uppercase, &
201 string_array_index, monotonic_array
202#ifdef use_deprecated_io
203public :: set_domain, nullify_domain
204#endif
205
206! public mpp interfaces
207public :: 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
212public :: input_nml_file
213public :: mpp_clock_id, mpp_clock_begin, mpp_clock_end
214public :: mpp_clock_sync, mpp_clock_detailed
215public :: 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
220public :: string
221
222! public mpp-io interfaces
223#ifdef use_deprecated_io
224public :: do_cf_compliance
225#endif
226
227interface monotonic_array
228 module procedure :: monotonic_array_r4, monotonic_array_r8
229end 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
234integer, public :: clock_flag_default
235!> @}
236 !> Namelist read error values
237 !> @ingroup fms_mod
238 TYPE nml_errors_type
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, &
287 warning_level, stack_size, domains_stack_size, &
288 print_memory_usage
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!> @{
311contains
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).
331subroutine 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)
393 if (domains_stack_size > 0) call mpp_domains_set_stack_size (domains_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
452 call memutils_init( print_memory_usage )
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
459end 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.
468subroutine 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
480end 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
729function string_array_index ( string, string_array, index ) result (found)
730character(len=*), intent(in) :: string !< Character string of arbitrary length.
731character(len=*), intent(in) :: string_array(:) !< Array/list of character strings.
732integer, optional, intent(out) :: index !< The index of string_array where the first match was found. If
733 !! no match was found then index = 0.
734logical :: found !< If an exact match was found then TRUE is returned, otherwise FALSE is returned.
735integer :: 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
752end 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.
757subroutine 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
781end subroutine write_version_number
782
783#include "fms_r4.fh"
784#include "fms_r8.fh"
785
786end 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
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 print_memuse_stats(text, unit, always)
Print memory usage stats to stdout, or a particular file.
Definition memutils.F90:71
subroutine, public memutils_init(print_flag)
Initialize the memutils module.
Definition memutils.F90:55
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.
subroutine mpp_get_fields(unit, variables)
Copy variable information from file (excluding data)
Get file global metadata.
Definition mpp_io.F90:522
subroutine mpp_sync(pelist, do_self)
Synchronize PEs in list.
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 C string to a Fortran string.
converts a kind=c_char to type c_ptr