mod_oasis_mpi.F90 101 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969
  1. !> Provides a generic and simpler interface into MPI calls for OASIS.
  2. MODULE mod_oasis_mpi
  3. !-------------------------------------------------------------------------------
  4. ! PURPOSE: general layer on MPI functions
  5. !-------------------------------------------------------------------------------
  6. use mod_oasis_kinds
  7. USE mod_oasis_data ,ONLY: nulprt, OASIS_Debug
  8. USE mod_oasis_sys ,ONLY: oasis_debug_enter, oasis_debug_exit, oasis_flush, oasis_abort, astr
  9. USE mod_oasis_timer,ONLY: oasis_timer_start, oasis_timer_stop
  10. implicit none
  11. private
  12. ! PUBLIC: Public interfaces
  13. public :: oasis_mpi_chkerr
  14. public :: oasis_mpi_send
  15. public :: oasis_mpi_recv
  16. public :: oasis_mpi_bcast
  17. public :: oasis_mpi_gathScatVInit
  18. public :: oasis_mpi_gatherV
  19. public :: oasis_mpi_scatterV
  20. public :: oasis_mpi_sum
  21. public :: oasis_mpi_min
  22. public :: oasis_mpi_max
  23. public :: oasis_mpi_commsize
  24. public :: oasis_mpi_commrank
  25. public :: oasis_mpi_initialized
  26. public :: oasis_mpi_wtime
  27. public :: oasis_mpi_abort
  28. public :: oasis_mpi_barrier
  29. public :: oasis_mpi_init
  30. public :: oasis_mpi_finalize
  31. public :: oasis_mpi_reducelists
  32. !> Generic overloaded interface into MPI send
  33. interface oasis_mpi_send ; module procedure &
  34. oasis_mpi_sendi0, &
  35. oasis_mpi_sendi1, &
  36. oasis_mpi_sendr0, &
  37. oasis_mpi_sendr1, &
  38. oasis_mpi_sendr3
  39. end interface
  40. !> Generic overloaded interface into MPI receive
  41. interface oasis_mpi_recv ; module procedure &
  42. oasis_mpi_recvi0, &
  43. oasis_mpi_recvi1, &
  44. oasis_mpi_recvr0, &
  45. oasis_mpi_recvr1, &
  46. oasis_mpi_recvr3
  47. end interface
  48. !> Generic overloaded interface into MPI broadcast
  49. interface oasis_mpi_bcast ; module procedure &
  50. oasis_mpi_bcastc0, &
  51. oasis_mpi_bcastc1, &
  52. oasis_mpi_bcastl0, &
  53. oasis_mpi_bcastl1, &
  54. oasis_mpi_bcasti0, &
  55. oasis_mpi_bcasti1, &
  56. oasis_mpi_bcasti2, &
  57. oasis_mpi_bcastr0, &
  58. oasis_mpi_bcastr1, &
  59. oasis_mpi_bcastr2, &
  60. oasis_mpi_bcastr3
  61. end interface
  62. !> Generic interface to oasis_mpi_gathScatVInit
  63. interface oasis_mpi_gathScatVInit ; module procedure &
  64. oasis_mpi_gathScatVInitr1
  65. end interface
  66. !> Generic interfaces into an MPI vector gather
  67. interface oasis_mpi_gatherv ; module procedure &
  68. oasis_mpi_gatherVr1
  69. end interface
  70. !> Generic interfaces into an MPI vector scatter
  71. interface oasis_mpi_scatterv ; module procedure &
  72. oasis_mpi_scatterVr1
  73. end interface
  74. !> Generic overloaded interface into MPI sum reduction
  75. interface oasis_mpi_sum ; module procedure &
  76. oasis_mpi_sumi0, &
  77. oasis_mpi_sumi1, &
  78. oasis_mpi_sumb0, &
  79. oasis_mpi_sumb1, &
  80. oasis_mpi_sumr0, &
  81. oasis_mpi_sumr1, &
  82. oasis_mpi_sumr2, &
  83. oasis_mpi_sumr3
  84. end interface
  85. !> Generic overloaded interface into MPI min reduction
  86. interface oasis_mpi_min ; module procedure &
  87. oasis_mpi_mini0, &
  88. oasis_mpi_mini1, &
  89. oasis_mpi_minr0, &
  90. oasis_mpi_minr1
  91. end interface
  92. !> Generic overloaded interface into MPI max reduction
  93. interface oasis_mpi_max ; module procedure &
  94. oasis_mpi_maxi0, &
  95. oasis_mpi_maxi1, &
  96. oasis_mpi_maxr0, &
  97. oasis_mpi_maxr1
  98. end interface
  99. ! mpi library include file
  100. #include <mpif.h>
  101. !===============================================================================
  102. CONTAINS
  103. !===============================================================================
  104. !> Checks MPI error codes and aborts
  105. !> This method compares rcode to MPI_SUCCESS. If rcode is an error,
  106. !> it queries MPI_ERROR_STRING for the error string associated with rcode, writes
  107. !> it out, and aborts with the string passed through the interface.
  108. SUBROUTINE oasis_mpi_chkerr(rcode,string)
  109. IMPLICIT none
  110. !----- arguments ---
  111. integer(ip_i4_p), intent(in) :: rcode !< MPI error code
  112. character(*), intent(in) :: string !< abort message
  113. !----- local ---
  114. character(*),parameter :: subname = '(oasis_mpi_chkerr)'
  115. character(MPI_MAX_ERROR_STRING) :: lstring
  116. integer(ip_i4_p) :: len
  117. integer(ip_i4_p) :: ierr
  118. !-------------------------------------------------------------------------------
  119. ! PURPOSE: layer on MPI error checking
  120. !-------------------------------------------------------------------------------
  121. call oasis_debug_enter(subname)
  122. lstring = ' '
  123. if (rcode /= MPI_SUCCESS) then
  124. call MPI_ERROR_STRING(rcode,lstring,len,ierr)
  125. call oasis_mpi_abort(subname//trim(string)//':'//trim(lstring),rcode)
  126. endif
  127. call oasis_debug_exit(subname)
  128. END SUBROUTINE oasis_mpi_chkerr
  129. !===============================================================================
  130. !===============================================================================
  131. !> Send a scalar integer
  132. SUBROUTINE oasis_mpi_sendi0(lvec,pid,tag,comm,string)
  133. IMPLICIT none
  134. !----- arguments ---
  135. integer(ip_i4_p), intent(in) :: lvec !< send value
  136. integer(ip_i4_p), intent(in) :: pid !< pid to send to
  137. integer(ip_i4_p), intent(in) :: tag !< tag
  138. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  139. character(*),optional,intent(in) :: string !< to identify caller
  140. !----- local ---
  141. character(*),parameter :: subname = '(oasis_mpi_sendi0)'
  142. integer(ip_i4_p) :: lsize
  143. integer(ip_i4_p) :: ierr
  144. !-------------------------------------------------------------------------------
  145. ! PURPOSE: Send a single integer
  146. !-------------------------------------------------------------------------------
  147. call oasis_debug_enter(subname)
  148. lsize = 1
  149. call MPI_SEND(lvec,lsize,MPI_INTEGER,pid,tag,comm,ierr)
  150. if (present(string)) then
  151. call oasis_mpi_chkerr(ierr,subName//trim(string))
  152. else
  153. call oasis_mpi_chkerr(ierr,subName)
  154. endif
  155. call oasis_debug_exit(subname)
  156. END SUBROUTINE oasis_mpi_sendi0
  157. !===============================================================================
  158. !===============================================================================
  159. !> Send an array of 1D integers
  160. SUBROUTINE oasis_mpi_sendi1(lvec,pid,tag,comm,string)
  161. IMPLICIT none
  162. !----- arguments ---
  163. integer(ip_i4_p), intent(in) :: lvec(:) !< send values
  164. integer(ip_i4_p), intent(in) :: pid !< pid to send to
  165. integer(ip_i4_p), intent(in) :: tag !< tag
  166. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  167. character(*),optional,intent(in) :: string !< to identify caller
  168. !----- local ---
  169. character(*),parameter :: subname = '(oasis_mpi_sendi1)'
  170. integer(ip_i4_p) :: lsize
  171. integer(ip_i4_p) :: ierr
  172. !-------------------------------------------------------------------------------
  173. ! PURPOSE: Send a vector of integers
  174. !-------------------------------------------------------------------------------
  175. call oasis_debug_enter(subname)
  176. lsize = size(lvec)
  177. call MPI_SEND(lvec,lsize,MPI_INTEGER,pid,tag,comm,ierr)
  178. if (present(string)) then
  179. call oasis_mpi_chkerr(ierr,subName//trim(string))
  180. else
  181. call oasis_mpi_chkerr(ierr,subName)
  182. endif
  183. call oasis_debug_exit(subname)
  184. END SUBROUTINE oasis_mpi_sendi1
  185. !===============================================================================
  186. !===============================================================================
  187. !> Send a scalar double
  188. SUBROUTINE oasis_mpi_sendr0(lvec,pid,tag,comm,string)
  189. IMPLICIT none
  190. !----- arguments ---
  191. real(ip_double_p),intent(in) :: lvec !< send values
  192. integer(ip_i4_p), intent(in) :: pid !< pid to send to
  193. integer(ip_i4_p), intent(in) :: tag !< tag
  194. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  195. character(*),optional,intent(in) :: string !< to identify caller
  196. !----- local ---
  197. character(*),parameter :: subname = '(oasis_mpi_sendr0)'
  198. integer(ip_i4_p) :: lsize
  199. integer(ip_i4_p) :: ierr
  200. !-------------------------------------------------------------------------------
  201. ! PURPOSE: Send a real scalar
  202. !-------------------------------------------------------------------------------
  203. call oasis_debug_enter(subname)
  204. lsize = 1
  205. call MPI_SEND(lvec,lsize,MPI_REAL8,pid,tag,comm,ierr)
  206. if (present(string)) then
  207. call oasis_mpi_chkerr(ierr,subName//trim(string))
  208. else
  209. call oasis_mpi_chkerr(ierr,subName)
  210. endif
  211. call oasis_debug_exit(subname)
  212. END SUBROUTINE oasis_mpi_sendr0
  213. !===============================================================================
  214. !===============================================================================
  215. !> Send an array of 1D doubles
  216. SUBROUTINE oasis_mpi_sendr1(lvec,pid,tag,comm,string)
  217. IMPLICIT none
  218. !----- arguments ---
  219. real(ip_double_p),intent(in) :: lvec(:) !< send values
  220. integer(ip_i4_p), intent(in) :: pid !< pid to send to
  221. integer(ip_i4_p), intent(in) :: tag !< tag
  222. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  223. character(*),optional,intent(in) :: string !< to identify caller
  224. !----- local ---
  225. character(*),parameter :: subname = '(oasis_mpi_sendr1)'
  226. integer(ip_i4_p) :: lsize
  227. integer(ip_i4_p) :: ierr
  228. !-------------------------------------------------------------------------------
  229. ! PURPOSE: Send a vector of reals
  230. !-------------------------------------------------------------------------------
  231. call oasis_debug_enter(subname)
  232. lsize = size(lvec)
  233. call MPI_SEND(lvec,lsize,MPI_REAL8,pid,tag,comm,ierr)
  234. if (present(string)) then
  235. call oasis_mpi_chkerr(ierr,subName//trim(string))
  236. else
  237. call oasis_mpi_chkerr(ierr,subName)
  238. endif
  239. call oasis_debug_exit(subname)
  240. END SUBROUTINE oasis_mpi_sendr1
  241. !===============================================================================
  242. !===============================================================================
  243. !> Send an array of 3D doubles
  244. SUBROUTINE oasis_mpi_sendr3(array,pid,tag,comm,string)
  245. IMPLICIT none
  246. !----- arguments ---
  247. real(ip_double_p),intent(in) :: array(:,:,:) !< send values
  248. integer(ip_i4_p), intent(in) :: pid !< pid to send to
  249. integer(ip_i4_p), intent(in) :: tag !< tag
  250. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  251. character(*),optional,intent(in) :: string !< to identify caller
  252. !----- local ---
  253. character(*),parameter :: subname = '(oasis_mpi_sendr3)'
  254. integer(ip_i4_p) :: lsize
  255. integer(ip_i4_p) :: ierr
  256. !-------------------------------------------------------------------------------
  257. ! PURPOSE: Send a vector of reals
  258. !-------------------------------------------------------------------------------
  259. call oasis_debug_enter(subname)
  260. lsize = size(array)
  261. call MPI_SEND(array,lsize,MPI_REAL8,pid,tag,comm,ierr)
  262. if (present(string)) then
  263. call oasis_mpi_chkerr(ierr,subName//trim(string))
  264. else
  265. call oasis_mpi_chkerr(ierr,subName)
  266. endif
  267. call oasis_debug_exit(subname)
  268. END SUBROUTINE oasis_mpi_sendr3
  269. !===============================================================================
  270. !===============================================================================
  271. !> Receive a scalar integer
  272. SUBROUTINE oasis_mpi_recvi0(lvec,pid,tag,comm,string)
  273. IMPLICIT none
  274. !----- arguments ---
  275. integer(ip_i4_p), intent(out):: lvec !< receive values
  276. integer(ip_i4_p), intent(in) :: pid !< pid to recv from
  277. integer(ip_i4_p), intent(in) :: tag !< tag
  278. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  279. character(*),optional,intent(in) :: string !< to identify caller
  280. !----- local ---
  281. character(*),parameter :: subname = '(oasis_mpi_recvi0)'
  282. integer(ip_i4_p) :: lsize
  283. integer(ip_i4_p) :: status(MPI_STATUS_SIZE) ! mpi status info
  284. integer(ip_i4_p) :: ierr
  285. !-------------------------------------------------------------------------------
  286. ! PURPOSE: Recv a vector of reals
  287. !-------------------------------------------------------------------------------
  288. call oasis_debug_enter(subname)
  289. lsize = 1
  290. call MPI_RECV(lvec,lsize,MPI_INTEGER,pid,tag,comm,status,ierr)
  291. if (present(string)) then
  292. call oasis_mpi_chkerr(ierr,subName//trim(string))
  293. else
  294. call oasis_mpi_chkerr(ierr,subName)
  295. endif
  296. call oasis_debug_exit(subname)
  297. END SUBROUTINE oasis_mpi_recvi0
  298. !===============================================================================
  299. !===============================================================================
  300. !> Receive an array of 1D integers
  301. SUBROUTINE oasis_mpi_recvi1(lvec,pid,tag,comm,string)
  302. IMPLICIT none
  303. !----- arguments ---
  304. integer(ip_i4_p), intent(out):: lvec(:) !< receive values
  305. integer(ip_i4_p), intent(in) :: pid !< pid to recv from
  306. integer(ip_i4_p), intent(in) :: tag !< tag
  307. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  308. character(*),optional,intent(in) :: string !< to identify caller
  309. !----- local ---
  310. character(*),parameter :: subname = '(oasis_mpi_recvi1)'
  311. integer(ip_i4_p) :: lsize
  312. integer(ip_i4_p) :: status(MPI_STATUS_SIZE) ! mpi status info
  313. integer(ip_i4_p) :: ierr
  314. !-------------------------------------------------------------------------------
  315. ! PURPOSE: Recv a vector of reals
  316. !-------------------------------------------------------------------------------
  317. call oasis_debug_enter(subname)
  318. lsize = size(lvec)
  319. call MPI_RECV(lvec,lsize,MPI_INTEGER,pid,tag,comm,status,ierr)
  320. if (present(string)) then
  321. call oasis_mpi_chkerr(ierr,subName//trim(string))
  322. else
  323. call oasis_mpi_chkerr(ierr,subName)
  324. endif
  325. call oasis_debug_exit(subname)
  326. END SUBROUTINE oasis_mpi_recvi1
  327. !===============================================================================
  328. !===============================================================================
  329. !> Receive a scalar double
  330. SUBROUTINE oasis_mpi_recvr0(lvec,pid,tag,comm,string)
  331. IMPLICIT none
  332. !----- arguments ---
  333. real(ip_double_p),intent(out):: lvec !< receive values
  334. integer(ip_i4_p), intent(in) :: pid !< pid to recv from
  335. integer(ip_i4_p), intent(in) :: tag !< tag
  336. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  337. character(*),optional,intent(in) :: string !< to identify caller
  338. !----- local ---
  339. character(*),parameter :: subname = '(oasis_mpi_recvr0)'
  340. integer(ip_i4_p) :: lsize
  341. integer(ip_i4_p) :: status(MPI_STATUS_SIZE) ! mpi status info
  342. integer(ip_i4_p) :: ierr
  343. !-------------------------------------------------------------------------------
  344. ! PURPOSE: Recv a vector of reals
  345. !-------------------------------------------------------------------------------
  346. call oasis_debug_enter(subname)
  347. lsize = 1
  348. call MPI_RECV(lvec,lsize,MPI_REAL8,pid,tag,comm,status,ierr)
  349. if (present(string)) then
  350. call oasis_mpi_chkerr(ierr,subName//trim(string))
  351. else
  352. call oasis_mpi_chkerr(ierr,subName)
  353. endif
  354. call oasis_debug_exit(subname)
  355. END SUBROUTINE oasis_mpi_recvr0
  356. !===============================================================================
  357. !===============================================================================
  358. !> Receive an array of 1D doubles
  359. SUBROUTINE oasis_mpi_recvr1(lvec,pid,tag,comm,string)
  360. IMPLICIT none
  361. !----- arguments ---
  362. real(ip_double_p),intent(out):: lvec(:) !< receive values
  363. integer(ip_i4_p), intent(in) :: pid !< pid to recv from
  364. integer(ip_i4_p), intent(in) :: tag !< tag
  365. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  366. character(*),optional,intent(in) :: string !< to identify caller
  367. !----- local ---
  368. character(*),parameter :: subname = '(oasis_mpi_recvr1)'
  369. integer(ip_i4_p) :: lsize
  370. integer(ip_i4_p) :: status(MPI_STATUS_SIZE) ! mpi status info
  371. integer(ip_i4_p) :: ierr
  372. !-------------------------------------------------------------------------------
  373. ! PURPOSE: Recv a vector of reals
  374. !-------------------------------------------------------------------------------
  375. call oasis_debug_enter(subname)
  376. lsize = size(lvec)
  377. call MPI_RECV(lvec,lsize,MPI_REAL8,pid,tag,comm,status,ierr)
  378. if (present(string)) then
  379. call oasis_mpi_chkerr(ierr,subName//trim(string))
  380. else
  381. call oasis_mpi_chkerr(ierr,subName)
  382. endif
  383. call oasis_debug_exit(subname)
  384. END SUBROUTINE oasis_mpi_recvr1
  385. !===============================================================================
  386. !===============================================================================
  387. !> Receive an array of 3D doubles
  388. SUBROUTINE oasis_mpi_recvr3(array,pid,tag,comm,string)
  389. IMPLICIT none
  390. !----- arguments ---
  391. real(ip_double_p),intent(out):: array(:,:,:) !< receive values
  392. integer(ip_i4_p), intent(in) :: pid !< pid to recv from
  393. integer(ip_i4_p), intent(in) :: tag !< tag
  394. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  395. character(*),optional,intent(in) :: string !< to identify caller
  396. !----- local ---
  397. character(*),parameter :: subname = '(oasis_mpi_recvr3)'
  398. integer(ip_i4_p) :: lsize
  399. integer(ip_i4_p) :: status(MPI_STATUS_SIZE) ! mpi status info
  400. integer(ip_i4_p) :: ierr
  401. !-------------------------------------------------------------------------------
  402. ! PURPOSE: Recv a vector of reals
  403. !-------------------------------------------------------------------------------
  404. call oasis_debug_enter(subname)
  405. lsize = size(array)
  406. call MPI_RECV(array,lsize,MPI_REAL8,pid,tag,comm,status,ierr)
  407. if (present(string)) then
  408. call oasis_mpi_chkerr(ierr,subName//trim(string))
  409. else
  410. call oasis_mpi_chkerr(ierr,subName)
  411. endif
  412. call oasis_debug_exit(subname)
  413. END SUBROUTINE oasis_mpi_recvr3
  414. !===============================================================================
  415. !===============================================================================
  416. !> Broadcast a scalar integer
  417. SUBROUTINE oasis_mpi_bcasti0(vec,comm,string,pebcast)
  418. IMPLICIT none
  419. !----- arguments ---
  420. integer(ip_i4_p), intent(inout):: vec !< values to broadcast
  421. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  422. character(*),optional,intent(in) :: string !< to identify caller
  423. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  424. !----- local ---
  425. character(*),parameter :: subname = '(oasis_mpi_bcasti0)'
  426. integer(ip_i4_p) :: ierr
  427. integer(ip_i4_p) :: lsize
  428. integer(ip_i4_p) :: lpebcast
  429. !-------------------------------------------------------------------------------
  430. ! PURPOSE: Broadcast an integer
  431. !-------------------------------------------------------------------------------
  432. call oasis_debug_enter(subname)
  433. lsize = 1
  434. lpebcast = 0
  435. if (present(pebcast)) lpebcast = pebcast
  436. call MPI_BCAST(vec,lsize,MPI_INTEGER,lpebcast,comm,ierr)
  437. if (present(string)) then
  438. call oasis_mpi_chkerr(ierr,subName//trim(string))
  439. else
  440. call oasis_mpi_chkerr(ierr,subName)
  441. endif
  442. call oasis_debug_exit(subname)
  443. END SUBROUTINE oasis_mpi_bcasti0
  444. !===============================================================================
  445. !===============================================================================
  446. !> Broadcast a scalar logical
  447. SUBROUTINE oasis_mpi_bcastl0(vec,comm,string,pebcast)
  448. IMPLICIT none
  449. !----- arguments ---
  450. logical, intent(inout):: vec !< values to broadcast
  451. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  452. character(*),optional,intent(in) :: string !< to identify caller
  453. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  454. !----- local ---
  455. character(*),parameter :: subname = '(oasis_mpi_bcastl0)'
  456. integer(ip_i4_p) :: ierr
  457. integer(ip_i4_p) :: lsize
  458. integer(ip_i4_p) :: lpebcast
  459. !-------------------------------------------------------------------------------
  460. ! PURPOSE: Broadcast a logical
  461. !-------------------------------------------------------------------------------
  462. call oasis_debug_enter(subname)
  463. lsize = 1
  464. lpebcast = 0
  465. if (present(pebcast)) lpebcast = pebcast
  466. call MPI_BCAST(vec,lsize,MPI_LOGICAL,lpebcast,comm,ierr)
  467. if (present(string)) then
  468. call oasis_mpi_chkerr(ierr,subName//trim(string))
  469. else
  470. call oasis_mpi_chkerr(ierr,subName)
  471. endif
  472. call oasis_debug_exit(subname)
  473. END SUBROUTINE oasis_mpi_bcastl0
  474. !===============================================================================
  475. !===============================================================================
  476. !> Broadcast a character string
  477. SUBROUTINE oasis_mpi_bcastc0(vec,comm,string,pebcast)
  478. IMPLICIT none
  479. !----- arguments ---
  480. character(len=*), intent(inout):: vec !< values to broadcast
  481. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  482. character(*),optional,intent(in) :: string !< to identify caller
  483. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  484. !----- local ---
  485. character(*),parameter :: subname = '(oasis_mpi_bcastc0)'
  486. integer(ip_i4_p) :: ierr
  487. integer(ip_i4_p) :: lsize
  488. integer(ip_i4_p) :: lpebcast
  489. !-------------------------------------------------------------------------------
  490. ! PURPOSE: Broadcast a character string
  491. !-------------------------------------------------------------------------------
  492. call oasis_debug_enter(subname)
  493. lsize = len(vec)
  494. lpebcast = 0
  495. if (present(pebcast)) lpebcast = pebcast
  496. call MPI_BCAST(vec,lsize,MPI_CHARACTER,lpebcast,comm,ierr)
  497. if (present(string)) then
  498. call oasis_mpi_chkerr(ierr,subName//trim(string))
  499. else
  500. call oasis_mpi_chkerr(ierr,subName)
  501. endif
  502. call oasis_debug_exit(subname)
  503. END SUBROUTINE oasis_mpi_bcastc0
  504. !===============================================================================
  505. !===============================================================================
  506. !> Broadcast an array of 1D character strings
  507. SUBROUTINE oasis_mpi_bcastc1(vec,comm,string,pebcast)
  508. IMPLICIT none
  509. !----- arguments ---
  510. character(len=*), intent(inout):: vec(:) !< values to broadcast
  511. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  512. character(*),optional,intent(in) :: string !< to identify caller
  513. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  514. !----- local ---
  515. character(*),parameter :: subname = '(oasis_mpi_bcastc1)'
  516. integer(ip_i4_p) :: ierr
  517. integer(ip_i4_p) :: lsize
  518. integer(ip_i4_p) :: lpebcast
  519. !-------------------------------------------------------------------------------
  520. ! PURPOSE: Broadcast a character string
  521. !-------------------------------------------------------------------------------
  522. call oasis_debug_enter(subname)
  523. lsize = size(vec)*len(vec)
  524. lpebcast = 0
  525. if (present(pebcast)) lpebcast = pebcast
  526. call MPI_BCAST(vec,lsize,MPI_CHARACTER,lpebcast,comm,ierr)
  527. if (present(string)) then
  528. call oasis_mpi_chkerr(ierr,subName//trim(string))
  529. else
  530. call oasis_mpi_chkerr(ierr,subName)
  531. endif
  532. call oasis_debug_exit(subname)
  533. END SUBROUTINE oasis_mpi_bcastc1
  534. !===============================================================================
  535. !===============================================================================
  536. !> Broadcast a scalar double
  537. SUBROUTINE oasis_mpi_bcastr0(vec,comm,string,pebcast)
  538. IMPLICIT none
  539. !----- arguments ---
  540. real(ip_double_p), intent(inout):: vec !< values to broadcast
  541. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  542. character(*),optional,intent(in) :: string !< to identify caller
  543. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  544. !----- local ---
  545. character(*),parameter :: subname = '(oasis_mpi_bcastr0)'
  546. integer(ip_i4_p) :: ierr
  547. integer(ip_i4_p) :: lsize
  548. integer(ip_i4_p) :: lpebcast
  549. !-------------------------------------------------------------------------------
  550. ! PURPOSE: Broadcast a real
  551. !-------------------------------------------------------------------------------
  552. call oasis_debug_enter(subname)
  553. lsize = 1
  554. lpebcast = 0
  555. if (present(pebcast)) lpebcast = pebcast
  556. call MPI_BCAST(vec,lsize,MPI_REAL8,lpebcast,comm,ierr)
  557. if (present(string)) then
  558. call oasis_mpi_chkerr(ierr,subName//trim(string))
  559. else
  560. call oasis_mpi_chkerr(ierr,subName)
  561. endif
  562. call oasis_debug_exit(subname)
  563. END SUBROUTINE oasis_mpi_bcastr0
  564. !===============================================================================
  565. !===============================================================================
  566. !> Broadcast an array of 1D integers
  567. SUBROUTINE oasis_mpi_bcasti1(vec,comm,string,pebcast)
  568. IMPLICIT none
  569. !----- arguments ---
  570. integer(ip_i4_p), intent(inout):: vec(:) !< values to broadcast
  571. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  572. character(*),optional,intent(in) :: string !< to identify caller
  573. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  574. !----- local ---
  575. character(*),parameter :: subname = '(oasis_mpi_bcasti1)'
  576. integer(ip_i4_p) :: ierr
  577. integer(ip_i4_p) :: lsize
  578. integer(ip_i4_p) :: lpebcast
  579. !-------------------------------------------------------------------------------
  580. ! PURPOSE: Broadcast a vector of integers
  581. !-------------------------------------------------------------------------------
  582. call oasis_debug_enter(subname)
  583. lsize = size(vec)
  584. lpebcast = 0
  585. if (present(pebcast)) lpebcast = pebcast
  586. call MPI_BCAST(vec,lsize,MPI_INTEGER,lpebcast,comm,ierr)
  587. if (present(string)) then
  588. call oasis_mpi_chkerr(ierr,subName//trim(string))
  589. else
  590. call oasis_mpi_chkerr(ierr,subName)
  591. endif
  592. call oasis_debug_exit(subname)
  593. END SUBROUTINE oasis_mpi_bcasti1
  594. !===============================================================================
  595. !===============================================================================
  596. !> Broadcast an array of 1D logicals
  597. SUBROUTINE oasis_mpi_bcastl1(vec,comm,string,pebcast)
  598. IMPLICIT none
  599. !----- arguments ---
  600. logical, intent(inout):: vec(:) !< values to broadcast
  601. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  602. character(*),optional,intent(in) :: string !< to identify caller
  603. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  604. !----- local ---
  605. character(*),parameter :: subname = '(oasis_mpi_bcastl1)'
  606. integer(ip_i4_p) :: ierr
  607. integer(ip_i4_p) :: lsize
  608. integer(ip_i4_p) :: lpebcast
  609. !-------------------------------------------------------------------------------
  610. ! PURPOSE: Broadcast a logical
  611. !-------------------------------------------------------------------------------
  612. call oasis_debug_enter(subname)
  613. lsize = size(vec)
  614. lpebcast = 0
  615. if (present(pebcast)) lpebcast = pebcast
  616. call MPI_BCAST(vec,lsize,MPI_LOGICAL,lpebcast,comm,ierr)
  617. if (present(string)) then
  618. call oasis_mpi_chkerr(ierr,subName//trim(string))
  619. else
  620. call oasis_mpi_chkerr(ierr,subName)
  621. endif
  622. call oasis_debug_exit(subname)
  623. END SUBROUTINE oasis_mpi_bcastl1
  624. !===============================================================================
  625. !===============================================================================
  626. !> Broadcast an array of 1D doubles
  627. SUBROUTINE oasis_mpi_bcastr1(vec,comm,string,pebcast)
  628. IMPLICIT none
  629. !----- arguments ---
  630. real(ip_double_p), intent(inout):: vec(:) !< values to broadcast
  631. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  632. character(*),optional,intent(in) :: string !< to identify caller
  633. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  634. !----- local ---
  635. character(*),parameter :: subname = '(oasis_mpi_bcastr1)'
  636. integer(ip_i4_p) :: ierr
  637. integer(ip_i4_p) :: lsize
  638. integer(ip_i4_p) :: lpebcast
  639. !-------------------------------------------------------------------------------
  640. ! PURPOSE: Broadcast a vector of reals
  641. !-------------------------------------------------------------------------------
  642. call oasis_debug_enter(subname)
  643. lsize = size(vec)
  644. lpebcast = 0
  645. if (present(pebcast)) lpebcast = pebcast
  646. call MPI_BCAST(vec,lsize,MPI_REAL8,lpebcast,comm,ierr)
  647. if (present(string)) then
  648. call oasis_mpi_chkerr(ierr,subName//trim(string))
  649. else
  650. call oasis_mpi_chkerr(ierr,subName)
  651. endif
  652. call oasis_debug_exit(subname)
  653. END SUBROUTINE oasis_mpi_bcastr1
  654. !===============================================================================
  655. !===============================================================================
  656. !> Broadcast an array of 2D doubles
  657. SUBROUTINE oasis_mpi_bcastr2(arr,comm,string,pebcast)
  658. IMPLICIT none
  659. !----- arguments -----
  660. real(ip_double_p), intent(inout):: arr(:,:) !< values to broadcast
  661. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  662. character(*),optional,intent(in) :: string !< to identify caller
  663. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  664. !----- local -----
  665. integer(ip_i4_p) :: ierr
  666. integer(ip_i4_p) :: lsize
  667. integer(ip_i4_p) :: lpebcast
  668. !----- formats -----
  669. character(*),parameter :: subname = '(oasis_mpi_bcastr2)'
  670. !-------------------------------------------------------------------------------
  671. ! PURPOSE: Broadcast a 2d array of reals
  672. !-------------------------------------------------------------------------------
  673. call oasis_debug_enter(subname)
  674. lsize = size(arr)
  675. lpebcast = 0
  676. if (present(pebcast)) lpebcast = pebcast
  677. call MPI_BCAST(arr,lsize,MPI_REAL8,lpebcast,comm,ierr)
  678. if (present(string)) then
  679. call oasis_mpi_chkerr(ierr,subName//trim(string))
  680. else
  681. call oasis_mpi_chkerr(ierr,subName)
  682. endif
  683. call oasis_debug_exit(subname)
  684. END SUBROUTINE oasis_mpi_bcastr2
  685. !===============================================================================
  686. !===============================================================================
  687. !> Broadcast an array of 2D integers
  688. SUBROUTINE oasis_mpi_bcasti2(arr,comm,string,pebcast)
  689. IMPLICIT none
  690. !----- arguments -----
  691. integer, intent(inout):: arr(:,:) !< values to broadcast
  692. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  693. character(*),optional,intent(in) :: string !< to identify caller
  694. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  695. !----- local -----
  696. integer(ip_i4_p) :: ierr
  697. integer(ip_i4_p) :: lsize
  698. integer(ip_i4_p) :: lpebcast
  699. !----- formats -----
  700. character(*),parameter :: subname = '(oasis_mpi_bcasti2)'
  701. !-------------------------------------------------------------------------------
  702. ! PURPOSE: Broadcast a 2d array of integers
  703. !-------------------------------------------------------------------------------
  704. call oasis_debug_enter(subname)
  705. lsize = size(arr)
  706. lpebcast = 0
  707. if (present(pebcast)) lpebcast = pebcast
  708. call MPI_BCAST(arr,lsize,MPI_INTEGER,lpebcast,comm,ierr)
  709. if (present(string)) then
  710. call oasis_mpi_chkerr(ierr,subName//trim(string))
  711. else
  712. call oasis_mpi_chkerr(ierr,subName)
  713. endif
  714. call oasis_debug_exit(subname)
  715. END SUBROUTINE oasis_mpi_bcasti2
  716. !===============================================================================
  717. !===============================================================================
  718. !> Broadcast an array of 3D doubles
  719. SUBROUTINE oasis_mpi_bcastr3(arr,comm,string,pebcast)
  720. IMPLICIT none
  721. !----- arguments -----
  722. real(ip_double_p), intent(inout):: arr(:,:,:) !< values to broadcast
  723. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  724. character(*),optional,intent(in) :: string !< to identify caller
  725. integer(ip_i4_p), optional, intent(in) :: pebcast !< bcast pe, default is task 0
  726. !----- local -----
  727. integer(ip_i4_p) :: ierr
  728. integer(ip_i4_p) :: lsize
  729. integer(ip_i4_p) :: lpebcast
  730. !----- formats -----
  731. character(*),parameter :: subname = '(oasis_mpi_bcastr3)'
  732. !-------------------------------------------------------------------------------
  733. ! PURPOSE: Broadcast a 3d array of reals
  734. !-------------------------------------------------------------------------------
  735. call oasis_debug_enter(subname)
  736. lsize = size(arr)
  737. lpebcast = 0
  738. if (present(pebcast)) lpebcast = pebcast
  739. call MPI_BCAST(arr,lsize,MPI_REAL8,lpebcast,comm,ierr)
  740. if (present(string)) then
  741. call oasis_mpi_chkerr(ierr,subName//trim(string))
  742. else
  743. call oasis_mpi_chkerr(ierr,subName)
  744. endif
  745. call oasis_debug_exit(subname)
  746. END SUBROUTINE oasis_mpi_bcastr3
  747. !===============================================================================
  748. !===============================================================================
  749. !> Initialize variables for oasis_mpi_gatherv and oasis_mpi_scatterv
  750. !> This method initializes glob1DArr, globSize, and displs for use
  751. !> in the oasis_mpi_gatherv and oasis_mpi_scatterv routines. locArr is the
  752. !> distributed array to gather from or scatter to.
  753. SUBROUTINE oasis_mpi_gathScatvInitr1(comm, rootid, locArr, glob1DArr, globSize, &
  754. displs, string )
  755. IMPLICIT none
  756. !----- arguments -----
  757. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  758. integer(ip_i4_p), intent(in) :: rootid !< MPI task to gather/scatter on
  759. real(ip_double_p),intent(in) :: locArr(:) !< Local array of distributed data
  760. real(ip_double_p),pointer :: glob1DArr(:) !< Global 1D array of gathered data
  761. integer(ip_i4_p), pointer :: globSize(:) !< Size of each distributed piece
  762. integer(ip_i4_p), pointer :: displs(:) !< Displacements for receive
  763. character(*),optional,intent(in):: string !< to identify caller
  764. !----- local -----
  765. integer(ip_i4_p) :: npes ! Number of MPI tasks
  766. integer(ip_i4_p) :: locSize ! Size of local distributed data
  767. integer(ip_i4_p), pointer :: sendSize(:) ! Size to send for initial gather
  768. integer(ip_i4_p) :: i ! Index
  769. integer(ip_i4_p) :: rank ! Rank of this MPI task
  770. integer(ip_i4_p) :: nSize ! Maximum size to send
  771. integer(ip_i4_p) :: ierr ! Error code
  772. integer(ip_i4_p) :: nSiz1D ! Size of 1D global array
  773. integer(ip_i4_p) :: maxSize ! Maximum size
  774. !----- formats -----
  775. character(*),parameter :: subname = '(oasis_mpi_gathScatvInitr1)'
  776. !-------------------------------------------------------------------------------
  777. ! PURPOSE: Setup arrays for a gatherv/scatterv operation
  778. !-------------------------------------------------------------------------------
  779. call oasis_debug_enter(subname)
  780. locSize = size(locarr)
  781. call oasis_mpi_commsize( comm, npes )
  782. call oasis_mpi_commrank( comm, rank )
  783. allocate( globSize(npes) )
  784. !
  785. ! --- Gather the send global sizes from each MPI task -----------------------
  786. !
  787. allocate( sendSize(npes) )
  788. sendSize(:) = 1
  789. globSize(:) = 1
  790. call MPI_GATHER( locSize, 1, MPI_INTEGER, globSize, sendSize, &
  791. MPI_INTEGER, rootid, comm, ierr )
  792. if (present(string)) then
  793. call oasis_mpi_chkerr(ierr,subName//trim(string))
  794. else
  795. call oasis_mpi_chkerr(ierr,subName)
  796. endif
  797. deallocate( sendSize )
  798. !
  799. ! --- Prepare the displacement and allocate arrays -------------------------
  800. !
  801. allocate( displs(npes) )
  802. displs(1) = 0
  803. if ( rootid /= rank )then
  804. maxSize = 1
  805. globSize = 1
  806. else
  807. maxSize = maxval(globSize)
  808. end if
  809. nsiz1D = min(maxSize,globSize(1))
  810. do i = 2, npes
  811. nSize = min(maxSize,globSize(i-1))
  812. displs(i) = displs(i-1) + nSize
  813. nsiz1D = nsiz1D + min(maxSize,globSize(i))
  814. end do
  815. allocate( glob1DArr(nsiz1D) )
  816. !----- Do some error checking for the root task arrays computed ----
  817. if ( rootid == rank )then
  818. if ( nsiz1D /= sum(globSize) ) &
  819. call oasis_mpi_abort( subName//" : Error, size of global array not right" )
  820. if ( any(displs < 0) .or. any(displs >= nsiz1D) ) &
  821. call oasis_mpi_abort( subName//" : Error, displacement array not right" )
  822. if ( (displs(npes)+globSize(npes)) /= nsiz1D ) &
  823. call oasis_mpi_abort( subName//" : Error, displacement array values too big" )
  824. end if
  825. call oasis_debug_exit(subname)
  826. END SUBROUTINE oasis_mpi_gathScatvInitr1
  827. !===============================================================================
  828. !===============================================================================
  829. !> Gather a vector of distributed data to a rootid
  830. !> This method passes in glob1DArr, globSize, and displs computed
  831. !> in the oasis_mpi_gathscatvinit routine and uses that information to
  832. !> gather the locArr into the glob1Darr on processor rootid in communicator
  833. !> comm.
  834. SUBROUTINE oasis_mpi_gathervr1(locarr, locSize, glob1DArr, globSize, displs, rootid, &
  835. comm, string )
  836. IMPLICIT none
  837. !----- arguments -----
  838. real(ip_double_p),intent(in) :: locArr(:) !< Local array
  839. real(ip_double_p),intent(inout) :: glob1DArr(:) !< Global 1D array to receive in on
  840. integer(ip_i4_p), intent(in) :: locSize !< Number to send from this PE
  841. integer(ip_i4_p), intent(in) :: globSize(:) !< Number to receive from each PE
  842. integer(ip_i4_p), intent(in) :: displs(:) !< Displacements for receives
  843. integer(ip_i4_p), intent(in) :: rootid !< MPI task to gather on
  844. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  845. character(*),optional,intent(in):: string !< to identify caller
  846. !----- local -----
  847. integer(ip_i4_p) :: ierr ! Error code
  848. !----- formats -----
  849. character(*),parameter :: subname = '(oasis_mpi_gathervr1)'
  850. !-------------------------------------------------------------------------------
  851. ! PURPOSE: Gather a 1D array of reals
  852. !-------------------------------------------------------------------------------
  853. call oasis_debug_enter(subname)
  854. call MPI_GATHERV( locarr, locSize, MPI_REAL8, glob1Darr, globSize, displs, &
  855. MPI_REAL8, rootid, comm, ierr )
  856. if (present(string)) then
  857. call oasis_mpi_chkerr(ierr,subName//trim(string))
  858. else
  859. call oasis_mpi_chkerr(ierr,subName)
  860. endif
  861. call oasis_debug_exit(subname)
  862. END SUBROUTINE oasis_mpi_gathervr1
  863. !===============================================================================
  864. !===============================================================================
  865. !> Scatter a vector of global data from a rootid
  866. !> This method passes in glob1DArr, globSize, and displs computed
  867. !> in the oasis_mpi_gathscatvinit routine and uses that information to
  868. !> scatter glob1Darr on processor rootid in communicator comm to locarr
  869. !> on other processors.
  870. SUBROUTINE oasis_mpi_scattervr1(locarr, locSize, glob1Darr, globSize, displs, rootid, &
  871. comm, string )
  872. IMPLICIT none
  873. !----- arguments -----
  874. real(ip_double_p),intent(out) :: locarr(:) !< Local array
  875. real(ip_double_p),intent(in) :: glob1Darr(:) !< Global 1D array to send from
  876. integer(ip_i4_p), intent(in) :: locSize !< Number to receive this PE
  877. integer(ip_i4_p), intent(in) :: globSize(:) !< Number to send to each PE
  878. integer(ip_i4_p), intent(in) :: displs(:) !< Displacements for send
  879. integer(ip_i4_p), intent(in) :: rootid !< MPI task to scatter on
  880. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  881. character(*),optional,intent(in):: string !< to identify caller
  882. !----- local -----
  883. integer(ip_i4_p) :: ierr ! Error code
  884. !----- formats -----
  885. character(*),parameter :: subname = '(oasis_mpi_scattervr1)'
  886. !-------------------------------------------------------------------------------
  887. ! PURPOSE: Scatter a 1D array of reals
  888. !-------------------------------------------------------------------------------
  889. call oasis_debug_enter(subname)
  890. call MPI_SCATTERV( glob1Darr, globSize, displs, MPI_REAL8, locarr, locSize, &
  891. MPI_REAL8, rootid, comm, ierr )
  892. if (present(string)) then
  893. call oasis_mpi_chkerr(ierr,subName//trim(string))
  894. else
  895. call oasis_mpi_chkerr(ierr,subName)
  896. endif
  897. call oasis_debug_exit(subname)
  898. END SUBROUTINE oasis_mpi_scattervr1
  899. !===============================================================================
  900. !===============================================================================
  901. !> Compute a global Sum for a scalar integer
  902. SUBROUTINE oasis_mpi_sumi0(lvec,gvec,comm,string,all)
  903. IMPLICIT none
  904. !----- arguments ---
  905. integer(ip_i4_p), intent(in) :: lvec !< local values
  906. integer(ip_i4_p), intent(out):: gvec !< global values
  907. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  908. character(*),optional,intent(in) :: string !< to identify caller
  909. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  910. !----- local ---
  911. character(*),parameter :: subname = '(oasis_mpi_sumi0)'
  912. logical :: lall
  913. character(len=256) :: lstring
  914. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  915. integer(ip_i4_p) :: lsize
  916. integer(ip_i4_p) :: gsize
  917. integer(ip_i4_p) :: ierr
  918. !-------------------------------------------------------------------------------
  919. ! PURPOSE: Finds sum of a distributed vector of values, assume local sum
  920. ! already computed
  921. !-------------------------------------------------------------------------------
  922. call oasis_debug_enter(subname)
  923. reduce_type = MPI_SUM
  924. if (present(all)) then
  925. lall = all
  926. else
  927. lall = .false.
  928. endif
  929. if (present(string)) then
  930. lstring = trim(subName)//":"//trim(string)
  931. else
  932. lstring = trim(subName)
  933. endif
  934. lsize = 1
  935. gsize = 1
  936. if (lsize /= gsize) then
  937. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  938. endif
  939. if (lall) then
  940. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,comm,ierr)
  941. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  942. else
  943. call MPI_REDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,0,comm,ierr)
  944. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  945. endif
  946. call oasis_debug_exit(subname)
  947. END SUBROUTINE oasis_mpi_sumi0
  948. !===============================================================================
  949. !===============================================================================
  950. !> Compute a 1D array of global sums for an array of 1D integers
  951. !> This sums an array of local integers to an array of summed integers.
  952. !> This does not reduce the array to a scalar.
  953. SUBROUTINE oasis_mpi_sumi1(lvec,gvec,comm,string,all)
  954. IMPLICIT none
  955. !----- arguments ---
  956. integer(ip_i4_p), intent(in) :: lvec(:) !< local values
  957. integer(ip_i4_p), intent(out):: gvec(:) !< global values
  958. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  959. character(*),optional,intent(in) :: string !< to identify caller
  960. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  961. !----- local ---
  962. character(*),parameter :: subname = '(oasis_mpi_sumi1)'
  963. logical :: lall
  964. character(len=256) :: lstring
  965. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  966. integer(ip_i4_p) :: lsize
  967. integer(ip_i4_p) :: gsize
  968. integer(ip_i4_p) :: ierr
  969. !-------------------------------------------------------------------------------
  970. ! PURPOSE: Finds sum of a distributed vector of values, assume local sum
  971. ! already computed
  972. !-------------------------------------------------------------------------------
  973. call oasis_debug_enter(subname)
  974. reduce_type = MPI_SUM
  975. if (present(all)) then
  976. lall = all
  977. else
  978. lall = .false.
  979. endif
  980. if (present(string)) then
  981. lstring = trim(subName)//":"//trim(string)
  982. else
  983. lstring = trim(subName)
  984. endif
  985. lsize = size(lvec)
  986. gsize = size(gvec)
  987. if (lsize /= gsize) then
  988. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  989. endif
  990. if (lall) then
  991. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,comm,ierr)
  992. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  993. else
  994. call MPI_REDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,0,comm,ierr)
  995. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  996. endif
  997. call oasis_debug_exit(subname)
  998. END SUBROUTINE oasis_mpi_sumi1
  999. !===============================================================================
  1000. !===============================================================================
  1001. !> Compute a global sum for a scalar 8 byte integer
  1002. SUBROUTINE oasis_mpi_sumb0(lvec,gvec,comm,string,all)
  1003. IMPLICIT none
  1004. !----- arguments ---
  1005. integer(ip_i8_p), intent(in) :: lvec !< local values
  1006. integer(ip_i8_p), intent(out):: gvec !< global values
  1007. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1008. character(*),optional,intent(in) :: string !< to identify caller
  1009. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1010. !----- local ---
  1011. character(*),parameter :: subname = '(oasis_mpi_sumb0)'
  1012. logical :: lall
  1013. character(len=256) :: lstring
  1014. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1015. integer(ip_i4_p) :: lsize
  1016. integer(ip_i4_p) :: gsize
  1017. integer(ip_i4_p) :: ierr
  1018. !-------------------------------------------------------------------------------
  1019. ! PURPOSE: Finds sum of a distributed vector of values, assume local sum
  1020. ! already computed
  1021. !-------------------------------------------------------------------------------
  1022. call oasis_debug_enter(subname)
  1023. reduce_type = MPI_SUM
  1024. if (present(all)) then
  1025. lall = all
  1026. else
  1027. lall = .false.
  1028. endif
  1029. if (present(string)) then
  1030. lstring = trim(subName)//":"//trim(string)
  1031. else
  1032. lstring = trim(subName)
  1033. endif
  1034. lsize = 1
  1035. gsize = 1
  1036. if (lsize /= gsize) then
  1037. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1038. endif
  1039. if (lall) then
  1040. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_INTEGER8,reduce_type,comm,ierr)
  1041. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1042. else
  1043. call MPI_REDUCE(lvec,gvec,gsize,MPI_INTEGER8,reduce_type,0,comm,ierr)
  1044. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1045. endif
  1046. call oasis_debug_exit(subname)
  1047. END SUBROUTINE oasis_mpi_sumb0
  1048. !===============================================================================
  1049. !===============================================================================
  1050. !> Compute a 1D array of global sums for an array of 1D 8 byte integers
  1051. !> This sums an array of local integers to an array of summed integers.
  1052. !> This does not reduce the array to a scalar.
  1053. SUBROUTINE oasis_mpi_sumb1(lvec,gvec,comm,string,all)
  1054. IMPLICIT none
  1055. !----- arguments ---
  1056. integer(ip_i8_p), intent(in) :: lvec(:) !< local values
  1057. integer(ip_i8_p), intent(out):: gvec(:) !< global values
  1058. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1059. character(*),optional,intent(in) :: string !< to identify caller
  1060. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1061. !----- local ---
  1062. character(*),parameter :: subname = '(oasis_mpi_sumb1)'
  1063. logical :: lall
  1064. character(len=256) :: lstring
  1065. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1066. integer(ip_i4_p) :: lsize
  1067. integer(ip_i4_p) :: gsize
  1068. integer(ip_i4_p) :: ierr
  1069. !-------------------------------------------------------------------------------
  1070. ! PURPOSE: Finds sum of a distributed vector of values, assume local sum
  1071. ! already computed
  1072. !-------------------------------------------------------------------------------
  1073. call oasis_debug_enter(subname)
  1074. reduce_type = MPI_SUM
  1075. if (present(all)) then
  1076. lall = all
  1077. else
  1078. lall = .false.
  1079. endif
  1080. if (present(string)) then
  1081. lstring = trim(subName)//":"//trim(string)
  1082. else
  1083. lstring = trim(subName)
  1084. endif
  1085. lsize = size(lvec)
  1086. gsize = size(gvec)
  1087. if (lsize /= gsize) then
  1088. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1089. endif
  1090. if (lall) then
  1091. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_INTEGER8,reduce_type,comm,ierr)
  1092. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1093. else
  1094. call MPI_REDUCE(lvec,gvec,gsize,MPI_INTEGER8,reduce_type,0,comm,ierr)
  1095. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1096. endif
  1097. call oasis_debug_exit(subname)
  1098. END SUBROUTINE oasis_mpi_sumb1
  1099. !===============================================================================
  1100. !===============================================================================
  1101. !> Compute a global sum for a scalar double
  1102. SUBROUTINE oasis_mpi_sumr0(lvec,gvec,comm,string,all)
  1103. IMPLICIT none
  1104. !----- arguments ---
  1105. real(ip_double_p), intent(in) :: lvec !< local values
  1106. real(ip_double_p), intent(out):: gvec !< global values
  1107. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1108. character(*),optional,intent(in) :: string !< to identify caller
  1109. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1110. !----- local ---
  1111. character(*),parameter :: subname = '(oasis_mpi_sumr0)'
  1112. logical :: lall
  1113. character(len=256) :: lstring
  1114. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1115. integer(ip_i4_p) :: lsize
  1116. integer(ip_i4_p) :: gsize
  1117. integer(ip_i4_p) :: ierr
  1118. !-------------------------------------------------------------------------------
  1119. ! PURPOSE: Finds sum of a distributed vector of values, assume local sum
  1120. ! already computed
  1121. !-------------------------------------------------------------------------------
  1122. call oasis_debug_enter(subname)
  1123. reduce_type = MPI_SUM
  1124. if (present(all)) then
  1125. lall = all
  1126. else
  1127. lall = .false.
  1128. endif
  1129. if (present(string)) then
  1130. lstring = trim(subName)//":"//trim(string)
  1131. else
  1132. lstring = trim(subName)
  1133. endif
  1134. lsize = 1
  1135. gsize = 1
  1136. if (lsize /= gsize) then
  1137. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1138. endif
  1139. if (lall) then
  1140. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,comm,ierr)
  1141. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1142. else
  1143. call MPI_REDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,0,comm,ierr)
  1144. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1145. endif
  1146. call oasis_debug_exit(subname)
  1147. END SUBROUTINE oasis_mpi_sumr0
  1148. !===============================================================================
  1149. !===============================================================================
  1150. !> Compute a 1D array of global sums for an array of 1D doubles
  1151. !> This sums an array of local doubles to an array of summed doubles.
  1152. !> This does not reduce the array to a scalar.
  1153. SUBROUTINE oasis_mpi_sumr1(lvec,gvec,comm,string,all)
  1154. IMPLICIT none
  1155. !----- arguments ---
  1156. real(ip_double_p), intent(in) :: lvec(:) !< local values
  1157. real(ip_double_p), intent(out):: gvec(:) !< global values
  1158. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1159. character(*),optional,intent(in) :: string !< to identify caller
  1160. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1161. !----- local ---
  1162. character(*),parameter :: subname = '(oasis_mpi_sumr1)'
  1163. logical :: lall
  1164. character(len=256) :: lstring
  1165. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1166. integer(ip_i4_p) :: lsize
  1167. integer(ip_i4_p) :: gsize
  1168. integer(ip_i4_p) :: ierr
  1169. !-------------------------------------------------------------------------------
  1170. ! PURPOSE: Finds sum of a distributed vector of values, assume local sum
  1171. ! already computed
  1172. !-------------------------------------------------------------------------------
  1173. call oasis_debug_enter(subname)
  1174. reduce_type = MPI_SUM
  1175. if (present(all)) then
  1176. lall = all
  1177. else
  1178. lall = .false.
  1179. endif
  1180. if (present(string)) then
  1181. lstring = trim(subName)//":"//trim(string)
  1182. else
  1183. lstring = trim(subName)
  1184. endif
  1185. lsize = size(lvec)
  1186. gsize = size(gvec)
  1187. if (lsize /= gsize) then
  1188. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1189. endif
  1190. if (lall) then
  1191. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,comm,ierr)
  1192. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1193. else
  1194. call MPI_REDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,0,comm,ierr)
  1195. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1196. endif
  1197. call oasis_debug_exit(subname)
  1198. END SUBROUTINE oasis_mpi_sumr1
  1199. !===============================================================================
  1200. !===============================================================================
  1201. !> Compute a 2D array of global sums for an array of 2D doubles
  1202. !> This sums an array of local doubles to an array of summed doubles.
  1203. !> This does not reduce the array to a scalar.
  1204. SUBROUTINE oasis_mpi_sumr2(lvec,gvec,comm,string,all)
  1205. IMPLICIT none
  1206. !----- arguments ---
  1207. real(ip_double_p), intent(in) :: lvec(:,:)!< local values
  1208. real(ip_double_p), intent(out):: gvec(:,:)!< global values
  1209. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1210. character(*),optional,intent(in) :: string !< to identify caller
  1211. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1212. !----- local ---
  1213. character(*),parameter :: subname = '(oasis_mpi_sumr2)'
  1214. logical :: lall
  1215. character(len=256) :: lstring
  1216. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1217. integer(ip_i4_p) :: lsize
  1218. integer(ip_i4_p) :: gsize
  1219. integer(ip_i4_p) :: ierr
  1220. !-------------------------------------------------------------------------------
  1221. ! PURPOSE: Finds sum of a distributed vector of values, assume local sum
  1222. ! already computed
  1223. !-------------------------------------------------------------------------------
  1224. call oasis_debug_enter(subname)
  1225. reduce_type = MPI_SUM
  1226. if (present(all)) then
  1227. lall = all
  1228. else
  1229. lall = .false.
  1230. endif
  1231. if (present(string)) then
  1232. lstring = trim(subName)//":"//trim(string)
  1233. else
  1234. lstring = trim(subName)
  1235. endif
  1236. lsize = size(lvec)
  1237. gsize = size(gvec)
  1238. if (lsize /= gsize) then
  1239. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1240. endif
  1241. if (lall) then
  1242. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,comm,ierr)
  1243. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1244. else
  1245. call MPI_REDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,0,comm,ierr)
  1246. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1247. endif
  1248. call oasis_debug_exit(subname)
  1249. END SUBROUTINE oasis_mpi_sumr2
  1250. !===============================================================================
  1251. !===============================================================================
  1252. !> Compute a 3D array of global sums for an array of 3D doubles
  1253. !> This sums an array of local doubles to an array of summed doubles.
  1254. !> This does not reduce the array to a scalar.
  1255. SUBROUTINE oasis_mpi_sumr3(lvec,gvec,comm,string,all)
  1256. IMPLICIT none
  1257. !----- arguments ---
  1258. real(ip_double_p), intent(in) :: lvec(:,:,:) !< local values
  1259. real(ip_double_p), intent(out):: gvec(:,:,:) !< global values
  1260. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1261. character(*),optional,intent(in) :: string !< to identify caller
  1262. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1263. !----- local ---
  1264. character(*),parameter :: subname = '(oasis_mpi_sumr3)'
  1265. logical :: lall
  1266. character(len=256) :: lstring
  1267. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1268. integer(ip_i4_p) :: lsize
  1269. integer(ip_i4_p) :: gsize
  1270. integer(ip_i4_p) :: ierr
  1271. !-------------------------------------------------------------------------------
  1272. ! PURPOSE: Finds sum of a distributed vector of values, assume local sum
  1273. ! already computed
  1274. !-------------------------------------------------------------------------------
  1275. call oasis_debug_enter(subname)
  1276. reduce_type = MPI_SUM
  1277. if (present(all)) then
  1278. lall = all
  1279. else
  1280. lall = .false.
  1281. endif
  1282. if (present(string)) then
  1283. lstring = trim(subName)//":"//trim(string)
  1284. else
  1285. lstring = trim(subName)
  1286. endif
  1287. lsize = size(lvec)
  1288. gsize = size(gvec)
  1289. if (lsize /= gsize) then
  1290. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1291. endif
  1292. if (lall) then
  1293. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,comm,ierr)
  1294. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1295. else
  1296. call MPI_REDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,0,comm,ierr)
  1297. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1298. endif
  1299. call oasis_debug_exit(subname)
  1300. END SUBROUTINE oasis_mpi_sumr3
  1301. !===============================================================================
  1302. !===============================================================================
  1303. !> Compute a global minimum for a scalar integer
  1304. SUBROUTINE oasis_mpi_mini0(lvec,gvec,comm,string,all)
  1305. IMPLICIT none
  1306. !----- arguments ---
  1307. integer(ip_i4_p), intent(in) :: lvec !< local values
  1308. integer(ip_i4_p), intent(out):: gvec !< global values
  1309. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1310. character(*),optional,intent(in) :: string !< to identify caller
  1311. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1312. !----- local ---
  1313. character(*),parameter :: subname = '(oasis_mpi_mini0)'
  1314. logical :: lall
  1315. character(len=256) :: lstring
  1316. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1317. integer(ip_i4_p) :: lsize
  1318. integer(ip_i4_p) :: gsize
  1319. integer(ip_i4_p) :: ierr
  1320. !-------------------------------------------------------------------------------
  1321. ! PURPOSE: Finds min of a distributed vector of values, assume local min
  1322. ! already computed
  1323. !-------------------------------------------------------------------------------
  1324. call oasis_debug_enter(subname)
  1325. reduce_type = MPI_MIN
  1326. if (present(all)) then
  1327. lall = all
  1328. else
  1329. lall = .false.
  1330. endif
  1331. if (present(string)) then
  1332. lstring = trim(subName)//":"//trim(string)
  1333. else
  1334. lstring = trim(subName)
  1335. endif
  1336. lsize = 1
  1337. gsize = 1
  1338. if (lsize /= gsize) then
  1339. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1340. endif
  1341. if (lall) then
  1342. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,comm,ierr)
  1343. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1344. else
  1345. call MPI_REDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,0,comm,ierr)
  1346. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1347. endif
  1348. call oasis_debug_exit(subname)
  1349. END SUBROUTINE oasis_mpi_mini0
  1350. !===============================================================================
  1351. !===============================================================================
  1352. !> Compute an array of global minimums for an array of 1D integers
  1353. SUBROUTINE oasis_mpi_mini1(lvec,gvec,comm,string,all)
  1354. IMPLICIT none
  1355. !----- arguments ---
  1356. integer(ip_i4_p), intent(in) :: lvec(:) !< local values
  1357. integer(ip_i4_p), intent(out):: gvec(:) !< global values
  1358. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1359. character(*),optional,intent(in) :: string !< to identify caller
  1360. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1361. !----- local ---
  1362. character(*),parameter :: subname = '(oasis_mpi_mini1)'
  1363. logical :: lall
  1364. character(len=256) :: lstring
  1365. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1366. integer(ip_i4_p) :: lsize
  1367. integer(ip_i4_p) :: gsize
  1368. integer(ip_i4_p) :: ierr
  1369. !-------------------------------------------------------------------------------
  1370. ! PURPOSE: Finds min of a distributed vector of values, assume local min
  1371. ! already computed
  1372. !-------------------------------------------------------------------------------
  1373. call oasis_debug_enter(subname)
  1374. reduce_type = MPI_MIN
  1375. if (present(all)) then
  1376. lall = all
  1377. else
  1378. lall = .false.
  1379. endif
  1380. if (present(string)) then
  1381. lstring = trim(subName)//":"//trim(string)
  1382. else
  1383. lstring = trim(subName)
  1384. endif
  1385. lsize = size(lvec)
  1386. gsize = size(gvec)
  1387. if (lsize /= gsize) then
  1388. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1389. endif
  1390. if (lall) then
  1391. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,comm,ierr)
  1392. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1393. else
  1394. call MPI_REDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,0,comm,ierr)
  1395. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1396. endif
  1397. call oasis_debug_exit(subname)
  1398. END SUBROUTINE oasis_mpi_mini1
  1399. !===============================================================================
  1400. !===============================================================================
  1401. !> Compute an global minimum for a scalar double
  1402. SUBROUTINE oasis_mpi_minr0(lvec,gvec,comm,string,all)
  1403. IMPLICIT none
  1404. !----- arguments ---
  1405. real(ip_double_p), intent(in) :: lvec !< local values
  1406. real(ip_double_p), intent(out):: gvec !< global values
  1407. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1408. character(*),optional,intent(in) :: string !< to identify caller
  1409. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1410. !----- local ---
  1411. character(*),parameter :: subname = '(oasis_mpi_minr0)'
  1412. logical :: lall
  1413. character(len=256) :: lstring
  1414. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1415. integer(ip_i4_p) :: lsize
  1416. integer(ip_i4_p) :: gsize
  1417. integer(ip_i4_p) :: ierr
  1418. !-------------------------------------------------------------------------------
  1419. ! PURPOSE: Finds min of a distributed vector of values, assume local min
  1420. ! already computed
  1421. !-------------------------------------------------------------------------------
  1422. call oasis_debug_enter(subname)
  1423. reduce_type = MPI_MIN
  1424. if (present(all)) then
  1425. lall = all
  1426. else
  1427. lall = .false.
  1428. endif
  1429. if (present(string)) then
  1430. lstring = trim(subName)//":"//trim(string)
  1431. else
  1432. lstring = trim(subName)
  1433. endif
  1434. lsize = 1
  1435. gsize = 1
  1436. if (lsize /= gsize) then
  1437. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1438. endif
  1439. if (lall) then
  1440. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,comm,ierr)
  1441. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1442. else
  1443. call MPI_REDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,0,comm,ierr)
  1444. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1445. endif
  1446. call oasis_debug_exit(subname)
  1447. END SUBROUTINE oasis_mpi_minr0
  1448. !===============================================================================
  1449. !===============================================================================
  1450. !> Compute an array of global minimums for an array of 1D doubles
  1451. SUBROUTINE oasis_mpi_minr1(lvec,gvec,comm,string,all)
  1452. IMPLICIT none
  1453. !----- arguments ---
  1454. real(ip_double_p), intent(in) :: lvec(:) !< local values
  1455. real(ip_double_p), intent(out):: gvec(:) !< global values
  1456. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1457. character(*),optional,intent(in) :: string !< to identify caller
  1458. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1459. !----- local ---
  1460. character(*),parameter :: subname = '(oasis_mpi_minr1)'
  1461. logical :: lall
  1462. character(len=256) :: lstring
  1463. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1464. integer(ip_i4_p) :: lsize
  1465. integer(ip_i4_p) :: gsize
  1466. integer(ip_i4_p) :: ierr
  1467. !-------------------------------------------------------------------------------
  1468. ! PURPOSE: Finds min of a distributed vector of values, assume local min
  1469. ! already computed
  1470. !-------------------------------------------------------------------------------
  1471. call oasis_debug_enter(subname)
  1472. reduce_type = MPI_MIN
  1473. if (present(all)) then
  1474. lall = all
  1475. else
  1476. lall = .false.
  1477. endif
  1478. if (present(string)) then
  1479. lstring = trim(subName)//":"//trim(string)
  1480. else
  1481. lstring = trim(subName)
  1482. endif
  1483. lsize = size(lvec)
  1484. gsize = size(gvec)
  1485. if (lsize /= gsize) then
  1486. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1487. endif
  1488. if (lall) then
  1489. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,comm,ierr)
  1490. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1491. else
  1492. call MPI_REDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,0,comm,ierr)
  1493. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1494. endif
  1495. call oasis_debug_exit(subname)
  1496. END SUBROUTINE oasis_mpi_minr1
  1497. !===============================================================================
  1498. !===============================================================================
  1499. !> Compute a global maximum for a scalar integer
  1500. SUBROUTINE oasis_mpi_maxi0(lvec,gvec,comm,string,all)
  1501. IMPLICIT none
  1502. !----- arguments ---
  1503. integer(ip_i4_p), intent(in) :: lvec !< local values
  1504. integer(ip_i4_p), intent(out):: gvec !< global values
  1505. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1506. character(*),optional,intent(in) :: string !< to identify caller
  1507. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1508. !----- local ---
  1509. character(*),parameter :: subname = '(oasis_mpi_maxi0)'
  1510. logical :: lall
  1511. character(len=256) :: lstring
  1512. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1513. integer(ip_i4_p) :: lsize
  1514. integer(ip_i4_p) :: gsize
  1515. integer(ip_i4_p) :: ierr
  1516. !-------------------------------------------------------------------------------
  1517. ! PURPOSE: Finds max of a distributed vector of values, assume local max
  1518. ! already computed
  1519. !-------------------------------------------------------------------------------
  1520. call oasis_debug_enter(subname)
  1521. reduce_type = MPI_MAX
  1522. if (present(all)) then
  1523. lall = all
  1524. else
  1525. lall = .false.
  1526. endif
  1527. if (present(string)) then
  1528. lstring = trim(subName)//":"//trim(string)
  1529. else
  1530. lstring = trim(subName)
  1531. endif
  1532. lsize = 1
  1533. gsize = 1
  1534. if (lsize /= gsize) then
  1535. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1536. endif
  1537. if (lall) then
  1538. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,comm,ierr)
  1539. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1540. else
  1541. call MPI_REDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,0,comm,ierr)
  1542. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1543. endif
  1544. call oasis_debug_exit(subname)
  1545. END SUBROUTINE oasis_mpi_maxi0
  1546. !===============================================================================
  1547. !===============================================================================
  1548. !> Compute an array of global maximums for an array of 1D integers
  1549. SUBROUTINE oasis_mpi_maxi1(lvec,gvec,comm,string,all)
  1550. IMPLICIT none
  1551. !----- arguments ---
  1552. integer(ip_i4_p), intent(in) :: lvec(:) !< local values
  1553. integer(ip_i4_p), intent(out):: gvec(:) !< global values
  1554. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1555. character(*),optional,intent(in) :: string !< to identify caller
  1556. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1557. !----- local ---
  1558. character(*),parameter :: subname = '(oasis_mpi_maxi1)'
  1559. logical :: lall
  1560. character(len=256) :: lstring
  1561. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1562. integer(ip_i4_p) :: lsize
  1563. integer(ip_i4_p) :: gsize
  1564. integer(ip_i4_p) :: ierr
  1565. !-------------------------------------------------------------------------------
  1566. ! PURPOSE: Finds max of a distributed vector of values, assume local max
  1567. ! already computed
  1568. !-------------------------------------------------------------------------------
  1569. call oasis_debug_enter(subname)
  1570. reduce_type = MPI_MAX
  1571. if (present(all)) then
  1572. lall = all
  1573. else
  1574. lall = .false.
  1575. endif
  1576. if (present(string)) then
  1577. lstring = trim(subName)//":"//trim(string)
  1578. else
  1579. lstring = trim(subName)
  1580. endif
  1581. lsize = size(lvec)
  1582. gsize = size(gvec)
  1583. if (lsize /= gsize) then
  1584. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1585. endif
  1586. if (lall) then
  1587. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,comm,ierr)
  1588. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1589. else
  1590. call MPI_REDUCE(lvec,gvec,gsize,MPI_INTEGER,reduce_type,0,comm,ierr)
  1591. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1592. endif
  1593. call oasis_debug_exit(subname)
  1594. END SUBROUTINE oasis_mpi_maxi1
  1595. !===============================================================================
  1596. !===============================================================================
  1597. !> Compute a global maximum for a scalar double
  1598. SUBROUTINE oasis_mpi_maxr0(lvec,gvec,comm,string,all)
  1599. IMPLICIT none
  1600. !----- arguments ---
  1601. real(ip_double_p), intent(in) :: lvec !< local values
  1602. real(ip_double_p), intent(out):: gvec !< global values
  1603. integer(ip_i4_p), intent(in) :: comm !< mpi communicator
  1604. character(*),optional,intent(in) :: string !< to identify caller
  1605. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1606. !----- local ---
  1607. character(*),parameter :: subname = '(oasis_mpi_maxr0)'
  1608. logical :: lall
  1609. character(len=256) :: lstring
  1610. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1611. integer(ip_i4_p) :: lsize
  1612. integer(ip_i4_p) :: gsize
  1613. integer(ip_i4_p) :: ierr
  1614. !-------------------------------------------------------------------------------
  1615. ! PURPOSE: Finds max of a distributed vector of values, assume local max
  1616. ! already computed
  1617. !-------------------------------------------------------------------------------
  1618. call oasis_debug_enter(subname)
  1619. reduce_type = MPI_MAX
  1620. if (present(all)) then
  1621. lall = all
  1622. else
  1623. lall = .false.
  1624. endif
  1625. if (present(string)) then
  1626. lstring = trim(subName)//":"//trim(string)
  1627. else
  1628. lstring = trim(subName)
  1629. endif
  1630. lsize = 1
  1631. gsize = 1
  1632. if (lsize /= gsize) then
  1633. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1634. endif
  1635. if (lall) then
  1636. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,comm,ierr)
  1637. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1638. else
  1639. call MPI_REDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,0,comm,ierr)
  1640. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1641. endif
  1642. call oasis_debug_exit(subname)
  1643. END SUBROUTINE oasis_mpi_maxr0
  1644. !===============================================================================
  1645. !===============================================================================
  1646. !> Compute an array of global maximums for an array of 1D doubles
  1647. SUBROUTINE oasis_mpi_maxr1(lvec,gvec,comm,string,all)
  1648. IMPLICIT none
  1649. !----- arguments ---
  1650. real(ip_double_p), intent(in) :: lvec(:) !< local values
  1651. real(ip_double_p), intent(out):: gvec(:) !< global values
  1652. integer(ip_i4_p) , intent(in) :: comm !< mpi communicator
  1653. character(*),optional,intent(in) :: string !< to identify caller
  1654. logical, optional,intent(in) :: all !< if true call allreduce, otherwise reduce to task 0
  1655. !----- local ---
  1656. character(*),parameter :: subname = '(oasis_mpi_maxr1)'
  1657. logical :: lall
  1658. character(len=256) :: lstring
  1659. integer(ip_i4_p) :: reduce_type ! mpi reduction type
  1660. integer(ip_i4_p) :: lsize
  1661. integer(ip_i4_p) :: gsize
  1662. integer(ip_i4_p) :: ierr
  1663. !-------------------------------------------------------------------------------
  1664. ! PURPOSE: Finds max of a distributed vector of values, assume local max
  1665. ! already computed
  1666. !-------------------------------------------------------------------------------
  1667. call oasis_debug_enter(subname)
  1668. reduce_type = MPI_MAX
  1669. if (present(all)) then
  1670. lall = all
  1671. else
  1672. lall = .false.
  1673. endif
  1674. if (present(string)) then
  1675. lstring = trim(subName)//":"//trim(string)
  1676. else
  1677. lstring = trim(subName)
  1678. endif
  1679. lsize = size(lvec)
  1680. gsize = size(gvec)
  1681. if (lsize /= gsize) then
  1682. call oasis_mpi_abort(subName//" lsize,gsize incompatable "//trim(string))
  1683. endif
  1684. if (lall) then
  1685. call MPI_ALLREDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,comm,ierr)
  1686. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_ALLREDUCE")
  1687. else
  1688. call MPI_REDUCE(lvec,gvec,gsize,MPI_REAL8,reduce_type,0,comm,ierr)
  1689. call oasis_mpi_chkerr(ierr,trim(lstring)//" MPI_REDUCE")
  1690. endif
  1691. call oasis_debug_exit(subname)
  1692. END SUBROUTINE oasis_mpi_maxr1
  1693. !===============================================================================
  1694. !===============================================================================
  1695. !> Get the total number of tasks associated with a communicator
  1696. SUBROUTINE oasis_mpi_commsize(comm,size,string)
  1697. IMPLICIT none
  1698. !----- arguments ---
  1699. integer,intent(in) :: comm !< mpi communicator
  1700. integer,intent(out) :: size !< output comm size
  1701. character(*),optional,intent(in) :: string !< to identify caller
  1702. !----- local ---
  1703. character(*),parameter :: subname = '(oasis_mpi_commsize)'
  1704. integer(ip_i4_p) :: ierr
  1705. !-------------------------------------------------------------------------------
  1706. ! PURPOSE: MPI commsize
  1707. !-------------------------------------------------------------------------------
  1708. call oasis_debug_enter(subname)
  1709. call MPI_COMM_SIZE(comm,size,ierr)
  1710. if (present(string)) then
  1711. call oasis_mpi_chkerr(ierr,subName//trim(string))
  1712. else
  1713. call oasis_mpi_chkerr(ierr,subName)
  1714. endif
  1715. call oasis_debug_exit(subname)
  1716. END SUBROUTINE oasis_mpi_commsize
  1717. !===============================================================================
  1718. !===============================================================================
  1719. !> Get the rank (task ID) for a task in a communicator
  1720. SUBROUTINE oasis_mpi_commrank(comm,rank,string)
  1721. IMPLICIT none
  1722. !----- arguments ---
  1723. integer,intent(in) :: comm !< mpi communicator
  1724. integer,intent(out) :: rank !< output task ID
  1725. character(*),optional,intent(in) :: string !< to identify caller
  1726. !----- local ---
  1727. character(*),parameter :: subname = '(oasis_mpi_commrank)'
  1728. integer(ip_i4_p) :: ierr
  1729. !-------------------------------------------------------------------------------
  1730. ! PURPOSE: MPI commrank
  1731. !-------------------------------------------------------------------------------
  1732. call oasis_debug_enter(subname)
  1733. call MPI_COMM_RANK(comm,rank,ierr)
  1734. if (present(string)) then
  1735. call oasis_mpi_chkerr(ierr,subName//trim(string))
  1736. else
  1737. call oasis_mpi_chkerr(ierr,subName)
  1738. endif
  1739. call oasis_debug_exit(subname)
  1740. END SUBROUTINE oasis_mpi_commrank
  1741. !===============================================================================
  1742. !===============================================================================
  1743. !> Check whether MPI has been initialized
  1744. SUBROUTINE oasis_mpi_initialized(flag,string)
  1745. IMPLICIT none
  1746. !----- arguments ---
  1747. logical,intent(out) :: flag !< true if MPI_INITIALIZED has been called
  1748. character(*),optional,intent(in) :: string !< to identify caller
  1749. !----- local ---
  1750. character(*),parameter :: subName = '(oasis_mpi_initialized)'
  1751. integer(ip_i4_p) :: ierr
  1752. !-------------------------------------------------------------------------------
  1753. ! PURPOSE: MPI initialized
  1754. !-------------------------------------------------------------------------------
  1755. call oasis_debug_enter(subname)
  1756. call MPI_INITIALIZED(flag,ierr)
  1757. if (present(string)) then
  1758. call oasis_mpi_chkerr(ierr,subName//trim(string))
  1759. else
  1760. call oasis_mpi_chkerr(ierr,subName)
  1761. endif
  1762. call oasis_debug_exit(subname)
  1763. END SUBROUTINE oasis_mpi_initialized
  1764. !===============================================================================
  1765. !===============================================================================
  1766. !> Return a timestamp from MPI_WTIME
  1767. SUBROUTINE oasis_mpi_wtime(wtime)
  1768. IMPLICIT none
  1769. !----- arguments ---
  1770. real(ip_r8_p), intent(out) :: wtime !< time in MPI_WTIME units
  1771. !----- local ---
  1772. character(*),parameter :: subName = '(oasis_mpi_wtime)'
  1773. !-------------------------------------------------------------------------------
  1774. ! PURPOSE: MPI wtime
  1775. !-------------------------------------------------------------------------------
  1776. call oasis_debug_enter(subname)
  1777. wtime = MPI_WTIME()
  1778. call oasis_debug_exit(subname)
  1779. END SUBROUTINE oasis_mpi_wtime
  1780. !===============================================================================
  1781. !===============================================================================
  1782. !> Write error messages and Call MPI_ABORT
  1783. SUBROUTINE oasis_mpi_abort(string,rcode)
  1784. IMPLICIT none
  1785. !----- arguments ---
  1786. character(*),optional,intent(in) :: string !< to identify caller
  1787. integer,optional,intent(in) :: rcode !< optional code
  1788. !----- local ---
  1789. character(*),parameter :: subName = '(oasis_mpi_abort)'
  1790. character(len=256) :: lstr
  1791. integer(ip_i4_p) :: ierr
  1792. integer :: rc ! return code
  1793. !-------------------------------------------------------------------------------
  1794. ! PURPOSE: MPI abort
  1795. !-------------------------------------------------------------------------------
  1796. call oasis_debug_enter(subname)
  1797. if ( present(string) .and. present(rcode)) then
  1798. write(lstr,'(a,i6.6)') trim(string)//' rcode = ',rcode
  1799. elseif (present(string)) then
  1800. lstr = trim(string)
  1801. else
  1802. lstr = ' '
  1803. endif
  1804. IF ( PRESENT(rcode)) THEN
  1805. CALL oasis_abort(cd_routine=subName,cd_message=TRIM(string),rcode=rcode)
  1806. ELSE
  1807. CALL oasis_abort(cd_routine=subName,cd_message=TRIM(string))
  1808. ENDIF
  1809. call oasis_debug_exit(subname)
  1810. END SUBROUTINE oasis_mpi_abort
  1811. !===============================================================================
  1812. !===============================================================================
  1813. !> Call MPI_BARRIER for a particular communicator
  1814. SUBROUTINE oasis_mpi_barrier(comm,string)
  1815. IMPLICIT none
  1816. !----- arguments ---
  1817. integer,intent(in) :: comm !< mpi communicator
  1818. character(*),optional,intent(in) :: string !< to identify caller
  1819. !----- local ---
  1820. character(*),parameter :: subname = '(oasis_mpi_barrier)'
  1821. integer(ip_i4_p) :: ierr
  1822. !-------------------------------------------------------------------------------
  1823. ! PURPOSE: MPI barrier
  1824. !-------------------------------------------------------------------------------
  1825. call oasis_debug_enter(subname)
  1826. call MPI_BARRIER(comm,ierr)
  1827. if (present(string)) then
  1828. call oasis_mpi_chkerr(ierr,subName//trim(string))
  1829. else
  1830. call oasis_mpi_chkerr(ierr,subName)
  1831. endif
  1832. call oasis_debug_exit(subname)
  1833. END SUBROUTINE oasis_mpi_barrier
  1834. !===============================================================================
  1835. !===============================================================================
  1836. !> Call MPI_INIT
  1837. SUBROUTINE oasis_mpi_init(string)
  1838. IMPLICIT none
  1839. !----- arguments ---
  1840. character(*),optional,intent(in) :: string !< to identify caller
  1841. !----- local ---
  1842. character(*),parameter :: subname = '(oasis_mpi_init)'
  1843. integer(ip_i4_p) :: ierr
  1844. !-------------------------------------------------------------------------------
  1845. ! PURPOSE: MPI init
  1846. !-------------------------------------------------------------------------------
  1847. call oasis_debug_enter(subname)
  1848. call MPI_INIT(ierr)
  1849. if (present(string)) then
  1850. call oasis_mpi_chkerr(ierr,subName//trim(string))
  1851. else
  1852. call oasis_mpi_chkerr(ierr,subName)
  1853. endif
  1854. call oasis_debug_exit(subname)
  1855. END SUBROUTINE oasis_mpi_init
  1856. !===============================================================================
  1857. !===============================================================================
  1858. !> Call MPI_FINALZE
  1859. SUBROUTINE oasis_mpi_finalize(string)
  1860. IMPLICIT none
  1861. !----- arguments ---
  1862. character(*),optional,intent(in) :: string !< to identify caller
  1863. !----- local ---
  1864. character(*),parameter :: subname = '(oasis_mpi_finalize)'
  1865. integer(ip_i4_p) :: ierr
  1866. !-------------------------------------------------------------------------------
  1867. ! PURPOSE: MPI finalize
  1868. !-------------------------------------------------------------------------------
  1869. call oasis_debug_enter(subname)
  1870. call MPI_FINALIZE(ierr)
  1871. if (present(string)) then
  1872. call oasis_mpi_chkerr(ierr,subName//trim(string))
  1873. else
  1874. call oasis_mpi_chkerr(ierr,subName)
  1875. endif
  1876. call oasis_debug_exit(subname)
  1877. END SUBROUTINE oasis_mpi_finalize
  1878. !===============================================================================
  1879. !===============================================================================
  1880. !> Custom method for reducing MPI lists across pes for OASIS
  1881. SUBROUTINE oasis_mpi_reducelists(linp1,comm,cntout,lout1,callstr,fastcheck,fastcheckout, &
  1882. linp2,lout2,spval2,linp3,lout3,spval3)
  1883. IMPLICIT none
  1884. !----- arguments ---
  1885. character(*),pointer,intent(in) :: linp1(:) !< input list on each task
  1886. integer ,intent(in) :: comm !< mpi communicator
  1887. integer ,intent(out) :: cntout !< size of lout1 list
  1888. character(*),pointer,intent(inout) :: lout1(:) !< reduced output list, same on all tasks
  1889. character(*) ,intent(in) :: callstr !< to identify caller
  1890. logical ,intent(in) ,optional :: fastcheck !< run a fastcheck first
  1891. logical ,intent(out) ,optional :: fastcheckout !< true if fastcheck worked
  1892. character(*),pointer,intent(in) ,optional :: linp2(:) !< input list on each task
  1893. character(*),pointer,intent(inout),optional :: lout2(:) !< reduced output list, same on all tasks
  1894. character(*) ,intent(in) ,optional :: spval2 !< unset value for linp2
  1895. integer ,pointer,intent(in) ,optional :: linp3(:) !< input list on each task
  1896. integer ,pointer,intent(inout),optional :: lout3(:) !< reduced output list, same on all tasks
  1897. integer ,intent(in) ,optional :: spval3 !< unset value for linp3
  1898. !----- local ---
  1899. integer(kind=ip_i4_p) :: m,n,k,p
  1900. integer(kind=ip_i4_p) :: llen,lsize
  1901. integer(kind=ip_i4_p) :: cnt, cntr
  1902. integer(kind=ip_i4_p) :: commrank, commsize
  1903. integer(kind=ip_i4_p) :: listcheck, listcheckall
  1904. integer(kind=ip_i4_p) :: maxloops, sendid, recvid, kfac
  1905. logical :: found, present2, present3
  1906. integer(kind=ip_i4_p) :: status(MPI_STATUS_SIZE) ! mpi status info
  1907. character(len=ic_lvar2),pointer :: recv_varf1(:),varf1a(:),varf1b(:)
  1908. character(len=ic_lvar2),pointer :: recv_varf2(:),varf2a(:),varf2b(:)
  1909. integer(kind=ip_i4_p) ,pointer :: recv_varf3(:),varf3a(:),varf3b(:)
  1910. character(len=ic_lvar2) :: string
  1911. logical, parameter :: local_timers_on = .false.
  1912. integer(ip_i4_p) :: ierr
  1913. character(*),parameter :: subname = '(oasis_mpi_reducelists)'
  1914. !-------------------------------------------------------------------------------
  1915. ! PURPOSE: Custom method for reducing MPI lists for OASIS using a log2
  1916. ! algorithm. This generates a list on all tasks that consists of the intersection
  1917. ! of all the values on all the tasks with each value listed once. linp1
  1918. ! is the input list, possibly different on each task. lout1
  1919. ! is the resulting list, the same on each task, consistenting of all unique
  1920. ! values of linp1 from all tasks. This ultimately reduces the list onto
  1921. ! the root task and then it's broadcast. The reduction occurs via a binary
  1922. ! type reduction from tasks to other tasks.
  1923. !-------------------------------------------------------------------------------
  1924. call oasis_debug_enter(subname)
  1925. string = trim(callstr)
  1926. if (present(fastcheckout)) fastcheckout = .false. ! by default
  1927. call oasis_mpi_commrank(comm,commrank,string=subname//trim(string))
  1928. call oasis_mpi_commsize(comm,commsize,string=subname//trim(string))
  1929. !-----------------------------------------------
  1930. !> * Check argument consistency
  1931. !-----------------------------------------------
  1932. if ((present(linp2) .and. .not.present(lout2)) .or. &
  1933. (present(lout2) .and. .not.present(linp2))) then
  1934. call oasis_mpi_abort(subname//trim(string)//" linp2 lout2 both must be present ")
  1935. endif
  1936. present2 = present(linp2)
  1937. if ((present(linp3) .and. .not.present(lout3)) .or. &
  1938. (present(lout3) .and. .not.present(linp3))) then
  1939. call oasis_mpi_abort(subname//trim(string)//" linp3 lout3 both must be present ")
  1940. endif
  1941. present3 = present(linp3)
  1942. if (len(linp1) > len(varf1a)) then
  1943. call oasis_mpi_abort(subname//trim(string)//" linp1 too long ")
  1944. endif
  1945. if (present(linp2)) then
  1946. if (size(linp2) /= size(linp1)) then
  1947. call oasis_mpi_abort(subname//trim(string)//" linp1 linp2 not same size ")
  1948. endif
  1949. if (len(linp2) > len(varf2a)) then
  1950. call oasis_mpi_abort(subname//trim(string)//" linp2 too long ")
  1951. endif
  1952. if (len(varf1a) /= len(varf2a)) then
  1953. call oasis_mpi_abort(subname//trim(string)//" varf1a varf2a not same len ")
  1954. endif
  1955. endif
  1956. if (present(linp3)) then
  1957. if (size(linp3) /= size(linp1)) then
  1958. call oasis_mpi_abort(subname//trim(string)//" linp1 linp3 not same size ")
  1959. endif
  1960. endif
  1961. !-----------------------------------------------
  1962. !> * Fast compare on all tasks
  1963. ! If all tasks have same list, just skip the reduction
  1964. !-----------------------------------------------
  1965. if (present(fastcheck)) then
  1966. if (fastcheck) then
  1967. if (local_timers_on) call oasis_timer_start(trim(string)//'_rl_fastcheck')
  1968. lsize = -1
  1969. if (commrank == 0) then
  1970. lsize = size(linp1)
  1971. endif
  1972. call oasis_mpi_bcast(lsize, comm, subname//trim(string)//' lsize check')
  1973. ! varf1a holds linp1 from root on all tasks
  1974. allocate(varf1a(lsize))
  1975. varf1a = ' '
  1976. if (commrank == 0) then
  1977. varf1a(1:lsize) = linp1(1:lsize)
  1978. endif
  1979. call oasis_mpi_bcast(varf1a, comm, subname//trim(string)//' varf1a check')
  1980. listcheck = 1
  1981. if (OASIS_DEBUG >= 20) then
  1982. write(nulprt,*) subname//trim(string),' sizes ',lsize,size(linp1)
  1983. endif
  1984. if (lsize /= size(linp1)) listcheck = 0
  1985. n = 0
  1986. do while (listcheck == 1 .and. n < lsize)
  1987. n = n + 1
  1988. if (varf1a(n) /= linp1(n)) listcheck = 0
  1989. if (OASIS_DEBUG >= 20) then
  1990. write(nulprt,*) subname//trim(string),' fcheck varf1a ',n,trim(linp1(n)),' ',trim(linp1(n)),listcheck
  1991. endif
  1992. enddo
  1993. deallocate(varf1a)
  1994. call oasis_mpi_min(listcheck,listcheckall,comm, subname//trim(string)//' listcheck',all=.true.)
  1995. if (OASIS_DEBUG >= 15) then
  1996. write(nulprt,*) subname//trim(string),' listcheck = ',listcheck,listcheckall
  1997. endif
  1998. if (local_timers_on) call oasis_timer_stop(trim(string)//'_rl_fastcheck')
  1999. !-------------------------------------------------
  2000. ! linp1 same on all tasks, update lout1, lout2, lout3 and return
  2001. !-------------------------------------------------
  2002. if (listcheckall == 1) then
  2003. cntout = lsize
  2004. allocate(lout1(lsize))
  2005. lout1(1:lsize) = linp1(1:lsize)
  2006. if (present2) then
  2007. allocate(lout2(lsize))
  2008. lout2(1:lsize) = linp2(1:lsize)
  2009. endif
  2010. if (present3) then
  2011. allocate(lout3(lsize))
  2012. lout3(1:lsize) = linp3(1:lsize)
  2013. endif
  2014. call oasis_debug_exit(subname)
  2015. if (present(fastcheckout)) fastcheckout = .true.
  2016. return
  2017. endif
  2018. endif ! fastcheck
  2019. endif ! present fastcheck
  2020. !-----------------------------------------------
  2021. !> * Generate initial unique local name list
  2022. !-----------------------------------------------
  2023. llen = len(linp1)
  2024. lsize = size(linp1)
  2025. if (OASIS_Debug >= 15) then
  2026. write(nulprt,*) subname//trim(string),' len, size = ',llen,lsize
  2027. call oasis_flush(nulprt)
  2028. endif
  2029. allocate(varf1a(max(lsize,20))) ! 20 is arbitrary starting number
  2030. if (present2) allocate(varf2a(max(lsize,20))) ! 20 is arbitrary starting number
  2031. if (present3) allocate(varf3a(max(lsize,20))) ! 20 is arbitrary starting number
  2032. cnt = 0
  2033. do n = 1,lsize
  2034. p = 0
  2035. found = .false.
  2036. do while (p < cnt .and. .not.found)
  2037. p = p + 1
  2038. if (linp1(n) == varf1a(p)) found = .true.
  2039. enddo
  2040. if (.not.found) then
  2041. cnt = cnt + 1
  2042. varf1a(cnt) = linp1(n)
  2043. if (present2) varf2a(cnt) = linp2(n)
  2044. if (present3) varf3a(cnt) = linp3(n)
  2045. endif
  2046. enddo
  2047. !-----------------------------------------------
  2048. !> * Log2 reduction of linp over tasks to root
  2049. !-----------------------------------------------
  2050. maxloops = int(sqrt(float(commsize+1)))+1
  2051. do m = 1,maxloops
  2052. kfac = 2**m
  2053. recvid = commrank + kfac/2 ! task to recv from
  2054. if (mod(commrank,kfac) /= 0 .or. &
  2055. recvid < 0 .or. recvid > commsize-1) &
  2056. recvid = -1
  2057. sendid = commrank - kfac/2 ! task to send to
  2058. if (mod(commrank+kfac/2,kfac) /= 0 .or. &
  2059. sendid < 0 .or. sendid > commsize-1) &
  2060. sendid = -1
  2061. if (OASIS_Debug >= 15) then
  2062. write(nulprt,*) subname//trim(string),' send/recv ids ',m,commrank,sendid,recvid
  2063. call oasis_flush(nulprt)
  2064. endif
  2065. !-----------------------------------------------
  2066. !> * Send list
  2067. !-----------------------------------------------
  2068. if (sendid >= 0) then
  2069. if (local_timers_on) call oasis_timer_start(trim(string)//'_rl_send')
  2070. call MPI_SEND(cnt, 1, MPI_INTEGER, sendid, 5900+m, comm, ierr)
  2071. call oasis_mpi_chkerr(ierr,subname//trim(string)//':send cnt')
  2072. if (cnt > 0) then
  2073. if (OASIS_Debug >= 15) then
  2074. write(nulprt,*) subname//trim(string),' send size ',commrank,m,cnt,ic_lvar2
  2075. call oasis_flush(nulprt)
  2076. endif
  2077. call MPI_SEND(varf1a(1:cnt), cnt*ic_lvar2, MPI_CHARACTER, sendid, 6900+m, comm, ierr)
  2078. call oasis_mpi_chkerr(ierr,subname//trim(string)//':send varf1a')
  2079. if (present2) then
  2080. call MPI_SEND(varf2a(1:cnt), cnt*ic_lvar2, MPI_CHARACTER, sendid, 7900+m, comm, ierr)
  2081. call oasis_mpi_chkerr(ierr,subname//trim(string)//':send varf2a')
  2082. endif
  2083. if (present3) then
  2084. call MPI_SEND(varf3a(1:cnt), cnt, MPI_INTEGER, sendid, 8900+m, comm, ierr)
  2085. call oasis_mpi_chkerr(ierr,subname//trim(string)//':send varf3a')
  2086. endif
  2087. endif ! cnt > 0
  2088. if (local_timers_on) call oasis_timer_stop (trim(string)//'_rl_send')
  2089. endif ! sendid >= 0
  2090. !-----------------------------------------------
  2091. !> * Recv list
  2092. !> * Determine the unique list
  2093. !-----------------------------------------------
  2094. if (recvid >= 0) then
  2095. if (local_timers_on) call oasis_timer_start (trim(string)//'_rl_recv')
  2096. call MPI_RECV(cntr, 1, MPI_INTEGER, recvid, 5900+m, comm, status, ierr)
  2097. call oasis_mpi_chkerr(ierr,subname//trim(string)//':recv cntr')
  2098. if (cntr > 0) then
  2099. if (OASIS_Debug >= 15) then
  2100. write(nulprt,*) subname//trim(string),' recv size ',commrank,m,cntr,ic_lvar2
  2101. call oasis_flush(nulprt)
  2102. endif
  2103. allocate(recv_varf1(cntr))
  2104. call MPI_RECV(recv_varf1, cntr*ic_lvar2, MPI_CHARACTER, recvid, 6900+m, comm, status, ierr)
  2105. call oasis_mpi_chkerr(ierr,subname//trim(string)//':recv varf1')
  2106. if (present2) then
  2107. allocate(recv_varf2(cntr))
  2108. call MPI_RECV(recv_varf2, cntr*ic_lvar2, MPI_CHARACTER, recvid, 7900+m, comm, status, ierr)
  2109. call oasis_mpi_chkerr(ierr,subname//trim(string)//':recv varf2')
  2110. endif
  2111. if (present3) then
  2112. allocate(recv_varf3(cntr))
  2113. call MPI_RECV(recv_varf3, cntr, MPI_INTEGER, recvid, 8900+m, comm, status, ierr)
  2114. call oasis_mpi_chkerr(ierr,subname//trim(string)//':recv varf3')
  2115. endif
  2116. endif ! cntr > 0
  2117. if (local_timers_on) call oasis_timer_stop (trim(string)//'_rl_recv')
  2118. if (local_timers_on) call oasis_timer_start(trim(string)//'_rl_rootsrch')
  2119. do n = 1,cntr
  2120. if (OASIS_Debug >= 15) write(nulprt,*) subname//trim(string),' check recv_varf1 ',m,n,trim(recv_varf1(n))
  2121. p = 0
  2122. found = .false.
  2123. do while (p < cnt .and. .not.found)
  2124. p = p + 1
  2125. if (recv_varf1(n) == varf1a(p)) then
  2126. found = .true.
  2127. if (present2) then
  2128. if (present(spval2)) then
  2129. !--- use something other than spval2 if it exists and check consistency
  2130. if (varf2a(p) == spval2) then
  2131. varf2a(p) = recv_varf2(n)
  2132. elseif (recv_varf2(n) /= spval2 .and. varf2a(p) /= recv_varf2(n)) then
  2133. call oasis_abort(cd_routine=subname//trim(string),cd_message= &
  2134. 'inconsistent linp2 value: '//trim(recv_varf2(n))//':'//trim(varf1a(p))//':'//trim(varf2a(p)))
  2135. endif
  2136. else
  2137. if (varf2a(p) /= recv_varf2(n)) then
  2138. call oasis_abort(cd_routine=subname//trim(string),cd_message= &
  2139. 'inconsistent linp2 value: '//trim(recv_varf2(n))//':'//trim(varf1a(p))//':'//trim(varf2a(p)))
  2140. endif
  2141. endif
  2142. endif
  2143. if (present3) then
  2144. if (present(spval3)) then
  2145. !--- use something other than spval3 if it exists and check consistency
  2146. if (varf3a(p) == spval3) then
  2147. varf3a(p) = recv_varf3(n)
  2148. elseif (recv_varf3(n) /= spval3 .and. varf3a(p) /= recv_varf3(n)) then
  2149. write(nulprt,*) subname//trim(string),astr,'inconsistent linp3 var: ',&
  2150. recv_varf3(n),':',trim(varf1a(p)),':',varf3a(p)
  2151. call oasis_abort(cd_routine=subname//trim(string),cd_message= &
  2152. 'inconsistent linp3 value: '//trim(varf1a(p)))
  2153. endif
  2154. else
  2155. if (varf3a(p) /= recv_varf3(n)) then
  2156. write(nulprt,*) subname//trim(string),astr,'inconsistent linp3 var: ',&
  2157. recv_varf3(n),':',trim(varf1a(p)),':',varf3a(p)
  2158. call oasis_abort(cd_routine=subname//trim(string),cd_message= &
  2159. 'inconsistent linp3 value: '//trim(varf1a(p)))
  2160. endif
  2161. endif
  2162. endif
  2163. endif
  2164. enddo
  2165. if (.not.found) then
  2166. cnt = cnt + 1
  2167. if (cnt > size(varf1a)) then
  2168. allocate(varf1b(size(varf1a)))
  2169. varf1b = varf1a
  2170. deallocate(varf1a)
  2171. if (OASIS_Debug >= 15) then
  2172. write(nulprt,*) subname//trim(string),' resize varf1a ',size(varf1b),cnt+cntr
  2173. call oasis_flush(nulprt)
  2174. endif
  2175. allocate(varf1a(cnt+cntr))
  2176. varf1a(1:size(varf1b)) = varf1b(1:size(varf1b))
  2177. deallocate(varf1b)
  2178. if (present2) then
  2179. allocate(varf2b(size(varf2a)))
  2180. varf2b = varf2a
  2181. deallocate(varf2a)
  2182. if (OASIS_Debug >= 15) then
  2183. write(nulprt,*) subname//trim(string),' resize varf2a ',size(varf2b),cnt+cntr
  2184. call oasis_flush(nulprt)
  2185. endif
  2186. allocate(varf2a(cnt+cntr))
  2187. varf2a(1:size(varf2b)) = varf2b(1:size(varf2b))
  2188. deallocate(varf2b)
  2189. endif
  2190. if (present3) then
  2191. allocate(varf3b(size(varf3a)))
  2192. varf3b = varf3a
  2193. deallocate(varf3a)
  2194. if (OASIS_Debug >= 15) then
  2195. write(nulprt,*) subname//trim(string),' resize varf3a ',size(varf3b),cnt+cntr
  2196. call oasis_flush(nulprt)
  2197. endif
  2198. allocate(varf3a(cnt+cntr))
  2199. varf3a(1:size(varf3b)) = varf3b(1:size(varf3b))
  2200. deallocate(varf3b)
  2201. endif
  2202. endif
  2203. varf1a(cnt) = recv_varf1(n)
  2204. if (present2) varf2a(cnt) = recv_varf2(n)
  2205. if (present3) varf3a(cnt) = recv_varf3(n)
  2206. endif
  2207. enddo ! cntr
  2208. if (local_timers_on) call oasis_timer_stop(trim(string)//'_rl_rootsrch')
  2209. if (cntr > 0) then
  2210. deallocate(recv_varf1)
  2211. if (present2) deallocate(recv_varf2)
  2212. if (present3) deallocate(recv_varf3)
  2213. endif
  2214. endif ! recvid >= 0
  2215. enddo ! maxloops
  2216. !-------------------------------------------------
  2217. !> * Broadcast the list information to all tasks from root
  2218. !-------------------------------------------------
  2219. if (local_timers_on) then
  2220. call oasis_timer_start(trim(string)//'_rl_bcast_barrier')
  2221. if (comm /= MPI_COMM_NULL) &
  2222. call MPI_BARRIER(comm, ierr)
  2223. call oasis_timer_stop(trim(string)//'_rl_bcast_barrier')
  2224. endif
  2225. if (local_timers_on) call oasis_timer_start(trim(string)//'_rl_bcast')
  2226. call oasis_mpi_bcast(cnt,comm,subname//trim(string)//' cnt')
  2227. cntout = cnt
  2228. allocate(lout1(cntout))
  2229. if (commrank == 0) then
  2230. do n = 1,cntout
  2231. lout1(n) = trim(varf1a(n))
  2232. enddo
  2233. endif
  2234. deallocate(varf1a)
  2235. call oasis_mpi_bcast(lout1,comm,subname//trim(string)//' lout1')
  2236. if (present2) then
  2237. allocate(lout2(cntout))
  2238. if (commrank == 0) then
  2239. do n = 1,cntout
  2240. lout2(n) = trim(varf2a(n))
  2241. enddo
  2242. endif
  2243. deallocate(varf2a)
  2244. call oasis_mpi_bcast(lout2,comm,subname//trim(string)//' lout2')
  2245. endif
  2246. if (present3) then
  2247. allocate(lout3(cntout))
  2248. if (commrank == 0) then
  2249. do n = 1,cntout
  2250. lout3(n) = varf3a(n)
  2251. enddo
  2252. endif
  2253. deallocate(varf3a)
  2254. call oasis_mpi_bcast(lout3,comm,subname//trim(string)//' lout3')
  2255. endif
  2256. !--- document
  2257. if (OASIS_debug >= 15) then
  2258. do n = 1,cnt
  2259. if (present2 .and. present3) then
  2260. write(nulprt,*) subname,trim(string),' list: ',n,trim(lout1(n)),' ',trim(lout2(n)),lout3(n)
  2261. elseif (present2) then
  2262. write(nulprt,*) subname,trim(string),' list: ',n,trim(lout1(n)),' ',trim(lout2(n))
  2263. elseif (present3) then
  2264. write(nulprt,*) subname,trim(string),' list: ',n,trim(lout1(n)),lout3(n)
  2265. else
  2266. write(nulprt,*) subname,trim(string),' list: ',n,trim(lout1(n))
  2267. endif
  2268. enddo
  2269. call oasis_flush(nulprt)
  2270. endif
  2271. if (local_timers_on) call oasis_timer_stop (trim(string)//'_rl_bcast')
  2272. call oasis_debug_exit(subname)
  2273. END SUBROUTINE oasis_mpi_reducelists
  2274. !===============================================================================
  2275. !===============================================================================
  2276. END MODULE mod_oasis_mpi