diaptr.F90 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. MODULE diaptr
  2. !!======================================================================
  3. !! *** MODULE diaptr ***
  4. !! Ocean physics: Computes meridonal transports and zonal means
  5. !!=====================================================================
  6. !! History : 1.0 ! 2003-09 (C. Talandier, G. Madec) Original code
  7. !! 2.0 ! 2006-01 (A. Biastoch) Allow sub-basins computation
  8. !! 3.2 ! 2010-03 (O. Marti, S. Flavoni) Add fields
  9. !! 3.3 ! 2010-10 (G. Madec) dynamical allocation
  10. !! 3.6 ! 2014-12 (C. Ethe) use of IOM
  11. !! 3.6 ! 2016-06 (T. Graham) Addition of diagnostics for CMIP6
  12. !!----------------------------------------------------------------------
  13. !!----------------------------------------------------------------------
  14. !! dia_ptr : Poleward Transport Diagnostics module
  15. !! dia_ptr_init : Initialization, namelist read
  16. !! ptr_sjk : "zonal" mean computation of a field - tracer or flux array
  17. !! ptr_sj : "zonal" and vertical sum computation of a "meridional" flux array
  18. !! (Generic interface to ptr_sj_3d, ptr_sj_2d)
  19. !!----------------------------------------------------------------------
  20. USE oce ! ocean dynamics and active tracers
  21. USE dom_oce ! ocean space and time domain
  22. USE phycst ! physical constants
  23. USE ldftra_oce
  24. !
  25. USE iom ! IOM library
  26. USE in_out_manager ! I/O manager
  27. USE lib_mpp ! MPP library
  28. USE timing ! preformance summary
  29. IMPLICIT NONE
  30. PRIVATE
  31. INTERFACE ptr_sj
  32. MODULE PROCEDURE ptr_sj_3d, ptr_sj_2d
  33. END INTERFACE
  34. PUBLIC ptr_sj ! call by tra_ldf & tra_adv routines
  35. PUBLIC ptr_sjk !
  36. PUBLIC dia_ptr_init ! call in step module
  37. PUBLIC dia_ptr ! call in step module
  38. PUBLIC dia_ptr_ohst_components ! called from tra_ldf/tra_adv routines
  39. ! !!** namelist namptr **
  40. REAL(wp), ALLOCATABLE, SAVE, PUBLIC, DIMENSION(:,:) :: htr_adv, htr_ldf, htr_eiv, htr_vt !: Heat TRansports (adv, diff, Bolus.)
  41. REAL(wp), ALLOCATABLE, SAVE, PUBLIC, DIMENSION(:,:) :: str_adv, str_ldf, str_eiv, str_vs !: Salt TRansports (adv, diff, Bolus.)
  42. REAL(wp), ALLOCATABLE, SAVE, PUBLIC, DIMENSION(:,:) :: htr_ove, str_ove !: heat Salt TRansports ( overturn.)
  43. REAL(wp), ALLOCATABLE, SAVE, PUBLIC, DIMENSION(:,:) :: htr_btr, str_btr !: heat Salt TRansports ( barotropic )
  44. LOGICAL, PUBLIC :: ln_diaptr ! Poleward transport flag (T) or not (F)
  45. LOGICAL, PUBLIC :: ln_subbas ! Atlantic/Pacific/Indian basins calculation
  46. INTEGER, PUBLIC :: nptr ! = 1 (l_subbas=F) or = 5 (glo, atl, pac, ind, ipc) (l_subbas=T)
  47. INTEGER :: n_glo = 1
  48. INTEGER :: n_atl = 2
  49. INTEGER :: n_ipc = 3
  50. INTEGER :: n_ind = 4
  51. INTEGER :: n_pac = 5
  52. REAL(wp) :: rc_sv = 1.e-6_wp ! conversion from m3/s to Sverdrup
  53. REAL(wp) :: rc_pwatt = 1.e-15_wp ! conversion from W to PW (further x rau0 x Cp)
  54. !REAL(wp) :: rc_ggram = 1.e-6_wp ! conversion from g to Gg
  55. !!JD : line above assumes that rc_ggram is implicitly multiplied by rau0=1000 - I prefer to explicit this
  56. REAL(wp) :: rc_ggram = 1.e-9_wp ! conversion from g to Gg (further x rau0)
  57. CHARACTER(len=3), ALLOCATABLE, SAVE, DIMENSION(:) :: clsubb
  58. REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: btmsk ! T-point basin interior masks
  59. REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: btm30 ! mask out Southern Ocean (=0 south of 30°S)
  60. REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: btmip ! basins as identified by OMIP6
  61. REAL(wp), TARGET, ALLOCATABLE, SAVE, DIMENSION(:) :: p_fval1d
  62. REAL(wp), TARGET, ALLOCATABLE, SAVE, DIMENSION(:,:) :: p_fval2d
  63. !! * Substitutions
  64. # include "domzgr_substitute.h90"
  65. # include "vectopt_loop_substitute.h90"
  66. !!----------------------------------------------------------------------
  67. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  68. !! $Id$
  69. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  70. !!----------------------------------------------------------------------
  71. CONTAINS
  72. SUBROUTINE dia_ptr( pvtr )
  73. !!----------------------------------------------------------------------
  74. !! *** ROUTINE dia_ptr ***
  75. !!----------------------------------------------------------------------
  76. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(in), OPTIONAL :: pvtr ! j-effective transport
  77. !
  78. INTEGER :: ji, jj, jk, jn ! dummy loop indices
  79. REAL(wp) :: zsfc,zvfc ! local scalar
  80. REAL(wp), DIMENSION(jpi,jpj) :: z2d ! 2D workspace
  81. REAL(wp), DIMENSION(jpi,jpj,jpk) :: z3d ! 3D workspace
  82. REAL(wp), DIMENSION(jpi,jpj,jpk) :: zmask ! 3D workspace
  83. REAL(wp), DIMENSION(jpi,jpj,jpk,jpts) :: zts ! 3D workspace
  84. REAL(wp), DIMENSION(jpj) :: vsum ! 1D workspace
  85. REAL(wp), DIMENSION(jpj,jpts) :: tssum ! 1D workspace
  86. !
  87. !
  88. !overturning calculation
  89. REAL(wp), DIMENSION(jpj,jpk,nptr) :: sjk , r1_sjk ! i-mean i-k-surface and its inverse
  90. REAL(wp), DIMENSION(jpj,jpk,nptr) :: v_msf, sn_jk , tn_jk ! i-mean T and S, j-Stream-Function
  91. ! REAL(wp), DIMENSION(jpi,jpj,jpk) :: zvn ! 3D workspace
  92. !CMIP6 outputs
  93. REAL(wp), DIMENSION(jpi,jpj,jpk,nptr) :: z4d
  94. REAL(wp), DIMENSION(jpi,jpj,nptr) :: z3d1, z3d2
  95. CHARACTER( len = 12 ) :: cl1
  96. !!----------------------------------------------------------------------
  97. !
  98. IF( nn_timing == 1 ) CALL timing_start('dia_ptr')
  99. CALL iom_put( 'basins', btmip ) ! output basins as identified by OMIP6
  100. !
  101. IF( PRESENT( pvtr ) ) THEN
  102. ! IF( iom_use("zomsfglo") .OR. iom_use("zomsf_znl") ) THEN ! effective MSF
  103. !z3d(1,:,:) = ptr_sjk( pvtr(:,:,:) ) ! zonal cumulative effective transport
  104. z4d(1,:,:,1) = ptr_sjk( pvtr(:,:,:), btmsk(:,:,1) ) ! zonal cumulative effective transport excluding closed-seas
  105. DO jk = jpkm1, 1, -1
  106. z4d(1,:,jk,1) = z4d(1,:,jk+1,1) - z4d(1,:,jk,1) ! effective j-Stream-Function (MSF)
  107. END DO
  108. DO ji = 1, jpi
  109. z4d(ji,:,:,1) = z4d(1,:,:,1)
  110. ENDDO
  111. cl1 = TRIM('zomsf'//clsubb(1) )
  112. CALL iom_put( cl1, z4d(:,:,:,1) * rc_sv )
  113. IF( ln_subbas ) THEN
  114. DO jn = 2, nptr ! by sub-basins
  115. z4d(1,:,:,jn) = ptr_sjk( pvtr(:,:,:), btmsk(:,:,jn)*btm30(:,:) )
  116. DO jk = jpkm1, 1, -1
  117. z4d(1,:,jk,jn) = z4d(1,:,jk+1,jn) - z4d(1,:,jk,jn) ! effective j-Stream-Function (MSF)
  118. END DO
  119. DO ji = 1, jpi
  120. z4d(ji,:,:,jn) = z4d(1,:,:,jn)
  121. ENDDO
  122. cl1 = TRIM('zomsf'//clsubb(jn) )
  123. CALL iom_put( cl1, z4d(:,:,:,jn) * rc_sv )
  124. END DO
  125. ! ENDIF
  126. CALL iom_put("zomsf_znl" , z4d(:,:,:,:) * rc_sv )
  127. ENDIF
  128. ! IF( iom_use("sopstove") .OR. iom_use("sophtove") .OR. iom_use("sopstbtr") .OR. iom_use("sophtbtr") &
  129. ! & .OR. iom_use("sopstove_znl") .OR. iom_use("sophtove_znl") &
  130. ! & .OR. iom_use("sopstbtr_znl") .OR. iom_use("sophtbtr_znl") ) THEN
  131. ! define fields multiplied by scalar
  132. zmask(:,:,:) = 0._wp
  133. zts(:,:,:,:) = 0._wp
  134. ! zvn(:,:,:) = 0._wp
  135. !!JD : removed to replace by pvtr which represents effective velocities
  136. DO jk = 1, jpkm1
  137. DO jj = 1, jpjm1
  138. DO ji = 1, jpi
  139. zvfc = e1v(ji,jj) * fse3v(ji,jj,jk)
  140. zmask(ji,jj,jk) = vmask(ji,jj,jk) * zvfc
  141. zts(ji,jj,jk,jp_tem) = (tsn(ji,jj,jk,jp_tem)+tsn(ji,jj+1,jk,jp_tem)) * 0.5 * zvfc !Tracers averaged onto V grid
  142. zts(ji,jj,jk,jp_sal) = (tsn(ji,jj,jk,jp_sal)+tsn(ji,jj+1,jk,jp_sal)) * 0.5 * zvfc
  143. ! zvn(ji,jj,jk) = vn(ji,jj,jk) * zvfc
  144. !!JD : vn is only the eulerian velocity, hence barotropic and overturning transports do not include contributions from parameterizations
  145. ENDDO
  146. ENDDO
  147. ENDDO
  148. ! ENDIF
  149. ! IF( iom_use("sopstove") .OR. iom_use("sophtove") &
  150. ! & .OR. iom_use("sopstove_znl") .OR. iom_use("sophtove_znl") ) THEN
  151. sjk(:,:,1) = ptr_sjk( zmask(:,:,:), btmsk(:,:,1) )
  152. r1_sjk(:,:,1) = 0._wp
  153. WHERE( sjk(:,:,1) /= 0._wp ) r1_sjk(:,:,1) = 1._wp / sjk(:,:,1)
  154. ! i-mean T and S, j-Stream-Function, global
  155. tn_jk(:,:,1) = ptr_sjk( zts(:,:,:,jp_tem) ) * r1_sjk(:,:,1)
  156. sn_jk(:,:,1) = ptr_sjk( zts(:,:,:,jp_sal) ) * r1_sjk(:,:,1)
  157. ! v_msf(:,:,1) = ptr_sjk( zvn(:,:,:) )
  158. v_msf(:,:,1) = ptr_sjk( pvtr(:,:,:), btmsk(:,:,1) )
  159. htr_ove(:,1) = SUM( v_msf(:,:,1)*tn_jk(:,:,1) ,2 )
  160. str_ove(:,1) = SUM( v_msf(:,:,1)*sn_jk(:,:,1) ,2 )
  161. z2d(1,:) = htr_ove(:,1) * rc_pwatt ! (conversion in PW)
  162. DO ji = 1, jpi
  163. z2d(ji,:) = z2d(1,:)
  164. ENDDO
  165. cl1 = 'sophtove'
  166. CALL iom_put( TRIM(cl1), z2d )
  167. z3d1(:,:,1) = z2d(:,:)
  168. z2d(1,:) = str_ove(:,1) * rc_ggram ! (conversion in Gg)
  169. DO ji = 1, jpi
  170. z2d(ji,:) = z2d(1,:)
  171. ENDDO
  172. cl1 = 'sopstove'
  173. CALL iom_put( TRIM(cl1), z2d )
  174. z3d2(:,:,1) = z2d(:,:)
  175. IF( ln_subbas ) THEN
  176. DO jn = 2, nptr
  177. sjk(:,:,jn) = ptr_sjk( zmask(:,:,:), btmsk(:,:,jn) )
  178. r1_sjk(:,:,jn) = 0._wp
  179. WHERE( sjk(:,:,jn) /= 0._wp ) r1_sjk(:,:,jn) = 1._wp / sjk(:,:,jn)
  180. ! i-mean T and S, j-Stream-Function, basin
  181. tn_jk(:,:,jn) = ptr_sjk( zts(:,:,:,jp_tem), btmsk(:,:,jn) ) * r1_sjk(:,:,jn)
  182. sn_jk(:,:,jn) = ptr_sjk( zts(:,:,:,jp_sal), btmsk(:,:,jn) ) * r1_sjk(:,:,jn)
  183. ! v_msf(:,:,jn) = ptr_sjk( zvn(:,:,:), btmsk(:,:,jn) )
  184. v_msf(:,:,jn) = ptr_sjk( pvtr(:,:,:), btmsk(:,:,jn) * btm30(:,:))
  185. htr_ove(:,jn) = SUM( v_msf(:,:,jn)*tn_jk(:,:,jn) ,2 )
  186. str_ove(:,jn) = SUM( v_msf(:,:,jn)*sn_jk(:,:,jn) ,2 )
  187. z2d(1,:) = htr_ove(:,jn) * rc_pwatt ! (conversion in PW)
  188. DO ji = 1, jpi
  189. z2d(ji,:) = z2d(1,:)
  190. ENDDO
  191. cl1 = TRIM('sophtove_'//clsubb(jn))
  192. CALL iom_put( cl1, z2d )
  193. z3d1(:,:,jn) = z2d(:,:)
  194. z2d(1,:) = str_ove(:,jn) * rc_ggram ! (conversion in Gg)
  195. DO ji = 1, jpi
  196. z2d(ji,:) = z2d(1,:)
  197. ENDDO
  198. cl1 = TRIM('sopstove_'//clsubb(jn))
  199. CALL iom_put( cl1, z2d )
  200. z3d2(:,:,jn) = z2d(:,:)
  201. END DO
  202. ENDIF
  203. CALL iom_put("sophtove_znl", z3d1 )
  204. CALL iom_put("sopstove_znl", z3d2 )
  205. ! ENDIF
  206. ! IF( iom_use("sopstbtr") .OR. iom_use("sophtbtr") &
  207. ! & .OR. iom_use("sopstbtr") .OR. iom_use("sophtbtr") ) THEN
  208. ! Calculate barotropic heat and salt transport here
  209. sjk(:,1,1) = ptr_sj( zmask(:,:,:), btmsk(:,:,1) )
  210. r1_sjk(:,1,1) = 0._wp
  211. WHERE( sjk(:,1,1) /= 0._wp ) r1_sjk(:,1,1) = 1._wp / sjk(:,1,1)
  212. ! vsum = ptr_sj( zvn(:,:,:), btmsk(:,:,1))
  213. vsum = ptr_sj( pvtr(:,:,:), btmsk(:,:,1))
  214. tssum(:,jp_tem) = ptr_sj( zts(:,:,:,jp_tem), btmsk(:,:,1) )
  215. tssum(:,jp_sal) = ptr_sj( zts(:,:,:,jp_sal), btmsk(:,:,1) )
  216. htr_btr(:,1) = vsum * tssum(:,jp_tem) * r1_sjk(:,1,1)
  217. str_btr(:,1) = vsum * tssum(:,jp_sal) * r1_sjk(:,1,1)
  218. z2d(1,:) = htr_btr(:,1) * rc_pwatt ! (conversion in PW)
  219. DO ji = 2, jpi
  220. z2d(ji,:) = z2d(1,:)
  221. ENDDO
  222. cl1 = 'sophtbtr'
  223. CALL iom_put( TRIM(cl1), z2d )
  224. z3d1(:,:,1) = z2d(:,:)
  225. z2d(1,:) = str_btr(:,1) * rc_ggram ! (conversion in Gg)
  226. DO ji = 2, jpi
  227. z2d(ji,:) = z2d(1,:)
  228. ENDDO
  229. cl1 = 'sopstbtr'
  230. CALL iom_put( TRIM(cl1), z2d )
  231. z3d2(:,:,1) = z2d(:,:)
  232. IF( ln_subbas ) THEN
  233. DO jn = 2, nptr
  234. sjk(:,1,jn) = ptr_sj( zmask(:,:,:), btmsk(:,:,jn) )
  235. r1_sjk(:,1,jn) = 0._wp
  236. WHERE( sjk(:,1,jn) /= 0._wp ) r1_sjk(:,1,jn) = 1._wp / sjk(:,1,jn)
  237. ! vsum = ptr_sj( zvn(:,:,:), btmsk(:,:,jn))
  238. vsum = ptr_sj( pvtr(:,:,:), btmsk(:,:,jn) * btm30(:,:))
  239. tssum(:,jp_tem) = ptr_sj( zts(:,:,:,jp_tem), btmsk(:,:,jn) )
  240. tssum(:,jp_sal) = ptr_sj( zts(:,:,:,jp_sal), btmsk(:,:,jn) )
  241. htr_btr(:,jn) = vsum * tssum(:,jp_tem) * r1_sjk(:,1,jn)
  242. str_btr(:,jn) = vsum * tssum(:,jp_sal) * r1_sjk(:,1,jn)
  243. z2d(1,:) = htr_btr(:,jn) * rc_pwatt ! (conversion in PW)
  244. DO ji = 1, jpi
  245. z2d(ji,:) = z2d(1,:)
  246. ENDDO
  247. cl1 = TRIM('sophtbtr_'//clsubb(jn))
  248. CALL iom_put( cl1, z2d )
  249. z3d1(:,:,jn) = z2d(:,:)
  250. z2d(1,:) = str_btr(:,jn) * rc_ggram ! (conversion in Gg)
  251. DO ji = 1, jpi
  252. z2d(ji,:) = z2d(1,:)
  253. ENDDO
  254. cl1 = TRIM('sopstbtr_'//clsubb(jn))
  255. CALL iom_put( cl1, z2d )
  256. z3d2(:,:,jn) = z2d(:,:)
  257. ENDDO
  258. ENDIF !ln_subbas
  259. CALL iom_put("sophtbtr_znl", z3d1 )
  260. CALL iom_put("sopstbtr_znl", z3d2 )
  261. ! ENDIF !iom_use("sopstbtr....)
  262. !
  263. ELSE
  264. !
  265. ! IF( iom_use("zotemglo") ) THEN ! i-mean i-k-surface
  266. DO jk = 1, jpkm1
  267. DO jj = 1, jpj
  268. DO ji = 1, jpi
  269. zsfc = e1t(ji,jj) * fse3t(ji,jj,jk)
  270. zmask(ji,jj,jk) = tmask(ji,jj,jk) * zsfc
  271. zts(ji,jj,jk,jp_tem) = tsn(ji,jj,jk,jp_tem) * zsfc
  272. zts(ji,jj,jk,jp_sal) = tsn(ji,jj,jk,jp_sal) * zsfc
  273. ENDDO
  274. ENDDO
  275. ENDDO
  276. DO jn = 1, nptr
  277. zmask(1,:,:) = ptr_sjk( zmask(:,:,:), btmsk(:,:,jn) )
  278. cl1 = TRIM('zosrf'//clsubb(jn) )
  279. CALL iom_put( cl1, zmask )
  280. !
  281. z3d(1,:,:) = ptr_sjk( zts(:,:,:,jp_tem), btmsk(:,:,jn) ) &
  282. & / MAX( zmask(1,:,:), 10.e-15 )
  283. DO ji = 1, jpi
  284. z3d(ji,:,:) = z3d(1,:,:)
  285. ENDDO
  286. cl1 = TRIM('zotem'//clsubb(jn) )
  287. CALL iom_put( cl1, z3d )
  288. !
  289. z3d(1,:,:) = ptr_sjk( zts(:,:,:,jp_sal), btmsk(:,:,jn) ) &
  290. & / MAX( zmask(1,:,:), 10.e-15 )
  291. DO ji = 1, jpi
  292. z3d(ji,:,:) = z3d(1,:,:)
  293. ENDDO
  294. cl1 = TRIM('zosal'//clsubb(jn) )
  295. CALL iom_put( cl1, z3d )
  296. END DO
  297. ! ENDIF
  298. !
  299. ! ! Advective and diffusive heat and salt transport
  300. ! IF( iom_use("sophtadv") .OR. iom_use("sopstadv") &
  301. ! & .OR. iom_use("sopstadv_znl") .OR. iom_use("sophtadv_znl") ) THEN
  302. z2d(1,:) = htr_adv(:,1) * rc_pwatt ! (conversion in PW)
  303. DO ji = 1, jpi
  304. z2d(ji,:) = z2d(1,:)
  305. ENDDO
  306. cl1 = 'sophtadv'
  307. CALL iom_put( TRIM(cl1), z2d )
  308. z3d1(:,:,1) = z2d(:,:)
  309. z2d(1,:) = str_adv(:,1) * rc_ggram ! (conversion in Gg)
  310. DO ji = 1, jpi
  311. z2d(ji,:) = z2d(1,:)
  312. ENDDO
  313. cl1 = 'sopstadv'
  314. CALL iom_put( TRIM(cl1), z2d )
  315. z3d2(:,:,1) = z2d(:,:)
  316. IF( ln_subbas ) THEN
  317. DO jn=2,nptr
  318. z2d(1,:) = htr_adv(:,jn) * rc_pwatt ! (conversion in PW)
  319. DO ji = 1, jpi
  320. z2d(ji,:) = z2d(1,:)
  321. ENDDO
  322. cl1 = TRIM('sophtadv_'//clsubb(jn))
  323. CALL iom_put( cl1, z2d )
  324. z3d1(:,:,jn) = z2d(:,:)
  325. z2d(1,:) = str_adv(:,jn) * rc_ggram ! (conversion in Gg)
  326. DO ji = 1, jpi
  327. z2d(ji,:) = z2d(1,:)
  328. ENDDO
  329. cl1 = TRIM('sopstadv_'//clsubb(jn))
  330. CALL iom_put( cl1, z2d )
  331. z3d2(:,:,jn) = z2d(:,:)
  332. ENDDO
  333. ENDIF
  334. CALL iom_put("sophtadv_znl", z3d1 )
  335. CALL iom_put("sopstadv_znl", z3d2 )
  336. ! ENDIF
  337. !
  338. ! IF( iom_use("sophtldf") .OR. iom_use("sopstldf") &
  339. ! & .OR. iom_use("sopstldf_znl") .OR. iom_use("sophtldf_znl") ) THEN
  340. z2d(1,:) = htr_ldf(:,1) * rc_pwatt ! (conversion in PW)
  341. DO ji = 1, jpi
  342. z2d(ji,:) = z2d(1,:)
  343. ENDDO
  344. cl1 = 'sophtldf'
  345. CALL iom_put( TRIM(cl1), z2d )
  346. z3d1(:,:,1) = z2d(:,:)
  347. z2d(1,:) = str_ldf(:,1) * rc_ggram ! (conversion in Gg)
  348. DO ji = 1, jpi
  349. z2d(ji,:) = z2d(1,:)
  350. ENDDO
  351. cl1 = 'sopstldf'
  352. CALL iom_put( TRIM(cl1), z2d )
  353. z3d2(:,:,1) = z2d(:,:)
  354. IF( ln_subbas ) THEN
  355. DO jn=2,nptr
  356. z2d(1,:) = htr_ldf(:,jn) * rc_pwatt ! (conversion in PW)
  357. DO ji = 1, jpi
  358. z2d(ji,:) = z2d(1,:)
  359. ENDDO
  360. cl1 = TRIM('sophtldf_'//clsubb(jn))
  361. CALL iom_put( cl1, z2d )
  362. z3d1(:,:,jn) = z2d(:,:)
  363. z2d(1,:) = str_ldf(:,jn) * rc_ggram ! (conversion in Gg)
  364. DO ji = 1, jpi
  365. z2d(ji,:) = z2d(1,:)
  366. ENDDO
  367. cl1 = TRIM('sopstldf_'//clsubb(jn))
  368. CALL iom_put( cl1, z2d )
  369. z3d2(:,:,jn) = z2d(:,:)
  370. ENDDO
  371. ENDIF
  372. CALL iom_put("sophtldf_znl", z3d1 )
  373. CALL iom_put("sopstldf_znl", z3d2 )
  374. ! ENDIF
  375. ! IF( iom_use("sopht_vt") .OR. iom_use("sopst_vs") &
  376. ! & .OR. iom_use("sopht_vt_znl") .OR. iom_use("sopst_vs_znl") ) THEN
  377. z2d(1,:) = htr_vt(:,1) * rc_pwatt ! (conversion in PW)
  378. DO ji = 1, jpi
  379. z2d(ji,:) = z2d(1,:)
  380. ENDDO
  381. cl1 = 'sopht_vt'
  382. CALL iom_put( TRIM(cl1), z2d )
  383. z3d1(:,:,1) = z2d(:,:)
  384. z2d(1,:) = str_vs(:,1) * rc_ggram ! (conversion in Gg)
  385. DO ji = 1, jpi
  386. z2d(ji,:) = z2d(1,:)
  387. ENDDO
  388. cl1 = 'sopst_vs'
  389. CALL iom_put( TRIM(cl1), z2d )
  390. z3d2(:,:,1) = z2d(:,:)
  391. IF( ln_subbas ) THEN
  392. DO jn=2,nptr
  393. z2d(1,:) = htr_vt(:,jn) * rc_pwatt ! (conversion in PW)
  394. DO ji = 1, jpi
  395. z2d(ji,:) = z2d(1,:)
  396. ENDDO
  397. cl1 = TRIM('sopht_vt_'//clsubb(jn))
  398. CALL iom_put( cl1, z2d )
  399. z3d1(:,:,jn) = z2d(:,:)
  400. z2d(1,:) = str_vs(:,jn) * rc_ggram ! (conversion in Gg)
  401. DO ji = 1, jpi
  402. z2d(ji,:) = z2d(1,:)
  403. ENDDO
  404. cl1 = TRIM('sopst_vs_'//clsubb(jn))
  405. CALL iom_put( cl1, z2d )
  406. z3d2(:,:,jn) = z2d(:,:)
  407. ENDDO
  408. ENDIF
  409. CALL iom_put("sopht_vt_znl", z3d1 )
  410. CALL iom_put("sopst_vs_znl", z3d2 )
  411. ! ENDIF
  412. #ifdef key_diaeiv
  413. IF(lk_traldf_eiv) THEN
  414. ! IF( iom_use("sophteiv") .OR. iom_use("sopsteiv") &
  415. ! & .OR. iom_use("sophteiv_znl") .OR. iom_use("sopsteiv_znl") ) THEN
  416. z2d(1,:) = htr_eiv(:,1) * rc_pwatt ! (conversion in PW)
  417. DO ji = 1, jpi
  418. z2d(ji,:) = z2d(1,:)
  419. ENDDO
  420. cl1 = 'sophteiv'
  421. CALL iom_put( TRIM(cl1), z2d )
  422. z3d1(:,:,1) = z2d(:,:)
  423. z2d(1,:) = str_eiv(:,1) * rc_ggram ! (conversion in Gg)
  424. DO ji = 1, jpi
  425. z2d(ji,:) = z2d(1,:)
  426. ENDDO
  427. cl1 = 'sopsteiv'
  428. CALL iom_put( TRIM(cl1), z2d )
  429. z3d2(:,:,1) = z2d(:,:)
  430. IF( ln_subbas ) THEN
  431. DO jn=2,nptr
  432. z2d(1,:) = htr_eiv(:,jn) * rc_pwatt ! (conversion in PW)
  433. DO ji = 1, jpi
  434. z2d(ji,:) = z2d(1,:)
  435. ENDDO
  436. cl1 = TRIM('sophteiv_'//clsubb(jn))
  437. CALL iom_put( cl1, z2d )
  438. z3d1(:,:,jn) = z2d(:,:)
  439. z2d(1,:) = str_eiv(:,jn) * rc_ggram ! (conversion in Gg)
  440. DO ji = 1, jpi
  441. z2d(ji,:) = z2d(1,:)
  442. ENDDO
  443. cl1 = TRIM('sopsteiv_'//clsubb(jn))
  444. CALL iom_put( cl1, z2d )
  445. z3d2(:,:,jn) = z2d(:,:)
  446. ENDDO
  447. ENDIF
  448. CALL iom_put("sophteiv_znl", z3d1 )
  449. CALL iom_put("sopsteiv_znl", z3d2 )
  450. ! ENDIF
  451. ENDIF
  452. #endif
  453. !
  454. ENDIF
  455. !
  456. IF( nn_timing == 1 ) CALL timing_stop('dia_ptr')
  457. !
  458. END SUBROUTINE dia_ptr
  459. SUBROUTINE dia_ptr_init
  460. !!----------------------------------------------------------------------
  461. !! *** ROUTINE dia_ptr_init ***
  462. !!
  463. !! ** Purpose : Initialization, namelist read
  464. !!----------------------------------------------------------------------
  465. INTEGER :: jn ! local integers
  466. INTEGER :: inum, ierr ! local integers
  467. INTEGER :: ios ! Local integer output status for namelist read
  468. !!
  469. NAMELIST/namptr/ ln_diaptr, ln_subbas
  470. !!----------------------------------------------------------------------
  471. REWIND( numnam_ref ) ! Namelist namptr in reference namelist : Poleward transport
  472. READ ( numnam_ref, namptr, IOSTAT = ios, ERR = 901)
  473. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namptr in reference namelist', lwp )
  474. REWIND( numnam_cfg ) ! Namelist namptr in configuration namelist : Poleward transport
  475. READ ( numnam_cfg, namptr, IOSTAT = ios, ERR = 902 )
  476. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namptr in configuration namelist', lwp )
  477. IF(lwm) WRITE ( numond, namptr )
  478. IF(lwp) THEN ! Control print
  479. WRITE(numout,*)
  480. WRITE(numout,*) 'dia_ptr_init : poleward transport and msf initialization'
  481. WRITE(numout,*) '~~~~~~~~~~~~'
  482. WRITE(numout,*) ' Namelist namptr : set ptr parameters'
  483. WRITE(numout,*) ' Poleward heat & salt transport (T) or not (F) ln_diaptr = ', ln_diaptr
  484. WRITE(numout,*) ' Global (F) or glo/Atl/Pac/Ind/Indo-Pac basins ln_subbas = ', ln_subbas
  485. ENDIF
  486. IF( ln_diaptr ) THEN
  487. !
  488. IF( ln_subbas ) THEN
  489. nptr = 5 ! Global, Atlantic, Pacific, Indian, Indo-Pacific
  490. ALLOCATE( clsubb(nptr) )
  491. clsubb(n_glo) = 'glo'
  492. clsubb(n_atl) = 'atl'
  493. clsubb(n_ipc) = 'ipc'
  494. clsubb(n_ind) = 'ind'
  495. clsubb(n_pac) = 'pac'
  496. ELSE
  497. nptr = 1 ! Global only
  498. ALLOCATE( clsubb(nptr) )
  499. clsubb(n_glo) = 'glo'
  500. ENDIF
  501. ! ! allocate dia_ptr arrays
  502. IF( dia_ptr_alloc() /= 0 ) CALL ctl_stop( 'STOP', 'dia_ptr_init : unable to allocate arrays' )
  503. rc_pwatt = rc_pwatt * rau0_rcp ! conversion from K.s-1 to PetaWatt
  504. rc_ggram = rc_ggram * rau0 ! conversion from m3/s to Gg/s
  505. IF( lk_mpp ) CALL mpp_ini_znl( numout ) ! Define MPI communicator for zonal sum
  506. IF( ln_subbas ) THEN ! load sub-basin mask
  507. CALL iom_open( 'subbasins', inum, ldstop = .FALSE. )
  508. ! CALL iom_get( inum, jpdom_data, 'glomsk', btmsk(:,:,1) ) ! global domain without closed seas (if required)
  509. CALL iom_get( inum, jpdom_data, 'atlmsk', btmsk(:,:,n_atl) ) ! Atlantic basin
  510. CALL iom_get( inum, jpdom_data, 'pacmsk', btmsk(:,:,n_pac) ) ! Pacific basin
  511. CALL iom_get( inum, jpdom_data, 'indmsk', btmsk(:,:,n_ind) ) ! Indian basin
  512. IF( iom_varid( inum, 'basins' , ldstop = .FALSE. ) > 0 ) THEN
  513. CALL iom_get( inum, jpdom_data, 'basins', btmip ) ! basins as identified by OMIP6
  514. !!JD : if basins exists as defined by OMIP6, then atlmsk, pacmsk and indmsk should be defined based on basins
  515. ELSE
  516. ! btmip(:,:) = btmsk(:,:,1)
  517. btmip(:,:) = tmask_i(:,:)
  518. ENDIF
  519. CALL iom_close( inum )
  520. btmsk(:,:,n_ipc) = MAX ( btmsk(:,:,n_ind), btmsk(:,:,n_pac) ) ! Indo-Pacific basin
  521. ! WHERE( gphit(:,:)*tmask_i(:,:) < -30._wp)
  522. !! JD : modification so that overturning streamfunction is available in Atlantic at 34S to compare with observations
  523. WHERE( gphit(:,:)*tmask_i(:,:) < -34._wp)
  524. btm30(:,:) = 0._wp ! mask out Southern Ocean
  525. ELSE WHERE
  526. btm30(:,:) = ssmask(:,:)
  527. END WHERE
  528. ENDIF
  529. btmsk(:,:,1) = tmask_i(:,:) ! global ocean
  530. IF( ln_subbas ) THEN ! load sub-basin mask
  531. DO jn = 2, nptr
  532. btmsk(:,:,jn) = btmsk(:,:,jn) * tmask_i(:,:) ! interior domain only
  533. END DO
  534. btmip(:,:) = btmip(:,:) * tmask_i(:,:) ! to make sure that periodicity is handled correctly
  535. ENDIF
  536. ! Initialise arrays to zero because diatpr is called before they are first calculated
  537. ! Note that this means diagnostics will not be exactly correct when model run is restarted.
  538. htr_adv(:,:) = 0._wp ; str_adv(:,:) = 0._wp
  539. htr_ldf(:,:) = 0._wp ; str_ldf(:,:) = 0._wp
  540. htr_eiv(:,:) = 0._wp ; str_eiv(:,:) = 0._wp
  541. htr_vt(:,:) = 0._wp ; str_vs(:,:) = 0._wp
  542. htr_ove(:,:) = 0._wp ; str_ove(:,:) = 0._wp
  543. htr_btr(:,:) = 0._wp ; str_btr(:,:) = 0._wp
  544. !
  545. ENDIF
  546. !
  547. END SUBROUTINE dia_ptr_init
  548. SUBROUTINE dia_ptr_ohst_components( ktra, cptr, pva )
  549. !!----------------------------------------------------------------------
  550. !! *** ROUTINE dia_ptr_ohst_components ***
  551. !!----------------------------------------------------------------------
  552. !! Wrapper for heat and salt transport calculations to calculate them for each basin
  553. !! Called from all advection and/or diffusion routines
  554. !!----------------------------------------------------------------------
  555. INTEGER , INTENT(in ) :: ktra ! tracer index
  556. CHARACTER(len=3) , INTENT(in) :: cptr ! transport type 'adv'/'ldf'/'eiv'
  557. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(in) :: pva ! 3D input array of advection/diffusion
  558. INTEGER :: jn !
  559. IF( cptr == 'adv' ) THEN
  560. IF( ktra == jp_tem ) htr_adv(:,1) = ptr_sj( pva(:,:,:) )
  561. IF( ktra == jp_sal ) str_adv(:,1) = ptr_sj( pva(:,:,:) )
  562. ENDIF
  563. IF( cptr == 'ldf' ) THEN
  564. IF( ktra == jp_tem ) htr_ldf(:,1) = ptr_sj( pva(:,:,:) )
  565. IF( ktra == jp_sal ) str_ldf(:,1) = ptr_sj( pva(:,:,:) )
  566. ENDIF
  567. IF( cptr == 'eiv' ) THEN
  568. IF( ktra == jp_tem ) htr_eiv(:,1) = ptr_sj( pva(:,:,:) )
  569. IF( ktra == jp_sal ) str_eiv(:,1) = ptr_sj( pva(:,:,:) )
  570. ENDIF
  571. IF( cptr == 'vts' ) THEN
  572. IF( ktra == jp_tem ) htr_vt(:,1) = ptr_sj( pva(:,:,:) )
  573. IF( ktra == jp_sal ) str_vs(:,1) = ptr_sj( pva(:,:,:) )
  574. ENDIF
  575. !
  576. IF( ln_subbas ) THEN
  577. !
  578. IF( cptr == 'adv' ) THEN
  579. IF( ktra == jp_tem ) THEN
  580. DO jn = 2, nptr
  581. htr_adv(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  582. END DO
  583. ENDIF
  584. IF( ktra == jp_sal ) THEN
  585. DO jn = 2, nptr
  586. str_adv(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  587. END DO
  588. ENDIF
  589. ENDIF
  590. IF( cptr == 'ldf' ) THEN
  591. IF( ktra == jp_tem ) THEN
  592. DO jn = 2, nptr
  593. htr_ldf(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  594. END DO
  595. ENDIF
  596. IF( ktra == jp_sal ) THEN
  597. DO jn = 2, nptr
  598. str_ldf(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  599. END DO
  600. ENDIF
  601. ENDIF
  602. IF( cptr == 'eiv' ) THEN
  603. IF( ktra == jp_tem ) THEN
  604. DO jn = 2, nptr
  605. htr_eiv(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  606. END DO
  607. ENDIF
  608. IF( ktra == jp_sal ) THEN
  609. DO jn = 2, nptr
  610. str_eiv(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  611. END DO
  612. ENDIF
  613. ENDIF
  614. IF( cptr == 'vts' ) THEN
  615. IF( ktra == jp_tem ) THEN
  616. DO jn = 2, nptr
  617. htr_vt(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  618. END DO
  619. ENDIF
  620. IF( ktra == jp_sal ) THEN
  621. DO jn = 2, nptr
  622. str_vs(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  623. END DO
  624. ENDIF
  625. ENDIF
  626. !
  627. ENDIF
  628. END SUBROUTINE dia_ptr_ohst_components
  629. FUNCTION dia_ptr_alloc()
  630. !!----------------------------------------------------------------------
  631. !! *** ROUTINE dia_ptr_alloc ***
  632. !!----------------------------------------------------------------------
  633. INTEGER :: dia_ptr_alloc ! return value
  634. INTEGER, DIMENSION(3) :: ierr
  635. !!----------------------------------------------------------------------
  636. ierr(:) = 0
  637. !
  638. ALLOCATE( btmsk(jpi,jpj,nptr) , &
  639. & htr_adv(jpj,nptr) , str_adv(jpj,nptr) , &
  640. & htr_eiv(jpj,nptr) , str_eiv(jpj,nptr) , &
  641. & htr_vt(jpj,nptr) , str_vs(jpj,nptr) , &
  642. & htr_ove(jpj,nptr) , str_ove(jpj,nptr) , &
  643. & htr_btr(jpj,nptr) , str_btr(jpj,nptr) , &
  644. & htr_ldf(jpj,nptr) , str_ldf(jpj,nptr) , STAT=ierr(1) )
  645. !
  646. ALLOCATE( p_fval1d(jpj), p_fval2d(jpj,jpk), Stat=ierr(2))
  647. !
  648. ALLOCATE( btm30(jpi,jpj), btmip(jpi,jpj), STAT=ierr(3) )
  649. !
  650. dia_ptr_alloc = MAXVAL( ierr )
  651. IF(lk_mpp) CALL mpp_sum( dia_ptr_alloc )
  652. !
  653. END FUNCTION dia_ptr_alloc
  654. FUNCTION ptr_sj_3d( pva, pmsk ) RESULT ( p_fval )
  655. !!----------------------------------------------------------------------
  656. !! *** ROUTINE ptr_sj_3d ***
  657. !!
  658. !! ** Purpose : i-k sum computation of a j-flux array
  659. !!
  660. !! ** Method : - i-k sum of pva using the interior 2D vmask (vmask_i).
  661. !! pva is supposed to be a masked flux (i.e. * vmask*e1v*e3v)
  662. !!
  663. !! ** Action : - p_fval: i-k-mean poleward flux of pva
  664. !!----------------------------------------------------------------------
  665. REAL(wp), INTENT(in), DIMENSION(jpi,jpj,jpk) :: pva ! mask flux array at V-point
  666. REAL(wp), INTENT(in), DIMENSION(jpi,jpj), OPTIONAL :: pmsk ! Optional 2D basin mask
  667. !
  668. INTEGER :: ji, jj, jk ! dummy loop arguments
  669. INTEGER :: ijpj ! ???
  670. REAL(wp), POINTER, DIMENSION(:) :: p_fval ! function value
  671. !!--------------------------------------------------------------------
  672. !
  673. p_fval => p_fval1d
  674. ijpj = jpj
  675. p_fval(:) = 0._wp
  676. IF( PRESENT( pmsk ) ) THEN
  677. !CDIR NOVERRCHK
  678. DO jk = 1, jpkm1
  679. !CDIR NOVERRCHK
  680. DO jj = 2, jpjm1
  681. !CDIR NOVERRCHK
  682. DO ji = fs_2, fs_jpim1 ! Vector opt.
  683. p_fval(jj) = p_fval(jj) + pva(ji,jj,jk) * tmask_i(ji,jj) * pmsk(ji,jj)
  684. END DO
  685. END DO
  686. END DO
  687. ELSE
  688. !CDIR NOVERRCHK
  689. DO jk = 1, jpkm1
  690. !CDIR NOVERRCHK
  691. DO jj = 2, jpjm1
  692. !CDIR NOVERRCHK
  693. DO ji = fs_2, fs_jpim1 ! Vector opt.
  694. p_fval(jj) = p_fval(jj) + pva(ji,jj,jk) * tmask_i(ji,jj)
  695. END DO
  696. END DO
  697. END DO
  698. ENDIF
  699. #if defined key_mpp_mpi
  700. IF(lk_mpp) CALL mpp_sum( p_fval, ijpj, ncomm_znl)
  701. #endif
  702. !
  703. END FUNCTION ptr_sj_3d
  704. FUNCTION ptr_sj_2d( pva, pmsk ) RESULT ( p_fval )
  705. !!----------------------------------------------------------------------
  706. !! *** ROUTINE ptr_sj_2d ***
  707. !!
  708. !! ** Purpose : "zonal" and vertical sum computation of a i-flux array
  709. !!
  710. !! ** Method : - i-k sum of pva using the interior 2D vmask (vmask_i).
  711. !! pva is supposed to be a masked flux (i.e. * vmask*e1v*e3v)
  712. !!
  713. !! ** Action : - p_fval: i-k-mean poleward flux of pva
  714. !!----------------------------------------------------------------------
  715. REAL(wp) , INTENT(in), DIMENSION(jpi,jpj) :: pva ! mask flux array at V-point
  716. REAL(wp) , INTENT(in), DIMENSION(jpi,jpj), OPTIONAL :: pmsk ! Optional 2D basin mask
  717. !
  718. INTEGER :: ji,jj ! dummy loop arguments
  719. INTEGER :: ijpj ! ???
  720. REAL(wp), POINTER, DIMENSION(:) :: p_fval ! function value
  721. !!--------------------------------------------------------------------
  722. !
  723. p_fval => p_fval1d
  724. ijpj = jpj
  725. p_fval(:) = 0._wp
  726. IF( PRESENT( pmsk ) ) THEN
  727. !CDIR NOVERRCHK
  728. DO jj = 2, jpjm1
  729. !CDIR NOVERRCHK
  730. DO ji = nldi, nlei ! No vector optimisation here. Better use a mask ?
  731. p_fval(jj) = p_fval(jj) + pva(ji,jj) * tmask_i(ji,jj) * pmsk(ji,jj)
  732. END DO
  733. END DO
  734. ELSE
  735. !CDIR NOVERRCHK
  736. DO jj = 2, jpjm1
  737. !CDIR NOVERRCHK
  738. DO ji = nldi, nlei ! No vector optimisation here. Better use a mask ?
  739. p_fval(jj) = p_fval(jj) + pva(ji,jj) * tmask_i(ji,jj)
  740. END DO
  741. END DO
  742. ENDIF
  743. #if defined key_mpp_mpi
  744. CALL mpp_sum( p_fval, ijpj, ncomm_znl )
  745. #endif
  746. !
  747. END FUNCTION ptr_sj_2d
  748. FUNCTION ptr_sjk( pta, pmsk ) RESULT ( p_fval )
  749. !!----------------------------------------------------------------------
  750. !! *** ROUTINE ptr_sjk ***
  751. !!
  752. !! ** Purpose : i-sum computation of an array
  753. !!
  754. !! ** Method : - i-sum of pva using the interior 2D vmask (vmask_i).
  755. !!
  756. !! ** Action : - p_fval: i-mean poleward flux of pva
  757. !!----------------------------------------------------------------------
  758. !!
  759. IMPLICIT none
  760. REAL(wp) , INTENT(in), DIMENSION(jpi,jpj,jpk) :: pta ! mask flux array at V-point
  761. REAL(wp) , INTENT(in), DIMENSION(jpi,jpj) , OPTIONAL :: pmsk ! Optional 2D basin mask
  762. !!
  763. INTEGER :: ji, jj, jk ! dummy loop arguments
  764. REAL(wp), POINTER, DIMENSION(:,:) :: p_fval ! return function value
  765. #if defined key_mpp_mpi
  766. INTEGER, DIMENSION(1) :: ish
  767. INTEGER, DIMENSION(2) :: ish2
  768. INTEGER :: ijpjjpk
  769. REAL(wp), DIMENSION(jpj*jpk) :: zwork ! mask flux array at V-point
  770. #endif
  771. !!--------------------------------------------------------------------
  772. !
  773. p_fval => p_fval2d
  774. p_fval(:,:) = 0._wp
  775. !
  776. IF( PRESENT( pmsk ) ) THEN
  777. !CDIR NOVERRCHK
  778. DO jk = 1, jpkm1
  779. !CDIR NOVERRCHK
  780. DO jj = 2, jpjm1
  781. !CDIR NOVERRCHK
  782. !!gm here, use of tmask_i ==> no need of loop over nldi, nlei....
  783. DO ji = nldi, nlei ! No vector optimisation here. Better use a mask ?
  784. p_fval(jj,jk) = p_fval(jj,jk) + pta(ji,jj,jk) * pmsk(ji,jj)
  785. END DO
  786. END DO
  787. END DO
  788. ELSE
  789. !CDIR NOVERRCHK
  790. DO jk = 1, jpkm1
  791. !CDIR NOVERRCHK
  792. DO jj = 2, jpjm1
  793. !CDIR NOVERRCHK
  794. DO ji = nldi, nlei ! No vector optimisation here. Better use a mask ?
  795. p_fval(jj,jk) = p_fval(jj,jk) + pta(ji,jj,jk) * tmask_i(ji,jj)
  796. END DO
  797. END DO
  798. END DO
  799. END IF
  800. !
  801. #if defined key_mpp_mpi
  802. ijpjjpk = jpj*jpk
  803. ish(1) = ijpjjpk ; ish2(1) = jpj ; ish2(2) = jpk
  804. zwork(1:ijpjjpk) = RESHAPE( p_fval, ish )
  805. CALL mpp_sum( zwork, ijpjjpk, ncomm_znl )
  806. p_fval(:,:) = RESHAPE( zwork, ish2 )
  807. #endif
  808. !
  809. END FUNCTION ptr_sjk
  810. !!======================================================================
  811. END MODULE diaptr