diaptr.F90 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  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. REAL(wp) :: rc_sv = 1.e-6_wp ! conversion from m3/s to Sverdrup
  48. REAL(wp) :: rc_pwatt = 1.e-15_wp ! conversion from W to PW (further x rau0 x Cp)
  49. REAL(wp) :: rc_ggram = 1.e-6_wp ! conversion from g to Pg
  50. CHARACTER(len=3), ALLOCATABLE, SAVE, DIMENSION(:) :: clsubb
  51. REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: btmsk ! T-point basin interior masks
  52. REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: btm30 ! mask out Southern Ocean (=0 south of 30°S)
  53. REAL(wp), TARGET, ALLOCATABLE, SAVE, DIMENSION(:) :: p_fval1d
  54. REAL(wp), TARGET, ALLOCATABLE, SAVE, DIMENSION(:,:) :: p_fval2d
  55. !! * Substitutions
  56. # include "domzgr_substitute.h90"
  57. # include "vectopt_loop_substitute.h90"
  58. !!----------------------------------------------------------------------
  59. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  60. !! $Id$
  61. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  62. !!----------------------------------------------------------------------
  63. CONTAINS
  64. SUBROUTINE dia_ptr( pvtr )
  65. !!----------------------------------------------------------------------
  66. !! *** ROUTINE dia_ptr ***
  67. !!----------------------------------------------------------------------
  68. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(in), OPTIONAL :: pvtr ! j-effective transport
  69. !
  70. INTEGER :: ji, jj, jk, jn ! dummy loop indices
  71. REAL(wp) :: zsfc,zvfc ! local scalar
  72. REAL(wp), DIMENSION(jpi,jpj) :: z2d ! 2D workspace
  73. REAL(wp), DIMENSION(jpi,jpj,jpk) :: z3d ! 3D workspace
  74. REAL(wp), DIMENSION(jpi,jpj,jpk) :: zmask ! 3D workspace
  75. REAL(wp), DIMENSION(jpi,jpj,jpk,jpts) :: zts ! 3D workspace
  76. REAL(wp), DIMENSION(jpj) :: vsum ! 1D workspace
  77. REAL(wp), DIMENSION(jpj,jpts) :: tssum ! 1D workspace
  78. !
  79. !overturning calculation
  80. REAL(wp), DIMENSION(jpj,jpk,nptr) :: sjk , r1_sjk ! i-mean i-k-surface and its inverse
  81. REAL(wp), DIMENSION(jpj,jpk,nptr) :: v_msf, sn_jk , tn_jk ! i-mean T and S, j-Stream-Function
  82. REAL(wp), DIMENSION(jpi,jpj,jpk) :: zvn ! 3D workspace
  83. CHARACTER( len = 12 ) :: cl1
  84. !!----------------------------------------------------------------------
  85. !
  86. IF( nn_timing == 1 ) CALL timing_start('dia_ptr')
  87. !
  88. IF( PRESENT( pvtr ) ) THEN
  89. IF( iom_use("zomsfglo") ) THEN ! effective MSF
  90. z3d(1,:,:) = ptr_sjk( pvtr(:,:,:) ) ! zonal cumulative effective transport
  91. DO jk = 2, jpkm1
  92. z3d(1,:,jk) = z3d(1,:,jk-1) + z3d(1,:,jk) ! effective j-Stream-Function (MSF)
  93. END DO
  94. DO ji = 1, jpi
  95. z3d(ji,:,:) = z3d(1,:,:)
  96. ENDDO
  97. cl1 = TRIM('zomsf'//clsubb(1) )
  98. CALL iom_put( cl1, z3d * rc_sv )
  99. DO jn = 2, nptr ! by sub-basins
  100. z3d(1,:,:) = ptr_sjk( pvtr(:,:,:), btmsk(:,:,jn)*btm30(:,:) )
  101. DO jk = 2, jpkm1
  102. z3d(1,:,jk) = z3d(1,:,jk-1) + z3d(1,:,jk) ! effective j-Stream-Function (MSF)
  103. END DO
  104. DO ji = 1, jpi
  105. z3d(ji,:,:) = z3d(1,:,:)
  106. ENDDO
  107. cl1 = TRIM('zomsf'//clsubb(jn) )
  108. CALL iom_put( cl1, z3d * rc_sv )
  109. END DO
  110. ENDIF
  111. IF( iom_use("sopstove") .OR. iom_use("sophtove") .OR. iom_use("sopstbtr") .OR. iom_use("sophtbtr") ) THEN
  112. ! define fields multiplied by scalar
  113. zmask(:,:,:) = 0._wp
  114. zts(:,:,:,:) = 0._wp
  115. zvn(:,:,:) = 0._wp
  116. DO jk = 1, jpkm1
  117. DO jj = 1, jpjm1
  118. DO ji = 1, jpi
  119. zvfc = e1v(ji,jj) * fse3v(ji,jj,jk)
  120. zmask(ji,jj,jk) = vmask(ji,jj,jk) * zvfc
  121. 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
  122. zts(ji,jj,jk,jp_sal) = (tsn(ji,jj,jk,jp_sal)+tsn(ji,jj+1,jk,jp_sal)) * 0.5 * zvfc
  123. zvn(ji,jj,jk) = vn(ji,jj,jk) * zvfc
  124. ENDDO
  125. ENDDO
  126. ENDDO
  127. ENDIF
  128. IF( iom_use("sopstove") .OR. iom_use("sophtove") ) THEN
  129. sjk(:,:,1) = ptr_sjk( zmask(:,:,:), btmsk(:,:,1) )
  130. r1_sjk(:,:,1) = 0._wp
  131. WHERE( sjk(:,:,1) /= 0._wp ) r1_sjk(:,:,1) = 1._wp / sjk(:,:,1)
  132. ! i-mean T and S, j-Stream-Function, global
  133. tn_jk(:,:,1) = ptr_sjk( zts(:,:,:,jp_tem) ) * r1_sjk(:,:,1)
  134. sn_jk(:,:,1) = ptr_sjk( zts(:,:,:,jp_sal) ) * r1_sjk(:,:,1)
  135. v_msf(:,:,1) = ptr_sjk( zvn(:,:,:) )
  136. htr_ove(:,1) = SUM( v_msf(:,:,1)*tn_jk(:,:,1) ,2 )
  137. str_ove(:,1) = SUM( v_msf(:,:,1)*sn_jk(:,:,1) ,2 )
  138. z2d(1,:) = htr_ove(:,1) * rc_pwatt ! (conversion in PW)
  139. DO ji = 1, jpi
  140. z2d(ji,:) = z2d(1,:)
  141. ENDDO
  142. cl1 = 'sophtove'
  143. CALL iom_put( TRIM(cl1), z2d )
  144. z2d(1,:) = str_ove(:,1) * rc_ggram ! (conversion in Gg)
  145. DO ji = 1, jpi
  146. z2d(ji,:) = z2d(1,:)
  147. ENDDO
  148. cl1 = 'sopstove'
  149. CALL iom_put( TRIM(cl1), z2d )
  150. IF( ln_subbas ) THEN
  151. DO jn = 2, nptr
  152. sjk(:,:,jn) = ptr_sjk( zmask(:,:,:), btmsk(:,:,jn) )
  153. r1_sjk(:,:,jn) = 0._wp
  154. WHERE( sjk(:,:,jn) /= 0._wp ) r1_sjk(:,:,jn) = 1._wp / sjk(:,:,jn)
  155. ! i-mean T and S, j-Stream-Function, basin
  156. tn_jk(:,:,jn) = ptr_sjk( zts(:,:,:,jp_tem), btmsk(:,:,jn) ) * r1_sjk(:,:,jn)
  157. sn_jk(:,:,jn) = ptr_sjk( zts(:,:,:,jp_sal), btmsk(:,:,jn) ) * r1_sjk(:,:,jn)
  158. v_msf(:,:,jn) = ptr_sjk( zvn(:,:,:), btmsk(:,:,jn) )
  159. htr_ove(:,jn) = SUM( v_msf(:,:,jn)*tn_jk(:,:,jn) ,2 )
  160. str_ove(:,jn) = SUM( v_msf(:,:,jn)*sn_jk(:,:,jn) ,2 )
  161. z2d(1,:) = htr_ove(:,jn) * rc_pwatt ! (conversion in PW)
  162. DO ji = 1, jpi
  163. z2d(ji,:) = z2d(1,:)
  164. ENDDO
  165. cl1 = TRIM('sophtove_'//clsubb(jn))
  166. CALL iom_put( cl1, z2d )
  167. z2d(1,:) = str_ove(:,jn) * rc_ggram ! (conversion in Gg)
  168. DO ji = 1, jpi
  169. z2d(ji,:) = z2d(1,:)
  170. ENDDO
  171. cl1 = TRIM('sopstove_'//clsubb(jn))
  172. CALL iom_put( cl1, z2d )
  173. END DO
  174. ENDIF
  175. ENDIF
  176. IF( iom_use("sopstbtr") .OR. iom_use("sophtbtr") ) THEN
  177. ! Calculate barotropic heat and salt transport here
  178. sjk(:,1,1) = ptr_sj( zmask(:,:,:), btmsk(:,:,1) )
  179. r1_sjk(:,1,1) = 0._wp
  180. WHERE( sjk(:,1,1) /= 0._wp ) r1_sjk(:,1,1) = 1._wp / sjk(:,1,1)
  181. vsum = ptr_sj( zvn(:,:,:), btmsk(:,:,1))
  182. tssum(:,jp_tem) = ptr_sj( zts(:,:,:,jp_tem), btmsk(:,:,1) )
  183. tssum(:,jp_sal) = ptr_sj( zts(:,:,:,jp_sal), btmsk(:,:,1) )
  184. htr_btr(:,1) = vsum * tssum(:,jp_tem) * r1_sjk(:,1,1)
  185. str_btr(:,1) = vsum * tssum(:,jp_sal) * r1_sjk(:,1,1)
  186. z2d(1,:) = htr_btr(:,1) * rc_pwatt ! (conversion in PW)
  187. DO ji = 2, jpi
  188. z2d(ji,:) = z2d(1,:)
  189. ENDDO
  190. cl1 = 'sophtbtr'
  191. CALL iom_put( TRIM(cl1), z2d )
  192. z2d(1,:) = str_btr(:,1) * rc_ggram ! (conversion in Gg)
  193. DO ji = 2, jpi
  194. z2d(ji,:) = z2d(1,:)
  195. ENDDO
  196. cl1 = 'sopstbtr'
  197. CALL iom_put( TRIM(cl1), z2d )
  198. IF( ln_subbas ) THEN
  199. DO jn = 2, nptr
  200. sjk(:,1,jn) = ptr_sj( zmask(:,:,:), btmsk(:,:,jn) )
  201. r1_sjk(:,1,jn) = 0._wp
  202. WHERE( sjk(:,1,jn) /= 0._wp ) r1_sjk(:,1,jn) = 1._wp / sjk(:,1,jn)
  203. vsum = ptr_sj( zvn(:,:,:), btmsk(:,:,jn))
  204. tssum(:,jp_tem) = ptr_sj( zts(:,:,:,jp_tem), btmsk(:,:,jn) )
  205. tssum(:,jp_sal) = ptr_sj( zts(:,:,:,jp_sal), btmsk(:,:,jn) )
  206. htr_btr(:,jn) = vsum * tssum(:,jp_tem) * r1_sjk(:,1,jn)
  207. str_btr(:,jn) = vsum * tssum(:,jp_sal) * r1_sjk(:,1,jn)
  208. z2d(1,:) = htr_btr(:,jn) * rc_pwatt ! (conversion in PW)
  209. DO ji = 1, jpi
  210. z2d(ji,:) = z2d(1,:)
  211. ENDDO
  212. cl1 = TRIM('sophtbtr_'//clsubb(jn))
  213. CALL iom_put( cl1, z2d )
  214. z2d(1,:) = str_btr(:,jn) * rc_ggram ! (conversion in Gg)
  215. DO ji = 1, jpi
  216. z2d(ji,:) = z2d(1,:)
  217. ENDDO
  218. cl1 = TRIM('sopstbtr_'//clsubb(jn))
  219. CALL iom_put( cl1, z2d )
  220. ENDDO
  221. ENDIF !ln_subbas
  222. ENDIF !iom_use("sopstbtr....)
  223. !
  224. ELSE
  225. !
  226. IF( iom_use("zotemglo") ) THEN ! i-mean i-k-surface
  227. DO jk = 1, jpkm1
  228. DO jj = 1, jpj
  229. DO ji = 1, jpi
  230. zsfc = e1t(ji,jj) * fse3t(ji,jj,jk)
  231. zmask(ji,jj,jk) = tmask(ji,jj,jk) * zsfc
  232. zts(ji,jj,jk,jp_tem) = tsn(ji,jj,jk,jp_tem) * zsfc
  233. zts(ji,jj,jk,jp_sal) = tsn(ji,jj,jk,jp_sal) * zsfc
  234. ENDDO
  235. ENDDO
  236. ENDDO
  237. DO jn = 1, nptr
  238. zmask(1,:,:) = ptr_sjk( zmask(:,:,:), btmsk(:,:,jn) )
  239. cl1 = TRIM('zosrf'//clsubb(jn) )
  240. CALL iom_put( cl1, zmask )
  241. !
  242. z3d(1,:,:) = ptr_sjk( zts(:,:,:,jp_tem), btmsk(:,:,jn) ) &
  243. & / MAX( zmask(1,:,:), 10.e-15 )
  244. DO ji = 1, jpi
  245. z3d(ji,:,:) = z3d(1,:,:)
  246. ENDDO
  247. cl1 = TRIM('zotem'//clsubb(jn) )
  248. CALL iom_put( cl1, z3d )
  249. !
  250. z3d(1,:,:) = ptr_sjk( zts(:,:,:,jp_sal), btmsk(:,:,jn) ) &
  251. & / MAX( zmask(1,:,:), 10.e-15 )
  252. DO ji = 1, jpi
  253. z3d(ji,:,:) = z3d(1,:,:)
  254. ENDDO
  255. cl1 = TRIM('zosal'//clsubb(jn) )
  256. CALL iom_put( cl1, z3d )
  257. END DO
  258. ENDIF
  259. !
  260. ! ! Advective and diffusive heat and salt transport
  261. IF( iom_use("sophtadv") .OR. iom_use("sopstadv") ) THEN
  262. z2d(1,:) = htr_adv(:,1) * rc_pwatt ! (conversion in PW)
  263. DO ji = 1, jpi
  264. z2d(ji,:) = z2d(1,:)
  265. ENDDO
  266. cl1 = 'sophtadv'
  267. CALL iom_put( TRIM(cl1), z2d )
  268. z2d(1,:) = str_adv(:,1) * rc_ggram ! (conversion in Gg)
  269. DO ji = 1, jpi
  270. z2d(ji,:) = z2d(1,:)
  271. ENDDO
  272. cl1 = 'sopstadv'
  273. CALL iom_put( TRIM(cl1), z2d )
  274. IF( ln_subbas ) THEN
  275. DO jn=2,nptr
  276. z2d(1,:) = htr_adv(:,jn) * rc_pwatt ! (conversion in PW)
  277. DO ji = 1, jpi
  278. z2d(ji,:) = z2d(1,:)
  279. ENDDO
  280. cl1 = TRIM('sophtadv_'//clsubb(jn))
  281. CALL iom_put( cl1, z2d )
  282. z2d(1,:) = str_adv(:,jn) * rc_ggram ! (conversion in Gg)
  283. DO ji = 1, jpi
  284. z2d(ji,:) = z2d(1,:)
  285. ENDDO
  286. cl1 = TRIM('sopstadv_'//clsubb(jn))
  287. CALL iom_put( cl1, z2d )
  288. ENDDO
  289. ENDIF
  290. ENDIF
  291. !
  292. IF( iom_use("sophtldf") .OR. iom_use("sopstldf") ) THEN
  293. z2d(1,:) = htr_ldf(:,1) * rc_pwatt ! (conversion in PW)
  294. DO ji = 1, jpi
  295. z2d(ji,:) = z2d(1,:)
  296. ENDDO
  297. cl1 = 'sophtldf'
  298. CALL iom_put( TRIM(cl1), z2d )
  299. z2d(1,:) = str_ldf(:,1) * rc_ggram ! (conversion in Gg)
  300. DO ji = 1, jpi
  301. z2d(ji,:) = z2d(1,:)
  302. ENDDO
  303. cl1 = 'sopstldf'
  304. CALL iom_put( TRIM(cl1), z2d )
  305. IF( ln_subbas ) THEN
  306. DO jn=2,nptr
  307. z2d(1,:) = htr_ldf(:,jn) * rc_pwatt ! (conversion in PW)
  308. DO ji = 1, jpi
  309. z2d(ji,:) = z2d(1,:)
  310. ENDDO
  311. cl1 = TRIM('sophtldf_'//clsubb(jn))
  312. CALL iom_put( cl1, z2d )
  313. z2d(1,:) = str_ldf(:,jn) * rc_ggram ! (conversion in Gg)
  314. DO ji = 1, jpi
  315. z2d(ji,:) = z2d(1,:)
  316. ENDDO
  317. cl1 = TRIM('sopstldf_'//clsubb(jn))
  318. CALL iom_put( cl1, z2d )
  319. ENDDO
  320. ENDIF
  321. ENDIF
  322. IF( iom_use("sopht_vt") .OR. iom_use("sopst_vs") ) THEN
  323. z2d(1,:) = htr_vt(:,1) * rc_pwatt ! (conversion in PW)
  324. DO ji = 1, jpi
  325. z2d(ji,:) = z2d(1,:)
  326. ENDDO
  327. cl1 = 'sopht_vt'
  328. CALL iom_put( TRIM(cl1), z2d )
  329. z2d(1,:) = str_vs(:,1) * rc_ggram ! (conversion in Gg)
  330. DO ji = 1, jpi
  331. z2d(ji,:) = z2d(1,:)
  332. ENDDO
  333. cl1 = 'sopst_vs'
  334. CALL iom_put( TRIM(cl1), z2d )
  335. IF( ln_subbas ) THEN
  336. DO jn=2,nptr
  337. z2d(1,:) = htr_vt(:,jn) * rc_pwatt ! (conversion in PW)
  338. DO ji = 1, jpi
  339. z2d(ji,:) = z2d(1,:)
  340. ENDDO
  341. cl1 = TRIM('sopht_vt_'//clsubb(jn))
  342. CALL iom_put( cl1, z2d )
  343. z2d(1,:) = str_vs(:,jn) * rc_ggram ! (conversion in Gg)
  344. DO ji = 1, jpi
  345. z2d(ji,:) = z2d(1,:)
  346. ENDDO
  347. cl1 = TRIM('sopst_vs_'//clsubb(jn))
  348. CALL iom_put( cl1, z2d )
  349. ENDDO
  350. ENDIF
  351. ENDIF
  352. #ifdef key_diaeiv
  353. IF(lk_traldf_eiv) THEN
  354. IF( iom_use("sophteiv") .OR. iom_use("sopsteiv") ) THEN
  355. z2d(1,:) = htr_eiv(:,1) * rc_pwatt ! (conversion in PW)
  356. DO ji = 1, jpi
  357. z2d(ji,:) = z2d(1,:)
  358. ENDDO
  359. cl1 = 'sophteiv'
  360. CALL iom_put( TRIM(cl1), z2d )
  361. z2d(1,:) = str_eiv(:,1) * rc_ggram ! (conversion in Gg)
  362. DO ji = 1, jpi
  363. z2d(ji,:) = z2d(1,:)
  364. ENDDO
  365. cl1 = 'sopsteiv'
  366. CALL iom_put( TRIM(cl1), z2d )
  367. IF( ln_subbas ) THEN
  368. DO jn=2,nptr
  369. z2d(1,:) = htr_eiv(:,jn) * rc_pwatt ! (conversion in PW)
  370. DO ji = 1, jpi
  371. z2d(ji,:) = z2d(1,:)
  372. ENDDO
  373. cl1 = TRIM('sophteiv_'//clsubb(jn))
  374. CALL iom_put( cl1, z2d )
  375. z2d(1,:) = str_eiv(:,jn) * rc_ggram ! (conversion in Gg)
  376. DO ji = 1, jpi
  377. z2d(ji,:) = z2d(1,:)
  378. ENDDO
  379. cl1 = TRIM('sopsteiv_'//clsubb(jn))
  380. CALL iom_put( cl1, z2d )
  381. ENDDO
  382. ENDIF
  383. ENDIF
  384. ENDIF
  385. #endif
  386. !
  387. ENDIF
  388. !
  389. IF( nn_timing == 1 ) CALL timing_stop('dia_ptr')
  390. !
  391. END SUBROUTINE dia_ptr
  392. SUBROUTINE dia_ptr_init
  393. !!----------------------------------------------------------------------
  394. !! *** ROUTINE dia_ptr_init ***
  395. !!
  396. !! ** Purpose : Initialization, namelist read
  397. !!----------------------------------------------------------------------
  398. INTEGER :: jn ! local integers
  399. INTEGER :: inum, ierr ! local integers
  400. INTEGER :: ios ! Local integer output status for namelist read
  401. !!
  402. NAMELIST/namptr/ ln_diaptr, ln_subbas
  403. !!----------------------------------------------------------------------
  404. REWIND( numnam_ref ) ! Namelist namptr in reference namelist : Poleward transport
  405. READ ( numnam_ref, namptr, IOSTAT = ios, ERR = 901)
  406. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namptr in reference namelist', lwp )
  407. REWIND( numnam_cfg ) ! Namelist namptr in configuration namelist : Poleward transport
  408. READ ( numnam_cfg, namptr, IOSTAT = ios, ERR = 902 )
  409. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namptr in configuration namelist', lwp )
  410. IF(lwm) WRITE ( numond, namptr )
  411. IF(lwp) THEN ! Control print
  412. WRITE(numout,*)
  413. WRITE(numout,*) 'dia_ptr_init : poleward transport and msf initialization'
  414. WRITE(numout,*) '~~~~~~~~~~~~'
  415. WRITE(numout,*) ' Namelist namptr : set ptr parameters'
  416. WRITE(numout,*) ' Poleward heat & salt transport (T) or not (F) ln_diaptr = ', ln_diaptr
  417. WRITE(numout,*) ' Global (F) or glo/Atl/Pac/Ind/Indo-Pac basins ln_subbas = ', ln_subbas
  418. ENDIF
  419. IF( ln_diaptr ) THEN
  420. !
  421. IF( ln_subbas ) THEN
  422. nptr = 5 ! Global, Atlantic, Pacific, Indian, Indo-Pacific
  423. ALLOCATE( clsubb(nptr) )
  424. clsubb(1) = 'glo' ; clsubb(2) = 'atl' ; clsubb(3) = 'pac' ; clsubb(4) = 'ind' ; clsubb(5) = 'ipc'
  425. ELSE
  426. nptr = 1 ! Global only
  427. ALLOCATE( clsubb(nptr) )
  428. clsubb(1) = 'glo'
  429. ENDIF
  430. ! ! allocate dia_ptr arrays
  431. IF( dia_ptr_alloc() /= 0 ) CALL ctl_stop( 'STOP', 'dia_ptr_init : unable to allocate arrays' )
  432. rc_pwatt = rc_pwatt * rau0_rcp ! conversion from K.s-1 to PetaWatt
  433. IF( lk_mpp ) CALL mpp_ini_znl( numout ) ! Define MPI communicator for zonal sum
  434. IF( ln_subbas ) THEN ! load sub-basin mask
  435. CALL iom_open( 'subbasins', inum, ldstop = .FALSE. )
  436. CALL iom_get( inum, jpdom_data, 'atlmsk', btmsk(:,:,2) ) ! Atlantic basin
  437. CALL iom_get( inum, jpdom_data, 'pacmsk', btmsk(:,:,3) ) ! Pacific basin
  438. CALL iom_get( inum, jpdom_data, 'indmsk', btmsk(:,:,4) ) ! Indian basin
  439. CALL iom_close( inum )
  440. btmsk(:,:,5) = MAX ( btmsk(:,:,3), btmsk(:,:,4) ) ! Indo-Pacific basin
  441. WHERE( gphit(:,:) < -30._wp) ; btm30(:,:) = 0._wp ! mask out Southern Ocean
  442. ELSE WHERE ; btm30(:,:) = ssmask(:,:)
  443. END WHERE
  444. ENDIF
  445. btmsk(:,:,1) = tmask_i(:,:) ! global ocean
  446. DO jn = 1, nptr
  447. btmsk(:,:,jn) = btmsk(:,:,jn) * tmask_i(:,:) ! interior domain only
  448. END DO
  449. ! Initialise arrays to zero because diatpr is called before they are first calculated
  450. ! Note that this means diagnostics will not be exactly correct when model run is restarted.
  451. htr_adv(:,:) = 0._wp ; str_adv(:,:) = 0._wp
  452. htr_ldf(:,:) = 0._wp ; str_ldf(:,:) = 0._wp
  453. htr_eiv(:,:) = 0._wp ; str_eiv(:,:) = 0._wp
  454. htr_vt(:,:) = 0._wp ; str_vs(:,:) = 0._wp
  455. htr_ove(:,:) = 0._wp ; str_ove(:,:) = 0._wp
  456. htr_btr(:,:) = 0._wp ; str_btr(:,:) = 0._wp
  457. !
  458. ENDIF
  459. !
  460. END SUBROUTINE dia_ptr_init
  461. SUBROUTINE dia_ptr_ohst_components( ktra, cptr, pva )
  462. !!----------------------------------------------------------------------
  463. !! *** ROUTINE dia_ptr_ohst_components ***
  464. !!----------------------------------------------------------------------
  465. !! Wrapper for heat and salt transport calculations to calculate them for each basin
  466. !! Called from all advection and/or diffusion routines
  467. !!----------------------------------------------------------------------
  468. INTEGER , INTENT(in ) :: ktra ! tracer index
  469. CHARACTER(len=3) , INTENT(in) :: cptr ! transport type 'adv'/'ldf'/'eiv'
  470. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(in) :: pva ! 3D input array of advection/diffusion
  471. INTEGER :: jn !
  472. IF( cptr == 'adv' ) THEN
  473. IF( ktra == jp_tem ) htr_adv(:,1) = ptr_sj( pva(:,:,:) )
  474. IF( ktra == jp_sal ) str_adv(:,1) = ptr_sj( pva(:,:,:) )
  475. ENDIF
  476. IF( cptr == 'ldf' ) THEN
  477. IF( ktra == jp_tem ) htr_ldf(:,1) = ptr_sj( pva(:,:,:) )
  478. IF( ktra == jp_sal ) str_ldf(:,1) = ptr_sj( pva(:,:,:) )
  479. ENDIF
  480. IF( cptr == 'eiv' ) THEN
  481. IF( ktra == jp_tem ) htr_eiv(:,1) = ptr_sj( pva(:,:,:) )
  482. IF( ktra == jp_sal ) str_eiv(:,1) = ptr_sj( pva(:,:,:) )
  483. ENDIF
  484. IF( cptr == 'vts' ) THEN
  485. IF( ktra == jp_tem ) htr_vt(:,1) = ptr_sj( pva(:,:,:) )
  486. IF( ktra == jp_sal ) str_vs(:,1) = ptr_sj( pva(:,:,:) )
  487. ENDIF
  488. !
  489. IF( ln_subbas ) THEN
  490. !
  491. IF( cptr == 'adv' ) THEN
  492. IF( ktra == jp_tem ) THEN
  493. DO jn = 2, nptr
  494. htr_adv(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  495. END DO
  496. ENDIF
  497. IF( ktra == jp_sal ) THEN
  498. DO jn = 2, nptr
  499. str_adv(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  500. END DO
  501. ENDIF
  502. ENDIF
  503. IF( cptr == 'ldf' ) THEN
  504. IF( ktra == jp_tem ) THEN
  505. DO jn = 2, nptr
  506. htr_ldf(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  507. END DO
  508. ENDIF
  509. IF( ktra == jp_sal ) THEN
  510. DO jn = 2, nptr
  511. str_ldf(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  512. END DO
  513. ENDIF
  514. ENDIF
  515. IF( cptr == 'eiv' ) THEN
  516. IF( ktra == jp_tem ) THEN
  517. DO jn = 2, nptr
  518. htr_eiv(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  519. END DO
  520. ENDIF
  521. IF( ktra == jp_sal ) THEN
  522. DO jn = 2, nptr
  523. str_eiv(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  524. END DO
  525. ENDIF
  526. ENDIF
  527. IF( cptr == 'vts' ) THEN
  528. IF( ktra == jp_tem ) THEN
  529. DO jn = 2, nptr
  530. htr_vt(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  531. END DO
  532. ENDIF
  533. IF( ktra == jp_sal ) THEN
  534. DO jn = 2, nptr
  535. str_vs(:,jn) = ptr_sj( pva(:,:,:), btmsk(:,:,jn) )
  536. END DO
  537. ENDIF
  538. ENDIF
  539. !
  540. ENDIF
  541. END SUBROUTINE dia_ptr_ohst_components
  542. FUNCTION dia_ptr_alloc()
  543. !!----------------------------------------------------------------------
  544. !! *** ROUTINE dia_ptr_alloc ***
  545. !!----------------------------------------------------------------------
  546. INTEGER :: dia_ptr_alloc ! return value
  547. INTEGER, DIMENSION(3) :: ierr
  548. !!----------------------------------------------------------------------
  549. ierr(:) = 0
  550. !
  551. ALLOCATE( btmsk(jpi,jpj,nptr) , &
  552. & htr_adv(jpj,nptr) , str_adv(jpj,nptr) , &
  553. & htr_eiv(jpj,nptr) , str_eiv(jpj,nptr) , &
  554. & htr_vt(jpj,nptr) , str_vs(jpj,nptr) , &
  555. & htr_ove(jpj,nptr) , str_ove(jpj,nptr) , &
  556. & htr_btr(jpj,nptr) , str_btr(jpj,nptr) , &
  557. & htr_ldf(jpj,nptr) , str_ldf(jpj,nptr) , STAT=ierr(1) )
  558. !
  559. ALLOCATE( p_fval1d(jpj), p_fval2d(jpj,jpk), Stat=ierr(2))
  560. !
  561. ALLOCATE( btm30(jpi,jpj), STAT=ierr(3) )
  562. !
  563. dia_ptr_alloc = MAXVAL( ierr )
  564. IF(lk_mpp) CALL mpp_sum( dia_ptr_alloc )
  565. !
  566. END FUNCTION dia_ptr_alloc
  567. FUNCTION ptr_sj_3d( pva, pmsk ) RESULT ( p_fval )
  568. !!----------------------------------------------------------------------
  569. !! *** ROUTINE ptr_sj_3d ***
  570. !!
  571. !! ** Purpose : i-k sum computation of a j-flux array
  572. !!
  573. !! ** Method : - i-k sum of pva using the interior 2D vmask (vmask_i).
  574. !! pva is supposed to be a masked flux (i.e. * vmask*e1v*e3v)
  575. !!
  576. !! ** Action : - p_fval: i-k-mean poleward flux of pva
  577. !!----------------------------------------------------------------------
  578. REAL(wp), INTENT(in), DIMENSION(jpi,jpj,jpk) :: pva ! mask flux array at V-point
  579. REAL(wp), INTENT(in), DIMENSION(jpi,jpj), OPTIONAL :: pmsk ! Optional 2D basin mask
  580. !
  581. INTEGER :: ji, jj, jk ! dummy loop arguments
  582. INTEGER :: ijpj ! ???
  583. REAL(wp), POINTER, DIMENSION(:) :: p_fval ! function value
  584. !!--------------------------------------------------------------------
  585. !
  586. p_fval => p_fval1d
  587. ijpj = jpj
  588. p_fval(:) = 0._wp
  589. IF( PRESENT( pmsk ) ) THEN
  590. DO jk = 1, jpkm1
  591. DO jj = 2, jpjm1
  592. DO ji = fs_2, fs_jpim1 ! Vector opt.
  593. p_fval(jj) = p_fval(jj) + pva(ji,jj,jk) * tmask_i(ji,jj) * pmsk(ji,jj)
  594. END DO
  595. END DO
  596. END DO
  597. ELSE
  598. DO jk = 1, jpkm1
  599. DO jj = 2, jpjm1
  600. DO ji = fs_2, fs_jpim1 ! Vector opt.
  601. p_fval(jj) = p_fval(jj) + pva(ji,jj,jk) * tmask_i(ji,jj)
  602. END DO
  603. END DO
  604. END DO
  605. ENDIF
  606. #if defined key_mpp_mpi
  607. IF(lk_mpp) CALL mpp_sum( p_fval, ijpj, ncomm_znl)
  608. #endif
  609. !
  610. END FUNCTION ptr_sj_3d
  611. FUNCTION ptr_sj_2d( pva, pmsk ) RESULT ( p_fval )
  612. !!----------------------------------------------------------------------
  613. !! *** ROUTINE ptr_sj_2d ***
  614. !!
  615. !! ** Purpose : "zonal" and vertical sum computation of a i-flux array
  616. !!
  617. !! ** Method : - i-k sum of pva using the interior 2D vmask (vmask_i).
  618. !! pva is supposed to be a masked flux (i.e. * vmask*e1v*e3v)
  619. !!
  620. !! ** Action : - p_fval: i-k-mean poleward flux of pva
  621. !!----------------------------------------------------------------------
  622. REAL(wp) , INTENT(in), DIMENSION(jpi,jpj) :: pva ! mask flux array at V-point
  623. REAL(wp) , INTENT(in), DIMENSION(jpi,jpj), OPTIONAL :: pmsk ! Optional 2D basin mask
  624. !
  625. INTEGER :: ji,jj ! dummy loop arguments
  626. INTEGER :: ijpj ! ???
  627. REAL(wp), POINTER, DIMENSION(:) :: p_fval ! function value
  628. !!--------------------------------------------------------------------
  629. !
  630. p_fval => p_fval1d
  631. ijpj = jpj
  632. p_fval(:) = 0._wp
  633. IF( PRESENT( pmsk ) ) THEN
  634. DO jj = 2, jpjm1
  635. DO ji = nldi, nlei ! No vector optimisation here. Better use a mask ?
  636. p_fval(jj) = p_fval(jj) + pva(ji,jj) * tmask_i(ji,jj) * pmsk(ji,jj)
  637. END DO
  638. END DO
  639. ELSE
  640. DO jj = 2, jpjm1
  641. DO ji = nldi, nlei ! No vector optimisation here. Better use a mask ?
  642. p_fval(jj) = p_fval(jj) + pva(ji,jj) * tmask_i(ji,jj)
  643. END DO
  644. END DO
  645. ENDIF
  646. #if defined key_mpp_mpi
  647. CALL mpp_sum( p_fval, ijpj, ncomm_znl )
  648. #endif
  649. !
  650. END FUNCTION ptr_sj_2d
  651. FUNCTION ptr_sjk( pta, pmsk ) RESULT ( p_fval )
  652. !!----------------------------------------------------------------------
  653. !! *** ROUTINE ptr_sjk ***
  654. !!
  655. !! ** Purpose : i-sum computation of an array
  656. !!
  657. !! ** Method : - i-sum of pva using the interior 2D vmask (vmask_i).
  658. !!
  659. !! ** Action : - p_fval: i-mean poleward flux of pva
  660. !!----------------------------------------------------------------------
  661. !!
  662. IMPLICIT none
  663. REAL(wp) , INTENT(in), DIMENSION(jpi,jpj,jpk) :: pta ! mask flux array at V-point
  664. REAL(wp) , INTENT(in), DIMENSION(jpi,jpj) , OPTIONAL :: pmsk ! Optional 2D basin mask
  665. !!
  666. INTEGER :: ji, jj, jk ! dummy loop arguments
  667. REAL(wp), POINTER, DIMENSION(:,:) :: p_fval ! return function value
  668. #if defined key_mpp_mpi
  669. INTEGER, DIMENSION(1) :: ish
  670. INTEGER, DIMENSION(2) :: ish2
  671. INTEGER :: ijpjjpk
  672. REAL(wp), DIMENSION(jpj*jpk) :: zwork ! mask flux array at V-point
  673. #endif
  674. !!--------------------------------------------------------------------
  675. !
  676. p_fval => p_fval2d
  677. p_fval(:,:) = 0._wp
  678. !
  679. IF( PRESENT( pmsk ) ) THEN
  680. DO jk = 1, jpkm1
  681. DO jj = 2, jpjm1
  682. !!gm here, use of tmask_i ==> no need of loop over nldi, nlei....
  683. DO ji = nldi, nlei ! No vector optimisation here. Better use a mask ?
  684. p_fval(jj,jk) = p_fval(jj,jk) + pta(ji,jj,jk) * pmsk(ji,jj)
  685. END DO
  686. END DO
  687. END DO
  688. ELSE
  689. DO jk = 1, jpkm1
  690. DO jj = 2, jpjm1
  691. DO ji = nldi, nlei ! No vector optimisation here. Better use a mask ?
  692. p_fval(jj,jk) = p_fval(jj,jk) + pta(ji,jj,jk) * tmask_i(ji,jj)
  693. END DO
  694. END DO
  695. END DO
  696. END IF
  697. !
  698. #if defined key_mpp_mpi
  699. ijpjjpk = jpj*jpk
  700. ish(1) = ijpjjpk ; ish2(1) = jpj ; ish2(2) = jpk
  701. zwork(1:ijpjjpk) = RESHAPE( p_fval, ish )
  702. CALL mpp_sum( zwork, ijpjjpk, ncomm_znl )
  703. p_fval(:,:) = RESHAPE( zwork, ish2 )
  704. #endif
  705. !
  706. END FUNCTION ptr_sjk
  707. !!======================================================================
  708. END MODULE diaptr