mod_oasis_string.F90 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718
  1. !> Character string manipulation methods
  2. !> These methods work generally on character strings, but also, more particularly
  3. !> on lists. A list is a character string that contains substrings separated by
  4. !> a delimeter. That delimeter can be set by the user but the default is ":".
  5. !> Colon delimeted lists are used in OASIS and MCT mainly to instantiate a list
  6. !> of fields, such as "temperature:humidity:zonal_velocity:meridiona_velocity".
  7. #define NEW_LGI_METHOD2a
  8. !!#define NEW_LGI_METHOD2b
  9. !===============================================================================
  10. !BOP ===========================================================================
  11. !
  12. ! !MODULE: mod_oasis_string -- string and list methods
  13. !
  14. ! !DESCRIPTION:
  15. ! General string and specific list method. A list is a single string
  16. ! that is delimited by a character forming multiple fields, ie,
  17. ! character(len=*) :: mylist = "t:s:u1:v1:u2:v2:taux:tauy"
  18. ! The delimiter is called listDel in this module, is default ":",
  19. ! but can be set by a call to oasis_string_listSetDel.
  20. !
  21. !
  22. ! !INTERFACE: ------------------------------------------------------------------
  23. module mod_oasis_string
  24. ! !USES:
  25. use mod_oasis_kinds
  26. use mod_oasis_parameters
  27. use mod_oasis_data
  28. use mod_oasis_sys
  29. use mod_oasis_timer
  30. implicit none
  31. private
  32. ! !PUBLIC TYPES:
  33. ! no public types
  34. ! !PUBLIC MEMBER FUNCTIONS:
  35. public :: oasis_string_countChar ! Count number of char in string, fn
  36. public :: oasis_string_toUpper ! Convert string to upper-case
  37. public :: oasis_string_toLower ! Convert string to lower-case
  38. public :: oasis_string_getParentDir ! For a pathname get the parent directory name
  39. public :: oasis_string_lastIndex ! Index of last substr in str
  40. public :: oasis_string_endIndex ! Index of end of substr in str
  41. public :: oasis_string_leftAlign ! remove leading white space
  42. public :: oasis_string_alphanum ! remove all non alpha-numeric characters
  43. public :: oasis_string_betweenTags ! get the substring between the two tags
  44. public :: oasis_string_parseCFtunit ! parse CF time units
  45. public :: oasis_string_clean ! Set string to all white space
  46. public :: oasis_string_listIsValid ! test for a valid "list"
  47. public :: oasis_string_listGetNum ! Get number of fields in list, fn
  48. public :: oasis_string_listGetIndex ! Get index of field
  49. public :: oasis_string_listGetIndexF ! function version of listGetIndex
  50. public :: oasis_string_listGetName ! get k-th field name
  51. public :: oasis_string_listIntersect ! get intersection of two field lists
  52. public :: oasis_string_listUnion ! get union of two field lists
  53. public :: oasis_string_listMerge ! merge two lists to form third
  54. public :: oasis_string_listAppend ! append list at end of another
  55. public :: oasis_string_listPrepend ! prepend list in front of another
  56. public :: oasis_string_listSetDel ! Set field delimeter in lists
  57. public :: oasis_string_listGetDel ! Get field delimeter in lists
  58. public :: oasis_string_setAbort ! set local abort flag
  59. public :: oasis_string_setDebug ! set local debug flag
  60. ! !PUBLIC DATA MEMBERS:
  61. ! no public data members
  62. !EOP
  63. character(len=1) ,save :: listDel = ":" ! note single exec implications
  64. character(len=2) ,save :: listDel2 = "::" ! note single exec implications
  65. logical ,save :: doabort = .true.
  66. integer(ip_i4_p),save :: debug = 0
  67. !===============================================================================
  68. contains
  69. !===============================================================================
  70. !===============================================================================
  71. !BOP ===========================================================================
  72. !
  73. ! !IROUTINE: oasis_string_countChar -- Count number of occurances of a character
  74. !
  75. ! !DESCRIPTION:
  76. !> Count number of occurances of a single character in a string
  77. ! \newline
  78. ! n = shr\_string\_countChar(string,character)
  79. !
  80. !
  81. ! !INTERFACE: ------------------------------------------------------------------
  82. integer function oasis_string_countChar(str,char,rc)
  83. implicit none
  84. ! !INPUT/OUTPUT PARAMETERS:
  85. character(*) ,intent(in) :: str !< string to search
  86. character(1) ,intent(in) :: char !< char to search for
  87. integer(ip_i4_p),intent(out),optional :: rc !< return code
  88. !EOP
  89. !----- local -----
  90. integer(ip_i4_p) :: count ! counts occurances of char
  91. integer(ip_i4_p) :: n ! generic index
  92. !----- formats -----
  93. character(*),parameter :: subName = "(oasis_string_countChar) "
  94. !-------------------------------------------------------------------------------
  95. ! Notes:
  96. !-------------------------------------------------------------------------------
  97. call oasis_debug_enter(subname)
  98. count = 0
  99. do n = 1, len_trim(str)
  100. if (str(n:n) == char) count = count + 1
  101. end do
  102. oasis_string_countChar = count
  103. if (present(rc)) rc = 0
  104. call oasis_debug_exit(subname)
  105. end function oasis_string_countChar
  106. !===============================================================================
  107. !BOP ===========================================================================
  108. ! !IROUTINE: oasis_string_toUpper -- Convert string to upper case
  109. !
  110. ! !DESCRIPTION:
  111. !> Convert the input string to upper-case.
  112. ! Use achar and iachar intrinsics to ensure use of ascii collating sequence.
  113. !
  114. !
  115. ! !INTERFACE: ------------------------------------------------------------------
  116. function oasis_string_toUpper(str)
  117. implicit none
  118. ! !INPUT/OUTPUT PARAMETERS:
  119. character(len=*), intent(in) :: str !< input string to convert to upper case
  120. character(len=len(str)) :: oasis_string_toUpper !< output converted string
  121. !----- local -----
  122. integer(ip_i4_p) :: i ! Index
  123. integer(ip_i4_p) :: aseq ! ascii collating sequence
  124. integer(ip_i4_p) :: LowerToUpper ! integer to convert case
  125. character(len=1) :: ctmp ! Character temporary
  126. !----- formats -----
  127. character(*),parameter :: subName = "(oasis_string_toUpper) "
  128. !-------------------------------------------------------------------------------
  129. !
  130. !-------------------------------------------------------------------------------
  131. call oasis_debug_enter(subname)
  132. LowerToUpper = iachar("A") - iachar("a")
  133. do i = 1, len(str)
  134. ctmp = str(i:i)
  135. aseq = iachar(ctmp)
  136. if ( aseq >= iachar("a") .and. aseq <= iachar("z") ) &
  137. ctmp = achar(aseq + LowertoUpper)
  138. oasis_string_toUpper(i:i) = ctmp
  139. end do
  140. call oasis_debug_exit(subname)
  141. end function oasis_string_toUpper
  142. !===============================================================================
  143. !BOP ===========================================================================
  144. ! !IROUTINE: oasis_string_toLower -- Convert string to lower case
  145. !
  146. ! !DESCRIPTION:
  147. !> Convert the input string to lower-case.
  148. ! Use achar and iachar intrinsics to ensure use of ascii collating sequence.
  149. !
  150. !
  151. ! !INTERFACE: ------------------------------------------------------------------
  152. function oasis_string_toLower(str)
  153. implicit none
  154. ! !INPUT/OUTPUT PARAMETERS:
  155. character(len=*), intent(in) :: str !< input string to convert to lower case
  156. character(len=len(str)) :: oasis_string_toLower !< output converted string
  157. !----- local -----
  158. integer(ip_i4_p) :: i ! Index
  159. integer(ip_i4_p) :: aseq ! ascii collating sequence
  160. integer(ip_i4_p) :: UpperToLower ! integer to convert case
  161. character(len=1) :: ctmp ! Character temporary
  162. !----- formats -----
  163. character(*),parameter :: subName = "(oasis_string_toLower) "
  164. !-------------------------------------------------------------------------------
  165. !
  166. !-------------------------------------------------------------------------------
  167. call oasis_debug_enter(subname)
  168. UpperToLower = iachar("a") - iachar("A")
  169. do i = 1, len(str)
  170. ctmp = str(i:i)
  171. aseq = iachar(ctmp)
  172. if ( aseq >= iachar("A") .and. aseq <= iachar("Z") ) &
  173. ctmp = achar(aseq + UpperToLower)
  174. oasis_string_toLower(i:i) = ctmp
  175. end do
  176. call oasis_debug_exit(subname)
  177. end function oasis_string_toLower
  178. !===============================================================================
  179. !BOP ===========================================================================
  180. ! !IROUTINE: oasis_string_getParentDir -- For pathname get the parent directory name
  181. !
  182. ! !DESCRIPTION:
  183. !> Get the parent directory pathname.
  184. !
  185. !
  186. ! !INTERFACE: ------------------------------------------------------------------
  187. function oasis_string_getParentDir(str)
  188. implicit none
  189. ! !INPUT/OUTPUT PARAMETERS:
  190. character(len=*), intent(in) :: str !< input string
  191. character(len=len(str)) :: oasis_string_getParentDir !< return directory path
  192. !----- local -----
  193. integer(ip_i4_p) :: i ! Index
  194. integer(ip_i4_p) :: nlen ! Length of string
  195. !----- formats -----
  196. character(*),parameter :: subName = "(oasis_string_getParentDir) "
  197. !-------------------------------------------------------------------------------
  198. !
  199. !-------------------------------------------------------------------------------
  200. call oasis_debug_enter(subname)
  201. nlen = len_trim(str)
  202. if ( str(nlen:nlen) == "/" ) nlen = nlen - 1
  203. i = index( str(1:nlen), "/", back=.true. )
  204. if ( i == 0 )then
  205. oasis_string_getParentDir = str
  206. else
  207. oasis_string_getParentDir = str(1:i-1)
  208. end if
  209. call oasis_debug_exit(subname)
  210. end function oasis_string_getParentDir
  211. !===============================================================================
  212. !BOP ===========================================================================
  213. !
  214. !
  215. ! !IROUTINE: oasis_string_lastIndex -- Get index of last substr within string
  216. !
  217. ! !DESCRIPTION:
  218. !> Get the index of the last occurance of a substring within a string
  219. ! \newline
  220. ! n = shr\_string\_lastIndex(string,substring)
  221. !
  222. !
  223. ! !INTERFACE: ------------------------------------------------------------------
  224. integer function oasis_string_lastIndex(string,substr,rc)
  225. implicit none
  226. ! !INPUT/OUTPUT PARAMETERS:
  227. character(*) ,intent(in) :: string !< input string to search
  228. character(*) ,intent(in) :: substr !< sub-string to search for
  229. integer(ip_i4_p),intent(out),optional :: rc !< return code
  230. !EOP
  231. !--- local ---
  232. !----- formats -----
  233. character(*),parameter :: subName = "(oasis_string_lastIndex) "
  234. !-------------------------------------------------------------------------------
  235. ! Note:
  236. ! - "new" F90 back option to index function makes this home-grown solution obsolete
  237. !-------------------------------------------------------------------------------
  238. call oasis_debug_enter(subname)
  239. oasis_string_lastIndex = index(string,substr,.true.)
  240. if (present(rc)) rc = 0
  241. call oasis_debug_exit(subname)
  242. end function oasis_string_lastIndex
  243. !===============================================================================
  244. !BOP ===========================================================================
  245. !
  246. ! !IROUTINE: oasis_string_endIndex -- Get the ending index of substr within string
  247. !
  248. ! !DESCRIPTION:
  249. !> Get the ending index of the first occurance of a substring within string
  250. ! \newline
  251. ! n = shr\_string\_endIndex(string,substring)
  252. !
  253. !
  254. ! !INTERFACE: ------------------------------------------------------------------
  255. integer function oasis_string_endIndex(string,substr,rc)
  256. implicit none
  257. ! !INPUT/OUTPUT PARAMETERS:
  258. character(*) ,intent(in) :: string !< string to search
  259. character(*) ,intent(in) :: substr !< sub-string to search for
  260. integer(ip_i4_p),intent(out),optional :: rc !< return code
  261. !EOP
  262. !--- local ---
  263. integer(ip_i4_p) :: i ! generic index
  264. !----- formats -----
  265. character(*),parameter :: subName = "(oasis_string_endIndex) "
  266. !-------------------------------------------------------------------------------
  267. ! Notes:
  268. ! * returns zero if substring not found, uses len_trim() intrinsic
  269. ! * very similar to: i = index(str,substr,back=.true.)
  270. ! * do we need this function?
  271. !-------------------------------------------------------------------------------
  272. call oasis_debug_enter(subname)
  273. i = index(trim(string),trim(substr))
  274. if ( i == 0 ) then
  275. oasis_string_endIndex = 0 ! substr is not in string
  276. else
  277. oasis_string_endIndex = i + len_trim(substr) - 1
  278. end if
  279. ! -------------------------------------------------------------------
  280. ! i = index(trim(string),trim(substr),back=.true.)
  281. ! if (i == len(string)+1) i = 0
  282. ! oasis_string_endIndex = i
  283. ! -------------------------------------------------------------------
  284. if (present(rc)) rc = 0
  285. call oasis_debug_exit(subname)
  286. end function oasis_string_endIndex
  287. !===============================================================================
  288. !BOP ===========================================================================
  289. !
  290. ! !IROUTINE: oasis_string_leftAlign -- remove leading white space
  291. !
  292. ! !DESCRIPTION:
  293. !> Remove leading white space
  294. ! \newline
  295. ! call shr\_string\_leftAlign(string)
  296. !
  297. !
  298. ! !INTERFACE: ------------------------------------------------------------------
  299. subroutine oasis_string_leftAlign(str,rc)
  300. implicit none
  301. ! !INPUT/OUTPUT PARAMETERS:
  302. character(*) ,intent(inout) :: str !< input and returned string
  303. integer(ip_i4_p),intent(out) ,optional :: rc !< return code
  304. !EOP
  305. !----- local ----
  306. integer(ip_i4_p) :: rCode ! return code
  307. !----- formats -----
  308. character(*),parameter :: subName = "(oasis_string_leftAlign) "
  309. !-------------------------------------------------------------------------------
  310. ! note:
  311. ! * ?? this routine isn't needed, use the intrisic adjustL instead ??
  312. !-------------------------------------------------------------------------------
  313. ! -------------------------------------------------------------------
  314. ! --- used this until I discovered the intrinsic function below
  315. ! do while (len_trim(str) > 0 )
  316. ! if (str(1:1) /= ' ') exit
  317. ! str = str(2:len_trim(str))
  318. ! end do
  319. ! rCode = 0
  320. ! !! (len_trim(str) == 0 ) rCode = 1 ! ?? appropriate ??
  321. ! -------------------------------------------------------------------
  322. call oasis_debug_enter(subname)
  323. str = adjustL(str)
  324. if (present(rc)) rc = 0
  325. call oasis_debug_exit(subname)
  326. end subroutine oasis_string_leftAlign
  327. !===============================================================================
  328. !BOP ===========================================================================
  329. !
  330. ! !IROUTINE: oasis_string_alphanum -- remove non alpha numeric characters
  331. !
  332. ! !DESCRIPTION:
  333. !> Remove all non alpha numeric characters from string
  334. ! \newline
  335. ! call shr\_string\_alphanum(string)
  336. !
  337. !
  338. ! !INTERFACE: ------------------------------------------------------------------
  339. subroutine oasis_string_alphanum(str,rc)
  340. implicit none
  341. ! !INPUT/OUTPUT PARAMETERS:
  342. character(*) ,intent(inout) :: str !< input and output string
  343. integer(ip_i4_p),intent(out) ,optional :: rc !< return code
  344. !EOP
  345. !----- local ----
  346. integer(ip_i4_p) :: rCode ! return code
  347. integer(ip_i4_p) :: n,icnt ! counters
  348. !----- formats -----
  349. character(*),parameter :: subName = "(oasis_string_alphaNum) "
  350. !-------------------------------------------------------------------------------
  351. !
  352. !-------------------------------------------------------------------------------
  353. call oasis_debug_enter(subname)
  354. icnt = 0
  355. do n=1,len_trim(str)
  356. if ((str(n:n) >= 'a' .and. str(n:n) <= 'z') .or. &
  357. (str(n:n) >= 'A' .and. str(n:n) <= 'Z') .or. &
  358. (str(n:n) >= '0' .and. str(n:n) <= '9')) then
  359. icnt = icnt + 1
  360. str(icnt:icnt) = str(n:n)
  361. endif
  362. enddo
  363. do n=icnt+1,len(str)
  364. str(n:n) = ' '
  365. enddo
  366. if (present(rc)) rc = 0
  367. call oasis_debug_exit(subname)
  368. end subroutine oasis_string_alphanum
  369. !===============================================================================
  370. !BOP ===========================================================================
  371. !
  372. ! !IROUTINE: oasis_string_betweenTags -- Get the substring between the two tags.
  373. !
  374. ! !DESCRIPTION:
  375. !> Get the substring found between the start and end strings.
  376. ! \newline
  377. ! call shr\_string\_betweenTags(string,startTag,endTag,substring,rc)
  378. !
  379. !
  380. ! !INTERFACE: ------------------------------------------------------------------
  381. subroutine oasis_string_betweenTags(string,startTag,endTag,substr,rc)
  382. implicit none
  383. ! !INPUT/OUTPUT PARAMETERS:
  384. character(*) ,intent(in) :: string !< input string to search
  385. character(*) ,intent(in) :: startTag !< start string
  386. character(*) ,intent(in) :: endTag !< end string
  387. character(*) ,intent(out) :: substr !< output sub-string between tags
  388. integer(ip_i4_p),intent(out),optional :: rc !< return code
  389. !EOP
  390. !--- local ---
  391. integer(ip_i4_p) :: iStart ! substring start index
  392. integer(ip_i4_p) :: iEnd ! substring end index
  393. integer(ip_i4_p) :: rCode ! return code
  394. !----- formats -----
  395. character(*),parameter :: subName = "(oasis_string_betweenTags) "
  396. !-------------------------------------------------------------------------------
  397. ! Notes:
  398. ! * assumes the leading/trailing white space is not part of start & end tags
  399. !-------------------------------------------------------------------------------
  400. call oasis_debug_enter(subname)
  401. iStart = oasis_string_endIndex(string,trim(adjustL(startTag))) ! end of start tag
  402. iEnd = index(string,trim(adjustL(endTag ))) ! start of end tag
  403. rCode = 0
  404. substr = ""
  405. if (iStart < 1) then
  406. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  407. WRITE(nulprt,*) subname,estr,"can't find start tag in string"
  408. WRITE(nulprt,*) subname,estr,"start tag = ",TRIM(startTag)
  409. WRITE(nulprt,*) subname,estr,"string = ",TRIM(string)
  410. CALL oasis_flush(nulprt)
  411. rCode = 1
  412. else if (iEnd < 1) then
  413. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  414. WRITE(nulprt,*) subname,estr,"can't find end tag in string"
  415. WRITE(nulprt,*) subname,estr,"end tag = ",TRIM( endTag)
  416. WRITE(nulprt,*) subname,estr,"string = ",TRIM(string)
  417. CALL oasis_flush(nulprt)
  418. rCode = 2
  419. else if ( iEnd <= iStart) then
  420. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  421. WRITE(nulprt,*) subname,estr,"start tag not before end tag"
  422. WRITE(nulprt,*) subname,estr,"start tag = ",TRIM(startTag)
  423. WRITE(nulprt,*) subname,estr,"end tag = ",TRIM( endTag)
  424. WRITE(nulprt,*) subname,estr,"string = ",TRIM(string)
  425. CALL oasis_flush(nulprt)
  426. rCode = 3
  427. else if ( iStart+1 == iEnd ) then
  428. substr = ""
  429. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  430. WRITE(nulprt,*) subname,wstr,"zero-length substring found in ",TRIM(string)
  431. CALL oasis_flush(nulprt)
  432. else
  433. substr = string(iStart+1:iEnd-1)
  434. IF (LEN_TRIM(substr) == 0) THEN
  435. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  436. WRITE(nulprt,*) subname,wstr,"white-space substring found in ",TRIM(string)
  437. CALL oasis_flush(nulprt)
  438. ENDIF
  439. end if
  440. if (present(rc)) rc = rCode
  441. call oasis_debug_exit(subname)
  442. end subroutine oasis_string_betweenTags
  443. !===============================================================================
  444. !BOP ===========================================================================
  445. !
  446. ! !IROUTINE: oasis_string_parseCFtunit -- Parse CF time unit
  447. !
  448. ! !DESCRIPTION:
  449. !> Parse CF time unit into a delta string name and a base time in yyyymmdd
  450. ! and seconds (nearest integer actually).
  451. ! \newline
  452. ! call shr\_string\_parseCFtunit(string,substring)
  453. ! \newline
  454. ! Input string is like "days since 0001-06-15 15:20:45.5 -6:00"
  455. ! - recognizes "days", "hours", "minutes", "seconds"
  456. ! - must have at least yyyy-mm-dd, hh:mm:ss.s is optional
  457. ! - expects a "since" in the string
  458. ! - ignores time zone part
  459. !
  460. !
  461. ! !INTERFACE: ------------------------------------------------------------------
  462. subroutine oasis_string_parseCFtunit(string,unit,bdate,bsec,rc)
  463. implicit none
  464. ! !INPUT/OUTPUT PARAMETERS:
  465. character(*) ,intent(in) :: string !< string to search
  466. character(*) ,intent(out) :: unit !< delta time unit
  467. integer(ip_i4_p),intent(out) :: bdate !< base date yyyymmdd
  468. real(ip_r8_p) ,intent(out) :: bsec !< base seconds
  469. integer(ip_i4_p),intent(out),optional :: rc !< return code
  470. !EOP
  471. !--- local ---
  472. integer(ip_i4_p) :: i,i1,i2 ! generic index
  473. character(ic_long) :: tbase ! baseline time
  474. character(ic_long) :: lstr ! local string
  475. integer(ip_i4_p) :: yr,mo,da,hr,min ! time stuff
  476. real(ip_r8_p) :: sec ! time stuff
  477. !----- formats -----
  478. character(*),parameter :: subName = "(oasis_string_parseCFtunit) "
  479. !-------------------------------------------------------------------------------
  480. ! Notes:
  481. ! o assume length of CF-1.0 time attribute char string < ic_long
  482. ! This is a reasonable assumption.
  483. !-------------------------------------------------------------------------------
  484. call oasis_debug_enter(subname)
  485. unit = 'none'
  486. bdate = 0
  487. bsec = 0.0_ip_r8_p
  488. i = oasis_string_lastIndex(string,'days ')
  489. if (i > 0) unit = 'days'
  490. i = oasis_string_lastIndex(string,'hours ')
  491. if (i > 0) unit = 'hours'
  492. i = oasis_string_lastIndex(string,'minutes ')
  493. if (i > 0) unit = 'minutes'
  494. i = oasis_string_lastIndex(string,'seconds ')
  495. if (i > 0) unit = 'seconds'
  496. if (trim(unit) == 'none') then
  497. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  498. WRITE(nulprt,*) subname,estr,'time unit unknown'
  499. CALL oasis_flush(nulprt)
  500. CALL oasis_string_abort(subName//' time unit unknown')
  501. endif
  502. i = oasis_string_lastIndex(string,' since ')
  503. if (i < 1) then
  504. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  505. WRITE(nulprt,*) subname,estr,'since does not appear in unit attribute for time '
  506. CALL oasis_flush(nulprt)
  507. CALL oasis_string_abort(subName//' no since in attr name')
  508. endif
  509. tbase = trim(string(i+6:))
  510. call oasis_string_leftAlign(tbase)
  511. if (debug > 0 .and. nulprt > 0) then
  512. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  513. WRITE(nulprt,*) TRIM(subName)//' '//'unit '//TRIM(unit)
  514. WRITE(nulprt,*) TRIM(subName)//' '//'tbase '//TRIM(tbase)
  515. CALL oasis_flush(nulprt)
  516. endif
  517. yr=0; mo=0; da=0; hr=0; min=0; sec=0
  518. i1 = 1
  519. i2 = index(tbase,'-') - 1
  520. lstr = tbase(i1:i2)
  521. read(lstr,*,ERR=200,END=200) yr
  522. tbase = tbase(i2+2:)
  523. call oasis_string_leftAlign(tbase)
  524. i2 = index(tbase,'-') - 1
  525. lstr = tbase(i1:i2)
  526. read(lstr,*,ERR=200,END=200) mo
  527. tbase = tbase(i2+2:)
  528. call oasis_string_leftAlign(tbase)
  529. i2 = index(tbase,' ') - 1
  530. lstr = tbase(i1:i2)
  531. read(lstr,*,ERR=200,END=200) da
  532. tbase = tbase(i2+2:)
  533. call oasis_string_leftAlign(tbase)
  534. i2 = index(tbase,':') - 1
  535. lstr = tbase(i1:i2)
  536. read(lstr,*,ERR=200,END=100) hr
  537. tbase = tbase(i2+2:)
  538. call oasis_string_leftAlign(tbase)
  539. i2 = index(tbase,':') - 1
  540. lstr = tbase(i1:i2)
  541. read(lstr,*,ERR=200,END=100) min
  542. tbase = tbase(i2+2:)
  543. call oasis_string_leftAlign(tbase)
  544. i2 = index(tbase,' ') - 1
  545. lstr = tbase(i1:i2)
  546. read(lstr,*,ERR=200,END=100) sec
  547. 100 continue
  548. IF (debug > 0 ) THEN
  549. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  550. WRITE(nulprt,*) TRIM(subName),'ymdhms:',yr,mo,da,hr,min,sec
  551. CALL oasis_flush(nulprt)
  552. ENDIF
  553. bdate = abs(yr)*10000 + mo*100 + da
  554. if (yr < 0) bdate = -bdate
  555. bsec = real(hr*3600 + min*60,ip_r8_p) + sec
  556. if (present(rc)) rc = 0
  557. call oasis_debug_exit(subname)
  558. return
  559. 200 continue
  560. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  561. write(nulprt,*) subname,estr,'200 on char num read '
  562. CALL oasis_flush(nulprt)
  563. call oasis_string_abort(subName//estr//'on char num read')
  564. call oasis_debug_exit(subname)
  565. end subroutine oasis_string_parseCFtunit
  566. !===============================================================================
  567. !BOP ===========================================================================
  568. !
  569. ! !IROUTINE: oasis_string_clean -- Clean a string, set it to "blank"
  570. !
  571. ! !DESCRIPTION:
  572. !> Clean a string, set it to blank
  573. ! \newline
  574. ! call shr\_string\_clean(string,rc)
  575. !
  576. !
  577. ! !INTERFACE: ------------------------------------------------------------------
  578. subroutine oasis_string_clean(string,rc)
  579. implicit none
  580. ! !INPUT/OUTPUT PARAMETERS:
  581. character(*) ,intent(inout) :: string !< string
  582. integer(ip_i4_p),optional,intent(out) :: rc !< return code
  583. !EOP
  584. !----- local -----
  585. integer(ip_i4_p) :: n ! counter
  586. integer(ip_i4_p) :: rCode ! return code
  587. !----- formats -----
  588. character(*),parameter :: subName = "(oasis_string_clean) "
  589. !-------------------------------------------------------------------------------
  590. ! Notes:
  591. !-------------------------------------------------------------------------------
  592. call oasis_debug_enter(subname)
  593. rCode = 0
  594. string = ' '
  595. if (present(rc)) rc = rCode
  596. call oasis_debug_exit(subname)
  597. end subroutine oasis_string_clean
  598. !===============================================================================
  599. !BOP ===========================================================================
  600. !
  601. ! !IROUTINE: oasis_string_listIsValid -- determine whether string is a valid list
  602. !
  603. ! !DESCRIPTION:
  604. !> Determine whether string is a valid list
  605. ! \newline
  606. ! logical_var = shr\_string\_listIsValid(list,rc)
  607. !
  608. !
  609. ! !INTERFACE: ------------------------------------------------------------------
  610. logical function oasis_string_listIsValid(list,rc)
  611. implicit none
  612. ! !INPUT/OUTPUT PARAMETERS:
  613. character(*) ,intent(in) :: list !< list/string
  614. integer(ip_i4_p),optional,intent(out) :: rc !< return code
  615. !EOP
  616. !----- local -----
  617. integer (ip_i4_p) :: nChar ! lenth of list
  618. integer (ip_i4_p) :: rCode ! return code
  619. !----- formats -----
  620. character(*),parameter :: subName = "(oasis_string_listIsValid) "
  621. !-------------------------------------------------------------------------------
  622. ! check that the list conforms to the list format
  623. !-------------------------------------------------------------------------------
  624. call oasis_debug_enter(subname)
  625. rCode = 0
  626. oasis_string_listIsValid = .true.
  627. nChar = len_trim(list)
  628. if (nChar < 1) then ! list is an empty string
  629. rCode = 1
  630. else if ( list(1:1) == listDel ) then ! first char is delimiter
  631. rCode = 2
  632. else if (list(nChar:nChar) == listDel ) then ! last char is delimiter
  633. rCode = 3
  634. else if (index(trim(list)," " ) > 0) then ! white-space in a field name
  635. rCode = 4
  636. else if (index(trim(list),listDel2) > 0) then ! found zero length field
  637. rCode = 5
  638. end if
  639. if (rCode /= 0) then
  640. oasis_string_listIsValid = .false.
  641. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  642. write(nulprt,*) subname,wstr,"invalid list = ",trim(list)
  643. CALL oasis_flush(nulprt)
  644. endif
  645. if (present(rc)) rc = rCode
  646. call oasis_debug_exit(subname)
  647. end function oasis_string_listIsValid
  648. !===============================================================================
  649. !BOP ===========================================================================
  650. !
  651. ! !IROUTINE: oasis_string_listGetName -- Get name of k-th field in list
  652. !
  653. ! !DESCRIPTION:
  654. !> Get name of k-th field in list
  655. ! \newline
  656. ! call shr\_string\_listGetName(list,k,name,rc)
  657. !
  658. !
  659. ! !INTERFACE: ------------------------------------------------------------------
  660. subroutine oasis_string_listGetName(list,k,name,rc)
  661. implicit none
  662. ! !INPUT/OUTPUT PARAMETERS:
  663. character(*) ,intent(in) :: list !< input list
  664. integer(ip_i4_p) ,intent(in) :: k !< index of field
  665. character(*) ,intent(out) :: name !< k-th name in list
  666. integer(ip_i4_p),optional,intent(out) :: rc !< return code
  667. !EOP
  668. !----- local -----
  669. integer(ip_i4_p) :: i,j,n ! generic indecies
  670. integer(ip_i4_p) :: kFlds ! number of fields in list
  671. integer(ip_i4_p) :: i0,i1 ! name = list(i0:i1)
  672. integer(ip_i4_p) :: rCode ! return code
  673. !----- formats -----
  674. character(*),parameter :: subName = "(oasis_string_listGetName) "
  675. !-------------------------------------------------------------------------------
  676. ! Notes:
  677. !-------------------------------------------------------------------------------
  678. call oasis_debug_enter(subname)
  679. rCode = 0
  680. !--- check that this is a valid list ---
  681. if (.not. oasis_string_listIsValid(list,rCode) ) then
  682. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  683. write(nulprt,*) subname,estr,"invalid list = ",trim(list)
  684. CALL oasis_flush(nulprt)
  685. call oasis_string_abort(subName//estr//"invalid list = "//trim(list))
  686. end if
  687. !--- check that this is a valid index ---
  688. kFlds = oasis_string_listGetNum(list)
  689. if (k<1 .or. kFlds<k) then
  690. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  691. WRITE(nulprt,*) subname,estr,"invalid index = ",k
  692. WRITE(nulprt,*) subname,estr," list = ",TRIM(list)
  693. CALL oasis_flush(nulprt)
  694. CALL oasis_string_abort(subName//estr//"invalid index")
  695. end if
  696. !--- start with whole list, then remove fields before and after desired field ---
  697. i0 = 1
  698. i1 = len_trim(list)
  699. !--- remove field names before desired field ---
  700. do n=2,k
  701. i = index(list(i0:i1),listDel)
  702. i0 = i0 + i
  703. end do
  704. !--- remove field names after desired field ---
  705. if ( k < kFlds ) then
  706. i = index(list(i0:i1),listDel)
  707. i1 = i0 + i - 2
  708. end if
  709. !--- copy result into output variable ---
  710. name = list(i0:i1)//" "
  711. if (present(rc)) rc = rCode
  712. call oasis_debug_exit(subname)
  713. end subroutine oasis_string_listGetName
  714. !===============================================================================
  715. !BOP ===========================================================================
  716. !
  717. ! !IROUTINE: oasis_string_listIntersect -- Get intersection of two field lists
  718. !
  719. ! !DESCRIPTION:
  720. !> Get intersection of two fields lists, write into third list
  721. ! \newline
  722. ! call shr\_string\_listIntersect(list1,list2,listout)
  723. !
  724. !
  725. ! !INTERFACE: ------------------------------------------------------------------
  726. subroutine oasis_string_listIntersect(list1,list2,listout,rc)
  727. implicit none
  728. ! !INPUT/OUTPUT PARAMETERS:
  729. character(*) ,intent(in) :: list1 !< input list 1
  730. character(*) ,intent(in) :: list2 !< input list 2
  731. character(*) ,intent(out) :: listout !< output list
  732. integer(ip_i4_p),optional,intent(out) :: rc !< return code
  733. !EOP
  734. !----- local -----
  735. integer(ip_i4_p) :: nf,n1,n2 ! counters
  736. character(ic_med) :: name ! field name
  737. integer(ip_i4_p) :: rCode ! return code
  738. !----- formats -----
  739. character(*),parameter :: subName = "(oasis_string_listIntersect) "
  740. !-------------------------------------------------------------------------------
  741. ! Notes:
  742. !-------------------------------------------------------------------------------
  743. call oasis_debug_enter(subname)
  744. rCode = 0
  745. nf = oasis_string_listGetNum(list1)
  746. call oasis_string_clean(listout)
  747. do n1 = 1,nf
  748. call oasis_string_listGetName(list1,n1,name,rCode)
  749. n2 = oasis_string_listGetIndexF(list2,name)
  750. if (n2 > 0) then
  751. call oasis_string_listAppend(listout,name)
  752. endif
  753. enddo
  754. if (present(rc)) rc = rCode
  755. call oasis_debug_exit(subname)
  756. end subroutine oasis_string_listIntersect
  757. !===============================================================================
  758. !BOP ===========================================================================
  759. !
  760. ! !IROUTINE: oasis_string_listUnion -- Get union of two field lists
  761. !
  762. ! !DESCRIPTION:
  763. !> Get union of two fields lists, write into third list
  764. ! \newline
  765. ! call shr\_string\_listUnion(list1,list2,listout)
  766. !
  767. !
  768. ! !INTERFACE: ------------------------------------------------------------------
  769. subroutine oasis_string_listUnion(list1,list2,listout,rc)
  770. implicit none
  771. ! !INPUT/OUTPUT PARAMETERS:
  772. character(*) ,intent(in) :: list1 !< input list 1
  773. character(*) ,intent(in) :: list2 !< input list 2
  774. character(*) ,intent(out) :: listout !< output list 3
  775. integer(ip_i4_p),optional,intent(out) :: rc !< return code
  776. !EOP
  777. !----- local -----
  778. integer(ip_i4_p) :: nf,n1,n2 ! counters
  779. character(ic_med) :: name ! field name
  780. integer(ip_i4_p) :: rCode ! return code
  781. !----- formats -----
  782. character(*),parameter :: subName = "(oasis_string_listUnion) "
  783. !-------------------------------------------------------------------------------
  784. ! Notes:
  785. !-------------------------------------------------------------------------------
  786. call oasis_debug_enter(subname)
  787. rCode = 0
  788. call oasis_string_clean(listout)
  789. nf = oasis_string_listGetNum(list1)
  790. do n1 = 1,nf
  791. call oasis_string_listGetName(list1,n1,name,rCode)
  792. n2 = oasis_string_listGetIndexF(listout,name)
  793. if (n2 < 1) then
  794. call oasis_string_listAppend(listout,name)
  795. endif
  796. enddo
  797. nf = oasis_string_listGetNum(list2)
  798. do n1 = 1,nf
  799. call oasis_string_listGetName(list2,n1,name,rCode)
  800. n2 = oasis_string_listGetIndexF(listout,name)
  801. if (n2 < 1) then
  802. call oasis_string_listAppend(listout,name)
  803. endif
  804. enddo
  805. if (present(rc)) rc = rCode
  806. call oasis_debug_exit(subname)
  807. end subroutine oasis_string_listUnion
  808. !===============================================================================
  809. !BOP ===========================================================================
  810. !
  811. ! !IROUTINE: oasis_string_listMerge -- Merge lists two list to third
  812. !
  813. ! !DESCRIPTION:
  814. !> Merge two lists into a third list
  815. ! \newline
  816. ! call shr\_string\_listMerge(list1,list2,listout)
  817. ! call shr\_string\_listMerge(list1,list2,list1)
  818. !
  819. !
  820. ! !INTERFACE: ------------------------------------------------------------------
  821. subroutine oasis_string_listMerge(list1,list2,listout,rc)
  822. implicit none
  823. ! !INPUT/OUTPUT PARAMETERS:
  824. character(*) ,intent(in) :: list1 !< input list 1
  825. character(*) ,intent(in) :: list2 !< input list 2
  826. character(*) ,intent(out) :: listout !< output list
  827. integer(ip_i4_p),optional,intent(out) :: rc !< return code
  828. !EOP
  829. !----- local -----
  830. character(ic_xl) :: l1,l2 ! local char strings
  831. integer(ip_i4_p) :: rCode ! return code
  832. !----- formats -----
  833. character(*),parameter :: subName = "(oasis_string_listMerge) "
  834. !-------------------------------------------------------------------------------
  835. ! Notes:
  836. ! - no input or output string should be longer than ic_xl
  837. !-------------------------------------------------------------------------------
  838. call oasis_debug_enter(subname)
  839. rCode = 0
  840. !--- make sure temp strings are large enough ---
  841. if ( (len(l1) < len_trim(list1)) .or. (len(l2) < len_trim(list2))) then
  842. call oasis_string_abort(subName//estr//"temp string not large enough")
  843. end if
  844. call oasis_string_clean(l1)
  845. call oasis_string_clean(l2)
  846. call oasis_string_clean(listout)
  847. l1 = trim(list1)
  848. l2 = trim(list2)
  849. call oasis_string_leftAlign(l1,rCode)
  850. call oasis_string_leftAlign(l2,rCode)
  851. if (len_trim(l1)+len_trim(l2)+1 > len(listout)) &
  852. call oasis_string_abort(subName//estr//"output list string not large enough")
  853. if (len_trim(l1) == 0) then
  854. listout = trim(l2)
  855. else
  856. listout = trim(l1)//":"//trim(l2)
  857. endif
  858. if (present(rc)) rc = rCode
  859. call oasis_debug_exit(subname)
  860. end subroutine oasis_string_listMerge
  861. !===============================================================================
  862. !BOP ===========================================================================
  863. !
  864. ! !IROUTINE: oasis_string_listAppend -- Append one list to another
  865. !
  866. ! !DESCRIPTION:
  867. !> Append one list to another
  868. ! \newline
  869. ! call shr\_string\_listAppend(list,listadd)
  870. !
  871. !
  872. ! !INTERFACE: ------------------------------------------------------------------
  873. subroutine oasis_string_listAppend(list,listadd,rc)
  874. implicit none
  875. ! !INPUT/OUTPUT PARAMETERS:
  876. character(*) ,intent(inout) :: list !< input and output list
  877. character(*) ,intent(in) :: listadd !< list to append
  878. integer(ip_i4_p),optional,intent(out) :: rc !< return code
  879. !EOP
  880. !----- local -----
  881. character(ic_xl) :: l1 ! local string
  882. integer(ip_i4_p) :: rCode ! return code
  883. !----- formats -----
  884. character(*),parameter :: subName = "(oasis_string_listAppend) "
  885. !-------------------------------------------------------------------------------
  886. ! Notes:
  887. ! - no input or output string should be longer than ic_xl
  888. !-------------------------------------------------------------------------------
  889. call oasis_debug_enter(subname)
  890. rCode = 0
  891. !--- make sure temp string is large enough ---
  892. if (len(l1) < len_trim(listAdd)) then
  893. call oasis_string_abort(subName//estr//'temp string not large enough')
  894. end if
  895. call oasis_string_clean(l1)
  896. l1 = trim(listadd)
  897. call oasis_string_leftAlign(l1,rCode)
  898. if (len_trim(list)+len_trim(l1)+1 > len(list)) &
  899. call oasis_string_abort(subName//estr//'output list string not large enough')
  900. if (len_trim(list) == 0) then
  901. list = trim(l1)
  902. else
  903. list = trim(list)//":"//trim(l1)
  904. endif
  905. if (present(rc)) rc = rCode
  906. call oasis_debug_exit(subname)
  907. end subroutine oasis_string_listAppend
  908. !===============================================================================
  909. !BOP ===========================================================================
  910. !
  911. ! !IROUTINE: oasis_string_listPrepend -- Prepend one list to another
  912. !
  913. ! !DESCRIPTION:
  914. !> Prepend one list to another
  915. ! \newline
  916. ! call shr\_string\_listPrepend(listadd,list)
  917. ! \newline
  918. ! results in listadd:list
  919. !
  920. !
  921. ! !INTERFACE: ------------------------------------------------------------------
  922. subroutine oasis_string_listPrepend(listadd,list,rc)
  923. implicit none
  924. ! !INPUT/OUTPUT PARAMETERS:
  925. character(*) ,intent(in) :: listadd ! input and output list
  926. character(*) ,intent(inout) :: list ! list to prepend
  927. integer(ip_i4_p),optional,intent(out) :: rc ! return code
  928. !EOP
  929. !----- local -----
  930. character(ic_xl) :: l1 ! local string
  931. integer(ip_i4_p) :: rCode ! return code
  932. !----- formats -----
  933. character(*),parameter :: subName = "(oasis_string_listPrepend) "
  934. !-------------------------------------------------------------------------------
  935. ! Notes:
  936. ! - no input or output string should be longer than ic_xl
  937. !-------------------------------------------------------------------------------
  938. call oasis_debug_enter(subname)
  939. rCode = 0
  940. !--- make sure temp string is large enough ---
  941. if (len(l1) < len_trim(listAdd)) then
  942. call oasis_string_abort(subName//estr//'temp string not large enough')
  943. end if
  944. call oasis_string_clean(l1)
  945. l1 = trim(listadd)
  946. call oasis_string_leftAlign(l1,rCode)
  947. call oasis_string_leftAlign(list,rCode)
  948. if (len_trim(list)+len_trim(l1)+1 > len(list)) &
  949. call oasis_string_abort(subName//estr//"output list string not large enough")
  950. if (len_trim(l1) == 0) then
  951. list = trim(list)
  952. else
  953. list = trim(l1)//":"//trim(list)
  954. endif
  955. if (present(rc)) rc = rCode
  956. call oasis_debug_exit(subname)
  957. end subroutine oasis_string_listPrepend
  958. !===============================================================================
  959. !BOP ===========================================================================
  960. !
  961. ! !IROUTINE: oasis_string_listGetIndexF -- Get index of field in string
  962. !
  963. ! !DESCRIPTION:
  964. !> Get the index of a field in a list
  965. ! \newline
  966. ! k = shr\_string\_listGetIndex(str,"taux")
  967. !
  968. !
  969. ! !INTERFACE: ------------------------------------------------------------------
  970. integer function oasis_string_listGetIndexF(string,fldStr)
  971. implicit none
  972. ! !INPUT/OUTPUT PARAMETERS:
  973. character(*),intent(in) :: string !< input string
  974. character(*),intent(in) :: fldStr !< name of field
  975. !EOP
  976. !----- local -----
  977. integer(ip_i4_p) :: k ! local index variable
  978. integer(ip_i4_p) :: rc ! error code
  979. !----- formats -----
  980. character(*),parameter :: subName = "(oasis_string_listGetIndexF) "
  981. !-------------------------------------------------------------------------------
  982. call oasis_debug_enter(subname)
  983. call oasis_string_listGetIndex(string,fldStr,k,print=.false.,rc=rc)
  984. oasis_string_listGetIndexF = k
  985. call oasis_debug_exit(subname)
  986. end function oasis_string_listGetIndexF
  987. #if (defined NEW_LGI_METHOD2a || defined NEW_LGI_METHOD2b)
  988. !===============================================================================
  989. !BOP ===========================================================================
  990. !
  991. ! !IROUTINE: oasis_string_listGetIndex -- Get index of field in string
  992. !
  993. ! !DESCRIPTION:
  994. !> Get the index of a field in a string
  995. ! \newline
  996. ! call shr\_string\_listGetIndex(str,"taux",k,rc)
  997. !
  998. !
  999. ! !INTERFACE: ------------------------------------------------------------------
  1000. subroutine oasis_string_listGetIndex(string,fldStr,kFld,print,rc)
  1001. implicit none
  1002. ! !INPUT/OUTPUT PARAMETERS:
  1003. character(*) ,intent(in) :: string !< input list
  1004. character(*) ,intent(in) :: fldStr !< name of field
  1005. integer(ip_i4_p),intent(out) :: kFld !< index of field in list
  1006. logical ,intent(in) ,optional :: print !< print switch
  1007. integer(ip_i4_p),intent(out),optional :: rc !< return code
  1008. !EOP
  1009. !----- local -----
  1010. integer(ip_i4_p) :: n,n1,n2 ! index for colon position
  1011. integer(ip_i4_p) :: lens ! length of string
  1012. logical :: found ! T => field found in fieldNames
  1013. logical :: lprint ! local print flag
  1014. !----- formats -----
  1015. character(*),parameter :: subName = "(oasis_string_listGetIndex) "
  1016. !-------------------------------------------------------------------------------
  1017. !-------------------------------------------------------------------------------
  1018. call oasis_debug_enter(subname)
  1019. ! call oasis_timer_start('tcx_slgi0')
  1020. ! call oasis_timer_start('tcx_slgia')
  1021. if (present(rc)) rc = 0
  1022. kfld = 0
  1023. found = .false.
  1024. lprint = .false.
  1025. if (present(print)) lprint = print
  1026. !--- confirm proper size of input data ---
  1027. if (len_trim(fldStr) < 1) then
  1028. IF (lprint) THEN
  1029. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  1030. WRITE(nulprt,*) subname,estr,"input field name has 0 length"
  1031. CALL oasis_flush(nulprt)
  1032. ENDIF
  1033. CALL oasis_string_abort(subName//"invalid field name")
  1034. end if
  1035. ! call oasis_timer_stop('tcx_slgia')
  1036. ! call oasis_timer_start('tcx_slgib')
  1037. lens = len_trim(string)
  1038. ! write(nulprt,*) subname,' tcx1 ',string
  1039. ! write(nulprt,*) subname,' tcx2 ',fldStr
  1040. n = index(string,listDel,back=.false.)
  1041. ! write(nulprt,*) subname,' tcx3 ',n
  1042. ! call oasis_timer_start('tcx_slgib')
  1043. ! call oasis_timer_start('tcx_slgic')
  1044. if (n <= 0) then ! single field only
  1045. ! call oasis_timer_start('tcx_slgic1')
  1046. if (trim(fldStr) == string(1:lens)) then
  1047. found = .true.
  1048. kFld = 1
  1049. endif
  1050. ! call oasis_timer_stop('tcx_slgic1')
  1051. ! write(nulprt,*) subname,' tcx4a ',found,kfld
  1052. elseif (n > 0) then
  1053. !--- check first string ---
  1054. ! call oasis_timer_start('tcx_slgic2')
  1055. if (trim(fldStr) == string(1:n-1)) then
  1056. found = .true.
  1057. kFld = 1
  1058. endif
  1059. ! write(nulprt,*) subname,' tcx4b ',found,kfld
  1060. ! call oasis_timer_stop('tcx_slgic2')
  1061. !--- check last string ---
  1062. if (.not.found) then
  1063. ! call oasis_timer_start('tcx_slgic3')
  1064. n = index(string,listDel,back=.true.)
  1065. if (trim(fldStr) == string(n+1:lens)) then
  1066. found = .true.
  1067. kFld = oasis_string_listGetNum(string)
  1068. endif
  1069. ! call oasis_timer_stop('tcx_slgic3')
  1070. ! write(nulprt,*) subname,' tcx4c ',found,kfld
  1071. endif
  1072. !--- check other strings ---
  1073. if (.not.found) then
  1074. ! call oasis_timer_start('tcx_slgic4')
  1075. n = index(string,':'//trim(fldStr)//':',back=.false.)
  1076. ! write(nulprt,*) subname,' tcx5a ',n
  1077. if (n > 0) then
  1078. found = .true.
  1079. #if defined NEW_LGI_METHOD2a
  1080. if (n <= lens) then
  1081. #endif
  1082. #if defined NEW_LGI_METHOD2b
  1083. if (n <= lens/2) then
  1084. #endif
  1085. ! call oasis_timer_start('tcx_slgic4a')
  1086. n1 = 0
  1087. kFld = 1
  1088. do while (n1 < n)
  1089. kFld = kFld + 1
  1090. n2 = index(string(n1+1:lens),listDel,back=.false.)
  1091. n1 = n1 + n2
  1092. ! write(nulprt,*) subname,' tcx5b ',kfld,n2,n1,n
  1093. enddo
  1094. ! call oasis_timer_stop('tcx_slgic4a')
  1095. else
  1096. ! call oasis_timer_start('tcx_slgic4b')
  1097. n1 = lens+1
  1098. kFld = oasis_string_listGetNum(string) + 1
  1099. ! call oasis_timer_stop('tcx_slgic4b')
  1100. ! call oasis_timer_start('tcx_slgic4c')
  1101. do while (n1 > n)
  1102. kFld = kFld - 1
  1103. n2 = index(string(1:n1-1),listDel,back=.true.)
  1104. n1 = n2
  1105. ! write(nulprt,*) subname,' tcx5c ',kfld,n2,n1,n
  1106. enddo
  1107. ! call oasis_timer_stop('tcx_slgic4c')
  1108. endif
  1109. endif
  1110. ! write(nulprt,*) subname,' tcx4d ',found,kfld
  1111. ! call oasis_timer_stop('tcx_slgic4')
  1112. endif
  1113. endif
  1114. ! call oasis_timer_stop('tcx_slgic')
  1115. ! call oasis_timer_start('tcx_slgid')
  1116. !--- not finding a field is not a fatal error ---
  1117. if (.not. found) then
  1118. IF (lprint) THEN
  1119. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  1120. WRITE(nulprt,*) subname,"FYI: field ",TRIM(fldStr)," not found in list ",TRIM(string)
  1121. CALL oasis_flush(nulprt)
  1122. ENDIF
  1123. if (present(rc)) rc = 1
  1124. end if
  1125. ! call oasis_timer_stop('tcx_slgid')
  1126. ! call oasis_timer_stop('tcx_slgi0')
  1127. call oasis_debug_exit(subname)
  1128. end subroutine oasis_string_listGetIndex
  1129. #endif
  1130. !===============================================================================
  1131. !BOP ===========================================================================
  1132. !
  1133. ! !IROUTINE: oasis_string_listGetNum -- get number of fields in a string list
  1134. !
  1135. ! !DESCRIPTION:
  1136. !> return number of fields in string list
  1137. !
  1138. !
  1139. ! !INTERFACE: ------------------------------------------------------------------
  1140. integer function oasis_string_listGetNum(str)
  1141. implicit none
  1142. ! !INPUT/OUTPUT PARAMETERS:
  1143. character(*),intent(in) :: str !< input list
  1144. !EOP
  1145. !----- local -----
  1146. integer(ip_i4_p) :: count ! counts occurances of char
  1147. !----- formats -----
  1148. character(*),parameter :: subName = "(oasis_string_listGetNum) "
  1149. !-------------------------------------------------------------------------------
  1150. ! Notes:
  1151. !-------------------------------------------------------------------------------
  1152. call oasis_debug_enter(subname)
  1153. oasis_string_listGetNum = 0
  1154. if (len_trim(str) > 0) then
  1155. count = oasis_string_countChar(str,listDel)
  1156. oasis_string_listGetNum = count + 1
  1157. endif
  1158. call oasis_debug_exit(subname)
  1159. end function oasis_string_listGetNum
  1160. !===============================================================================
  1161. !BOP ===========================================================================
  1162. !
  1163. ! !IROUTINE: oasis_string_listSetDel -- Set list delimeter character
  1164. !
  1165. ! !DESCRIPTION:
  1166. !> Set field delimeter character in lists
  1167. ! \newline
  1168. ! call shr\_string\_listSetDel(":")
  1169. !
  1170. !
  1171. ! !INTERFACE: ------------------------------------------------------------------
  1172. subroutine oasis_string_listSetDel(cflag)
  1173. implicit none
  1174. ! !INPUT/OUTPUT PARAMETERS:
  1175. character(len=1),intent(in) :: cflag !< field delimeter
  1176. !EOP
  1177. !--- formats ---
  1178. character(*),parameter :: subName = "(oasis_string_listSetDel) "
  1179. !-------------------------------------------------------------------------------
  1180. call oasis_debug_enter(subname)
  1181. IF (debug > 0) THEN
  1182. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  1183. WRITE(nulprt,*) subname,' changing listDel from '//TRIM(listDel)//' to '//TRIM(cflag)
  1184. CALL oasis_flush(nulprt)
  1185. ENDIF
  1186. listDel = trim(cflag)
  1187. listDel2 = listDel//listDel
  1188. call oasis_debug_exit(subname)
  1189. end subroutine oasis_string_listSetDel
  1190. !===============================================================================
  1191. !BOP ===========================================================================
  1192. !
  1193. ! !IROUTINE: oasis_string_listGetDel -- Get list delimeter character
  1194. !
  1195. ! !DESCRIPTION:
  1196. !> Get field delimeter character in lists
  1197. ! \newline
  1198. ! call shr\_string\_listGetDel(del)
  1199. !
  1200. !
  1201. ! !INTERFACE: ------------------------------------------------------------------
  1202. subroutine oasis_string_listGetDel(del)
  1203. implicit none
  1204. ! !INPUT/OUTPUT PARAMETERS:
  1205. character(*),intent(out) :: del !< field delimeter
  1206. !EOP
  1207. !--- formats ---
  1208. character(*),parameter :: subName = "(oasis_string_listGetDel) "
  1209. !-------------------------------------------------------------------------------
  1210. call oasis_debug_enter(subname)
  1211. del = trim(listDel)
  1212. call oasis_debug_exit(subname)
  1213. end subroutine oasis_string_listGetDel
  1214. !===============================================================================
  1215. !BOP ===========================================================================
  1216. !
  1217. ! !IROUTINE: oasis_string_setAbort -- Set local oasis_string abort flag
  1218. !
  1219. ! !DESCRIPTION:
  1220. !> Set local oasis_string abort flag, true = abort, false = print and continue
  1221. ! \newline
  1222. ! call shr\_string\_setAbort(.false.)
  1223. !
  1224. !
  1225. ! !INTERFACE: ------------------------------------------------------------------
  1226. subroutine oasis_string_setAbort(flag)
  1227. implicit none
  1228. ! !INPUT/OUTPUT PARAMETERS:
  1229. logical,intent(in) :: flag !< abort flag
  1230. !EOP
  1231. !--- formats ---
  1232. character(*),parameter :: subName = "(oasis_string_setAbort) "
  1233. !-------------------------------------------------------------------------------
  1234. call oasis_debug_enter(subname)
  1235. if (debug > 0) then
  1236. if (flag) then
  1237. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  1238. WRITE(nulprt,*) subname,' setting abort to true'
  1239. CALL oasis_flush(nulprt)
  1240. else
  1241. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  1242. WRITE(nulprt,*) subname,' setting abort to false'
  1243. CALL oasis_flush(nulprt)
  1244. endif
  1245. endif
  1246. doabort = flag
  1247. call oasis_debug_exit(subname)
  1248. end subroutine oasis_string_setAbort
  1249. !===============================================================================
  1250. !BOP ===========================================================================
  1251. !
  1252. ! !IROUTINE: oasis_string_setDebug -- Set local oasis_string debug level
  1253. !
  1254. ! !DESCRIPTION:
  1255. !> Set local oasis_string debug level, 0 = production
  1256. ! \newline
  1257. ! call shr\_string\_setDebug(2)
  1258. !
  1259. !
  1260. ! !INTERFACE: ------------------------------------------------------------------
  1261. subroutine oasis_string_setDebug(iFlag)
  1262. implicit none
  1263. ! !INPUT/OUTPUT PARAMETERS:
  1264. integer(ip_i4_p),intent(in) :: iFlag !< requested debug level
  1265. !EOP
  1266. !--- local ---
  1267. !--- formats ---
  1268. character(*),parameter :: subName = "(oasis_string_setDebug) "
  1269. !-------------------------------------------------------------------------------
  1270. ! NTOE: write statement can be expensive if called many times.
  1271. !-------------------------------------------------------------------------------
  1272. call oasis_debug_enter(subname)
  1273. ! if (OASIS_debug > 0) write(nulprt,*) subname,' changing debug level from ',debug,' to ',iflag
  1274. debug = iFlag
  1275. call oasis_debug_exit(subname)
  1276. end subroutine oasis_string_setDebug
  1277. !===============================================================================
  1278. !===============================================================================
  1279. !> Supports aborts in the string module
  1280. subroutine oasis_string_abort(string)
  1281. implicit none
  1282. ! !INPUT/OUTPUT PARAMETERS:
  1283. character(*),optional,intent(in) :: string !< error string
  1284. !EOP
  1285. !--- local ---
  1286. character(ic_xl) :: lstring
  1287. character(*),parameter :: subName = "(oasis_string_abort)"
  1288. !-------------------------------------------------------------------------------
  1289. ! NOTE:
  1290. ! - no input or output string should be longer than ic_xl
  1291. !-------------------------------------------------------------------------------
  1292. call oasis_debug_enter(subname)
  1293. lstring = ''
  1294. if (present(string)) lstring = string
  1295. if (doabort) then
  1296. WRITE(nulprt,*) subname,estr,'abort for ',TRIM(lstring)
  1297. call oasis_abort()
  1298. else
  1299. write(nulprt,*) subname,wstr,'no abort for '//trim(lstring)
  1300. CALL oasis_flush(nulprt)
  1301. endif
  1302. call oasis_debug_exit(subname)
  1303. end subroutine oasis_string_abort
  1304. !===============================================================================
  1305. !===============================================================================
  1306. end module mod_oasis_string