tm5_partools.F90 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806
  1. !
  2. #define TRACEBACK write (gol,'("in ",a," (",a,", line",i5,")")') rname, __FILE__, __LINE__; call goErr
  3. #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
  4. #define IF_NOTOK_MPI(action) if (ierr/=MPI_SUCCESS) then; TRACEBACK; action; return; end if
  5. #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if
  6. !
  7. #include "tm5.inc"
  8. !
  9. !-----------------------------------------------------------------------------
  10. ! TM5 !
  11. !-----------------------------------------------------------------------------
  12. !BOP
  13. !
  14. ! !MODULE: PARTOOLS
  15. !
  16. ! !DESCRIPTION: MPI general tools. This module:
  17. !
  18. ! - holds MPI constants, specifically defining some if we are not running with MPI
  19. !
  20. ! - initializes, finalizes and aborts MPI (wrappers, so it works if not runnning MPI):
  21. !
  22. ! TM5_MPI_Init, TM5_MPI_Init2 (init row/col communicators)
  23. ! TM5_MPI_Done
  24. ! TM5_MPI_Abort
  25. !
  26. ! - provides wrappers around some of MPI broadcast/barrier/reduce calls :
  27. !
  28. ! PAR_BARRIER :
  29. ! PAR_STOPMPI :
  30. ! PAR_BROADCAST_STATUS :
  31. ! PAR_BROADCAST :
  32. ! PAR_REDUCE : reduction is done across the array. Result size = 1
  33. ! PAR_REDUCE_ELEMENT : reduction is done for each element. Result size = size of original array
  34. !
  35. ! These are general tools, that deal with MPI, regardless of the domain decomposition used.
  36. !
  37. ! - Some of these call can be limited to the 'row' or 'col' communicators, but
  38. ! this is partially implemented (although trivial to extent if needed)
  39. !
  40. !\\
  41. !\\
  42. ! !INTERFACE:
  43. !
  44. MODULE PARTOOLS
  45. !
  46. ! !USES:
  47. !
  48. use GO, only : gol, goPr, goErr
  49. use dims, only : nregions_all
  50. #ifdef MPI
  51. use mpi
  52. #endif
  53. IMPLICIT NONE
  54. !
  55. ! !PUBLIC DATA MEMBERS:
  56. !
  57. integer, parameter :: PAR_OPER_SUM = 100 ! mpi reduce flag
  58. integer :: localComm ! global communicator (equal to MPI_COMM_WORLD if not coupled model)
  59. integer :: row_comm ! row communicator
  60. integer :: col_comm ! column communicator
  61. integer :: my_real ! platform dependent reference to real values for MPI
  62. integer :: myid ! rank in localComm
  63. integer :: npes ! total number of PE's
  64. integer :: npe_lat ! #pes in lat direction
  65. integer :: npe_lon ! #pes in long direction
  66. integer :: ierr ! return status of MPI routine calls
  67. integer :: root ! myid of root in localComm
  68. integer :: RowRootId ! myid of row_root of my row (in localComm)
  69. #ifndef MPI
  70. integer, parameter :: MPI_SUCCESS = 0
  71. integer, parameter :: MPI_INFO_NULL = 0
  72. integer, parameter :: MPI_CHARACTER = 0
  73. integer, parameter :: MPI_INTEGER = 0
  74. integer, parameter :: MPI_PROC_NULL = -999
  75. #endif
  76. logical :: isRoot, isRowRoot ! is process global root, row root?
  77. character(len=6) :: procname ! character keys for each processor
  78. !
  79. ! !PRIVATE DATA MEMBERS:
  80. !
  81. integer, private :: irow, jcol ! rank in column and row communicators
  82. character(len=*), parameter, private :: mname='ParTools'
  83. !
  84. ! !INTERFACE:
  85. !
  86. INTERFACE Par_Broadcast
  87. MODULE PROCEDURE Par_Broadcast_i0
  88. MODULE PROCEDURE Par_Broadcast_i1
  89. MODULE PROCEDURE Par_Broadcast_s
  90. MODULE PROCEDURE Par_Broadcast_l0
  91. MODULE PROCEDURE Par_Broadcast_l1
  92. MODULE PROCEDURE Par_Broadcast_r0
  93. MODULE PROCEDURE Par_Broadcast_r1
  94. MODULE PROCEDURE Par_Broadcast_r2
  95. MODULE PROCEDURE Par_Broadcast_r3
  96. END INTERFACE
  97. INTERFACE Par_Reduce
  98. MODULE PROCEDURE Par_Reduce_i0
  99. MODULE PROCEDURE Par_Reduce_r0
  100. MODULE PROCEDURE Par_Reduce_r1 ! r1, r2, ... are useful only to get results that do not depend
  101. ! MODULE PROCEDURE Par_Reduce_r2 ! on the number of processors (when summing). It is cheaper to
  102. MODULE PROCEDURE Par_Reduce_r3 ! do the operation on each proc, and then reduce a single value.
  103. END INTERFACE
  104. INTERFACE Par_Reduce_Element
  105. MODULE PROCEDURE Par_Reduce_element_r1
  106. MODULE PROCEDURE Par_Reduce_element_r2
  107. MODULE PROCEDURE Par_Reduce_element_r3
  108. END INTERFACE
  109. !
  110. ! !REVISION HISTORY:
  111. ! 18 Jan 2012 - P. Le Sager - revamped for lon-lat MPI domain decomposition
  112. !
  113. ! !REMARKS:
  114. !
  115. !EOP
  116. !------------------------------------------------------------------------
  117. CONTAINS
  118. !--------------------------------------------------------------------------
  119. ! TM5 !
  120. !--------------------------------------------------------------------------
  121. !BOP
  122. !
  123. ! !IROUTINE: TM5_MPI_Init
  124. !
  125. ! !DESCRIPTION: initializes MPI
  126. !\\
  127. !\\
  128. ! !INTERFACE:
  129. !
  130. SUBROUTINE TM5_MPI_Init( status, comm )
  131. !
  132. ! !OUTPUT PARAMETERS:
  133. !
  134. integer, intent(out) :: status
  135. !
  136. ! !INPUT PARAMETERS:
  137. !
  138. integer, intent(in), optional :: comm
  139. !
  140. ! !REVISION HISTORY:
  141. !
  142. !EOP
  143. !------------------------------------------------------------------------
  144. !BOC
  145. character(len=*), parameter :: rname = mname//'/TM5_MPI_Init'
  146. #ifdef MPI
  147. ! communicator provided, for example by prism coupler ?
  148. if ( present(comm) ) then
  149. localComm = comm
  150. else
  151. ! init mpi here to set MPI_COMM_WORLD etc
  152. call MPI_INIT( ierr )
  153. IF_NOTOK_MPI(status=1)
  154. localComm = MPI_COMM_WORLD
  155. end if
  156. ! obtain number of proceses:
  157. call MPI_COMM_SIZE( localComm, npes, ierr )
  158. IF_NOTOK_MPI(status=1)
  159. ! obtain proces number:
  160. call MPI_COMM_RANK( localComm, myid, ierr )
  161. IF_NOTOK_MPI(status=1)
  162. ! set root in localComm to PE 0; 'real' default to double precision
  163. root = 0
  164. my_real = MPI_DOUBLE_PRECISION
  165. #else
  166. localComm = 0 ! dummy communicator
  167. npes = 1 ! single processor
  168. root = 0 ! id for root processor
  169. myid = root ! only one processor, so this is always root
  170. #endif
  171. ! set processor names: pe0000, pe0001, ...
  172. write (procname,'("pe",i4.4)') myid
  173. isRoot = ( myid == root )
  174. ! ok
  175. status = 0
  176. END SUBROUTINE TM5_MPI_Init
  177. !EOC
  178. !--------------------------------------------------------------------------
  179. ! TM5 !
  180. !--------------------------------------------------------------------------
  181. !BOP
  182. !
  183. ! !IROUTINE: TM5_MPI_INIT2
  184. !
  185. ! !DESCRIPTION: Step #2 of initialization, which requires input from rcfile.
  186. ! It defines the extra row and column communicators.
  187. !\\
  188. !\\
  189. ! !INTERFACE:
  190. !
  191. SUBROUTINE TM5_MPI_Init2( nlon, nlat, status )
  192. !
  193. ! !INPUT PARAMETERS:
  194. !
  195. integer, intent(in) :: nlat, nlon ! # PE on each direction
  196. !
  197. ! !OUTPUT PARAMETERS:
  198. !
  199. integer, intent(out) :: status
  200. !
  201. ! !REVISION HISTORY:
  202. ! 21 Feb 2012 - P. Le Sager -
  203. !
  204. !EOP
  205. !------------------------------------------------------------------------
  206. !BOC
  207. character(len=*), parameter :: rname = mname//'/TM5_MPI_Init2'
  208. integer :: irow, jcol
  209. npe_lat=nlat
  210. npe_lon=nlon
  211. #ifdef MPI
  212. irow = myid/npe_lon
  213. jcol = mod(myid,npe_lon)
  214. ! NOTE: could use myid as key for rank designation if that facilitates some comm
  215. call MPI_COMM_SPLIT(localComm, irow, jcol, row_comm, ierr)
  216. IF_NOTOK_MPI(status=1)
  217. isRowRoot = jcol==0
  218. RowRootId = (myid/npe_lon)*npe_lon
  219. ! define column communicator [not needed yet]
  220. call MPI_COMM_SPLIT(localComm, jcol, irow, col_comm, ierr)
  221. IF_NOTOK_MPI(status=1)
  222. #else
  223. row_comm = 0 ! dummy communicator
  224. col_comm = 0 ! dummy communicator
  225. #endif
  226. status = 0
  227. END SUBROUTINE TM5_MPI_Init2
  228. !EOC
  229. !--------------------------------------------------------------------------
  230. ! TM5 !
  231. !--------------------------------------------------------------------------
  232. !BOP
  233. !
  234. ! !IROUTINE: TM5_MPI_Done
  235. !
  236. ! !DESCRIPTION: finalizes MPI
  237. !\\
  238. !\\
  239. ! !INTERFACE:
  240. !
  241. SUBROUTINE TM5_MPI_Done( status, comm )
  242. !
  243. ! !OUTPUT PARAMETERS:
  244. !
  245. integer, intent(out) :: status
  246. !
  247. ! !INPUT PARAMETERS:
  248. !
  249. integer, intent(in), optional :: comm
  250. !
  251. ! !REVISION HISTORY:
  252. !
  253. !EOP
  254. !------------------------------------------------------------------------
  255. !BOC
  256. character(len=*), parameter :: rname = mname//'/TM5_MPI_Done'
  257. #ifdef MPI
  258. ! shut-down communication, only if communicator is not provided
  259. if (.not. present(comm) ) then
  260. !write (*,'("call MPI_Finalize from proces ",i6)') myid
  261. call MPI_Finalize( ierr )
  262. IF_NOTOK_MPI(status=1)
  263. end if
  264. #endif
  265. ! ok
  266. status = 0
  267. END SUBROUTINE TM5_MPI_Done
  268. !EOC
  269. !--------------------------------------------------------------------------
  270. ! TM5 !
  271. !--------------------------------------------------------------------------
  272. !BOP
  273. !
  274. ! !IROUTINE: TM5_MPI_Abort
  275. !
  276. ! !DESCRIPTION:
  277. !\\
  278. !\\
  279. ! !INTERFACE:
  280. !
  281. subroutine TM5_MPI_Abort( errorcode, status )
  282. !
  283. ! !USES:
  284. !
  285. use GO, only : goExit
  286. !
  287. ! !INPUT PARAMETERS:
  288. !
  289. integer, intent(in) :: errorcode
  290. !
  291. ! !OUTPUT PARAMETERS:
  292. !
  293. integer, intent(out) :: status
  294. !
  295. ! !REVISION HISTORY:
  296. ! 18 Jan 2012 - P. Le Sager -
  297. !
  298. ! !REMARKS:
  299. !
  300. ! (pls, 8-4-2011) Sometimes the code does not return from MPI_Abort, for
  301. ! example when a problem reading restart files occurs. From the doc:
  302. ! -------------------------------------------------
  303. ! "Before the error value is returned, the current MPI error handler is
  304. ! called. By default, this error handler aborts the MPI job, except for
  305. ! I/O function errors."
  306. ! -------------------------------------------------
  307. ! so, the only way to nicely abort is to close files when an i/o error
  308. ! occurs. Done with a new macro for problems with reading/writing restart
  309. ! (see tm5_restart.F90). Check if your module/routine is prone to
  310. ! i/o error, and apply a similar patch.
  311. !
  312. !EOP
  313. !------------------------------------------------------------------------
  314. !BOC
  315. character(len=*), parameter :: rname = mname//'/TM5_MPI_Abort'
  316. #ifdef MPI
  317. ! emergency break ...
  318. call MPI_Abort( localComm, errorcode, ierr )
  319. IF_NOTOK_MPI(status=1)
  320. #else
  321. ! system exit:
  322. call goExit( errorcode )
  323. #endif
  324. ! ok
  325. status = 0
  326. end subroutine TM5_MPI_Abort
  327. !EOC
  328. !--------------------------------------------------------------------------
  329. ! TM5 !
  330. !--------------------------------------------------------------------------
  331. !BOP
  332. !
  333. ! !IROUTINE: Par_Barrier
  334. !
  335. ! !DESCRIPTION:
  336. !\\
  337. !\\
  338. ! !INTERFACE:
  339. !
  340. SUBROUTINE PAR_BARRIER( ROW, COL)
  341. !
  342. ! !INPUT PARAMETERS:
  343. !
  344. logical, intent(in), optional :: row, col ! to limit call to sub-communicator
  345. !
  346. ! !REVISION HISTORY:
  347. !
  348. !EOP
  349. !------------------------------------------------------------------------
  350. !BOC
  351. character(len=*), parameter :: rname = mname//'/PAR_BARRIER'
  352. #ifdef MPI
  353. integer :: l_comm
  354. l_comm=localComm
  355. if(present(row)) then
  356. if(row) l_comm=row_comm
  357. end if
  358. if(present(col)) then
  359. if(col) l_comm=col_comm
  360. end if
  361. call mpi_barrier( l_comm, ierr )
  362. IF_NOTOK_MPI(write (gol,*)"error MPI_BARRIER in PAR_BARRIER";call goErr)
  363. #endif
  364. END SUBROUTINE PAR_BARRIER
  365. !EOC
  366. !--------------------------------------------------------------------------
  367. ! TM5 !
  368. !--------------------------------------------------------------------------
  369. !BOP
  370. !
  371. ! !IROUTINE: Par_StopMPI
  372. !
  373. ! !DESCRIPTION:
  374. !\\
  375. !\\
  376. ! !INTERFACE:
  377. !
  378. subroutine Par_StopMPI
  379. !
  380. ! !REVISION HISTORY:
  381. !
  382. !EOP
  383. !------------------------------------------------------------------------
  384. !BOC
  385. character(len=*), parameter :: rname = mname//'/Par_StopMPI'
  386. write (*,'("WARNING - (par_)stopmpi should be avoided; please trace back to main program ...")')
  387. #ifdef MPI
  388. ! shut down mpi communication:
  389. call mpi_finalize(ierr)
  390. IF_NOTOK_MPI(write (gol,*)"error MPI_FINALIZE in Par_StopMPI";call goErr)
  391. #endif
  392. ! fortran stop ....
  393. stop 'Fortran STOP in Par_StopMPI ...'
  394. end subroutine Par_StopMPI
  395. !EOC
  396. !--------------------------------------------------------------------------
  397. ! TM5 !
  398. !--------------------------------------------------------------------------
  399. !BOP
  400. !
  401. ! !IROUTINE: Par_Broadcast_Status
  402. !
  403. ! !DESCRIPTION: Broadcast integer istat from id PE to all. Same as
  404. ! Par_Broadcast_i(istat, id, istat)
  405. !\\
  406. !\\
  407. ! !INTERFACE:
  408. !
  409. subroutine Par_Broadcast_Status( istat, id )
  410. !
  411. ! !INPUT/OUTPUT PARAMETERS:
  412. !
  413. integer, intent(inout) :: istat
  414. !
  415. ! !INPUT PARAMETERS:
  416. !
  417. integer, intent(in) :: id
  418. !
  419. ! !REVISION HISTORY:
  420. !
  421. ! !REMARKS:
  422. !
  423. !EOP
  424. !------------------------------------------------------------------------
  425. !BOC
  426. character(len=*), parameter :: rname = mname//'/Par_Broadcast_Status'
  427. integer :: status
  428. #ifdef MPI
  429. ! send the input status to all other processes:
  430. call Par_Broadcast( istat, status, id=id )
  431. IF_NOTOK_RETURN(istat=1)
  432. #endif
  433. end subroutine Par_Broadcast_Status
  434. !EOC
  435. !--------------------------------------------------------------------------
  436. ! TM5 !
  437. !--------------------------------------------------------------------------
  438. !BOP
  439. !
  440. ! !IROUTINE: Par_Broadcast_i0
  441. !
  442. ! !DESCRIPTION: broadcast one integer (scalar case)
  443. !\\
  444. !\\
  445. ! !INTERFACE:
  446. !
  447. subroutine Par_Broadcast_i0( i, status, ID, ROW, COL )
  448. !
  449. ! !INPUT/OUTPUT PARAMETERS:
  450. !
  451. integer, intent(inout) :: i
  452. integer, intent(out) :: status
  453. integer, intent(in), optional :: id ! broadcaster ID (default is communicator root)
  454. logical, intent(in), optional :: row ! limit to PE on row_comm (default is global localComm)
  455. logical, intent(in), optional :: col ! limit to PE on col_comm (default is global localComm)
  456. !
  457. ! !REVISION HISTORY:
  458. ! 26 Mar 2012 - P. Le Sager - added ROW, COL options. Made ID optional.
  459. !
  460. !EOP
  461. !------------------------------------------------------------------------
  462. !BOC
  463. character(len=*), parameter :: rname = mname//'/Par_Broadcast_i'
  464. logical :: l_row, l_col
  465. integer :: l_root, l_comm, l_id
  466. #ifdef MPI
  467. l_row=.false. ; if(present(row)) l_row=row
  468. l_col=.false. ; if(present(col)) l_col=col
  469. if(l_row)then
  470. l_root = 0 ! by our own design
  471. l_comm = row_comm
  472. else if(l_col) then
  473. l_root = 0 ! by our own design
  474. l_comm = col_comm
  475. else
  476. l_root = root
  477. l_comm = localComm
  478. end if
  479. l_id = l_root
  480. if(present(id)) l_id=id
  481. call MPI_BCast( i, 1, MPI_INTEGER, l_id, l_comm, ierr )
  482. IF_NOTOK_MPI(status=1)
  483. #endif
  484. status = 0
  485. end subroutine Par_Broadcast_i0
  486. !EOC
  487. !--------------------------------------------------------------------------
  488. ! TM5 !
  489. !--------------------------------------------------------------------------
  490. !BOP
  491. !
  492. ! !IROUTINE: Par_Broadcast_i1
  493. !
  494. ! !DESCRIPTION: Broadcast 1-D array of integers.
  495. !\\
  496. !\\
  497. ! !INTERFACE:
  498. !
  499. subroutine Par_Broadcast_i1( i, status, ID, ROW, COL )
  500. !
  501. ! !INPUT/OUTPUT PARAMETERS:
  502. !
  503. integer, intent(inout) :: i(:)
  504. integer, intent(out) :: status
  505. integer, intent(in), optional :: id ! broadcaster ID (default is communicator root)
  506. logical, intent(in), optional :: row ! limit to PE on row_comm (default is global localComm)
  507. logical, intent(in), optional :: col ! limit to PE on col_comm (default is global localComm)
  508. !
  509. !EOP
  510. !------------------------------------------------------------------------
  511. !BOC
  512. character(len=*), parameter :: rname = mname//'/Par_Broadcast_i'
  513. logical :: l_row, l_col
  514. integer :: l_root, l_comm, l_id
  515. #ifdef MPI
  516. l_row=.false. ; if(present(row)) l_row=row
  517. l_col=.false. ; if(present(col)) l_col=col
  518. if(l_row)then
  519. l_root = 0 ! by our own design
  520. l_comm = row_comm
  521. else if(l_col) then
  522. l_root = 0 ! by our own design
  523. l_comm = col_comm
  524. else
  525. l_root = root
  526. l_comm = localComm
  527. end if
  528. l_id = l_root
  529. if(present(id)) l_id=id
  530. call MPI_BCast( i, size(i), MPI_INTEGER, l_id, l_comm, ierr )
  531. IF_NOTOK_MPI(status=1)
  532. #endif
  533. status = 0
  534. end subroutine Par_Broadcast_i1
  535. !EOC
  536. !--------------------------------------------------------------------------
  537. ! TM5 !
  538. !--------------------------------------------------------------------------
  539. !BOP
  540. !
  541. ! !IROUTINE: Par_Broadcast_s
  542. !
  543. ! !DESCRIPTION:
  544. !\\
  545. !\\
  546. ! !INTERFACE:
  547. !
  548. subroutine Par_Broadcast_s( s, status, ID, ROW, COL )
  549. !
  550. ! !INPUT/OUTPUT PARAMETERS:
  551. !
  552. character(len=*), intent(inout) :: s
  553. integer, intent(out) :: status
  554. integer, intent(in), optional :: id ! broadcaster ID (default is communicator root)
  555. logical, intent(in), optional :: row ! limit to PE on row_comm (default is global localComm)
  556. logical, intent(in), optional :: col ! limit to PE on col_comm (default is global localComm)
  557. !
  558. ! !REVISION HISTORY:
  559. ! 26 Mar 2012 - P. Le Sager - added ROW, COL options. Made ID optional.
  560. !
  561. !EOP
  562. !------------------------------------------------------------------------
  563. !BOC
  564. character(len=*), parameter :: rname = mname//'/Par_Broadcast_s'
  565. logical :: l_row, l_col
  566. integer :: l_root, l_comm, l_id
  567. #ifdef MPI
  568. l_row=.false. ; if(present(row)) l_row=row
  569. l_col=.false. ; if(present(col)) l_col=col
  570. if(l_row)then
  571. l_root = 0 ! by our own design
  572. l_comm = row_comm
  573. else if(l_col) then
  574. l_root = 0 ! by our own design
  575. l_comm = col_comm
  576. else
  577. l_root = root
  578. l_comm = localComm
  579. end if
  580. l_id = l_root
  581. if(present(id)) l_id=id
  582. call MPI_BCast( s, len(s), MPI_CHARACTER, l_id, l_comm, ierr )
  583. IF_NOTOK_MPI(status=1)
  584. #endif
  585. status = 0
  586. end subroutine Par_Broadcast_s
  587. !EOC
  588. !--------------------------------------------------------------------------
  589. ! TM5 !
  590. !--------------------------------------------------------------------------
  591. !BOP
  592. !
  593. ! !IROUTINE: Par_Broadcast_l0
  594. !
  595. ! !DESCRIPTION:
  596. !\\
  597. !\\
  598. ! !INTERFACE:
  599. !
  600. subroutine Par_Broadcast_l0( x, status, ID, ROW, COL )
  601. !
  602. ! !INPUT/OUTPUT PARAMETERS:
  603. !
  604. logical, intent(inout) :: x
  605. integer, intent(out) :: status
  606. integer, intent(in), optional :: id ! broadcaster ID (default is communicator root)
  607. logical, intent(in), optional :: row ! limit to PE on row_comm (default is global localComm)
  608. logical, intent(in), optional :: col ! limit to PE on col_comm (default is global localComm)
  609. !
  610. ! !REVISION HISTORY:
  611. ! 26 Mar 2012 - P. Le Sager - added ROW, COL options. Made ID optional.
  612. !
  613. !EOP
  614. !------------------------------------------------------------------------
  615. !BOC
  616. character(len=*), parameter :: rname = mname//'/Par_Broadcast_l0'
  617. logical :: l_row, l_col
  618. integer :: l_root, l_comm, l_id
  619. #ifdef MPI
  620. l_row=.false. ; if(present(row)) l_row=row
  621. l_col=.false. ; if(present(col)) l_col=col
  622. if(l_row)then
  623. l_root = 0 ! by our own design
  624. l_comm = row_comm
  625. else if(l_col) then
  626. l_root = 0 ! by our own design
  627. l_comm = col_comm
  628. else
  629. l_root = root
  630. l_comm = localComm
  631. end if
  632. l_id = l_root
  633. if(present(id)) l_id=id
  634. call mpi_bcast( x, 1, MPI_LOGICAL, l_id, l_comm, ierr )
  635. IF_NOTOK_MPI(status=1)
  636. #endif
  637. status = 0
  638. end subroutine Par_Broadcast_l0
  639. !EOC
  640. !--------------------------------------------------------------------------
  641. ! TM5 !
  642. !--------------------------------------------------------------------------
  643. !BOP
  644. !
  645. ! !IROUTINE: Par_Broadcast_l1
  646. !
  647. ! !DESCRIPTION:
  648. !\\
  649. !\\
  650. ! !INTERFACE:
  651. !
  652. subroutine Par_Broadcast_l1( x, status, ID, ROW, COL )
  653. !
  654. ! !INPUT/OUTPUT PARAMETERS:
  655. !
  656. logical, intent(inout) :: x(:)
  657. integer, intent(out) :: status
  658. integer, intent(in), optional :: id ! broadcaster ID (default is communicator root)
  659. logical, intent(in), optional :: row ! limit to PE on row_comm (default is global localComm)
  660. logical, intent(in), optional :: col ! limit to PE on col_comm (default is global localComm)
  661. !
  662. ! !REVISION HISTORY:
  663. ! 26 Mar 2012 - P. Le Sager - added ROW, COL options. Made ID optional.
  664. !
  665. !EOP
  666. !------------------------------------------------------------------------
  667. !BOC
  668. character(len=*), parameter :: rname = mname//'/Par_Broadcast_l1'
  669. logical :: l_row, l_col
  670. integer :: l_root, l_comm, l_id
  671. #ifdef MPI
  672. l_row=.false. ; if(present(row)) l_row=row
  673. l_col=.false. ; if(present(col)) l_col=col
  674. if(l_row)then
  675. l_root = 0 ! by our own design
  676. l_comm = row_comm
  677. else if(l_col) then
  678. l_root = 0 ! by our own design
  679. l_comm = col_comm
  680. else
  681. l_root = root
  682. l_comm = localComm
  683. end if
  684. l_id = l_root
  685. if(present(id)) l_id=id
  686. call mpi_bcast( x, size(x), MPI_LOGICAL, l_id, l_comm, ierr )
  687. IF_NOTOK_MPI(status=1)
  688. #endif
  689. status = 0
  690. end subroutine Par_Broadcast_l1
  691. !EOC
  692. !--------------------------------------------------------------------------
  693. ! TM5 !
  694. !--------------------------------------------------------------------------
  695. !BOP
  696. !
  697. ! !IROUTINE: Par_Broadcast_r0
  698. !
  699. ! !DESCRIPTION:
  700. !\\
  701. !\\
  702. ! !INTERFACE:
  703. !
  704. subroutine Par_Broadcast_r0( x, status, ID, ROW, COL )
  705. !
  706. ! !INPUT/OUTPUT PARAMETERS:
  707. !
  708. real, intent(inout) :: x
  709. integer, intent(out) :: status
  710. integer, intent(in), optional :: id ! broadcaster ID (default is communicator root)
  711. logical, intent(in), optional :: row ! limit to PE on row_comm (default is global localComm)
  712. logical, intent(in), optional :: col ! limit to PE on col_comm (default is global localComm)
  713. !
  714. ! !REVISION HISTORY:
  715. ! 26 Mar 2012 - P. Le Sager - added ROW, COL options. Made ID optional.
  716. !
  717. !EOP
  718. !------------------------------------------------------------------------
  719. !BOC
  720. character(len=*), parameter :: rname = mname//'/Par_Broadcast_r0'
  721. logical :: l_row, l_col
  722. integer :: l_root, l_comm, l_id
  723. #ifdef MPI
  724. l_row=.false. ; if(present(row)) l_row=row
  725. l_col=.false. ; if(present(col)) l_col=col
  726. if(l_row)then
  727. l_root = 0 ! by our own design
  728. l_comm = row_comm
  729. else if(l_col) then
  730. l_root = 0 ! by our own design
  731. l_comm = col_comm
  732. else
  733. l_root = root
  734. l_comm = localComm
  735. end if
  736. l_id = l_root
  737. if(present(id)) l_id=id
  738. call mpi_bcast( x, 1, my_real, l_id, l_comm, ierr )
  739. IF_NOTOK_MPI(status=1)
  740. #endif
  741. status = 0
  742. end subroutine Par_Broadcast_r0
  743. !EOC
  744. !--------------------------------------------------------------------------
  745. ! TM5 !
  746. !--------------------------------------------------------------------------
  747. !BOP
  748. !
  749. ! !IROUTINE: Par_Broadcast_r1
  750. !
  751. ! !DESCRIPTION:
  752. !\\
  753. !\\
  754. ! !INTERFACE:
  755. !
  756. subroutine Par_Broadcast_r1( x, status, ID, ROW, COL )
  757. !
  758. ! !INPUT/OUTPUT PARAMETERS:
  759. !
  760. real, intent(inout) :: x(:)
  761. integer, intent(out) :: status
  762. integer, intent(in), optional :: id ! broadcaster ID (default is communicator root)
  763. logical, intent(in), optional :: row ! limit to PE on row_comm (default is global localComm)
  764. logical, intent(in), optional :: col ! limit to PE on col_comm (default is global localComm)
  765. !
  766. ! !REVISION HISTORY:
  767. ! 26 Mar 2012 - P. Le Sager - added ROW, COL options. Made ID optional.
  768. !
  769. !EOP
  770. !------------------------------------------------------------------------
  771. !BOC
  772. character(len=*), parameter :: rname = mname//'/Par_Broadcast_r1'
  773. logical :: l_row, l_col
  774. integer :: l_root, l_comm, l_id
  775. #ifdef MPI
  776. l_row=.false. ; if(present(row)) l_row=row
  777. l_col=.false. ; if(present(col)) l_col=col
  778. if(l_row)then
  779. l_root = 0 ! by our own design
  780. l_comm = row_comm
  781. else if(l_col) then
  782. l_root = 0 ! by our own design
  783. l_comm = col_comm
  784. else
  785. l_root = root
  786. l_comm = localComm
  787. end if
  788. l_id = l_root
  789. if(present(id)) l_id=id
  790. call mpi_bcast( x, size(x), my_real, l_id, l_comm, ierr )
  791. IF_NOTOK_MPI(status=1)
  792. #endif
  793. status = 0
  794. end subroutine Par_Broadcast_r1
  795. !EOC
  796. !--------------------------------------------------------------------------
  797. ! TM5 !
  798. !--------------------------------------------------------------------------
  799. !BOP
  800. !
  801. ! !IROUTINE: Par_Broadcast_r2
  802. !
  803. ! !DESCRIPTION:
  804. !\\
  805. !\\
  806. ! !INTERFACE:
  807. !
  808. subroutine Par_Broadcast_r2( x, status, ID, ROW, COL )
  809. !
  810. ! !INPUT/OUTPUT PARAMETERS:
  811. !
  812. real, intent(inout) :: x(:,:)
  813. integer, intent(out) :: status
  814. integer, intent(in), optional :: id ! broadcaster ID (default is communicator root)
  815. logical, intent(in), optional :: row ! limit to PE on row_comm (default is global localComm)
  816. logical, intent(in), optional :: col ! limit to PE on col_comm (default is global localComm)
  817. !
  818. ! !REVISION HISTORY:
  819. ! 26 Mar 2012 - P. Le Sager - added ROW, COL options. Made ID optional.
  820. !
  821. !EOP
  822. !------------------------------------------------------------------------
  823. !BOC
  824. character(len=*), parameter :: rname = mname//'/Par_Broadcast_r2'
  825. logical :: l_row, l_col
  826. integer :: l_root, l_comm, l_id
  827. #ifdef MPI
  828. l_row=.false. ; if(present(row)) l_row=row
  829. l_col=.false. ; if(present(col)) l_col=col
  830. if(l_row)then
  831. l_root = 0 ! by our own design
  832. l_comm = row_comm
  833. else if(l_col) then
  834. l_root = 0 ! by our own design
  835. l_comm = col_comm
  836. else
  837. l_root = root
  838. l_comm = localComm
  839. end if
  840. l_id = l_root
  841. if(present(id)) l_id=id
  842. call mpi_bcast( x, size(x), my_real, l_id, l_comm, ierr )
  843. IF_NOTOK_MPI(status=1)
  844. #endif
  845. status = 0
  846. end subroutine Par_Broadcast_r2
  847. !EOC
  848. !--------------------------------------------------------------------------
  849. ! TM5 !
  850. !--------------------------------------------------------------------------
  851. !BOP
  852. !
  853. ! !IROUTINE: Par_Broadcast_r3
  854. !
  855. ! !DESCRIPTION:
  856. !\\
  857. !\\
  858. ! !INTERFACE:
  859. !
  860. subroutine Par_Broadcast_r3( x, status, ID, ROW, COL )
  861. !
  862. ! !INPUT/OUTPUT PARAMETERS:
  863. !
  864. real, intent(inout) :: x(:,:,:)
  865. integer, intent(out) :: status
  866. integer, intent(in), optional :: id ! broadcaster ID (default is communicator root)
  867. logical, intent(in), optional :: row ! limit to PE on row_comm (default is global localComm)
  868. logical, intent(in), optional :: col ! limit to PE on col_comm (default is global localComm)
  869. !
  870. ! !REVISION HISTORY:
  871. ! 26 Mar 2012 - P. Le Sager - added ROW, COL options. Made ID optional.
  872. !
  873. !EOP
  874. !------------------------------------------------------------------------
  875. !BOC
  876. character(len=*), parameter :: rname = mname//'/Par_Broadcast_r3'
  877. logical :: l_row, l_col
  878. integer :: l_root, l_comm, l_id
  879. #ifdef MPI
  880. l_row=.false. ; if(present(row)) l_row=row
  881. l_col=.false. ; if(present(col)) l_col=col
  882. if(l_row)then
  883. l_root = 0 ! by our own design
  884. l_comm = row_comm
  885. else if(l_col) then
  886. l_root = 0 ! by our own design
  887. l_comm = col_comm
  888. else
  889. l_root = root
  890. l_comm = localComm
  891. end if
  892. l_id = l_root
  893. if(present(id)) l_id=id
  894. call mpi_bcast( x, size(x), my_real, l_id, l_comm, ierr )
  895. IF_NOTOK_MPI(status=1)
  896. #endif
  897. status = 0
  898. end subroutine Par_Broadcast_r3
  899. !EOC
  900. !--------------------------------------------------------------------------
  901. ! TM5 !
  902. !--------------------------------------------------------------------------
  903. !BOP
  904. !
  905. ! !IROUTINE: PAR_REDUCE_I0
  906. !
  907. ! !DESCRIPTION: Wrapper around MPI_REDUCE or MPI_ALLREDUCE.
  908. !
  909. ! Apply to a SINGLE INTEGER.
  910. !\\
  911. !\\
  912. ! !INTERFACE:
  913. !
  914. SUBROUTINE PAR_REDUCE_I0( DATA, OP, RESULTAT, STATUS, ALL, ROW )
  915. !
  916. ! !INPUT PARAMETERS:
  917. !
  918. integer, intent(in) :: data
  919. character(len=3), intent(in) :: op ! 'MAX', 'MIN' or 'SUM'
  920. logical, intent(in), optional :: all ! use MPI_ALLREDUCE instead of MPI_REDUCE
  921. logical, intent(in), optional :: row ! limit to PE on row_comm
  922. !
  923. ! !OUTPUT PARAMETERS:
  924. !
  925. integer, intent(out) :: resultat
  926. integer, intent(out) :: status
  927. !
  928. ! !REVISION HISTORY:
  929. ! 19 Jun 2013 - Ph. Le Sager - v0 (copy from par_reduce_r0)
  930. !
  931. !EOP
  932. !------------------------------------------------------------------------
  933. !BOC
  934. character(len=*), parameter :: rname = mname//'/PAR_REDUCE_I0'
  935. logical :: l_row, l_all
  936. integer :: l_root, l_comm, l_id, l_op
  937. #ifdef MPI
  938. l_row=.false. ; if(present(row)) l_row=row
  939. l_all=.false. ; if(present(all)) l_all=all
  940. if(l_row)then
  941. l_root = 0 ! by our own design
  942. l_comm = row_comm
  943. l_id = jcol
  944. else
  945. l_root = root
  946. l_comm = localComm
  947. l_id = myid
  948. end if
  949. ! degenerate cases first
  950. if(l_row.and.(npe_lon==1)) then
  951. resultat = data
  952. else
  953. SELECT CASE( OP )
  954. case('sum', 'Sum', 'SUM')
  955. l_op = MPI_SUM
  956. case('max', 'Max', 'MAX')
  957. l_op = MPI_MAX
  958. case('min', 'Min', 'MIN')
  959. l_op = MPI_MIN
  960. case default
  961. write(gol,*) 'UNSUPPORTED OPERATION :', OP; status=1
  962. IF_NOTOK_RETURN(status=1)
  963. END SELECT
  964. if (l_all) then
  965. call MPI_ALLREDUCE(data, resultat, 1, MPI_INTEGER, l_op, l_comm, ierr)
  966. IF_NOTOK_MPI(status=1)
  967. else
  968. call MPI_REDUCE(data, resultat, 1, MPI_INTEGER, l_op, l_root, l_comm, ierr)
  969. IF_NOTOK_MPI(status=1)
  970. end if
  971. end if
  972. #else
  973. resultat = data
  974. #endif
  975. status=0
  976. END SUBROUTINE PAR_REDUCE_I0
  977. !EOC
  978. !--------------------------------------------------------------------------
  979. ! TM5 !
  980. !--------------------------------------------------------------------------
  981. !BOP
  982. !
  983. ! !IROUTINE: PAR_REDUCE_R0
  984. !
  985. ! !DESCRIPTION: Wrapper around MPI_REDUCE or MPI_ALLREDUCE.
  986. !
  987. ! Apply to a SINGLE REAL.
  988. !\\
  989. !\\
  990. ! !INTERFACE:
  991. !
  992. SUBROUTINE PAR_REDUCE_R0( DATA, OP, RESULTAT, STATUS, ALL, ROW, COL )
  993. !
  994. ! !INPUT PARAMETERS:
  995. !
  996. real, intent(in) :: data
  997. character(len=3), intent(in) :: op ! 'MAX', 'MIN' or 'SUM'
  998. logical, intent(in), optional :: all ! use MPI_ALLREDUCE instead of MPI_REDUCE
  999. logical, intent(in), optional :: row ! limit to PE on row_comm
  1000. logical, intent(in), optional :: col ! limit to PE on col_comm
  1001. !
  1002. ! !OUTPUT PARAMETERS:
  1003. !
  1004. real, intent(out) :: resultat
  1005. integer, intent(out) :: status
  1006. !
  1007. ! !REVISION HISTORY:
  1008. ! 01 Nov 2011 - P. Le Sager - v0
  1009. !
  1010. !EOP
  1011. !------------------------------------------------------------------------
  1012. !BOC
  1013. character(len=*), parameter :: rname = mname//'/PAR_REDUCE_R0'
  1014. logical :: l_row, l_all, l_col
  1015. integer :: l_root, l_comm, l_id, l_op
  1016. #ifdef MPI
  1017. l_col=.false. ; if(present(col)) l_col=col
  1018. l_row=.false. ; if(present(row)) l_row=row
  1019. l_all=.false. ; if(present(all)) l_all=all
  1020. if(l_row)then
  1021. l_root = 0 ! by our own design
  1022. l_comm = row_comm
  1023. l_id = jcol
  1024. else if(l_col) then
  1025. l_root = 0 ! by our own design
  1026. l_comm = col_comm
  1027. l_id = irow
  1028. else
  1029. l_root = root
  1030. l_comm = localComm
  1031. l_id = myid
  1032. end if
  1033. ! degenerate cases first
  1034. if(l_row.and.(npe_lon==1)) then
  1035. resultat = data
  1036. else
  1037. SELECT CASE( OP )
  1038. case('sum', 'Sum', 'SUM')
  1039. l_op = MPI_SUM
  1040. case('max', 'Max', 'MAX')
  1041. l_op = MPI_MAX
  1042. case('min', 'Min', 'MIN')
  1043. l_op = MPI_MIN
  1044. case default
  1045. write(gol,*) 'UNSUPPORTED OPERATION :', OP; status=1
  1046. IF_NOTOK_RETURN(status=1)
  1047. END SELECT
  1048. if (l_all) then
  1049. call MPI_ALLREDUCE(data, resultat, 1, my_real, l_op, l_comm, ierr)
  1050. IF_NOTOK_MPI(status=1)
  1051. else
  1052. call MPI_REDUCE(data, resultat, 1, my_real, l_op, l_root, l_comm, ierr)
  1053. IF_NOTOK_MPI(status=1)
  1054. end if
  1055. end if
  1056. #else
  1057. resultat = data
  1058. #endif
  1059. status=0
  1060. END SUBROUTINE PAR_REDUCE_R0
  1061. !EOC
  1062. !--------------------------------------------------------------------------
  1063. ! TM5 !
  1064. !--------------------------------------------------------------------------
  1065. !BOP
  1066. !
  1067. ! !IROUTINE: PAR_REDUCE_R1
  1068. !
  1069. ! !DESCRIPTION: Global reduction. Data are gathered on root, where OP is
  1070. ! then done. Apply to a 1D REAL.
  1071. !\\
  1072. !\\
  1073. ! !INTERFACE:
  1074. !
  1075. SUBROUTINE PAR_REDUCE_R1( DATA, OP, RESULTAT, STATUS, ALL, ROW )
  1076. !
  1077. ! !INPUT PARAMETERS:
  1078. !
  1079. real, intent(in) :: data(:)
  1080. character(len=3), intent(in) :: op ! 'MAX', 'MIN' or 'SUM'
  1081. logical, intent(in), optional :: all ! mimic mpi_allreduce instead of mpi_reduce
  1082. logical, intent(in), optional :: row ! limit to PE on row_comm
  1083. !
  1084. ! !OUTPUT PARAMETERS:
  1085. !
  1086. real, intent(out) :: resultat
  1087. integer, intent(out) :: status
  1088. !
  1089. ! !REVISION HISTORY:
  1090. ! 01 Nov 2011 - P. Le Sager - FIXME: NOT TESTED
  1091. !
  1092. ! !REMARKS:
  1093. !
  1094. ! (1) this is a convenient tool to get same results independently of the
  1095. ! number of processors. If this is not what you want, you can do OP
  1096. ! on each processor before calling par_reduce_r0 : it is less expensive.
  1097. !
  1098. !EOP
  1099. !------------------------------------------------------------------------
  1100. !BOC
  1101. character(len=*), parameter :: rname = mname//'/PAR_REDUCE_R1'
  1102. #ifdef MPI
  1103. real, allocatable :: glb(:)
  1104. logical :: l_row
  1105. integer :: sz, l_root, l_comm, l_id
  1106. sz = size(data)
  1107. l_row=.false.
  1108. if(present(row)) l_row=row
  1109. if(l_row)then
  1110. allocate( glb(npe_lon*sz) )
  1111. l_root = 0
  1112. l_comm = row_comm
  1113. l_id = jcol
  1114. else
  1115. allocate( glb(npes*sz) )
  1116. l_root = root
  1117. l_comm = localComm
  1118. l_id = myid
  1119. end if
  1120. CALL MPI_GATHER( data, sz, my_real, glb, sz, my_real, l_root, l_comm, ierr)
  1121. IF_NOTOK_MPI(status=1)
  1122. if (l_root==l_id) then
  1123. select case( op )
  1124. case('sum', 'Sum', 'SUM')
  1125. resultat = sum(glb)
  1126. case('max', 'Max', 'MAX')
  1127. resultat = maxval(glb)
  1128. case('min', 'Min', 'MIN')
  1129. resultat = minval(glb)
  1130. case default
  1131. write(gol,*) 'UNSUPPORTED OPERATION'; status=1
  1132. IF_NOTOK_RETURN(status=1)
  1133. end select
  1134. end if
  1135. deallocate(glb)
  1136. if (present(all)) then
  1137. if (all) call MPI_bcast(resultat, 1, my_real, l_root, l_comm, ierr)
  1138. end if
  1139. #else
  1140. select case( op )
  1141. case('sum', 'Sum', 'SUM')
  1142. resultat = sum(data)
  1143. case('max', 'Max', 'MAX')
  1144. resultat = maxval(data)
  1145. case('min', 'Min', 'MIN')
  1146. resultat = minval(data)
  1147. case default
  1148. write(gol,*) 'UNSUPPORTED OPERATION'; status=1
  1149. IF_NOTOK_RETURN(status=1)
  1150. end select
  1151. #endif
  1152. status=0
  1153. END SUBROUTINE PAR_REDUCE_R1
  1154. !EOC
  1155. !--------------------------------------------------------------------------
  1156. ! TM5 !
  1157. !--------------------------------------------------------------------------
  1158. !BOP
  1159. !
  1160. ! !IROUTINE: PAR_REDUCE_R2
  1161. !
  1162. ! !DESCRIPTION:
  1163. !\\
  1164. !\\
  1165. ! !INTERFACE:
  1166. !
  1167. ! subroutine Par_Reduce_r2( send, recv, oper, id_recv, status )
  1168. !
  1169. ! !REMARKS:
  1170. ! in TM5 v3, this routine was a wrapper around MPI_REDUCE( ..., MPI_SUM, ...), and was called
  1171. ! in project CLIMAQS/user_output_pdump.F90 (an updated retro output) and in
  1172. ! various user_output_retro.F90, to sum budget...
  1173. ! =====> in tm5-mp, this routine became PAR_REDUCE_ELEMENT_R2 ()
  1174. ! TO DEVELOP IF YOU NEED RESULT THAT ARE INDEPENDENT OF THE NUMBER OF
  1175. ! PROCESSOR YOU ARE USING.
  1176. ! end subroutine Par_Reduce_r2
  1177. !EOC
  1178. !--------------------------------------------------------------------------
  1179. ! TM5 !
  1180. !--------------------------------------------------------------------------
  1181. !BOP
  1182. !
  1183. ! !IROUTINE: PAR_REDUCE_R3
  1184. !
  1185. ! !DESCRIPTION: Global reduction. Data are gathered on root, where OP is
  1186. ! then done. Apply to a 3D REAL.
  1187. !\\
  1188. !\\
  1189. ! !INTERFACE:
  1190. !
  1191. SUBROUTINE PAR_REDUCE_R3( DATA, OP, RESULTAT, STATUS, ALL, ROW )
  1192. !
  1193. ! !INPUT PARAMETERS:
  1194. !
  1195. real, intent(in) :: data(:,:,:)
  1196. character(len=3), intent(in) :: op ! 'MAX', 'MIN' or 'SUM'
  1197. logical, intent(in), optional :: all ! mimic mpi_allreduce instead of mpi_reduce
  1198. logical, intent(in), optional :: row ! limit to PE on row_comm
  1199. !
  1200. ! !OUTPUT PARAMETERS:
  1201. !
  1202. real, intent(out) :: resultat
  1203. integer, intent(out) :: status
  1204. !
  1205. ! !REVISION HISTORY:
  1206. !
  1207. ! !REMARKS:
  1208. !
  1209. ! (1) this is a convenient tool to get same results independently of the
  1210. ! number of processors. If this is not what you want, you can do OP
  1211. ! on each processor before calling par_reduce_r0 : it is less expensive.
  1212. !
  1213. !EOP
  1214. !------------------------------------------------------------------------
  1215. !BOC
  1216. character(len=*), parameter :: rname = mname//'/PAR_REDUCE_R3'
  1217. #ifdef MPI
  1218. real, allocatable :: glb(:)
  1219. logical :: l_row
  1220. integer :: sz, l_root, l_comm, l_id
  1221. sz = size(data)
  1222. l_row=.false.
  1223. if(present(row)) l_row=row
  1224. if(l_row)then
  1225. allocate( glb(npe_lon*sz) )
  1226. l_root = 0
  1227. l_comm = row_comm
  1228. l_id = jcol
  1229. else
  1230. allocate( glb(npes*sz) )
  1231. l_root = root
  1232. l_comm = localComm
  1233. l_id = myid
  1234. end if
  1235. CALL MPI_GATHER( data, sz, my_real, glb, sz, my_real, l_root, l_comm, ierr)
  1236. IF_NOTOK_MPI(status=1)
  1237. if (l_root==l_id) then
  1238. select case( op )
  1239. case('sum', 'Sum', 'SUM')
  1240. resultat = sum(glb)
  1241. case('max', 'Max', 'MAX')
  1242. resultat = maxval(glb)
  1243. case('min', 'Min', 'MIN')
  1244. resultat = minval(glb)
  1245. case default
  1246. write(gol,*) 'UNSUPPORTED OPERATION'; status=1
  1247. IF_NOTOK_RETURN(status=1)
  1248. end select
  1249. end if
  1250. deallocate(glb)
  1251. if (present(all)) then
  1252. if (all) call MPI_bcast(resultat, 1, my_real, l_root, l_comm, ierr)
  1253. end if
  1254. #else
  1255. select case( op )
  1256. case('sum', 'Sum', 'SUM')
  1257. resultat = sum(data)
  1258. case('max', 'Max', 'MAX')
  1259. resultat = maxval(data)
  1260. case('min', 'Min', 'MIN')
  1261. resultat = minval(data)
  1262. case default
  1263. write(gol,*) 'UNSUPPORTED OPERATION'; status=1
  1264. IF_NOTOK_RETURN(status=1)
  1265. end select
  1266. #endif
  1267. status=0
  1268. END SUBROUTINE PAR_REDUCE_R3
  1269. !EOC
  1270. !--------------------------------------------------------------------------
  1271. ! TM5 !
  1272. !--------------------------------------------------------------------------
  1273. !BOP
  1274. !
  1275. ! !IROUTINE: PAR_REDUCE_ELEMENT_R1
  1276. !
  1277. ! !DESCRIPTION: reduce 1D arrays element-wise
  1278. !\\
  1279. !\\
  1280. ! !INTERFACE:
  1281. !
  1282. SUBROUTINE PAR_REDUCE_ELEMENT_R1 (DATA, OP, RESULTAT, STATUS, ALL, ROW)
  1283. !
  1284. ! !USES:
  1285. !
  1286. use dims, only : CheckShape
  1287. !
  1288. ! !INPUT PARAMETERS:
  1289. !
  1290. real, intent(in) :: data(:)
  1291. character(len=3), intent(in) :: op ! 'MAX', 'MIN' or 'SUM'
  1292. logical, intent(in), optional :: all ! mimic mpi_allreduce instead of mpi_reduce
  1293. logical, intent(in), optional :: row ! limit to PE on row_comm
  1294. !
  1295. ! !OUTPUT PARAMETERS:
  1296. !
  1297. real, intent(out) :: resultat(:)
  1298. integer, intent(out) :: status
  1299. !
  1300. ! !REVISION HISTORY:
  1301. ! 1 Mar 2012 - P. Le Sager - v0
  1302. !
  1303. ! !REMARKS:
  1304. !
  1305. !EOP
  1306. !------------------------------------------------------------------------
  1307. !BOC
  1308. character(len=*), parameter :: rname = mname//'/PAR_REDUCE_ELEMENT_R2'
  1309. logical :: l_row, l_all
  1310. integer :: l_root, l_comm, l_id, l_op
  1311. call CheckShape( shape(data), shape(resultat), status )
  1312. IF_NOTOK_RETURN(status=1)
  1313. #ifdef MPI
  1314. l_row=.false. ; if(present(row)) l_row=row
  1315. l_all=.false. ; if(present(all)) l_all=all
  1316. if(l_row)then
  1317. l_root = 0 ! by our own design
  1318. l_comm = row_comm
  1319. l_id = jcol
  1320. else
  1321. l_root = root
  1322. l_comm = localComm
  1323. l_id = myid
  1324. end if
  1325. ! degenerate cases first
  1326. if(l_row.and.(npe_lon==1)) then
  1327. resultat = data
  1328. else
  1329. SELECT CASE( OP )
  1330. case('sum', 'Sum', 'SUM')
  1331. l_op = MPI_SUM
  1332. case('max', 'Max', 'MAX')
  1333. l_op = MPI_MAX
  1334. case('min', 'Min', 'MIN')
  1335. l_op = MPI_MIN
  1336. case default
  1337. write(gol,*) 'UNSUPPORTED OPERATION :', OP; status=1
  1338. IF_NOTOK_RETURN(status=1)
  1339. END SELECT
  1340. if (l_all) then
  1341. call MPI_ALLREDUCE(data, resultat, size(data), my_real, l_op, l_comm, ierr)
  1342. IF_NOTOK_MPI(status=1)
  1343. else
  1344. call MPI_REDUCE(data, resultat, size(data), my_real, l_op, l_root, l_comm, ierr)
  1345. IF_NOTOK_MPI(status=1)
  1346. end if
  1347. end if
  1348. #else
  1349. resultat = data
  1350. #endif
  1351. status=0
  1352. END SUBROUTINE PAR_REDUCE_ELEMENT_R1
  1353. !EOC
  1354. !--------------------------------------------------------------------------
  1355. ! TM5 !
  1356. !--------------------------------------------------------------------------
  1357. !BOP
  1358. !
  1359. ! !IROUTINE: PAR_REDUCE_ELEMENT_R2
  1360. !
  1361. ! !DESCRIPTION: reduce 2D arrays element-wise
  1362. !\\
  1363. !\\
  1364. ! !INTERFACE:
  1365. !
  1366. SUBROUTINE PAR_REDUCE_ELEMENT_R2 (DATA, OP, RESULTAT, STATUS, ALL, ROW)
  1367. !
  1368. ! !USES:
  1369. !
  1370. use dims, only : CheckShape
  1371. !
  1372. ! !INPUT PARAMETERS:
  1373. !
  1374. real, intent(in) :: data(:,:)
  1375. character(len=3), intent(in) :: op ! 'MAX', 'MIN' or 'SUM'
  1376. logical, intent(in), optional :: all ! mimic mpi_allreduce instead of mpi_reduce
  1377. logical, intent(in), optional :: row ! limit to PE on row_comm
  1378. !
  1379. ! !OUTPUT PARAMETERS:
  1380. !
  1381. real, intent(out) :: resultat(:,:)
  1382. integer, intent(out) :: status
  1383. !
  1384. ! !REVISION HISTORY:
  1385. ! 1 Mar 2012 - P. Le Sager - v0
  1386. !
  1387. ! !REMARKS:
  1388. !
  1389. !EOP
  1390. !------------------------------------------------------------------------
  1391. !BOC
  1392. character(len=*), parameter :: rname = mname//'/PAR_REDUCE_ELEMENT_R2'
  1393. logical :: l_row, l_all
  1394. integer :: l_root, l_comm, l_id, l_op
  1395. call CheckShape( shape(data), shape(resultat), status )
  1396. IF_NOTOK_RETURN(status=1)
  1397. #ifdef MPI
  1398. l_row=.false. ; if(present(row)) l_row=row
  1399. l_all=.false. ; if(present(all)) l_all=all
  1400. if(l_row)then
  1401. l_root = 0 ! by our own design
  1402. l_comm = row_comm
  1403. l_id = jcol
  1404. else
  1405. l_root = root
  1406. l_comm = localComm
  1407. l_id = myid
  1408. end if
  1409. ! degenerate cases first
  1410. if(l_row.and.(npe_lon==1)) then
  1411. resultat = data
  1412. else
  1413. SELECT CASE( OP )
  1414. case('sum', 'Sum', 'SUM')
  1415. l_op = MPI_SUM
  1416. case('max', 'Max', 'MAX')
  1417. l_op = MPI_MAX
  1418. case('min', 'Min', 'MIN')
  1419. l_op = MPI_MIN
  1420. case default
  1421. write(gol,*) 'UNSUPPORTED OPERATION :', OP; status=1
  1422. IF_NOTOK_RETURN(status=1)
  1423. END SELECT
  1424. if (l_all) then
  1425. call MPI_ALLREDUCE(data, resultat, size(data), my_real, l_op, l_comm, ierr)
  1426. IF_NOTOK_MPI(status=1)
  1427. else
  1428. call MPI_REDUCE(data, resultat, size(data), my_real, l_op, l_root, l_comm, ierr)
  1429. IF_NOTOK_MPI(status=1)
  1430. end if
  1431. end if
  1432. #else
  1433. resultat = data
  1434. #endif
  1435. status=0
  1436. END SUBROUTINE PAR_REDUCE_ELEMENT_R2
  1437. !EOC
  1438. !--------------------------------------------------------------------------
  1439. ! TM5 !
  1440. !--------------------------------------------------------------------------
  1441. !BOP
  1442. !
  1443. ! !IROUTINE: PAR_REDUCE_ELEMENT_R3
  1444. !
  1445. ! !DESCRIPTION: reduce 3D arrays element-wise
  1446. !\\
  1447. !\\
  1448. ! !INTERFACE:
  1449. !
  1450. SUBROUTINE PAR_REDUCE_ELEMENT_R3 (DATA, OP, RESULTAT, STATUS, ALL, ROW)
  1451. !
  1452. ! !USES:
  1453. !
  1454. use dims, only : CheckShape
  1455. !
  1456. ! !INPUT PARAMETERS:
  1457. !
  1458. real, intent(in) :: data(:,:,:)
  1459. character(len=3), intent(in) :: op ! 'MAX', 'MIN' or 'SUM'
  1460. logical, intent(in), optional :: all ! mimic mpi_allreduce instead of mpi_reduce
  1461. logical, intent(in), optional :: row ! limit to PE on row_comm
  1462. !
  1463. ! !OUTPUT PARAMETERS:
  1464. !
  1465. real, intent(out) :: resultat(:,:,:)
  1466. integer, intent(out) :: status
  1467. !
  1468. ! !REVISION HISTORY:
  1469. ! 1 Mar 2012 - P. Le Sager - v0
  1470. !
  1471. ! !REMARKS:
  1472. !
  1473. !EOP
  1474. !------------------------------------------------------------------------
  1475. !BOC
  1476. character(len=*), parameter :: rname = mname//'/PAR_REDUCE_ELEMENT_R3'
  1477. logical :: l_row, l_all
  1478. integer :: l_root, l_comm, l_id, l_op
  1479. call CheckShape( shape(data), shape(resultat), status )
  1480. IF_NOTOK_RETURN(status=1)
  1481. #ifdef MPI
  1482. l_row=.false. ; if(present(row)) l_row=row
  1483. l_all=.false. ; if(present(all)) l_all=all
  1484. if(l_row)then
  1485. l_root = 0 ! by our own design
  1486. l_comm = row_comm
  1487. l_id = jcol
  1488. else
  1489. l_root = root
  1490. l_comm = localComm
  1491. l_id = myid
  1492. end if
  1493. ! degenerate cases first
  1494. if(l_row.and.(npe_lon==1)) then
  1495. resultat = data
  1496. else
  1497. SELECT CASE( OP )
  1498. case('sum', 'Sum', 'SUM')
  1499. l_op = MPI_SUM
  1500. case('max', 'Max', 'MAX')
  1501. l_op = MPI_MAX
  1502. case('min', 'Min', 'MIN')
  1503. l_op = MPI_MIN
  1504. case default
  1505. write(gol,*) 'UNSUPPORTED OPERATION :', OP; status=1
  1506. IF_NOTOK_RETURN(status=1)
  1507. END SELECT
  1508. if (l_all) then
  1509. call MPI_ALLREDUCE(data, resultat, size(data), my_real, l_op, l_comm, ierr)
  1510. IF_NOTOK_MPI(status=1)
  1511. else
  1512. call MPI_REDUCE(data, resultat, size(data), my_real, l_op, l_root, l_comm, ierr)
  1513. IF_NOTOK_MPI(status=1)
  1514. end if
  1515. end if
  1516. #else
  1517. resultat = data
  1518. #endif
  1519. status=0
  1520. END SUBROUTINE PAR_REDUCE_ELEMENT_R3
  1521. !EOC
  1522. END MODULE ParTools