m_List.F90 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112
  1. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  3. !-----------------------------------------------------------------------
  4. ! CVS m_List.F90,v 1.36 2007-11-06 00:03:31 jacob Exp
  5. ! CVS MCT_2_8_0
  6. !BOP -------------------------------------------------------------------
  7. !
  8. ! !MODULE: m_List - A List Manager
  9. !
  10. ! !DESCRIPTION: A {\em List} is a character buffer comprising
  11. ! substrings called {\em items} separated by colons, combined with
  12. ! indexing information describing (1) the starting point in the character
  13. ! buffer of each substring, and (2) the length of each substring. The
  14. ! only constraints on the valid list items are (1) the value of an
  15. ! item does not contain the ``\verb":"'' delimitter, and (2) leading
  16. ! and trailing blanks are stripped from any character string presented
  17. ! to define a list item (although any imbeded blanks are retained).
  18. !
  19. ! {\bf Example:} Suppose we wish to define a List containing the
  20. ! items {\tt 'latitude'}, {\tt 'longitude'}, and {\tt 'pressure'}.
  21. ! The character buffer of the List containing these items will be the
  22. ! 27-character string
  23. ! \begin{verbatim}
  24. ! 'latitude:longitude:pressure'
  25. ! \end{verbatim}
  26. ! and the indexing information is summarized in the table below.
  27. !
  28. !\begin{table}[htbp]
  29. !\begin{center}
  30. !\begin{tabular}{|c|c|c|}
  31. !\hline
  32. !{\bf Item} & {\bf Starting Point in Buffer} & {\bf Length} \\
  33. !\hline
  34. !{\tt latitude} & 1 & 8 \\
  35. !\hline
  36. !{\tt longitude} & 9 & 9 \\
  37. !\hline
  38. !{\tt pressure} & 20 & 8\\
  39. !\hline
  40. !\end{tabular}
  41. !\end{center}
  42. !\end{table}
  43. !
  44. ! One final note: All operations for the {\tt List} datatype are
  45. ! {\bf case sensitive}.
  46. !
  47. ! !INTERFACE:
  48. module m_List
  49. ! !USES:
  50. !
  51. ! No other Fortran modules are used.
  52. implicit none
  53. private ! except
  54. ! !PUBLIC TYPES:
  55. public :: List ! The class data structure
  56. Type List
  57. #ifdef SEQUENCE
  58. sequence
  59. #endif
  60. character(len=1),dimension(:),pointer :: bf
  61. integer, dimension(:,:),pointer :: lc
  62. End Type List
  63. ! !PUBLIC MEMBER FUNCTIONS:
  64. public :: init
  65. public :: clean
  66. public :: nullify
  67. public :: index
  68. public :: get_indices
  69. public :: test_indices
  70. public :: nitem
  71. public :: get
  72. public :: identical
  73. public :: assignment(=)
  74. public :: allocated
  75. public :: copy
  76. public :: exportToChar
  77. public :: exportToString
  78. public :: CharBufferSize
  79. public :: append
  80. public :: concatenate
  81. public :: bcast
  82. public :: send
  83. public :: recv
  84. public :: GetSharedListIndices
  85. interface init ; module procedure &
  86. init_, &
  87. initStr_, &
  88. initstr1_
  89. end interface
  90. interface clean; module procedure clean_; end interface
  91. interface nullify; module procedure nullify_; end interface
  92. interface index; module procedure &
  93. index_, &
  94. indexStr_
  95. end interface
  96. interface get_indices; module procedure get_indices_; end interface
  97. interface test_indices; module procedure test_indices_; end interface
  98. interface nitem; module procedure nitem_; end interface
  99. interface get ; module procedure &
  100. get_, &
  101. getall_, &
  102. getrange_
  103. end interface
  104. interface identical; module procedure identical_; end interface
  105. interface assignment(=)
  106. module procedure copy_
  107. end interface
  108. interface allocated ; module procedure &
  109. allocated_
  110. end interface
  111. interface copy ; module procedure copy_ ; end interface
  112. interface exportToChar ; module procedure &
  113. exportToChar_
  114. end interface
  115. interface exportToString ; module procedure &
  116. exportToString_
  117. end interface
  118. interface CharBufferSize ; module procedure &
  119. CharBufferSize_
  120. end interface
  121. interface append ; module procedure append_ ; end interface
  122. interface concatenate ; module procedure concatenate_ ; end interface
  123. interface bcast; module procedure bcast_; end interface
  124. interface send; module procedure send_; end interface
  125. interface recv; module procedure recv_; end interface
  126. interface GetSharedListIndices; module procedure &
  127. GetSharedListIndices_
  128. end interface
  129. ! !REVISION HISTORY:
  130. ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  131. ! 16May01 - J. Larson <larson@mcs.anl.gov> - Several changes / fixes:
  132. ! public interface for copy_(), corrected version of copy_(),
  133. ! corrected version of bcast_().
  134. ! 15Oct01 - J. Larson <larson@mcs.anl.gov> - Added the LOGICAL
  135. ! function identical_().
  136. ! 14Dec01 - J. Larson <larson@mcs.anl.gov> - Added the LOGICAL
  137. ! function allocated_().
  138. ! 13Feb02 - J. Larson <larson@mcs.anl.gov> - Added the List query
  139. ! functions exportToChar() and CharBufferLength().
  140. ! 13Jun02- R.L. Jacob <jacob@mcs.anl.gov> - Move GetSharedListIndices
  141. ! from mct to this module.
  142. !EOP ___________________________________________________________________
  143. character(len=*),parameter :: myname='MCT(MPEU)::m_List'
  144. contains
  145. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  146. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  147. !BOP -------------------------------------------------------------------
  148. !
  149. ! !IROUTINE: init_ - Initialize a List from a CHARACTER String
  150. !
  151. ! !DESCRIPTION:
  152. !
  153. ! A list is a string in the form of ``\verb"Larry:Moe:Curly"'',
  154. ! or ``\verb"lat:lon:lev"'', combined with substring location and
  155. ! length information. Through the initialization call, the
  156. ! items delimited by ``\verb":"'' are stored as an array of sub-
  157. ! strings of a long string, accessible through an array of substring
  158. ! indices. The only constraints now on the valid list entries are,
  159. ! (1) the value of an entry does not contain ``\verb":"'', and (2)
  160. ! The leading and the trailing blanks are insignificant, although
  161. ! any imbeded blanks are. For example,
  162. !
  163. ! \begin{verbatim}
  164. ! call init_(aList, 'batman :SUPERMAN:Green Lantern: Aquaman')
  165. ! \end{verbatim}
  166. ! will result in {\tt aList} having four items: 'batman', 'SUPERMAN',
  167. ! 'Green Lantern', and 'Aquaman'. That is
  168. ! \begin{verbatim}
  169. ! aList%bf = 'batman:SUPERMAN:Green Lantern:Aquaman'
  170. ! \end{verbatim}
  171. !
  172. ! !INTERFACE:
  173. subroutine init_(aList,Values)
  174. ! !USES:
  175. !
  176. use m_die,only : die
  177. use m_mall,only : mall_mci,mall_ison
  178. implicit none
  179. ! !INPUT PARAMETERS:
  180. !
  181. character(len=*),intent(in) :: Values ! ":" delimited names
  182. ! !OUTPUT PARAMETERS:
  183. !
  184. type(List),intent(out) :: aList ! an indexed string values
  185. ! !REVISION HISTORY:
  186. ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  187. !EOP ___________________________________________________________________
  188. character(len=*),parameter :: myname_=myname//'::init_'
  189. character(len=1) :: c
  190. integer :: ib,ie,id,lb,le,ni,i,ier
  191. ! Pass 1, getting the sizes
  192. le=0
  193. ni=0
  194. ib=1
  195. ie=0
  196. id=0
  197. do i=1,len(Values)
  198. c=Values(i:i)
  199. select case(c)
  200. case(' ')
  201. if(ib==i) ib=i+1 ! moving ib up, starting from the next
  202. case(':')
  203. if(ib<=ie) then
  204. ni=ni+1
  205. id=1 ! mark a ':'
  206. endif
  207. ib=i+1 ! moving ib up, starting from the next
  208. case default
  209. ie=i
  210. if(id==1) then ! count an earlier marked ':'
  211. id=0
  212. le=le+1
  213. endif
  214. le=le+1
  215. end select
  216. end do
  217. if(ib<=ie) ni=ni+1
  218. ! COMPILER MAY NOT SIGNAL AN ERROR IF
  219. ! ALIST HAS ALREADY BEEN INITIALIZED.
  220. ! PLEASE CHECK FOR PREVIOUS INITIALIZATION
  221. allocate(aList%bf(le),aList%lc(0:1,ni),stat=ier)
  222. if(ier /= 0) call die(myname_,'allocate()',ier)
  223. if(mall_ison()) then
  224. call mall_mci(aList%bf,myname)
  225. call mall_mci(aList%lc,myname)
  226. endif
  227. ! Pass 2, copy the value and assign the pointers
  228. lb=1
  229. le=0
  230. ni=0
  231. ib=1
  232. ie=0
  233. id=0
  234. do i=1,len(Values)
  235. c=Values(i:i)
  236. select case(c)
  237. case(' ')
  238. if(ib==i) ib=i+1 ! moving ib up, starting from the next
  239. case(':')
  240. if(ib<=ie) then
  241. ni=ni+1
  242. aList%lc(0:1,ni)=(/lb,le/)
  243. id=1 ! mark a ':'
  244. endif
  245. ib=i+1 ! moving ib up, starting from the next
  246. lb=le+2 ! skip to the next non-':' and non-','
  247. case default
  248. ie=i
  249. if(id==1) then ! copy an earlier marked ':'
  250. id=0
  251. le=le+1
  252. aList%bf(le)=':'
  253. endif
  254. le=le+1
  255. aList%bf(le)=c
  256. end select
  257. end do
  258. if(ib<=ie) then
  259. ni=ni+1
  260. aList%lc(0:1,ni)=(/lb,le/)
  261. endif
  262. end subroutine init_
  263. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  264. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  265. !BOP -------------------------------------------------------------------
  266. !
  267. ! !IROUTINE: initStr_ - Initialize a List Using the String Type
  268. !
  269. ! !DESCRIPTION: This routine initializes a {\tt List} datatype given
  270. ! an input {\tt String} datatype (see {\tt m\_String} for more
  271. ! information regarding the {\tt String} type). The contents of the
  272. ! input {\tt String} argument {\tt pstr} must adhere to the restrictions
  273. ! stated for character input stated in the prologue of the routine
  274. ! {\tt init\_()} in this module.
  275. !
  276. ! !INTERFACE:
  277. subroutine initStr_(aList, pstr)
  278. ! !USES:
  279. !
  280. use m_String, only : String,toChar
  281. implicit none
  282. ! !INPUT PARAMETERS:
  283. !
  284. type(String),intent(in) :: pstr
  285. ! !OUTPUT PARAMETERS:
  286. !
  287. type(List),intent(out) :: aList ! an indexed string values
  288. ! !REVISION HISTORY:
  289. ! 23Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  290. !EOP ___________________________________________________________________
  291. character(len=*),parameter :: myname_=myname//'::initStr_'
  292. call init_(aList,toChar(pstr))
  293. end subroutine initStr_
  294. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  295. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  296. !BOP -------------------------------------------------------------------
  297. !
  298. ! !IROUTINE: initStr1_ - Initialize a List Using an Array of Strings
  299. !
  300. ! !DESCRIPTION: This routine initializes a {\tt List} datatype given
  301. ! as input array of {\tt String} datatypes (see {\tt m\_String} for more
  302. ! information regarding the {\tt String} type). The contents of each
  303. ! {\tt String} element of the input array {\tt strs} must adhere to the
  304. ! restrictions stated for character input stated in the prologue of the
  305. ! routine {\tt init\_()} in this module. Specifically, no element in
  306. ! {\tt strs} may contain the colon \verb':' delimiter, and any
  307. ! leading or trailing blanks will be stripped (though embedded blank
  308. ! spaces will be retained). For example, consider an invocation of
  309. ! {\tt initStr1\_()} where the array {\tt strs(:)} contains four entries:
  310. ! {\tt strs(1)='John'}, {\tt strs(2)=' Paul'},
  311. ! {\tt strs(3)='George '}, and {\tt strs(4)=' Ringo'}. The resulting
  312. ! {\tt List} output {\tt aList} will have
  313. ! \begin{verbatim}
  314. ! aList%bf = 'John:Paul:George:Ringo'
  315. ! \end{verbatim}
  316. ! !INTERFACE:
  317. subroutine initStr1_(aList, strs)
  318. ! !USES:
  319. !
  320. use m_String, only : String,toChar
  321. use m_String, only : len
  322. use m_String, only : ptr_chars
  323. use m_die,only : die
  324. implicit none
  325. ! !INPUT PARAMETERS:
  326. !
  327. type(String),dimension(:),intent(in) :: strs
  328. ! !OUTPUT PARAMETERS:
  329. !
  330. type(List),intent(out) :: aList ! an indexed string values
  331. ! !REVISION HISTORY:
  332. ! 23Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  333. !EOP ___________________________________________________________________
  334. character(len=*),parameter :: myname_=myname//'::initStr1_'
  335. character(len=1),allocatable,dimension(:) :: ch1
  336. integer :: ier
  337. integer :: n,i,lc,le
  338. n=size(strs)
  339. le=0
  340. do i=1,n
  341. le=le+len(strs(i))
  342. end do
  343. le=le+n-1 ! for n-1 ":"s
  344. allocate(ch1(le),stat=ier)
  345. if(ier/=0) call die(myname_,'allocate()',ier)
  346. le=0
  347. do i=1,n
  348. if(i>1) then
  349. le=le+1
  350. ch1(le)=':'
  351. endif
  352. lc=le+1
  353. le=le+len(strs(i))
  354. ch1(lc:le)=ptr_chars(strs(i))
  355. end do
  356. call init_(aList,toChar(ch1))
  357. deallocate(ch1,stat=ier)
  358. if(ier/=0) call die(myname_,'deallocate()',ier)
  359. end subroutine initStr1_
  360. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  361. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  362. !BOP -------------------------------------------------------------------
  363. !
  364. ! !IROUTINE: clean_ - Deallocate Memory Used by a List
  365. !
  366. ! !DESCRIPTION: This routine deallocates the allocated memory components
  367. ! of the input/output {\tt List} argument {\tt aList}. Specifically, it
  368. ! deallocates {\tt aList\%bf} and {\tt aList\%lc}. If the optional
  369. ! output {\tt INTEGER} arguemnt {\tt stat} is supplied, no warning will
  370. ! be printed if the Fortran intrinsic {\tt deallocate()} returns with an
  371. ! error condition.
  372. !
  373. ! !INTERFACE:
  374. subroutine clean_(aList, stat)
  375. ! !USES:
  376. !
  377. use m_die, only : warn
  378. use m_mall, only : mall_mco,mall_ison
  379. implicit none
  380. ! !INPUT/OUTPUT PARAMETERS:
  381. !
  382. type(List), intent(inout) :: aList
  383. ! !OUTPUT PARAMETERS:
  384. !
  385. integer, optional, intent(out) :: stat
  386. ! !REVISION HISTORY:
  387. ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  388. ! 1Mar02 - E.T. Ong <eong@mcs.anl.gov> - added stat argument and
  389. ! removed die to prevent crashes.
  390. !EOP ___________________________________________________________________
  391. character(len=*),parameter :: myname_=myname//'::clean_'
  392. integer :: ier
  393. if(mall_ison()) then
  394. if(associated(aList%bf)) call mall_mco(aList%bf,myname_)
  395. if(associated(aList%lc)) call mall_mco(aList%lc,myname_)
  396. endif
  397. if(associated(aList%bf) .and. associated(aList%lc)) then
  398. deallocate(aList%bf, aList%lc, stat=ier)
  399. if(present(stat)) then
  400. stat=ier
  401. else
  402. if(ier /= 0) call warn(myname_,'deallocate(aList%...)',ier)
  403. endif
  404. endif
  405. end subroutine clean_
  406. !--- -------------------------------------------------------------------
  407. ! Math + Computer Science Division / Argonne National Laboratory !
  408. !BOP -------------------------------------------------------------------
  409. !
  410. ! !IROUTINE: nullify_ - Nullify Pointers in a List
  411. !
  412. ! !DESCRIPTION: In Fortran 90, pointers may have three states:
  413. ! (1) {\tt ASSOCIATED}, that is the pointer is pointing at a target,
  414. ! (2) {\tt UNASSOCIATED}, and (3) {\tt UNINITIALIZED}. On some
  415. ! platforms, the Fortran intrinsic function {\tt associated()}
  416. ! will view uninitialized pointers as {\tt UNASSOCIATED} by default.
  417. ! This is not always the case. It is good programming practice to
  418. ! nullify pointers if they are not to be used. This routine nullifies
  419. ! the pointers present in the {\tt List} datatype.
  420. !
  421. ! !INTERFACE:
  422. subroutine nullify_(aList)
  423. ! !USES:
  424. !
  425. use m_die,only : die
  426. implicit none
  427. ! !INPUT/OUTPUT PARAMETERS:
  428. !
  429. type(List),intent(inout) :: aList
  430. ! !REVISION HISTORY:
  431. ! 18Jun01 - J.W. Larson - <larson@mcs.anl.gov> - initial version
  432. !EOP ___________________________________________________________________
  433. character(len=*),parameter :: myname_=myname//'::nullify_'
  434. nullify(aList%bf)
  435. nullify(aList%lc)
  436. end subroutine nullify_
  437. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  438. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  439. !BOP -------------------------------------------------------------------
  440. !
  441. ! !IROUTINE: nitem_ - Return the Number of Items in a List
  442. !
  443. ! !DESCRIPTION:
  444. ! This function enumerates the number of items in the input {\tt List}
  445. ! argument {\tt aList}. For example, suppose
  446. ! \begin{verbatim}
  447. ! aList%bf = 'John:Paul:George:Ringo'
  448. ! \end{verbatim}
  449. ! Then,
  450. ! $${\tt nitem\_(aList)} = 4 .$$
  451. !
  452. ! !INTERFACE:
  453. integer function nitem_(aList)
  454. ! !USES:
  455. !
  456. implicit none
  457. ! !INPUT PARAMETERS:
  458. !
  459. type(List),intent(in) :: aList
  460. ! !REVISION HISTORY:
  461. ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  462. ! 10Oct01 - J.W. Larson <larson@mcs.anl.gov> - modified routine to
  463. ! check pointers aList%bf and aList%lc using the f90
  464. ! intrinsic ASSOCIATED before proceeding with the item
  465. ! count. If these pointers are UNASSOCIATED, an item
  466. ! count of zero is returned.
  467. !EOP ___________________________________________________________________
  468. character(len=*),parameter :: myname_=myname//'::nitem_'
  469. integer :: NumItems
  470. ! Initialize item count to zero
  471. NumItems = 0
  472. ! If the List pointers are ASSOCIATED, perform item count:
  473. if(ASSOCIATED(aList%bf) .and. ASSOCIATED(aList%lc)) then
  474. NumItems = size(aList%lc,2)
  475. endif
  476. nitem_ = NumItems
  477. end function nitem_
  478. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  479. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  480. !BOP -------------------------------------------------------------------
  481. !
  482. ! !IROUTINE: index_ - Return Rank in a List of a Given Item (CHARACTER)
  483. !
  484. ! !DESCRIPTION:
  485. ! This function returns the rank of an item (defined by the
  486. ! {\tt CHARACTER} argument {\tt item}) in the input {\tt List} argument
  487. ! {\tt aList}. If {\tt item} is not present in {\tt aList}, then zero
  488. ! is returned. For example, suppose
  489. ! \begin{verbatim}
  490. ! aList%bf = 'Bob:Carol:Ted:Alice'
  491. ! \end{verbatim}
  492. ! Then, ${\tt index\_(aList, 'Ted')}=3$, ${\tt index\_(aList, 'Carol')}=2$,
  493. ! and ${\tt index\_(aList, 'The Dude')}=0.$
  494. !
  495. ! !INTERFACE:
  496. integer function index_(aList, item)
  497. ! !USES:
  498. !
  499. use m_String, only : toChar
  500. implicit none
  501. ! !INPUT PARAMETERS:
  502. !
  503. type(List), intent(in) :: aList ! a List of names
  504. character(len=*),intent(in) :: item ! a given item name
  505. ! !REVISION HISTORY:
  506. ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  507. !EOP ___________________________________________________________________
  508. character(len=*),parameter :: myname_=myname//'::index_'
  509. integer :: i,lb,le
  510. integer :: itemLength, length, nMatch, j
  511. ! How long is the input item name?
  512. itemLength = len(item)
  513. ! Set output to zero (no item match) value:
  514. index_=0
  515. ! Now, go through the aList one item at a time
  516. ITEM_COMPARE: do i=1,size(aList%lc,2) ! == nitem_(aList)
  517. ! Compute some stats for the current item in aList:
  518. lb=aList%lc(0,i) ! starting index of item in aList%bf
  519. le=aList%lc(1,i) ! ending index item in aList%bf
  520. length = le -lb + 1 ! length of the current item
  521. if(length /= itemLength) then ! this list item can't match input item
  522. CYCLE ! that is, jump to the next item in aList...
  523. else ! compare one character at a time...
  524. ! Initialize number of matching characters in the two strings
  525. nMatch = 0
  526. ! Now, compare item to the current item in aList one character
  527. ! at a time:
  528. CHAR_COMPARE: do j=1,length
  529. if(aList%bf(lb+j-1) == item(j:j)) then ! a match for this character
  530. nMatch = nMatch + 1
  531. else
  532. EXIT
  533. endif
  534. end do CHAR_COMPARE
  535. ! Check the number of leading characters in the current item in aList
  536. ! that match the input item. If it is equal to the item length, then
  537. ! we have found a match and are finished. Otherwise, we cycle on to
  538. ! the next item in aList.
  539. if(nMatch == itemLength) then
  540. index_ = i
  541. EXIT
  542. endif
  543. ! Old code that does not work with V. of the IBM
  544. ! if(item==toChar(aList%bf(lb:le))) then
  545. ! index_=i
  546. ! exit
  547. endif
  548. end do ITEM_COMPARE
  549. end function index_
  550. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  551. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  552. !BOP -------------------------------------------------------------------
  553. !
  554. ! !IROUTINE: indexStr_ - Return Rank in a List of a Given Item (String)
  555. !
  556. ! !DESCRIPTION:
  557. ! This function performs the same operation as the function
  558. ! {\tt index\_()}, but the item to be indexed is instead presented in
  559. ! the form of a {\tt String} datatype (see the module {\tt m\_String}
  560. ! for more information about the {\tt String} type). This routine
  561. ! searches through the input {\tt List} argument {\tt aList} for an
  562. ! item that matches the item defined by {\tt itemStr}, and if a match
  563. ! is found, the rank of the item in the list is returned (see also the
  564. ! prologue for the routine {\tt index\_()} in this module). If no match
  565. ! is found, a value of zero is returned.
  566. !
  567. ! !INTERFACE:
  568. integer function indexStr_(aList, itemStr)
  569. ! !USES:
  570. !
  571. use m_String,only : String,toChar
  572. implicit none
  573. ! !INPUT PARAMETERS:
  574. !
  575. type(List), intent(in) :: aList ! a List of names
  576. type(String), intent(in) :: itemStr
  577. ! !REVISION HISTORY:
  578. ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  579. ! 25Oct02 - R. Jacob <jacob@mcs.anl.gov> - just call index_ above
  580. !EOP ___________________________________________________________________
  581. character(len=*),parameter :: myname_=myname//'::indexStr_'
  582. indexStr_=0
  583. indexStr_=index_(aList,toChar(itemStr))
  584. end function indexStr_
  585. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  586. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  587. !BOP -------------------------------------------------------------------
  588. !
  589. ! !IROUTINE: allocated_ - Check Pointers in a List for Association Status
  590. !
  591. ! !DESCRIPTION:
  592. ! This function checks the input {\tt List} argument {\tt inList} to
  593. ! determine whether or not it has been allocated. It does this by
  594. ! invoking the Fortran90 intrinsic function {\tt associated()} on the
  595. ! pointers {\tt inList\%bf} and {\tt inList\%lc}. If both of these
  596. ! pointers are associated, the return value is {\tt .TRUE.}.
  597. !
  598. ! {\bf N.B.:} In Fortran90, pointers have three different states:
  599. ! {\tt ASSOCIATED}, {\tt UNASSOCIATED}, and {\tt UNDEFINED}.
  600. ! If a pointer is {\tt UNDEFINED}, this function may return either
  601. ! {\tt .TRUE.} or {\tt .FALSE.} values, depending on the Fortran90
  602. ! compiler. To avoid such problems, we advise that users invoke the
  603. ! {\tt List} method {\tt nullify()} to nullify any {\tt List} pointers
  604. ! for {\tt List} variables that are not initialized.
  605. !
  606. ! !INTERFACE:
  607. logical function allocated_(inList)
  608. ! !USES:
  609. use m_die,only : die
  610. implicit none
  611. ! !INPUT PARAMETERS:
  612. type(List), intent(in) :: inList
  613. ! !REVISION HISTORY:
  614. ! 14Dec01 - J. Larson <larson@mcs.anl.gov> - inital version
  615. !EOP ___________________________________________________________________
  616. character(len=*),parameter :: myname_=myname//'::allocated_'
  617. allocated_ = associated(inList%bf) .and. associated(inList%lc)
  618. end function allocated_
  619. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  620. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  621. !BOP -------------------------------------------------------------------
  622. !
  623. ! !IROUTINE: copy_ - Copy a List
  624. !
  625. ! !DESCRIPTION:
  626. ! This routine copies the contents of the input {\tt List} argument
  627. ! {\tt xL} into the output {\tt List} argument {\tt yL}.
  628. !
  629. ! !INTERFACE:
  630. subroutine copy_(yL,xL) ! yL=xL
  631. ! !USES:
  632. !
  633. use m_die,only : die
  634. use m_stdio
  635. use m_String ,only : String
  636. use m_String ,only : String_clean
  637. use m_mall,only : mall_mci,mall_ison
  638. implicit none
  639. ! !INPUT PARAMETERS:
  640. !
  641. type(List),intent(in) :: xL
  642. ! !OUTPUT PARAMETERS:
  643. !
  644. type(List),intent(out) :: yL
  645. ! !REVISION HISTORY:
  646. ! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  647. ! 16May01 - J. Larson <larson@mcs.anl.gov> - simpler, working
  648. ! version that exploits the String datatype (see m_String)
  649. ! 1Aug02 - Larson/Ong - Added logic for correct copying of blank
  650. ! Lists.
  651. !EOP ___________________________________________________________________
  652. character(len=*),parameter :: myname_=myname//'::copy_'
  653. type(String) DummStr
  654. if(size(xL%lc,2) > 0) then
  655. ! Download input List info from xL to String DummStr
  656. call getall_(DummStr,xL)
  657. ! Initialize yL from DummStr
  658. call initStr_(yL,DummStr)
  659. call String_clean(DummStr)
  660. else
  661. if(size(xL%lc,2) < 0) then ! serious error...
  662. write(stderr,'(2a,i8)') myname_, &
  663. ':: FATAL size(xL%lc,2) = ',size(xL%lc,2)
  664. endif
  665. ! Initialize yL as a blank list
  666. call init_(yL, ' ')
  667. endif
  668. end subroutine copy_
  669. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  670. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  671. !BOP -------------------------------------------------------------------
  672. !
  673. ! !IROUTINE: exportToChar_ - Export List to a CHARACTER
  674. !
  675. ! !DESCRIPTION: This function returns the character buffer portion of
  676. ! the input {\tt List} argument {\tt inList}---that is, the contents of
  677. ! {\tt inList\%bf}---as a {\tt CHARACTER} (suitable for printing). An
  678. ! example of the use of this function is:
  679. ! \begin{verbatim}
  680. ! write(stdout,'(1a)') exportToChar(inList)
  681. ! \end{verbatim}
  682. ! which writes the contents of {\tt inList\%bf} to the Fortran device
  683. ! {\tt stdout}.
  684. !
  685. ! !INTERFACE:
  686. function exportToChar_(inList)
  687. ! !USES:
  688. !
  689. use m_die, only : die
  690. use m_stdio, only : stderr
  691. use m_String, only : String
  692. use m_String, only : String_ToChar => toChar
  693. use m_String, only : String_clean
  694. implicit none
  695. ! ! INPUT PARAMETERS:
  696. type(List), intent(in) :: inList
  697. ! ! OUTPUT PARAMETERS:
  698. character(len=size(inList%bf,1)) :: exportToChar_
  699. ! !REVISION HISTORY:
  700. ! 13Feb02 - J. Larson <larson@mcs.anl.gov> - initial version.
  701. ! 06Jun03 - R. Jacob <jacob@mcs.anl.gov> - return blank if List is not allocated
  702. !EOP ___________________________________________________________________
  703. character(len=*),parameter :: myname_=myname//'::exportToChar_'
  704. type(String) DummStr
  705. ! Download input List info from inList to String DummStr
  706. if(allocated_(inList)) then
  707. call getall_(DummStr,inList)
  708. exportToChar_ = String_ToChar(DummStr)
  709. call String_clean(DummStr)
  710. else
  711. exportToChar_ = ''
  712. endif
  713. end function exportToChar_
  714. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  715. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  716. !BOP -------------------------------------------------------------------
  717. !
  718. ! !IROUTINE: exportToString_ - Export List to a String
  719. !
  720. ! !DESCRIPTION: This function returns the character buffer portion of
  721. ! the input {\tt List} argument {\tt inList}---that is, the contents of
  722. ! {\tt inList\%bf}---as a {\tt String} (see the mpeu module m\_String
  723. ! for more information regarding the {\tt String} type). This function
  724. ! was created to circumvent problems with implementing inheritance of
  725. ! the function {\tt exportToChar\_()} to other datatypes build on top
  726. ! of the {\tt List} type.
  727. !
  728. ! !INTERFACE:
  729. function exportToString_(inList)
  730. ! !USES:
  731. !
  732. use m_die, only : die
  733. use m_stdio, only : stderr
  734. use m_String, only : String
  735. use m_String, only : String_init => init
  736. implicit none
  737. ! ! INPUT PARAMETERS:
  738. type(List), intent(in) :: inList
  739. ! ! OUTPUT PARAMETERS:
  740. type(String) :: exportToString_
  741. ! !REVISION HISTORY:
  742. ! 14Aug02 - J. Larson <larson@mcs.anl.gov> - initial version.
  743. !EOP ___________________________________________________________________
  744. character(len=*),parameter :: myname_=myname//'::exportToString_'
  745. if(allocated_(inList)) then
  746. call getall_(exportToString_, inList)
  747. else
  748. call String_init(exportToString_, 'NOTHING')
  749. endif
  750. end function exportToString_
  751. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  752. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  753. !BOP -------------------------------------------------------------------
  754. !
  755. ! !IROUTINE: CharBufferSize_ - Return size of a List's Character Buffer
  756. !
  757. ! !DESCRIPTION: This function returns the length of the character
  758. ! buffer portion of the input {\tt List} argument {\tt inList} (that
  759. ! is, the number of characters stored in {\tt inList\%bf}) as an
  760. ! {\tt INTEGER}. Suppose for the sake of argument that {\tt inList}
  761. ! was created using the following call to {\tt init\_()}:
  762. ! \begin{verbatim}
  763. ! call init_(inList, 'Groucho:Harpo:Chico:Zeppo')
  764. ! \end{verbatim}
  765. ! Then, using the above example value of {\tt inList}, we can use
  766. ! {\tt CharBufferSize\_()} as follows:
  767. ! \begin{verbatim}
  768. ! integer :: BufferLength
  769. ! BufferLength = CharBufferSize(inList)
  770. ! \end{verbatim}
  771. ! and the resulting value of {\tt BufferLength} will be 25.
  772. !
  773. ! !INTERFACE:
  774. integer function CharBufferSize_(inList)
  775. ! !USES:
  776. !
  777. use m_die, only : die
  778. use m_stdio, only : stderr
  779. implicit none
  780. ! ! INPUT PARAMETERS:
  781. type(List), intent(in) :: inList
  782. ! !REVISION HISTORY:
  783. ! 13Feb02 - J. Larson <larson@mcs.anl.gov> - initial version.
  784. !EOP ___________________________________________________________________
  785. character(len=*),parameter :: myname_=myname//'::CharBufferSize_'
  786. if(allocated_(inList)) then
  787. CharBufferSize_ = size(inList%bf)
  788. else
  789. write(stderr,'(2a)') myname_,":: Argument inList not allocated."
  790. call die(myname_)
  791. endif
  792. end function CharBufferSize_
  793. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  794. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  795. !BOP -------------------------------------------------------------------
  796. !
  797. ! !IROUTINE: get_ - Retrieve a Numbered Item from a List as a String
  798. !
  799. ! !DESCRIPTION:
  800. ! This routine retrieves a numbered item (defined by the input
  801. ! {\tt INTEGER} argument {\tt ith}) from the input {\tt List} argument
  802. ! {\tt aList}, and returns it in the output {\tt String} argument
  803. ! {\tt itemStr} (see the module {\tt m\_String} for more information
  804. ! about the {\tt String} type). If the argument {\tt ith} is nonpositive,
  805. ! or greater than the number of items in {\tt aList}, a String containing
  806. ! one blank space is returned.
  807. !
  808. ! !INTERFACE:
  809. subroutine get_(itemStr, ith, aList)
  810. ! !USES:
  811. !
  812. use m_String, only : String, init, toChar
  813. implicit none
  814. ! !INPUT PARAMETERS:
  815. !
  816. integer, intent(in) :: ith
  817. type(List), intent(in) :: aList
  818. ! !OUTPUT PARAMETERS:
  819. !
  820. type(String),intent(out) :: itemStr
  821. ! !REVISION HISTORY:
  822. ! 23Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  823. ! 14May07 - Larson, Jacob - add space to else case string so function
  824. ! matches documentation.
  825. !EOP ___________________________________________________________________
  826. character(len=*),parameter :: myname_=myname//'::get_'
  827. integer :: lb,le
  828. if(ith>0 .and. ith <= size(aList%lc,2)) then
  829. lb=aList%lc(0,ith)
  830. le=aList%lc(1,ith)
  831. call init(itemStr,toChar(aList%bf(lb:le)))
  832. else
  833. call init(itemStr,' ')
  834. endif
  835. end subroutine get_
  836. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  837. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  838. !BOP -------------------------------------------------------------------
  839. !
  840. ! !IROUTINE: getall_ - Return all Items from a List as one String
  841. !
  842. ! !DESCRIPTION:
  843. ! This routine returns all the items from the input {\tt List} argument
  844. ! {\tt aList} in the output {\tt String} argument {\tt itemStr} (see
  845. ! the module {\tt m\_String} for more information about the {\tt String}
  846. ! type). The contents of the character buffer in {\tt itemStr} will
  847. ! be the all of the items in {\tt aList}, separated by the colon delimiter.
  848. !
  849. ! !INTERFACE:
  850. subroutine getall_(itemStr, aList)
  851. ! !USES:
  852. !
  853. use m_String, only : String, init, toChar
  854. implicit none
  855. ! !INPUT PARAMETERS:
  856. !
  857. type(List), intent(in) :: aList
  858. ! !OUTPUT PARAMETERS:
  859. !
  860. type(String), intent(out) :: itemStr
  861. ! !REVISION HISTORY:
  862. ! 23Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  863. !EOP ___________________________________________________________________
  864. character(len=*),parameter :: myname_=myname//'::getall_'
  865. integer :: lb,le,ni
  866. ni=size(aList%lc,2)
  867. lb=aList%lc(0,1)
  868. le=aList%lc(1,ni)
  869. call init(itemStr,toChar(aList%bf(lb:le)))
  870. end subroutine getall_
  871. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  872. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  873. !BOP -------------------------------------------------------------------
  874. !
  875. ! !IROUTINE: getrange_ - Return a Range of Items from a List as one String
  876. !
  877. ! !DESCRIPTION:
  878. ! This routine returns all the items ranked {\tt i1} through {\tt i2}
  879. ! from the input {\tt List} argument {\tt aList} in the output
  880. ! {\tt String} argument {\tt itemStr} (see the module {\tt m\_String}
  881. ! for more information about the {\tt String} type). The contents of
  882. ! the character buffer in {\tt itemStr} will be items in {\tt i1} through
  883. ! {\tt i2} {\tt aList}, separated by the colon delimiter.
  884. !
  885. ! !INTERFACE:
  886. subroutine getrange_(itemStr, i1, i2, aList)
  887. ! !USES:
  888. !
  889. use m_die, only : die
  890. use m_stdio, only : stderr
  891. use m_String, only : String,init,toChar
  892. implicit none
  893. ! !INPUT PARAMETERS:
  894. !
  895. integer, intent(in) :: i1
  896. integer, intent(in) :: i2
  897. type(List), intent(in) :: aList
  898. ! !OUTPUT PARAMETERS:
  899. !
  900. type(String),intent(out) :: itemStr
  901. ! !REVISION HISTORY:
  902. ! 23Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  903. ! 26Jul02 - J. Larson - Added argument checks.
  904. !EOP ___________________________________________________________________
  905. character(len=*),parameter :: myname_=myname//'::getrange_'
  906. integer :: lb,le,ni
  907. ! Argument Sanity Checks:
  908. if(.not. allocated_(aList)) then
  909. write(stderr,'(2a)') myname_, &
  910. ':: FATAL--List argument aList is not initialized.'
  911. call die(myname_)
  912. endif
  913. ! is i2 >= i1 as we assume?
  914. if(i1 > i2) then
  915. write(stderr,'(2a,2(a,i8))') myname_, &
  916. ':: FATAL. Starting/Ending item ranks are out of order; ', &
  917. 'i2 must be greater or equal to i1. i1 =',i1,' i2 = ',i2
  918. call die(myname_)
  919. endif
  920. ni=size(aList%lc,2) ! the number of items in aList...
  921. ! is i1 or i2 too big?
  922. if(i1 > ni) then
  923. write(stderr,'(2a,2(a,i8))') myname_, &
  924. ':: FATAL--i1 is greater than the number of items in ', &
  925. 'The List argument aList: i1 =',i1,' ni = ',ni
  926. call die(myname_)
  927. endif
  928. if(i2 > ni) then
  929. write(stderr,'(2a,2(a,i8))') myname_, &
  930. ':: FATAL--i2 is greater than the number of items in ', &
  931. 'The List argument aList: i2 =',i2,' ni = ',ni
  932. call die(myname_)
  933. endif
  934. ! End of Argument Sanity Checks.
  935. lb=aList%lc(0,max(1,i1))
  936. le=aList%lc(1,min(ni,i2))
  937. call init(itemStr,toChar(aList%bf(lb:le)))
  938. end subroutine getrange_
  939. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  940. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  941. !BOP -------------------------------------------------------------------
  942. !
  943. ! !IROUTINE: identical_ - Compare Two Lists for Equality
  944. !
  945. ! !DESCRIPTION:
  946. ! This function compares the string buffer and indexing information in
  947. ! the two input {\tt List} arguments {\tt yL} and {\tt xL}. If the
  948. ! string buffers and index buffers of {\tt yL} and {\tt xL} match, this
  949. ! function returns a value of {\tt .TRUE.} Otherwise, it returns a
  950. ! value of {\tt .FALSE.}
  951. !
  952. ! !INTERFACE:
  953. logical function identical_(yL, xL)
  954. ! !USES:
  955. !
  956. use m_die,only : die
  957. use m_String ,only : String
  958. use m_String ,only : String_clean
  959. implicit none
  960. ! !INPUT PARAMETERS:
  961. !
  962. type(List), intent(in) :: yL
  963. type(List), intent(in) :: xL
  964. ! !REVISION HISTORY:
  965. ! 14Oct01 - J. Larson <larson@mcs.anl.gov> - original version
  966. !EOP ___________________________________________________________________
  967. character(len=*),parameter :: myname_=myname//'::identical_'
  968. logical :: myIdentical
  969. type(String) :: DummStr
  970. integer :: n, NumItems
  971. ! Compare the number of the items in the Lists xL and yL.
  972. ! If they differ, myIdentical is set to .FALSE. and we are
  973. ! finished. If both Lists sport the same number of items,
  974. ! we must compare them one-by-one...
  975. myIdentical = .FALSE.
  976. if(nitem_(yL) == nitem_(xL)) then
  977. NumItems = nitem_(yL)
  978. COMPARE_LOOP: do n=1,NumItems
  979. call get_(DummStr, n, yL) ! retrieve nth tag as a String
  980. if( indexStr_(xL, Dummstr) /= n ) then ! a discrepency spotted.
  981. call String_clean(Dummstr)
  982. myIdentical = .FALSE.
  983. EXIT
  984. else
  985. call String_clean(Dummstr)
  986. endif
  987. myIdentical = .TRUE. ! we survived the whole test process.
  988. end do COMPARE_LOOP
  989. endif
  990. identical_ = myIdentical
  991. end function identical_
  992. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  993. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  994. !BOP -------------------------------------------------------------------
  995. !
  996. ! !IROUTINE: get_indices_ - Index Multiple Items in a List
  997. !
  998. ! !DESCRIPTION: This routine takes as input a {\tt List} argument
  999. ! {\tt aList}, and a {\tt CHARACTER} string {Values}, which is a colon-
  1000. ! delimited string of items, and returns an {\tt INTEGER} array
  1001. ! {\tt indices(:)}, which contain the rank of each item in {\tt aList}.
  1002. ! For example, suppose {\tt aList} was created from the character string
  1003. ! \begin{verbatim}
  1004. ! 'happy:sleepy:sneezey:grumpy:dopey::bashful:doc'
  1005. ! \end{verbatim}
  1006. ! and get\_indices\_() is invoked as follows:
  1007. ! \begin{verbatim}
  1008. ! call get_indices_(indices, aList, 'sleepy:grumpy:bashful:doc')
  1009. ! \end{verbatim}
  1010. ! The array {\tt indices(:)} will be returned with 4 entries:
  1011. ! ${\tt indices(1)}=2$, ${\tt indices(2)}=4$, ${\tt indices(3)}=6$, and
  1012. ! ${\tt indices(4)}=7$.
  1013. !
  1014. ! {\bf N.B.}: This routine operates on the assumption that each of the
  1015. ! substrings in the colon-delimited string {\tt Values} is an item in
  1016. ! {\tt aList}. If this assumption is invalid, this routine terminates
  1017. ! execution with an error message.
  1018. !
  1019. ! {\bf N.B.}: The pointer {\tt indices} must be {\tt UNASSOCIATED} on entry
  1020. ! to this routine, and will be {\tt ASSOCIATED} upon return. After this pointer
  1021. ! is no longer needed, it should be deallocated. Failure to do so will result
  1022. ! in a memory leak.
  1023. !
  1024. ! !INTERFACE:
  1025. subroutine get_indices_(indices, aList, Values)
  1026. ! !USES:
  1027. !
  1028. use m_stdio
  1029. use m_die
  1030. use m_String, only : String
  1031. use m_String, only : String_clean => clean
  1032. use m_String, only : String_toChar => toChar
  1033. implicit none
  1034. ! !INPUT PARAMETERS:
  1035. !
  1036. type(List), intent(in) :: aList ! an indexed string values
  1037. character(len=*), intent(in) :: Values ! ":" delimited names
  1038. ! !OUTPUT PARAMETERS:
  1039. !
  1040. integer, dimension(:), pointer :: indices
  1041. ! !REVISION HISTORY:
  1042. ! 31May98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  1043. ! 12Feb03 - J. Larson <larson@mcs.anl.gov> Working refactored version
  1044. !EOP ___________________________________________________________________
  1045. character(len=*),parameter :: myname_=myname//'::get_indices_'
  1046. type(List) :: tList
  1047. type(String) :: tStr
  1048. integer :: i, ierr, n
  1049. ! Create working list based on input colon-delimited string
  1050. call init_(tList, values)
  1051. ! Count items in tList and allocate indices(:) accordingly
  1052. n = nitem_(tList)
  1053. if(n > nitem_(aList)) then
  1054. write(stderr,'(5a,2(i8,a))') myname_, &
  1055. ':: FATAL--more items in argument Values than aList! Input string', &
  1056. 'Values = "',Values,'" has ',n,' items. aList has ',nitem_(aList), &
  1057. ' items.'
  1058. call die(myname_)
  1059. endif
  1060. allocate(indices(n), stat=ierr)
  1061. if(ierr /= 0) then
  1062. write(stderr,'(2a,i8,a)') myname_, &
  1063. ':: FATAL--allocate(indices(...) failed with stat=',ierr,&
  1064. '. On entry to this routine, this pointer must be NULL.'
  1065. call die(myname_)
  1066. endif
  1067. ! Retrieve each item from tList as a String and index it
  1068. do i=1,n
  1069. call get_(tStr,i,tList)
  1070. indices(i) = indexStr_(aList,tStr)
  1071. if(indices(i) == 0) then ! ith item not present in aList!
  1072. write(stderr,'(4a)') myname_, &
  1073. ':: FATAL--item "',String_toChar(tStr),'" not found.'
  1074. call die(myname_)
  1075. endif
  1076. call String_clean(tStr)
  1077. end do
  1078. ! Clean up temporary List tList
  1079. call clean_(tList)
  1080. end subroutine get_indices_
  1081. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1082. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  1083. !BOP -------------------------------------------------------------------
  1084. !
  1085. ! !IROUTINE: test_indices_ - Test/Index Multiple Items in a List
  1086. !
  1087. ! !DESCRIPTION: This routine takes as input a {\tt List} argument
  1088. ! {\tt aList}, and a {\tt CHARACTER} string {Values}, which is a colon-
  1089. ! delimited string of items, and returns an {\tt INTEGER} array
  1090. ! {\tt indices(:)}, which contain the rank of each item in {\tt aList}.
  1091. ! For example, suppose {\tt aList} was created from the character string
  1092. ! \begin{verbatim}
  1093. ! 'happy:sleepy:sneezey:grumpy:dopey::bashful:doc'
  1094. ! \end{verbatim}
  1095. ! and {\tt test\_indices\_()} is invoked as follows:
  1096. ! \begin{verbatim}
  1097. ! call test_indices_(indices, aList, 'sleepy:grumpy:bashful:doc')
  1098. ! \end{verbatim}
  1099. ! The array {\tt indices(:)} will be returned with 4 entries:
  1100. ! ${\tt indices(1)}=2$, ${\tt indices(2)}=4$, ${\tt indices(3)}=6$, and
  1101. ! ${\tt indices(4)}=7$.
  1102. !
  1103. ! Now suppose {\tt test\_indices\_()} is invoked as follows:
  1104. ! \begin{verbatim}
  1105. ! call test_indices_(indices, aList, 'sleepy:grumpy:bashful:Snow White')
  1106. ! \end{verbatim}
  1107. ! The array {\tt indices(:)} will be returned with 4 entries:
  1108. ! ${\tt indices(1)}=2$, ${\tt indices(2)}=4$, ${\tt indices(3)}=6$, and
  1109. ! ${\tt indices(4)}=0$.
  1110. !
  1111. ! {\bf N.B.}: This routine operates on the assumption that one or more
  1112. ! of the substrings in the colon-delimited string {\tt Values} is may not
  1113. ! be an item in {\tt aList}. If an item in {\tt Values} is {\em not} in
  1114. ! {\tt aList}, its corresponding entry in {\tt indices(:)} is set to zero.
  1115. !
  1116. ! {\bf N.B.}: The pointer {\tt indices} must be {\tt UNASSOCIATED} on entry
  1117. ! to this routine, and will be {\tt ASSOCIATED} upon return. After this pointer
  1118. ! is no longer needed, it should be deallocated. Failure to do so will result
  1119. ! in a memory leak.
  1120. !
  1121. ! !INTERFACE:
  1122. subroutine test_indices_(indices, aList, Values)
  1123. ! !USES:
  1124. !
  1125. use m_stdio
  1126. use m_die
  1127. use m_String, only : String
  1128. use m_String, only : String_clean => clean
  1129. use m_String, only : String_toChar => toChar
  1130. implicit none
  1131. ! !INPUT PARAMETERS:
  1132. !
  1133. type(List), intent(in) :: aList ! an indexed string values
  1134. character(len=*), intent(in) :: Values ! ":" delimited names
  1135. ! !OUTPUT PARAMETERS:
  1136. !
  1137. integer, dimension(:), pointer :: indices
  1138. ! !REVISION HISTORY:
  1139. ! 12Feb03 - J. Larson <larson@mcs.anl.gov> Working refactored version
  1140. !EOP ___________________________________________________________________
  1141. character(len=*),parameter :: myname_=myname//'::test_indices_'
  1142. type(List) :: tList
  1143. type(String) :: tStr
  1144. integer :: i, ierr, n
  1145. ! Create working list based on input colon-delimited string
  1146. call init_(tList, values)
  1147. ! Count items in tList and allocate indices(:) accordingly
  1148. n = nitem_(tList)
  1149. allocate(indices(n), stat=ierr)
  1150. if(ierr /= 0) then
  1151. write(stderr,'(2a,i8,a)') myname_, &
  1152. ':: FATAL--allocate(indices(...) failed with stat=',ierr,&
  1153. '. On entry to this routine, this pointer must be NULL.'
  1154. call die(myname_)
  1155. endif
  1156. ! Retrieve each item from tList as a String and index it
  1157. do i=1,n
  1158. call get_(tStr,i,tList)
  1159. indices(i) = indexStr_(aList,tStr)
  1160. call String_clean(tStr)
  1161. end do
  1162. ! Clean up temporary List tList
  1163. call clean_(tList)
  1164. end subroutine test_indices_
  1165. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1166. ! Math and Computer Science Division, Argonne National Laboratory !
  1167. !BOP -------------------------------------------------------------------
  1168. !
  1169. ! !IROUTINE: append_ - Append One List Onto the End of Another
  1170. !
  1171. ! !DESCRIPTION: This routine takes two {\tt List} arguments
  1172. ! {\tt iList1} and {\tt iList2}, and appends {\tt List2} onto
  1173. ! the end of {\tt List1}.
  1174. !
  1175. ! {\bf N.B.}: There is no check for shared items in the arguments
  1176. ! {\tt List1} and {\tt List2}. It is the user's responsibility to
  1177. ! ensure {\tt List1} and {\tt List2} share no items. If this routine
  1178. ! is invoked in such a manner that {\tt List1} and {\tt List2} share
  1179. ! common items, the resultant value of {\tt List1} will produce
  1180. ! ambiguous results for some of the {\tt List} query functions.
  1181. !
  1182. ! {\bf N.B.}: The outcome of this routine is order dependent. That is,
  1183. ! the entries of {\tt iList2} will follow the {\em input} entries in
  1184. ! {\tt iList1}.
  1185. !
  1186. ! !INTERFACE:
  1187. subroutine append_(iList1, iList2)
  1188. !
  1189. ! !USES:
  1190. !
  1191. use m_stdio
  1192. use m_die, only : die
  1193. use m_mpif90
  1194. use m_String, only: String
  1195. use m_String, only: String_toChar => toChar
  1196. use m_String, only: String_len
  1197. use m_String, only: String_clean => clean
  1198. implicit none
  1199. ! !INPUT PARAMETERS:
  1200. !
  1201. type(List), intent(in) :: iList2
  1202. ! !INPUT/OUTPUT PARAMETERS:
  1203. !
  1204. type(List), intent(inout) :: iList1
  1205. ! !REVISION HISTORY:
  1206. ! 6Aug02 - J. Larson - Initial version
  1207. !EOP ___________________________________________________________________
  1208. character(len=*),parameter :: myname_=myname//'::append_'
  1209. type(List) :: DummyList
  1210. call copy_(DummyList, iList1)
  1211. call clean_(iList1)
  1212. call concatenate(DummyList, iList2, iList1)
  1213. call clean_(DummyList)
  1214. end subroutine append_
  1215. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1216. ! Math and Computer Science Division, Argonne National Laboratory !
  1217. !BOP -------------------------------------------------------------------
  1218. !
  1219. ! !IROUTINE: concatenate_ - Concatenates two Lists to form a Third List.
  1220. !
  1221. ! !DESCRIPTION: This routine takes two input {\tt List} arguments
  1222. ! {\tt iList1} and {\tt iList2}, and concatenates them, producing an
  1223. ! output {\tt List} argument {\tt oList}.
  1224. !
  1225. ! {\bf N.B.}: The nature of this routine is such that one must
  1226. ! {\bf never} supply as the actual value of {\tt oList} the same
  1227. ! value supplied for either {\tt iList1} or {\tt iList2}.
  1228. !
  1229. ! {\bf N.B.}: The outcome of this routine is order dependent. That is,
  1230. ! the entries of {\tt iList2} will follow {\tt iList1}.
  1231. !
  1232. ! !INTERFACE:
  1233. subroutine concatenate_(iList1, iList2, oList)
  1234. !
  1235. ! !USES:
  1236. !
  1237. use m_stdio
  1238. use m_die, only : die
  1239. use m_mpif90
  1240. use m_String, only: String
  1241. use m_String, only: String_init => init
  1242. use m_String, only: String_clean => clean
  1243. implicit none
  1244. ! !INPUT PARAMETERS:
  1245. !
  1246. type(List), intent(in) :: iList1
  1247. type(List), intent(in) :: iList2
  1248. ! !OUTPUT PARAMETERS:
  1249. !
  1250. type(List), intent(out) :: oList
  1251. ! !BUGS: For now, the List concatenate algorithm relies on fixed-length
  1252. ! CHARACTER variables as intermediate storage. The lengths of these
  1253. ! scratch variables is hard-wired to 10000, which should be large enough
  1254. ! for most applications. This undesirable feature should be corrected
  1255. ! ASAP.
  1256. !
  1257. ! !REVISION HISTORY:
  1258. ! 8May01 - J.W. Larson - initial version.
  1259. ! 17May01 - J.W. Larson - Re-worked and tested successfully.
  1260. ! 17Jul02 - E. Ong - fixed the bug mentioned above
  1261. !EOP ___________________________________________________________________
  1262. character(len=*),parameter :: myname_=myname//'::concatenate_'
  1263. character, dimension(:), allocatable :: CatBuff
  1264. integer :: CatBuffLength, i, ierr, Length1, Length2
  1265. type(String) :: CatString
  1266. ! First, handle the case of either iList1 and/or iList2 being
  1267. ! null
  1268. if((nitem_(iList1) == 0) .or. (nitem_(iList2) == 0)) then
  1269. if((nitem_(iList1) == 0) .and. (nitem_(iList2) == 0)) then
  1270. call init_(oList,'')
  1271. else
  1272. if((nitem_(iList1) == 0) .and. (nitem_(iList2) > 0)) then
  1273. call copy_(oList, iList2)
  1274. endif
  1275. if((nitem_(iList1) > 0) .and. (nitem_(iList2) == 0)) then
  1276. call copy_(oList,iList1)
  1277. endif
  1278. endif
  1279. else ! both lists are non-null
  1280. ! Step one: Get lengths of character buffers of iList1 and iList2:
  1281. Length1 = CharBufferSize_(iList1)
  1282. Length2 = CharBufferSize_(iList2)
  1283. ! Step two: create CatBuff(:) as workspace
  1284. CatBuffLength = Length1 + Length2 + 1
  1285. allocate(CatBuff(CatBuffLength), stat=ierr)
  1286. if(ierr /= 0) then
  1287. write(stderr,'(2a,i8)') myname_, &
  1288. ':: FATAL--allocate(CatBuff(...) failed. ierr=',ierr
  1289. call die(myname_)
  1290. endif
  1291. ! Step three: concatenate CHARACTERs with the colon separator
  1292. ! into CatBuff(:)
  1293. do i=1,Length1
  1294. CatBuff(i) = iList1%bf(i)
  1295. end do
  1296. CatBuff(Length1 + 1) = ':'
  1297. do i=1,Length2
  1298. CatBuff(Length1 + 1 + i) = iList2%bf(i)
  1299. end do
  1300. ! Step four: initialize a String CatString:
  1301. call String_init(CatString, CatBuff)
  1302. ! Step five: initialize oList:
  1303. call initStr_(oList, CatString)
  1304. ! The concatenation is complete. Now, clean up
  1305. call String_clean(CatString)
  1306. deallocate(CatBuff,stat=ierr)
  1307. if(ierr /= 0) then
  1308. write(stderr,'(2a,i8)') myname_, &
  1309. ':: FATAL--deallocate(CatBuff) failed. ierr=',ierr
  1310. call die(myname_)
  1311. endif
  1312. endif
  1313. end subroutine concatenate_
  1314. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1315. ! Math and Computer Science Division, Argonne National Laboratory !
  1316. !BOP -------------------------------------------------------------------
  1317. !
  1318. ! !IROUTINE: bcast_ - MPI Broadcast for the List Type
  1319. !
  1320. ! !DESCRIPTION: This routine takes an input {\tt List} argument
  1321. ! {\tt iList} (on input, valid on the root only), and broadcasts it.
  1322. !
  1323. ! {\bf N.B.}: The outcome of this routine, {\tt ioList} on non-root
  1324. ! processes, represents allocated memory. When this {\tt List} is
  1325. ! no longer needed, it must be deallocated by invoking the routine
  1326. ! {\tt List\_clean()}. Failure to do so will cause a memory leak.
  1327. !
  1328. ! !INTERFACE:
  1329. subroutine bcast_(ioList, root, comm, status)
  1330. !
  1331. ! !USES:
  1332. !
  1333. use m_stdio, only : stderr
  1334. use m_die, only : MP_perr_die, die
  1335. use m_String, only: String
  1336. use m_String, only: String_bcast => bcast
  1337. use m_String, only: String_clean => clean
  1338. use m_mpif90
  1339. implicit none
  1340. ! !INPUT PARAMETERS:
  1341. !
  1342. integer, intent(in) :: root
  1343. integer, intent(in) :: comm
  1344. ! !INPUT/OUTPUT PARAMETERS:
  1345. !
  1346. type(List), intent(inout) :: ioList
  1347. ! !OUTPUT PARAMETERS:
  1348. !
  1349. integer, optional, intent(out) :: status
  1350. ! !REVISION HISTORY:
  1351. ! 7May01 - J.W. Larson - initial version.
  1352. ! 14May01 - R.L. Jacob - fix error checking
  1353. ! 16May01 - J.W. Larson - new, simpler String-based algorigthm
  1354. ! (see m_String for details), which works properly on
  1355. ! the SGI platform.
  1356. ! 13Jun01 - J.W. Larson <larson@mcs.anl.gov> - Initialize status
  1357. ! (if present).
  1358. !EOP ___________________________________________________________________
  1359. character(len=*),parameter :: myname_=myname//'::bcast_'
  1360. integer :: myID, ierr
  1361. type(String) :: DummStr
  1362. ! Initialize status (if present)
  1363. if(present(status)) status = 0
  1364. ! Which process am I?
  1365. call MPI_COMM_RANK(comm, myID, ierr)
  1366. if(ierr /= 0) then
  1367. if(present(status)) then
  1368. status = ierr
  1369. write(stderr,'(2a,i4)') myname_,":: MPI_COMM_RANK(), ierr=",ierr
  1370. return
  1371. else
  1372. call MP_perr_die(myname_,"MPI_COMM_RANK()",ierr)
  1373. endif
  1374. endif
  1375. ! on the root, convert ioList into the String variable DummStr
  1376. if(myID == root) then
  1377. if(CharBufferSize_(ioList) <= 0) then
  1378. call die(myname_, 'Attempting to broadcast an empty list!',&
  1379. CharBufferSize_(ioList))
  1380. endif
  1381. call getall_(DummStr, ioList)
  1382. endif
  1383. ! Broadcast DummStr
  1384. call String_bcast(DummStr, root, comm, ierr)
  1385. if(ierr /= 0) then
  1386. if(present(status)) then
  1387. status = ierr
  1388. write(stderr,'(2a,i4)') myname_,":: call String_bcast(), ierr=",ierr
  1389. return
  1390. else
  1391. call MP_perr_die(myname_,"String_bcast() failed, stat=",ierr)
  1392. endif
  1393. endif
  1394. ! Initialize ioList off the root using DummStr
  1395. if(myID /= root) then
  1396. call initStr_(ioList, DummStr)
  1397. endif
  1398. ! And now, the List broadcast is complete.
  1399. call String_clean(DummStr)
  1400. end subroutine bcast_
  1401. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1402. ! Math and Computer Science Division, Argonne National Laboratory !
  1403. !BOP -------------------------------------------------------------------
  1404. !
  1405. ! !IROUTINE: send_ - MPI Point-to-Point Send for the List Type
  1406. !
  1407. ! !DESCRIPTION: This routine takes an input {\tt List} argument
  1408. ! {\tt inList} and sends it to processor {\tt dest} on the communicator
  1409. ! associated with the fortran 90 {\tt INTEGER} handle {\tt comm}. The
  1410. ! message is tagged by the input {\tt INTEGER} argument {\tt TagBase}.
  1411. ! The success (failure) of this operation is reported in the zero
  1412. ! (nonzero) optional output argument {\tt status}.
  1413. !
  1414. ! {\bf N.B.}: One must avoid assigning elsewhere the MPI tag values
  1415. ! {\tt TagBase} and {\tt TagBase+1}. This is because {\tt send\_()}
  1416. ! performs the send of the {\tt List} as a pair of operations. The
  1417. ! first send is the number of characters in {\tt inList\%bf}, and is
  1418. ! given MPI tag value {\tt TagBase}. The second send is the
  1419. ! {\tt CHARACTER} data present in {\tt inList\%bf}, and is given MPI
  1420. ! tag value {\tt TagBase+1}.
  1421. !
  1422. ! !INTERFACE:
  1423. subroutine send_(inList, dest, TagBase, comm, status)
  1424. !
  1425. ! !USES:
  1426. !
  1427. use m_stdio
  1428. use m_die, only : MP_perr_die
  1429. use m_mpif90
  1430. use m_String, only: String
  1431. use m_String, only: String_toChar => toChar
  1432. use m_String, only: String_len
  1433. use m_String, only: String_clean => clean
  1434. implicit none
  1435. ! !INPUT PARAMETERS:
  1436. !
  1437. type(List), intent(in) :: inList
  1438. integer, intent(in) :: dest
  1439. integer, intent(in) :: TagBase
  1440. integer, intent(in) :: comm
  1441. ! !OUTPUT PARAMETERS:
  1442. !
  1443. integer, optional, intent(out) :: status
  1444. ! !REVISION HISTORY:
  1445. ! 6Jun01 - J.W. Larson - initial version.
  1446. ! 13Jun01 - J.W. Larson <larson@mcs.anl.gov> - Initialize status
  1447. ! (if present).
  1448. !EOP ___________________________________________________________________
  1449. character(len=*),parameter :: myname_=myname//'::send_'
  1450. type(String) :: DummStr
  1451. integer :: ierr, length
  1452. ! Set status flag to zero (success) if present:
  1453. if(present(status)) status = 0
  1454. ! Step 1. Extract CHARACTER buffer from inList and store it
  1455. ! in String variable DummStr, determine its length.
  1456. call getall_(DummStr, inList)
  1457. length = String_len(DummStr)
  1458. ! Step 2. Send Length of String DummStr to process dest.
  1459. call MPI_SEND(length, 1, MP_type(length), dest, TagBase, comm, ierr)
  1460. if(ierr /= 0) then
  1461. if(present(status)) then
  1462. write(stderr,'(2a,i8)') myname_, &
  1463. ':: MPI_SEND(length...) failed. ierror=', ierr
  1464. status = ierr
  1465. return
  1466. else
  1467. call MP_perr_die(myname_,':: MPI_SEND(length...) failed',ierr)
  1468. endif
  1469. endif
  1470. ! Step 3. Send CHARACTER portion of String DummStr
  1471. ! to process dest.
  1472. call MPI_SEND(DummStr%c(1), length, MP_CHARACTER, dest, TagBase+1, &
  1473. comm, ierr)
  1474. if(ierr /= 0) then
  1475. if(present(status)) then
  1476. write(stderr,'(2a,i8)') myname_, &
  1477. ':: MPI_SEND(DummStr%c...) failed. ierror=', ierr
  1478. status = ierr
  1479. return
  1480. else
  1481. call MP_perr_die(myname_,':: MPI_SEND(DummStr%c...) failed',ierr)
  1482. endif
  1483. endif
  1484. end subroutine send_
  1485. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1486. ! Math and Computer Science Division, Argonne National Laboratory !
  1487. !BOP -------------------------------------------------------------------
  1488. !
  1489. ! !IROUTINE: recv_ - MPI Point-to-Point Receive for the List Type
  1490. !
  1491. ! !DESCRIPTION: This routine receives the output {\tt List} argument
  1492. ! {\tt outList} from processor {\tt source} on the communicator associated
  1493. ! with the fortran 90 {\tt INTEGER} handle {\tt comm}. The message is
  1494. ! tagged by the input {\tt INTEGER} argument {\tt TagBase}. The success
  1495. ! (failure) of this operation is reported in the zero (nonzero) optional
  1496. ! output argument {\tt status}.
  1497. !
  1498. ! {\bf N.B.}: One must avoid assigning elsewhere the MPI tag values
  1499. ! {\tt TagBase} and {\tt TagBase+1}. This is because {\tt recv\_()}
  1500. ! performs the receive of the {\tt List} as a pair of operations. The
  1501. ! first receive is the number of characters in {\tt outList\%bf}, and
  1502. ! is given MPI tag value {\tt TagBase}. The second receive is the
  1503. ! {\tt CHARACTER} data present in {\tt outList\%bf}, and is given MPI
  1504. ! tag value {\tt TagBase+1}.
  1505. !
  1506. ! !INTERFACE:
  1507. subroutine recv_(outList, source, TagBase, comm, status)
  1508. !
  1509. ! !USES:
  1510. !
  1511. use m_stdio, only : stderr
  1512. use m_die, only : MP_perr_die
  1513. use m_mpif90
  1514. use m_String, only : String
  1515. implicit none
  1516. ! !INPUT PARAMETERS:
  1517. !
  1518. integer, intent(in) :: source
  1519. integer, intent(in) :: TagBase
  1520. integer, intent(in) :: comm
  1521. ! !OUTPUT PARAMETERS:
  1522. !
  1523. type(List), intent(out) :: outList
  1524. integer, optional, intent(out) :: status
  1525. ! !REVISION HISTORY:
  1526. ! 6Jun01 - J.W. Larson - initial version.
  1527. ! 11Jun01 - R. Jacob - small bug fix; status in MPI_RECV
  1528. ! 13Jun01 - J.W. Larson <larson@mcs.anl.gov> - Initialize status
  1529. ! (if present).
  1530. !EOP ___________________________________________________________________
  1531. character(len=*),parameter :: myname_=myname//'::recv_'
  1532. integer :: ierr, length
  1533. integer :: MPstatus(MP_STATUS_SIZE)
  1534. type(String) :: DummStr
  1535. ! Initialize status to zero (success), if present.
  1536. if(present(status)) status = 0
  1537. ! Step 1. Receive Length of String DummStr from process source.
  1538. call MPI_RECV(length, 1, MP_type(length), source, TagBase, comm, &
  1539. MPstatus, ierr)
  1540. if(ierr /= 0) then
  1541. if(present(status)) then
  1542. write(stderr,'(2a,i8)') myname_, &
  1543. ':: MPI_RECV(length...) failed. ierror=', ierr
  1544. status = ierr
  1545. return
  1546. else
  1547. call MP_perr_die(myname_,':: MPI_RECV(length...) failed',ierr)
  1548. endif
  1549. endif
  1550. allocate(DummStr%c(length), stat=ierr)
  1551. ! Step 2. Send CHARACTER portion of String DummStr
  1552. ! to process dest.
  1553. call MPI_RECV(DummStr%c(1), length, MP_CHARACTER, source, TagBase+1, &
  1554. comm, MPstatus, ierr)
  1555. if(ierr /= 0) then
  1556. if(present(status)) then
  1557. write(stderr,'(2a,i8)') myname_, &
  1558. ':: MPI_RECV(DummStr%c...) failed. ierror=', ierr
  1559. status = ierr
  1560. return
  1561. else
  1562. call MP_perr_die(myname_,':: MPI_RECV(DummStr%c...) failed',ierr)
  1563. endif
  1564. endif
  1565. ! Step 3. Initialize outList.
  1566. call initStr_(outList, DummStr)
  1567. end subroutine recv_
  1568. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1569. ! Math and Computer Science Division, Argonne National Laboratory !
  1570. !BOP -------------------------------------------------------------------
  1571. !
  1572. ! !IROUTINE: GetSharedListIndices_ - Index Shared Items for Two Lists
  1573. !
  1574. ! !DESCRIPTION: {\tt GetSharedListIndices\_()} compares two user-
  1575. ! supplied {\tt List} arguments {\tt List1} and {\tt Lis2} to determine:
  1576. ! the number of shared items {\tt NumShared}, and arrays of the locations
  1577. ! {\tt Indices1} and {\tt Indices2} in {\tt List1} and {\tt List2},
  1578. ! respectively.
  1579. !
  1580. ! {\bf N.B.:} This routine returns two allocated arrays: {\tt Indices1(:)}
  1581. ! and {\tt Indices2(:)}. Both of these arrays must be deallocated once they
  1582. ! are no longer needed. Failure to do this will create a memory leak.
  1583. !
  1584. ! !INTERFACE:
  1585. subroutine GetSharedListIndices_(List1, List2, NumShared, Indices1, &
  1586. Indices2)
  1587. !
  1588. ! !USES:
  1589. !
  1590. use m_die, only : MP_perr_die, die, warn
  1591. use m_String, only : String
  1592. use m_String, only : String_clean => clean
  1593. implicit none
  1594. ! !INPUT PARAMETERS:
  1595. !
  1596. type(List), intent(in) :: List1
  1597. type(List), intent(in) :: List2
  1598. ! !OUTPUT PARAMETERS:
  1599. !
  1600. integer, intent(out) :: NumShared
  1601. integer,dimension(:), pointer :: Indices1
  1602. integer,dimension(:), pointer :: Indices2
  1603. ! !REVISION HISTORY:
  1604. ! 7Feb01 - J.W. Larson <larson@mcs.anl.gov> - initial version
  1605. !EOP ___________________________________________________________________
  1606. character(len=*),parameter :: myname_=myname//'::GetSharedListIndices_'
  1607. ! Error flag
  1608. integer :: ierr
  1609. ! number of items in List1 and List2, respectively:
  1610. integer :: nitem1, nitem2
  1611. ! MAXIMUM number of matches possible:
  1612. integer :: NumSharedMax
  1613. ! Temporary storage for a string tag retrieved from a list:
  1614. type(String) :: tag
  1615. ! Loop counters / temporary indices:
  1616. integer :: n1, n2
  1617. ! Determine the number of items in each list:
  1618. nitem1 = nitem_(List1)
  1619. nitem2 = nitem_(List2)
  1620. ! The maximum number of list item matches possible
  1621. ! is the minimum(nitem1,nitem2):
  1622. NumSharedMax = min(nitem1,nitem2)
  1623. ! Allocate sufficient space for the matches we may find:
  1624. allocate(Indices1(NumSharedMax), Indices2(NumSharedMax), stat=ierr)
  1625. if(ierr /= 0) call die(myname_,'allocate() Indices1 and 2',ierr)
  1626. ! Initialize the counter for the number of matches found:
  1627. NumShared = 0
  1628. ! Scan through the two lists. For the sake of speed, loop
  1629. ! over the shorter of the two lists...
  1630. if(nitem1 <= nitem2) then ! List1 is shorter--scan it...
  1631. do n1=1,NumSharedMax
  1632. ! Retrieve string tag n1 from List1:
  1633. call get_(tag, n1, List1)
  1634. ! Index this tag WRT List2--a nonzero value signifies a match
  1635. n2 = indexStr_(List2, tag)
  1636. ! Clear out tag for the next iteration...
  1637. call String_clean(tag)
  1638. ! If we have a hit, update NumShared, and load the indices
  1639. ! n1 and n2 in Indices1 and Indices2, respectively...
  1640. if((0 < n2) .and. (n2 <= nitem2)) then
  1641. NumShared = NumShared + 1
  1642. Indices1(NumShared) = n1
  1643. Indices2(NumShared) = n2
  1644. endif
  1645. end do ! do n1=1,NumSharedMax
  1646. else ! List1 is shorter--scan it...
  1647. do n2=1,NumSharedMax
  1648. ! Retrieve string tag n2 from List2:
  1649. call get_(tag, n2, List2)
  1650. ! Index this tag WRT List1--a nonzero value signifies a match
  1651. n1 = indexStr_(List1, tag)
  1652. ! Clear out tag for the next iteration...
  1653. call String_clean(tag)
  1654. ! If we have a hit, update NumShared, and load the indices
  1655. ! n1 and n2 in Indices1 and Indices2, respectively...
  1656. if((0 < n1) .and. (n1 <= nitem1)) then
  1657. NumShared = NumShared + 1
  1658. Indices1(NumShared) = n1
  1659. Indices2(NumShared) = n2
  1660. endif
  1661. end do ! do n2=1,NumSharedMax
  1662. endif ! if(nitem1 <= nitem2)...
  1663. end subroutine GetSharedListIndices_
  1664. end module m_List
  1665. !.