ROMS
Loading...
Searching...
No Matches
strings.F
Go to the documentation of this file.
1#include "cppdefs.h"
3!
4!git $Id$
5!================================================== Hernan G. Arango ===
6! Copyright (c) 2002-2025 The ROMS Group !
7! Licensed under a MIT/X style license !
8! See License_ROMS.md !
9!=======================================================================
10! !
11! This module contains several string manipulation functions: !
12! !
13! FoundError checks action flag against no-error code !
14! GlobalError global check action flag against no-error code !
15! StandardName sets standard_name attribute !
16! TaskError task check action flag against no-error code !
17! assign_string allocates and assign string !
18! find_string scans a character array for a specified string !
19! join_string concatenate character array into a single string !
20! lowercase converts input string characters to lowercase !
21! uppercase converts input string characters to uppercase !
22! !
23! Examples: !
24! !
25! IF (.not.find_string(var_name,n_var,'spherical',varid)) THEN !
26! ... !
27! END IF !
28! !
29! string=lowercase('MY UPPERCASE STRING') !
30! !
31! string=uppercase('my lowercase string') !
32! !
33!=======================================================================
34!
35 implicit none
36!
37 PRIVATE
38!
39 PUBLIC :: founderror
40 PUBLIC :: globalerror
41 PUBLIC :: standardname
42 PUBLIC :: taskerror
43 PUBLIC :: assign_string
44 PUBLIC :: find_string
45 PUBLIC :: join_string
46 PUBLIC :: lowercase
47 PUBLIC :: uppercase
48!
49 CONTAINS
50!
51 FUNCTION founderror (flag, NoErr, line, routine) RESULT (foundit)
52!
53!=======================================================================
54! !
55! This logical function checks ROMS execution flag against no-error !
56! code and issue a message if they are not equal. !
57! !
58! On Input: !
59! !
60! flag ROMS execution flag (integer) !
61! NoErr No Error code (integer) !
62! line Calling model routine line (integer) !
63! routine Calling model routine (string) !
64! !
65! On Output: !
66! !
67! foundit The value of the result is TRUE/FALSE if the !
68! execution flag is in error. !
69! !
70!=======================================================================
71!
72 USE mod_iounits, ONLY : stdout
73 USE mod_parallel, ONLY : master
74!
75! Imported variable declarations.
76!
77 integer, intent(in) :: flag, noerr, line
78
79 character (len=*), intent(in) :: routine
80!
81! Local variable declarations.
82!
83 logical :: foundit
84!
85!-----------------------------------------------------------------------
86! Scan array for requested string.
87!-----------------------------------------------------------------------
88!
89 foundit=.false.
90 IF (flag.ne.noerr) THEN
91 foundit=.true.
92 IF (master) THEN
93 WRITE (stdout,10) flag, line, trim(routine)
94 10 FORMAT (' Found Error: ', i0, t20, 'Line: ', i0, &
95 & t35, 'Source: ', a)
96 END IF
97 FLUSH (stdout)
98 END IF
99
100 RETURN
101 END FUNCTION founderror
102!
103 FUNCTION globalerror (ng, model, flag, NoErr, line, routine) &
104 & result(foundit)
105!
106!=======================================================================
107! !
108! This logical function checks ROMS execution flag against no-error !
109! code and issue a message if they are not equal. It can be used in !
110! split, disjointed, distributed-memory communicators. All process !
111! in application needs to call this function and the master process !
112! knows to flag value to broadcast. !
113! !
114! If not distributed-memory, this function has the same capability !
115! as FoundError. !
116! !
117! On Input: !
118! !
119! ng Nested grid number (integer) !
120! model Calling model identifier (integer) !
121! flag ROMS execution flag (integer) !
122! NoErr No Error code (integer) !
123! line Calling model routine line (integer) !
124! routine Calling model routine (string) !
125! !
126! On Output: !
127! !
128! flag Updated flag value to all processes (integer) !
129! foundit The value of the result is TRUE/FALSE if the !
130! execution flag is in error. !
131! !
132!=======================================================================
133!
134 USE mod_parallel
135 USE mod_iounits, ONLY : stdout
136
137#if defined DISTRIBUTE && defined DISJOINTED
139#endif
140!
141! Imported variable declarations.
142!
143 integer, intent(in) :: ng, model, noerr, line
144 integer, intent(inout) :: flag
145
146 character (len=*), intent(in) :: routine
147!
148! Local variable declarations.
149!
150 logical :: foundit
151 logical :: masterprocess
152#ifdef DISTRIBUTE
153 integer :: mycomm
154#endif
155!
156!-----------------------------------------------------------------------
157! Set master process.
158#ifdef DISTRIBUTE
159! Set distribute-memory communicator and broadcast flag value to all
160! processes.
161#endif
162!-----------------------------------------------------------------------
163!
164#ifdef DISTRIBUTE
165# ifdef DISJOINTED
166 mycomm=full_comm_world
167 masterprocess=fullrank.eq.0
168# else
169 mycomm=ocn_comm_world
170 masterprocess=myrank.eq.0
171# endif
172#else
173 masterprocess=master
174#endif
175#if defined DISTRIBUTE && defined DISJOINTED
176!
177 CALL mp_bcasti (ng, model, flag, mycomm)
178#endif
179!
180!-----------------------------------------------------------------------
181! Scan array for requested string.
182!-----------------------------------------------------------------------
183!
184 foundit=.false.
185 IF (flag.ne.noerr) THEN
186 foundit=.true.
187 IF (masterprocess) THEN
188 WRITE (stdout,10) flag, line, trim(routine)
189 10 FORMAT (' Found Error: ', i2.2, t20, 'Line: ', i0, &
190 & t35, 'Source: ', a)
191 END IF
192 FLUSH (stdout)
193 END IF
194
195 RETURN
196 END FUNCTION globalerror
197!
198 FUNCTION taskerror (ng, model, flag, NoErr, line, routine) &
199 & result(foundit)
200!
201!=======================================================================
202! !
203! This logical function checks ROMS execution flag against no-error !
204! code and issue a message if they are not equal. It can be used in !
205! split, disjointed-tasks, distributed-memory communicators. All !
206! processes in the task section needs to call this function and its !
207! master process knows to flag value to broadcast. !
208! !
209! If not distributed-memory, this function has the same capability !
210! as FoundError and GlobalError. !
211! !
212! On Input: !
213! !
214! ng Nested grid number (integer) !
215! model Calling model identifier (integer) !
216! flag ROMS execution flag (integer) !
217! NoErr No Error code (integer) !
218! line Calling model routine line (integer) !
219! routine Calling model routine (string) !
220! !
221! On Output: !
222! !
223! flag Updated flag value to all processes (integer) !
224! foundit The value of the result is TRUE/FALSE if the !
225! execution flag is in error. !
226! !
227!=======================================================================
228!
229 USE mod_parallel
230 USE mod_iounits, ONLY : stdout
231
232#if defined DISTRIBUTE && defined DISJOINTED
234#endif
235!
236! Imported variable declarations.
237!
238 integer, intent(in) :: ng, model, noerr, line
239 integer, intent(inout) :: flag
240
241 character (len=*), intent(in) :: routine
242!
243! Local variable declarations.
244!
245 logical :: foundit
246 logical :: masterprocess
247#ifdef DISTRIBUTE
248 integer :: mycomm
249#endif
250!
251!-----------------------------------------------------------------------
252! Set master process.
253#ifdef DISTRIBUTE
254! Set distribute-memory communicator and broadcast flag value to all
255! processes.
256#endif
257!-----------------------------------------------------------------------
258!
259#ifdef DISTRIBUTE
260# ifdef DISJOINTED
261# ifdef CONCURRENT_KERNEL
262 mycomm=task_comm_world
263 masterprocess=taskrank.eq.0
264# else
265 mycomm=full_comm_world
266 masterprocess=fullrank.eq.0
267# endif
268# else
269 mycomm=ocn_comm_world
270 masterprocess=myrank.eq.0
271# endif
272#else
273 masterprocess=master
274#endif
275#if defined DISTRIBUTE && defined DISJOINTED
276!
277 CALL mp_bcasti (ng, model, flag, mycomm)
278#endif
279!
280!-----------------------------------------------------------------------
281! Scan array for requested string.
282!-----------------------------------------------------------------------
283!
284 foundit=.false.
285 IF (flag.ne.noerr) THEN
286 foundit=.true.
287 IF (masterprocess) THEN
288 WRITE (stdout,10) flag, line, trim(routine)
289 10 FORMAT (' Found Error: ', i2.2, t20, 'Line: ', i0, &
290 & t35, 'Source: ', a)
291 END IF
292 FLUSH (stdout)
293 END IF
294
295 RETURN
296 END FUNCTION taskerror
297!
298 SUBROUTINE standardname (Sname, variable, prefix, suffix)
299!
300!=======================================================================
301! !
302! This routine concatenates prefix and suffix strings to generate the !
303! 'standard_name' attribute. Blank spaces in the prefix are replaced !
304! with underscore. !
305! !
306! On Input: !
307! !
308! variable Standard name main variable (character) !
309! prefix Standard name prefix (OPTIONAL, character) !
310! suffix Standard name suffix (OPTIONAL, character) !
311! !
312! On Output: !
313! !
314! Sname concatenated standard name (character) !
315! !
316!=======================================================================
317!
318! Imported variable declarations.
319!
320 character (len=*), intent(in) :: variable
321 character (len=*), optional, intent(in) :: prefix
322 character (len=*), optional, intent(in) :: suffix
323 character (len=*), intent(out) :: sname
324!
325! Local variable declarations.
326!
327 integer :: icomma, lstr, i
328!
329!-----------------------------------------------------------------------
330! Generate 'standard_name' attribute.
331!-----------------------------------------------------------------------
332!
333 DO i=1,len(sname)
334 sname(i:i)=char(32)
335 END DO
336!
337! Replace blank space with underscore, CHAR(95).
338!
339 lstr=len_trim(variable)
340 icomma=index(variable,char(44),back=.false.)
341 IF (icomma.gt.0) THEN ! remove comma
342 sname=variable(1:icomma-1) // variable(icomma+1:lstr)
343 lstr=len_trim(sname)
344 ELSE
345 sname(1:lstr)=variable(1:lstr)
346 END IF
347!
348 DO i=1,lstr
349 IF (sname(i:i).eq.char(32)) THEN
350 sname(i:i)=char(95)
351 END IF
352 END DO
353!
354! Append prefix and or suffix string(s).
355
356 IF (PRESENT(prefix)) THEN
357 sname=trim(adjustl(prefix)) // trim(adjustl(sname))
358 END IF
359!
360 IF (PRESENT(suffix)) THEN
361 sname=trim(adjustl(sname)) // trim(adjustl(suffix))
362 END IF
363!
364 RETURN
365 END SUBROUTINE standardname
366!
367 FUNCTION assign_string (A, string) RESULT (ErrFlag)
368!
369!=======================================================================
370! !
371! This routine assigns allocatable strings. It allocates/reallocates !
372! output string variable. !
373! !
374! On Input: !
375! !
376! string String to be assigned (character) !
377! !
378! On Output: !
379! !
380! A Assigned allocatable string (character) !
381! ErrFlag Error flag (integer) !
382! !
383!=======================================================================
384!
385! Imported variable declarations.
386!
387 character (len=:), allocatable, intent(inout) :: a
388 character (len=*), intent(in) :: string
389!
390! Local variable declarations.
391!
392 integer :: lstr
393 integer :: errflag
394!
395!-----------------------------------------------------------------------
396! Allocate output string to the size of input string.
397!-----------------------------------------------------------------------
398!
399 errflag=-1
400!
401 lstr=len_trim(string)
402 IF (.not.allocated(a)) THEN
403 allocate ( character(LEN=lstr) :: a, stat=errflag)
404 ELSE
405 deallocate (a)
406 allocate ( character(LEN=lstr) :: a, stat=errflag)
407 END IF
408!
409! Assign requested value.
410!
411 a=string
412!
413 RETURN
414 END FUNCTION assign_string
415!
416 FUNCTION find_string (A, Asize, string, Aindex) RESULT (foundit)
417!
418!=======================================================================
419! !
420! This logical function scans an array of type character for an !
421! specific string. !
422! !
423! On Input: !
424! !
425! A Array of strings (character) !
426! Asize Size of A (integer) !
427! string String to search (character) !
428! !
429! On Output: !
430! !
431! Aindex Array element containing the string (integer) !
432! foundit The value of the result is TRUE/FALSE if the !
433! string was found or not. !
434! !
435!=======================================================================
436!
437! Imported variable declarations.
438!
439 integer, intent(in) :: asize
440
441 integer, intent(out) :: aindex
442
443 character (len=*), intent(in) :: a(asize)
444 character (len=*), intent(in) :: string
445!
446! Local variable declarations.
447!
448 logical :: foundit
449
450 integer :: i
451!
452!-----------------------------------------------------------------------
453! Scan array for requested string.
454!-----------------------------------------------------------------------
455!
456 foundit=.false.
457 aindex=0
458 DO i=1,asize
459 IF (trim(a(i)).eq.trim(string)) THEN
460 foundit=.true.
461 aindex=i
462 EXIT
463 END IF
464 END DO
465
466 RETURN
467 END FUNCTION find_string
468!
469 SUBROUTINE join_string (A, Asize, string, Lstring)
470!
471!=======================================================================
472! !
473! This routine concatenate a character array into a single string !
474! with each element separated by commas. !
475! !
476! On Input: !
477! !
478! A Array of strings (character) !
479! Asize Size of A (integer) !
480! !
481! On Output: !
482! !
483! string Concatenated string (character) !
484! Lstring Length of concatenated string (integer) !
485! !
486!=======================================================================
487!
488! Imported variable declarations.
489!
490 integer, intent(in) :: asize
491
492 integer, intent(out) :: lstring
493
494 character (len=*), intent(in) :: a(asize)
495 character (len=*), intent(out) :: string
496!
497! Local variable declarations.
498!
499 integer :: i, ie, is, lstr
500!
501!-----------------------------------------------------------------------
502! Concatenate input character array.
503!-----------------------------------------------------------------------
504!
505! Initialize to blank string.
506!
507 lstr=len(string)
508 DO i=1,lstr
509 string(i:i)=' '
510 END DO
511!
512! Concatenate.
513!
514 is=1
515 DO i=1,asize
516 lstr=len_trim(a(i))
517 IF (lstr.gt.0) THEN
518 ie=is+lstr-1
519 string(is:ie)=trim(a(i))
520 is=ie+1
521 string(is:is)=','
522 is=is+2
523 END IF
524 END DO
525 lstring=len_trim(string)-1
526
527 RETURN
528 END SUBROUTINE join_string
529!
530 FUNCTION lowercase (Sinp) RESULT (Sout)
531!
532!=======================================================================
533! !
534! This character function converts input string elements to !
535! lowercase. !
536! !
537! On Input: !
538! !
539! Sinp String with uppercase elements (character) !
540! !
541! On Output: !
542! !
543! Sout Lowercase string (character) !
544! !
545! Reference: !
546! !
547! Cooper Redwine, 1995: "Upgrading to Fortran 90", Springer- !
548! Verlag, New York, pp 416. !
549! !
550!=======================================================================
551!
552! Imported variable declarations.
553!
554 character (*), intent(in) :: sinp
555!
556! Local variable definitions.
557!
558 integer :: i, j, lstr
559
560 character (LEN(Sinp)) :: sout
561
562 character (26), parameter :: lcase = 'abcdefghijklmnopqrstuvwxyz'
563 character (26), parameter :: ucase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
564!
565!-----------------------------------------------------------------------
566! Convert input string to lowercase.
567!-----------------------------------------------------------------------
568!
569 lstr=len(sinp)
570 sout=sinp
571 DO i=1,lstr
572 j=index(ucase, sout(i:i))
573 IF (j.ne.0) THEN
574 sout(i:i)=lcase(j:j)
575 END IF
576 END DO
577
578 RETURN
579 END FUNCTION lowercase
580!
581 FUNCTION uppercase (Sinp) RESULT (Sout)
582!
583!=======================================================================
584! !
585! This character function converts input string elements to !
586! uppercase. !
587! !
588! On Input: !
589! !
590! Sinp String with lowercase characters (character) !
591! !
592! On Output: !
593! !
594! Sout Uppercase string (character) !
595! !
596! Reference: !
597! !
598! Cooper Redwine, 1995: "Upgrading to Fortran 90", Springer- !
599! Verlag, New York, pp 416. !
600! !
601!=======================================================================
602!
603! Imported variable declarations.
604!
605 character (*), intent(in) :: sinp
606!
607! Local variable definitions.
608!
609 integer :: i, j, lstr
610
611 character (LEN(Sinp)) :: sout
612
613 character (26), parameter :: lcase = 'abcdefghijklmnopqrstuvwxyz'
614 character (26), parameter :: ucase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
615!
616!-----------------------------------------------------------------------
617! Convert input string to uppercase.
618!-----------------------------------------------------------------------
619!
620 lstr=len(sinp)
621 sout=sinp
622 DO i=1,lstr
623 j=index(lcase, sout(i:i))
624 IF (j.ne.0) THEN
625 sout(i:i)=ucase(j:j)
626 END IF
627 END DO
628
629 RETURN
630 END FUNCTION uppercase
631
632 END MODULE strings_mod
subroutine mp_barrier(ng, model, inpcomm)
Definition distribute.F:126
integer stdout
integer taskrank
integer fullrank
logical master
integer ocn_comm_world
logical function, public taskerror(ng, model, flag, noerr, line, routine)
Definition strings.F:200
character(len(sinp)) function, public uppercase(sinp)
Definition strings.F:582
character(len(sinp)) function, public lowercase(sinp)
Definition strings.F:531
logical function, public find_string(a, asize, string, aindex)
Definition strings.F:417
integer function, public assign_string(a, string)
Definition strings.F:368
subroutine, public join_string(a, asize, string, lstring)
Definition strings.F:470
subroutine, public standardname(sname, variable, prefix, suffix)
Definition strings.F:299
logical function, public globalerror(ng, model, flag, noerr, line, routine)
Definition strings.F:105
logical function, public founderror(flag, noerr, line, routine)
Definition strings.F:52