lib_fortran.F90 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. MODULE lib_fortran
  2. !!======================================================================
  3. !! *** MODULE lib_fortran ***
  4. !! Fortran utilities: includes some low levels fortran functionality
  5. !!======================================================================
  6. !! History : 3.2 ! 2010-05 (M. Dunphy, R. Benshila) Original code
  7. !! 3.4 ! 2013-06 (C. Rousset) add glob_min, glob_max
  8. !! + 3d dim. of input is fexible (jpk, jpl...)
  9. !!----------------------------------------------------------------------
  10. !!----------------------------------------------------------------------
  11. !! glob_sum : generic interface for global masked summation over
  12. !! the interior domain for 1 or 2 2D or 3D arrays
  13. !! it works only for T points
  14. !! SIGN : generic interface for SIGN to overwrite f95 behaviour
  15. !! of intrinsinc sign function
  16. !!----------------------------------------------------------------------
  17. USE par_oce ! Ocean parameter
  18. USE dom_oce ! ocean domain
  19. USE in_out_manager ! I/O manager
  20. USE lib_mpp ! distributed memory computing
  21. IMPLICIT NONE
  22. PRIVATE
  23. PUBLIC glob_sum ! used in many places
  24. PUBLIC DDPDD ! also used in closea module
  25. PUBLIC glob_min, glob_max
  26. #if defined key_nosignedzero
  27. PUBLIC SIGN
  28. #endif
  29. INTERFACE glob_sum
  30. MODULE PROCEDURE glob_sum_1d, glob_sum_2d, glob_sum_3d, &
  31. & glob_sum_2d_a, glob_sum_3d_a
  32. END INTERFACE
  33. INTERFACE glob_min
  34. MODULE PROCEDURE glob_min_2d, glob_min_3d,glob_min_2d_a, glob_min_3d_a
  35. END INTERFACE
  36. INTERFACE glob_max
  37. MODULE PROCEDURE glob_max_2d, glob_max_3d,glob_max_2d_a, glob_max_3d_a
  38. END INTERFACE
  39. #if defined key_nosignedzero
  40. INTERFACE SIGN
  41. MODULE PROCEDURE SIGN_SCALAR, SIGN_ARRAY_1D, SIGN_ARRAY_2D, SIGN_ARRAY_3D, &
  42. & SIGN_ARRAY_1D_A, SIGN_ARRAY_2D_A, SIGN_ARRAY_3D_A, &
  43. & SIGN_ARRAY_1D_B, SIGN_ARRAY_2D_B, SIGN_ARRAY_3D_B
  44. END INTERFACE
  45. #endif
  46. !!----------------------------------------------------------------------
  47. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  48. !! $Id: lib_fortran.F90 4161 2013-11-07 10:01:27Z cetlod $
  49. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  50. !!----------------------------------------------------------------------
  51. CONTAINS
  52. #if ! defined key_mpp_rep
  53. ! --- SUM ---
  54. FUNCTION glob_sum_1d( ptab, kdim )
  55. !!-----------------------------------------------------------------------
  56. !! *** FUNCTION glob_sum_1D ***
  57. !!
  58. !! ** Purpose : perform a masked sum on the inner global domain of a 1D array
  59. !!-----------------------------------------------------------------------
  60. INTEGER :: kdim
  61. REAL(wp), INTENT(in), DIMENSION(kdim) :: ptab ! input 1D array
  62. REAL(wp) :: glob_sum_1d ! global sum
  63. !!-----------------------------------------------------------------------
  64. !
  65. glob_sum_1d = SUM( ptab(:) )
  66. IF( lk_mpp ) CALL mpp_sum( glob_sum_1d )
  67. !
  68. END FUNCTION glob_sum_1d
  69. FUNCTION glob_sum_2d( ptab )
  70. !!-----------------------------------------------------------------------
  71. !! *** FUNCTION glob_sum_2D ***
  72. !!
  73. !! ** Purpose : perform a masked sum on the inner global domain of a 2D array
  74. !!-----------------------------------------------------------------------
  75. REAL(wp), INTENT(in), DIMENSION(:,:) :: ptab ! input 2D array
  76. REAL(wp) :: glob_sum_2d ! global masked sum
  77. !!-----------------------------------------------------------------------
  78. !
  79. glob_sum_2d = SUM( ptab(:,:)*tmask_i(:,:) )
  80. IF( lk_mpp ) CALL mpp_sum( glob_sum_2d )
  81. !
  82. END FUNCTION glob_sum_2d
  83. FUNCTION glob_sum_3d( ptab )
  84. !!-----------------------------------------------------------------------
  85. !! *** FUNCTION glob_sum_3D ***
  86. !!
  87. !! ** Purpose : perform a masked sum on the inner global domain of a 3D array
  88. !!-----------------------------------------------------------------------
  89. REAL(wp), INTENT(in), DIMENSION(:,:,:) :: ptab ! input 3D array
  90. REAL(wp) :: glob_sum_3d ! global masked sum
  91. !!
  92. INTEGER :: jk
  93. INTEGER :: ijpk ! local variable: size of the 3d dimension of ptab
  94. !!-----------------------------------------------------------------------
  95. !
  96. ijpk = SIZE(ptab,3)
  97. !
  98. glob_sum_3d = 0.e0
  99. DO jk = 1, ijpk
  100. glob_sum_3d = glob_sum_3d + SUM( ptab(:,:,jk)*tmask_i(:,:) )
  101. END DO
  102. IF( lk_mpp ) CALL mpp_sum( glob_sum_3d )
  103. !
  104. END FUNCTION glob_sum_3d
  105. FUNCTION glob_sum_2d_a( ptab1, ptab2 )
  106. !!-----------------------------------------------------------------------
  107. !! *** FUNCTION glob_sum_2D _a ***
  108. !!
  109. !! ** Purpose : perform a masked sum on the inner global domain of two 2D array
  110. !!-----------------------------------------------------------------------
  111. REAL(wp), INTENT(in), DIMENSION(:,:) :: ptab1, ptab2 ! input 2D array
  112. REAL(wp) , DIMENSION(2) :: glob_sum_2d_a ! global masked sum
  113. !!-----------------------------------------------------------------------
  114. !
  115. glob_sum_2d_a(1) = SUM( ptab1(:,:)*tmask_i(:,:) )
  116. glob_sum_2d_a(2) = SUM( ptab2(:,:)*tmask_i(:,:) )
  117. IF( lk_mpp ) CALL mpp_sum( glob_sum_2d_a, 2 )
  118. !
  119. END FUNCTION glob_sum_2d_a
  120. FUNCTION glob_sum_3d_a( ptab1, ptab2 )
  121. !!-----------------------------------------------------------------------
  122. !! *** FUNCTION glob_sum_3D_a ***
  123. !!
  124. !! ** Purpose : perform a masked sum on the inner global domain of two 3D array
  125. !!-----------------------------------------------------------------------
  126. REAL(wp), INTENT(in), DIMENSION(:,:,:) :: ptab1, ptab2 ! input 3D array
  127. REAL(wp) , DIMENSION(2) :: glob_sum_3d_a ! global masked sum
  128. !!
  129. INTEGER :: jk
  130. INTEGER :: ijpk ! local variable: size of the 3d dimension of ptab
  131. !!-----------------------------------------------------------------------
  132. !
  133. ijpk = SIZE(ptab1,3)
  134. !
  135. glob_sum_3d_a(:) = 0.e0
  136. DO jk = 1, ijpk
  137. glob_sum_3d_a(1) = glob_sum_3d_a(1) + SUM( ptab1(:,:,jk)*tmask_i(:,:) )
  138. glob_sum_3d_a(2) = glob_sum_3d_a(2) + SUM( ptab2(:,:,jk)*tmask_i(:,:) )
  139. END DO
  140. IF( lk_mpp ) CALL mpp_sum( glob_sum_3d_a, 2 )
  141. !
  142. END FUNCTION glob_sum_3d_a
  143. #else
  144. !!----------------------------------------------------------------------
  145. !! 'key_mpp_rep' MPP reproducibility
  146. !!----------------------------------------------------------------------
  147. ! --- SUM ---
  148. FUNCTION glob_sum_1d( ptab, kdim )
  149. !!----------------------------------------------------------------------
  150. !! *** FUNCTION glob_sum_1d ***
  151. !!
  152. !! ** Purpose : perform a sum in calling DDPDD routine
  153. !!----------------------------------------------------------------------
  154. INTEGER , INTENT(in) :: kdim
  155. REAL(wp), INTENT(in), DIMENSION(kdim) :: ptab
  156. REAL(wp) :: glob_sum_1d ! global sum
  157. !!
  158. COMPLEX(wp):: ctmp
  159. REAL(wp) :: ztmp
  160. INTEGER :: ji ! dummy loop indices
  161. !!-----------------------------------------------------------------------
  162. !
  163. ztmp = 0.e0
  164. ctmp = CMPLX( 0.e0, 0.e0, wp )
  165. DO ji = 1, kdim
  166. ztmp = ptab(ji)
  167. CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
  168. END DO
  169. IF( lk_mpp ) CALL mpp_sum( ctmp ) ! sum over the global domain
  170. glob_sum_1d = REAL(ctmp,wp)
  171. !
  172. END FUNCTION glob_sum_1d
  173. FUNCTION glob_sum_2d( ptab )
  174. !!----------------------------------------------------------------------
  175. !! *** FUNCTION glob_sum_2d ***
  176. !!
  177. !! ** Purpose : perform a sum in calling DDPDD routine
  178. !!----------------------------------------------------------------------
  179. REAL(wp), INTENT(in), DIMENSION(:,:) :: ptab
  180. REAL(wp) :: glob_sum_2d ! global masked sum
  181. !!
  182. COMPLEX(wp):: ctmp
  183. REAL(wp) :: ztmp
  184. INTEGER :: ji, jj ! dummy loop indices
  185. !!-----------------------------------------------------------------------
  186. !
  187. ztmp = 0.e0
  188. ctmp = CMPLX( 0.e0, 0.e0, wp )
  189. DO jj = 1, jpj
  190. DO ji =1, jpi
  191. ztmp = ptab(ji,jj) * tmask_i(ji,jj)
  192. CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
  193. END DO
  194. END DO
  195. IF( lk_mpp ) CALL mpp_sum( ctmp ) ! sum over the global domain
  196. glob_sum_2d = REAL(ctmp,wp)
  197. !
  198. END FUNCTION glob_sum_2d
  199. FUNCTION glob_sum_3d( ptab )
  200. !!----------------------------------------------------------------------
  201. !! *** FUNCTION glob_sum_3d ***
  202. !!
  203. !! ** Purpose : perform a sum on a 3D array in calling DDPDD routine
  204. !!----------------------------------------------------------------------
  205. REAL(wp), INTENT(in), DIMENSION(:,:,:) :: ptab
  206. REAL(wp) :: glob_sum_3d ! global masked sum
  207. !!
  208. COMPLEX(wp):: ctmp
  209. REAL(wp) :: ztmp
  210. INTEGER :: ji, jj, jk ! dummy loop indices
  211. INTEGER :: ijpk ! local variables: size of ptab
  212. !!-----------------------------------------------------------------------
  213. !
  214. ijpk = SIZE(ptab,3)
  215. !
  216. ztmp = 0.e0
  217. ctmp = CMPLX( 0.e0, 0.e0, wp )
  218. DO jk = 1, ijpk
  219. DO jj = 1, jpj
  220. DO ji =1, jpi
  221. ztmp = ptab(ji,jj,jk) * tmask_i(ji,jj)
  222. CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
  223. END DO
  224. END DO
  225. END DO
  226. IF( lk_mpp ) CALL mpp_sum( ctmp ) ! sum over the global domain
  227. glob_sum_3d = REAL(ctmp,wp)
  228. !
  229. END FUNCTION glob_sum_3d
  230. FUNCTION glob_sum_2d_a( ptab1, ptab2 )
  231. !!----------------------------------------------------------------------
  232. !! *** FUNCTION glob_sum_2d_a ***
  233. !!
  234. !! ** Purpose : perform a sum on two 2D arrays in calling DDPDD routine
  235. !!----------------------------------------------------------------------
  236. REAL(wp), INTENT(in), DIMENSION(:,:) :: ptab1, ptab2
  237. REAL(wp) :: glob_sum_2d_a ! global masked sum
  238. !!
  239. COMPLEX(wp):: ctmp
  240. REAL(wp) :: ztmp
  241. INTEGER :: ji, jj ! dummy loop indices
  242. !!-----------------------------------------------------------------------
  243. !
  244. ztmp = 0.e0
  245. ctmp = CMPLX( 0.e0, 0.e0, wp )
  246. DO jj = 1, jpj
  247. DO ji =1, jpi
  248. ztmp = ptab1(ji,jj) * tmask_i(ji,jj)
  249. CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
  250. ztmp = ptab2(ji,jj) * tmask_i(ji,jj)
  251. CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
  252. END DO
  253. END DO
  254. IF( lk_mpp ) CALL mpp_sum( ctmp ) ! sum over the global domain
  255. glob_sum_2d_a = REAL(ctmp,wp)
  256. !
  257. END FUNCTION glob_sum_2d_a
  258. FUNCTION glob_sum_3d_a( ptab1, ptab2 )
  259. !!----------------------------------------------------------------------
  260. !! *** FUNCTION glob_sum_3d_a ***
  261. !!
  262. !! ** Purpose : perform a sum on two 3D array in calling DDPDD routine
  263. !!----------------------------------------------------------------------
  264. REAL(wp), INTENT(in), DIMENSION(:,:,:) :: ptab1, ptab2
  265. REAL(wp) :: glob_sum_3d_a ! global masked sum
  266. !!
  267. COMPLEX(wp):: ctmp
  268. REAL(wp) :: ztmp
  269. INTEGER :: ji, jj, jk ! dummy loop indices
  270. INTEGER :: ijpk ! local variables: size of ptab
  271. !!-----------------------------------------------------------------------
  272. !
  273. ijpk = SIZE(ptab1,3)
  274. !
  275. ztmp = 0.e0
  276. ctmp = CMPLX( 0.e0, 0.e0, wp )
  277. DO jk = 1, ijpk
  278. DO jj = 1, jpj
  279. DO ji = 1, jpi
  280. ztmp = ptab1(ji,jj,jk) * tmask_i(ji,jj)
  281. CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
  282. ztmp = ptab2(ji,jj,jk) * tmask_i(ji,jj)
  283. CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
  284. END DO
  285. END DO
  286. END DO
  287. IF( lk_mpp ) CALL mpp_sum( ctmp ) ! sum over the global domain
  288. glob_sum_3d_a = REAL(ctmp,wp)
  289. !
  290. END FUNCTION glob_sum_3d_a
  291. #endif
  292. ! --- MIN ---
  293. FUNCTION glob_min_2d( ptab )
  294. !!-----------------------------------------------------------------------
  295. !! *** FUNCTION glob_min_2D ***
  296. !!
  297. !! ** Purpose : perform a masked min on the inner global domain of a 2D array
  298. !!-----------------------------------------------------------------------
  299. REAL(wp), INTENT(in), DIMENSION(:,:) :: ptab ! input 2D array
  300. REAL(wp) :: glob_min_2d ! global masked min
  301. !!-----------------------------------------------------------------------
  302. !
  303. glob_min_2d = MINVAL( ptab(:,:)*tmask_i(:,:) )
  304. IF( lk_mpp ) CALL mpp_min( glob_min_2d )
  305. !
  306. END FUNCTION glob_min_2d
  307. FUNCTION glob_min_3d( ptab )
  308. !!-----------------------------------------------------------------------
  309. !! *** FUNCTION glob_min_3D ***
  310. !!
  311. !! ** Purpose : perform a masked min on the inner global domain of a 3D array
  312. !!-----------------------------------------------------------------------
  313. REAL(wp), INTENT(in), DIMENSION(:,:,:) :: ptab ! input 3D array
  314. REAL(wp) :: glob_min_3d ! global masked min
  315. !!
  316. INTEGER :: jk
  317. INTEGER :: ijpk ! local variable: size of the 3d dimension of ptab
  318. !!-----------------------------------------------------------------------
  319. !
  320. ijpk = SIZE(ptab,3)
  321. !
  322. glob_min_3d = MINVAL( ptab(:,:,1)*tmask_i(:,:) )
  323. DO jk = 2, ijpk
  324. glob_min_3d = MIN( glob_min_3d, MINVAL( ptab(:,:,jk)*tmask_i(:,:) ) )
  325. END DO
  326. IF( lk_mpp ) CALL mpp_min( glob_min_3d )
  327. !
  328. END FUNCTION glob_min_3d
  329. FUNCTION glob_min_2d_a( ptab1, ptab2 )
  330. !!-----------------------------------------------------------------------
  331. !! *** FUNCTION glob_min_2D _a ***
  332. !!
  333. !! ** Purpose : perform a masked min on the inner global domain of two 2D array
  334. !!-----------------------------------------------------------------------
  335. REAL(wp), INTENT(in), DIMENSION(:,:) :: ptab1, ptab2 ! input 2D array
  336. REAL(wp) , DIMENSION(2) :: glob_min_2d_a ! global masked min
  337. !!-----------------------------------------------------------------------
  338. !
  339. glob_min_2d_a(1) = MINVAL( ptab1(:,:)*tmask_i(:,:) )
  340. glob_min_2d_a(2) = MINVAL( ptab2(:,:)*tmask_i(:,:) )
  341. IF( lk_mpp ) CALL mpp_min( glob_min_2d_a, 2 )
  342. !
  343. END FUNCTION glob_min_2d_a
  344. FUNCTION glob_min_3d_a( ptab1, ptab2 )
  345. !!-----------------------------------------------------------------------
  346. !! *** FUNCTION glob_min_3D_a ***
  347. !!
  348. !! ** Purpose : perform a masked min on the inner global domain of two 3D array
  349. !!-----------------------------------------------------------------------
  350. REAL(wp), INTENT(in), DIMENSION(:,:,:) :: ptab1, ptab2 ! input 3D array
  351. REAL(wp) , DIMENSION(2) :: glob_min_3d_a ! global masked min
  352. !!
  353. INTEGER :: jk
  354. INTEGER :: ijpk ! local variable: size of the 3d dimension of ptab
  355. !!-----------------------------------------------------------------------
  356. !
  357. ijpk = SIZE(ptab1,3)
  358. !
  359. glob_min_3d_a(1) = MINVAL( ptab1(:,:,1)*tmask_i(:,:) )
  360. glob_min_3d_a(2) = MINVAL( ptab2(:,:,1)*tmask_i(:,:) )
  361. DO jk = 2, ijpk
  362. glob_min_3d_a(1) = MIN( glob_min_3d_a(1), MINVAL( ptab1(:,:,jk)*tmask_i(:,:) ) )
  363. glob_min_3d_a(2) = MIN( glob_min_3d_a(2), MINVAL( ptab2(:,:,jk)*tmask_i(:,:) ) )
  364. END DO
  365. IF( lk_mpp ) CALL mpp_min( glob_min_3d_a, 2 )
  366. !
  367. END FUNCTION glob_min_3d_a
  368. ! --- MAX ---
  369. FUNCTION glob_max_2d( ptab )
  370. !!-----------------------------------------------------------------------
  371. !! *** FUNCTION glob_max_2D ***
  372. !!
  373. !! ** Purpose : perform a masked max on the inner global domain of a 2D array
  374. !!-----------------------------------------------------------------------
  375. REAL(wp), INTENT(in), DIMENSION(:,:) :: ptab ! input 2D array
  376. REAL(wp) :: glob_max_2d ! global masked max
  377. !!-----------------------------------------------------------------------
  378. !
  379. glob_max_2d = MAXVAL( ptab(:,:)*tmask_i(:,:) )
  380. IF( lk_mpp ) CALL mpp_max( glob_max_2d )
  381. !
  382. END FUNCTION glob_max_2d
  383. FUNCTION glob_max_3d( ptab )
  384. !!-----------------------------------------------------------------------
  385. !! *** FUNCTION glob_max_3D ***
  386. !!
  387. !! ** Purpose : perform a masked max on the inner global domain of a 3D array
  388. !!-----------------------------------------------------------------------
  389. REAL(wp), INTENT(in), DIMENSION(:,:,:) :: ptab ! input 3D array
  390. REAL(wp) :: glob_max_3d ! global masked max
  391. !!
  392. INTEGER :: jk
  393. INTEGER :: ijpk ! local variable: size of the 3d dimension of ptab
  394. !!-----------------------------------------------------------------------
  395. !
  396. ijpk = SIZE(ptab,3)
  397. !
  398. glob_max_3d = MAXVAL( ptab(:,:,1)*tmask_i(:,:) )
  399. DO jk = 2, ijpk
  400. glob_max_3d = MAX( glob_max_3d, MAXVAL( ptab(:,:,jk)*tmask_i(:,:) ) )
  401. END DO
  402. IF( lk_mpp ) CALL mpp_max( glob_max_3d )
  403. !
  404. END FUNCTION glob_max_3d
  405. FUNCTION glob_max_2d_a( ptab1, ptab2 )
  406. !!-----------------------------------------------------------------------
  407. !! *** FUNCTION glob_max_2D _a ***
  408. !!
  409. !! ** Purpose : perform a masked max on the inner global domain of two 2D array
  410. !!-----------------------------------------------------------------------
  411. REAL(wp), INTENT(in), DIMENSION(:,:) :: ptab1, ptab2 ! input 2D array
  412. REAL(wp) , DIMENSION(2) :: glob_max_2d_a ! global masked max
  413. !!-----------------------------------------------------------------------
  414. !
  415. glob_max_2d_a(1) = MAXVAL( ptab1(:,:)*tmask_i(:,:) )
  416. glob_max_2d_a(2) = MAXVAL( ptab2(:,:)*tmask_i(:,:) )
  417. IF( lk_mpp ) CALL mpp_max( glob_max_2d_a, 2 )
  418. !
  419. END FUNCTION glob_max_2d_a
  420. FUNCTION glob_max_3d_a( ptab1, ptab2 )
  421. !!-----------------------------------------------------------------------
  422. !! *** FUNCTION glob_max_3D_a ***
  423. !!
  424. !! ** Purpose : perform a masked max on the inner global domain of two 3D array
  425. !!-----------------------------------------------------------------------
  426. REAL(wp), INTENT(in), DIMENSION(:,:,:) :: ptab1, ptab2 ! input 3D array
  427. REAL(wp) , DIMENSION(2) :: glob_max_3d_a ! global masked max
  428. !!
  429. INTEGER :: jk
  430. INTEGER :: ijpk ! local variable: size of the 3d dimension of ptab
  431. !!-----------------------------------------------------------------------
  432. !
  433. ijpk = SIZE(ptab1,3)
  434. !
  435. glob_max_3d_a(1) = MAXVAL( ptab1(:,:,1)*tmask_i(:,:) )
  436. glob_max_3d_a(2) = MAXVAL( ptab2(:,:,1)*tmask_i(:,:) )
  437. DO jk = 2, ijpk
  438. glob_max_3d_a(1) = MAX( glob_max_3d_a(1), MAXVAL( ptab1(:,:,jk)*tmask_i(:,:) ) )
  439. glob_max_3d_a(2) = MAX( glob_max_3d_a(2), MAXVAL( ptab2(:,:,jk)*tmask_i(:,:) ) )
  440. END DO
  441. IF( lk_mpp ) CALL mpp_max( glob_max_3d_a, 2 )
  442. !
  443. END FUNCTION glob_max_3d_a
  444. SUBROUTINE DDPDD( ydda, yddb )
  445. !!----------------------------------------------------------------------
  446. !! *** ROUTINE DDPDD ***
  447. !!
  448. !! ** Purpose : Add a scalar element to a sum
  449. !!
  450. !!
  451. !! ** Method : The code uses the compensated summation with doublet
  452. !! (sum,error) emulated useing complex numbers. ydda is the
  453. !! scalar to add to the summ yddb
  454. !!
  455. !! ** Action : This does only work for MPI.
  456. !!
  457. !! References : Using Acurate Arithmetics to Improve Numerical
  458. !! Reproducibility and Sability in Parallel Applications
  459. !! Yun HE and Chris H. Q. DING, Journal of Supercomputing 18, 259-277, 2001
  460. !!----------------------------------------------------------------------
  461. COMPLEX(wp), INTENT(in ) :: ydda
  462. COMPLEX(wp), INTENT(inout) :: yddb
  463. !
  464. REAL(wp) :: zerr, zt1, zt2 ! local work variables
  465. !!-----------------------------------------------------------------------
  466. !
  467. ! Compute ydda + yddb using Knuth's trick.
  468. zt1 = REAL(ydda) + REAL(yddb)
  469. zerr = zt1 - REAL(ydda)
  470. zt2 = ( (REAL(yddb) - zerr) + (REAL(ydda) - (zt1 - zerr)) ) &
  471. & + AIMAG(ydda) + AIMAG(yddb)
  472. !
  473. ! The result is t1 + t2, after normalization.
  474. yddb = CMPLX( zt1 + zt2, zt2 - ((zt1 + zt2) - zt1), wp )
  475. !
  476. END SUBROUTINE DDPDD
  477. #if defined key_nosignedzero
  478. !!----------------------------------------------------------------------
  479. !! 'key_nosignedzero' F90 SIGN
  480. !!----------------------------------------------------------------------
  481. FUNCTION SIGN_SCALAR( pa, pb )
  482. !!-----------------------------------------------------------------------
  483. !! *** FUNCTION SIGN_SCALAR ***
  484. !!
  485. !! ** Purpose : overwrite f95 behaviour of intrinsinc sign function
  486. !!-----------------------------------------------------------------------
  487. REAL(wp) :: pa,pb ! input
  488. REAL(wp) :: SIGN_SCALAR ! result
  489. !!-----------------------------------------------------------------------
  490. IF ( pb >= 0.e0) THEN ; SIGN_SCALAR = ABS(pa)
  491. ELSE ; SIGN_SCALAR =-ABS(pa)
  492. ENDIF
  493. END FUNCTION SIGN_SCALAR
  494. FUNCTION SIGN_ARRAY_1D( pa, pb )
  495. !!-----------------------------------------------------------------------
  496. !! *** FUNCTION SIGN_ARRAY_1D ***
  497. !!
  498. !! ** Purpose : overwrite f95 behaviour of intrinsinc sign function
  499. !!-----------------------------------------------------------------------
  500. REAL(wp) :: pa,pb(:) ! input
  501. REAL(wp) :: SIGN_ARRAY_1D(SIZE(pb,1)) ! result
  502. !!-----------------------------------------------------------------------
  503. WHERE ( pb >= 0.e0 ) ; SIGN_ARRAY_1D = ABS(pa)
  504. ELSEWHERE ; SIGN_ARRAY_1D =-ABS(pa)
  505. END WHERE
  506. END FUNCTION SIGN_ARRAY_1D
  507. FUNCTION SIGN_ARRAY_2D(pa,pb)
  508. !!-----------------------------------------------------------------------
  509. !! *** FUNCTION SIGN_ARRAY_2D ***
  510. !!
  511. !! ** Purpose : overwrite f95 behaviour of intrinsinc sign function
  512. !!-----------------------------------------------------------------------
  513. REAL(wp) :: pa,pb(:,:) ! input
  514. REAL(wp) :: SIGN_ARRAY_2D(SIZE(pb,1),SIZE(pb,2)) ! result
  515. !!-----------------------------------------------------------------------
  516. WHERE ( pb >= 0.e0 ) ; SIGN_ARRAY_2D = ABS(pa)
  517. ELSEWHERE ; SIGN_ARRAY_2D =-ABS(pa)
  518. END WHERE
  519. END FUNCTION SIGN_ARRAY_2D
  520. FUNCTION SIGN_ARRAY_3D(pa,pb)
  521. !!-----------------------------------------------------------------------
  522. !! *** FUNCTION SIGN_ARRAY_3D ***
  523. !!
  524. !! ** Purpose : overwrite f95 behaviour of intrinsinc sign function
  525. !!-----------------------------------------------------------------------
  526. REAL(wp) :: pa,pb(:,:,:) ! input
  527. REAL(wp) :: SIGN_ARRAY_3D(SIZE(pb,1),SIZE(pb,2),SIZE(pb,3)) ! result
  528. !!-----------------------------------------------------------------------
  529. WHERE ( pb >= 0.e0 ) ; SIGN_ARRAY_3D = ABS(pa)
  530. ELSEWHERE ; SIGN_ARRAY_3D =-ABS(pa)
  531. END WHERE
  532. END FUNCTION SIGN_ARRAY_3D
  533. FUNCTION SIGN_ARRAY_1D_A(pa,pb)
  534. !!-----------------------------------------------------------------------
  535. !! *** FUNCTION SIGN_ARRAY_1D_A ***
  536. !!
  537. !! ** Purpose : overwrite f95 behaviour of intrinsinc sign function
  538. !!-----------------------------------------------------------------------
  539. REAL(wp) :: pa(:),pb(:) ! input
  540. REAL(wp) :: SIGN_ARRAY_1D_A(SIZE(pb,1)) ! result
  541. !!-----------------------------------------------------------------------
  542. WHERE ( pb >= 0.e0 ) ; SIGN_ARRAY_1D_A = ABS(pa)
  543. ELSEWHERE ; SIGN_ARRAY_1D_A =-ABS(pa)
  544. END WHERE
  545. END FUNCTION SIGN_ARRAY_1D_A
  546. FUNCTION SIGN_ARRAY_2D_A(pa,pb)
  547. !!-----------------------------------------------------------------------
  548. !! *** FUNCTION SIGN_ARRAY_2D_A ***
  549. !!
  550. !! ** Purpose : overwrite f95 behaviour of intrinsinc sign function
  551. !!-----------------------------------------------------------------------
  552. REAL(wp) :: pa(:,:),pb(:,:) ! input
  553. REAL(wp) :: SIGN_ARRAY_2D_A(SIZE(pb,1),SIZE(pb,2)) ! result
  554. !!-----------------------------------------------------------------------
  555. WHERE ( pb >= 0.e0 ) ; SIGN_ARRAY_2D_A = ABS(pa)
  556. ELSEWHERE ; SIGN_ARRAY_2D_A =-ABS(pa)
  557. END WHERE
  558. END FUNCTION SIGN_ARRAY_2D_A
  559. FUNCTION SIGN_ARRAY_3D_A(pa,pb)
  560. !!-----------------------------------------------------------------------
  561. !! *** FUNCTION SIGN_ARRAY_3D_A ***
  562. !!
  563. !! ** Purpose : overwrite f95 behaviour of intrinsinc sign function
  564. !!-----------------------------------------------------------------------
  565. REAL(wp) :: pa(:,:,:),pb(:,:,:) ! input
  566. REAL(wp) :: SIGN_ARRAY_3D_A(SIZE(pb,1),SIZE(pb,2),SIZE(pb,3)) ! result
  567. !!-----------------------------------------------------------------------
  568. WHERE ( pb >= 0.e0 ) ; SIGN_ARRAY_3D_A = ABS(pa)
  569. ELSEWHERE ; SIGN_ARRAY_3D_A =-ABS(pa)
  570. END WHERE
  571. END FUNCTION SIGN_ARRAY_3D_A
  572. FUNCTION SIGN_ARRAY_1D_B(pa,pb)
  573. !!-----------------------------------------------------------------------
  574. !! *** FUNCTION SIGN_ARRAY_1D_B ***
  575. !!
  576. !! ** Purpose : overwrite f95 behaviour of intrinsinc sign function
  577. !!-----------------------------------------------------------------------
  578. REAL(wp) :: pa(:),pb ! input
  579. REAL(wp) :: SIGN_ARRAY_1D_B(SIZE(pa,1)) ! result
  580. !!-----------------------------------------------------------------------
  581. IF( pb >= 0.e0 ) THEN ; SIGN_ARRAY_1D_B = ABS(pa)
  582. ELSE ; SIGN_ARRAY_1D_B =-ABS(pa)
  583. ENDIF
  584. END FUNCTION SIGN_ARRAY_1D_B
  585. FUNCTION SIGN_ARRAY_2D_B(pa,pb)
  586. !!-----------------------------------------------------------------------
  587. !! *** FUNCTION SIGN_ARRAY_2D_B ***
  588. !!
  589. !! ** Purpose : overwrite f95 behaviour of intrinsinc sign function
  590. !!-----------------------------------------------------------------------
  591. REAL(wp) :: pa(:,:),pb ! input
  592. REAL(wp) :: SIGN_ARRAY_2D_B(SIZE(pa,1),SIZE(pa,2)) ! result
  593. !!-----------------------------------------------------------------------
  594. IF( pb >= 0.e0 ) THEN ; SIGN_ARRAY_2D_B = ABS(pa)
  595. ELSE ; SIGN_ARRAY_2D_B =-ABS(pa)
  596. ENDIF
  597. END FUNCTION SIGN_ARRAY_2D_B
  598. FUNCTION SIGN_ARRAY_3D_B(pa,pb)
  599. !!-----------------------------------------------------------------------
  600. !! *** FUNCTION SIGN_ARRAY_3D_B ***
  601. !!
  602. !! ** Purpose : overwrite f95 behaviour of intrinsinc sign function
  603. !!-----------------------------------------------------------------------
  604. REAL(wp) :: pa(:,:,:),pb ! input
  605. REAL(wp) :: SIGN_ARRAY_3D_B(SIZE(pa,1),SIZE(pa,2),SIZE(pa,3)) ! result
  606. !!-----------------------------------------------------------------------
  607. IF( pb >= 0.e0 ) THEN ; SIGN_ARRAY_3D_B = ABS(pa)
  608. ELSE ; SIGN_ARRAY_3D_B =-ABS(pa)
  609. ENDIF
  610. END FUNCTION SIGN_ARRAY_3D_B
  611. #endif
  612. !!======================================================================
  613. END MODULE lib_fortran