diaptr.F90 40 KB

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