diadct.F90 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313
  1. MODULE diadct
  2. !!=====================================================================
  3. !! *** MODULE diadct ***
  4. !! Ocean diagnostics: Compute the transport trough a sec.
  5. !!===============================================================
  6. !! History :
  7. !!
  8. !! original : 02/99 (Y Drillet)
  9. !! addition : 10/01 (Y Drillet, R Bourdalle Badie)
  10. !! : 10/05 (M Laborie) F90
  11. !! addition : 04/07 (G Garric) Ice sections
  12. !! bugfix : 04/07 (C Bricaud) test on sec%nb_point
  13. !! initialisation of ztransp1,ztransp2,...
  14. !! nemo_v_3_4: 09/2011 (C Bricaud)
  15. !!
  16. !!
  17. !!----------------------------------------------------------------------
  18. #if defined key_diadct
  19. !!----------------------------------------------------------------------
  20. !! 'key_diadct' :
  21. !!----------------------------------------------------------------------
  22. !!----------------------------------------------------------------------
  23. !! dia_dct : Compute the transport through a sec.
  24. !! dia_dct_init : Read namelist.
  25. !! readsec : Read sections description and pathway
  26. !! removepoints : Remove points which are common to 2 procs
  27. !! transport : Compute transport for each sections
  28. !! dia_dct_wri : Write tranports results in ascii files
  29. !! interp : Compute temperature/salinity/density at U-point or V-point
  30. !!
  31. !!----------------------------------------------------------------------
  32. !! * Modules used
  33. USE oce ! ocean dynamics and tracers
  34. USE dom_oce ! ocean space and time domain
  35. USE phycst ! physical constants
  36. USE in_out_manager ! I/O manager
  37. USE daymod ! calendar
  38. USE dianam ! build name of file
  39. USE lib_mpp ! distributed memory computing library
  40. #if defined key_lim2
  41. USE ice_2
  42. #endif
  43. #if defined key_lim3
  44. USE ice
  45. #endif
  46. USE domvvl
  47. USE timing ! preformance summary
  48. USE wrk_nemo ! working arrays
  49. IMPLICIT NONE
  50. PRIVATE
  51. !! * Routine accessibility
  52. PUBLIC dia_dct ! routine called by step.F90
  53. PUBLIC dia_dct_init ! routine called by opa.F90
  54. PUBLIC diadct_alloc ! routine called by nemo_init in nemogcm.F90
  55. PRIVATE readsec
  56. PRIVATE removepoints
  57. PRIVATE transport
  58. PRIVATE dia_dct_wri
  59. #include "domzgr_substitute.h90"
  60. !! * Shared module variables
  61. LOGICAL, PUBLIC, PARAMETER :: lk_diadct = .TRUE. !: model-data diagnostics flag
  62. !! * Module variables
  63. INTEGER :: nn_dct ! Frequency of computation
  64. INTEGER :: nn_dctwri ! Frequency of output
  65. INTEGER :: nn_secdebug ! Number of the section to debug
  66. INTEGER, PARAMETER :: nb_class_max = 10
  67. INTEGER, PARAMETER :: nb_sec_max = 150
  68. INTEGER, PARAMETER :: nb_point_max = 2000
  69. INTEGER, PARAMETER :: nb_type_class = 10
  70. INTEGER, PARAMETER :: nb_3d_vars = 3
  71. INTEGER, PARAMETER :: nb_2d_vars = 2
  72. INTEGER :: nb_sec
  73. TYPE POINT_SECTION
  74. INTEGER :: I,J
  75. END TYPE POINT_SECTION
  76. TYPE COORD_SECTION
  77. REAL(wp) :: lon,lat
  78. END TYPE COORD_SECTION
  79. TYPE SECTION
  80. CHARACTER(len=60) :: name ! name of the sec
  81. LOGICAL :: llstrpond ! true if you want the computation of salt and
  82. ! heat transports
  83. LOGICAL :: ll_ice_section ! ice surface and ice volume computation
  84. LOGICAL :: ll_date_line ! = T if the section crosses the date-line
  85. TYPE(COORD_SECTION), DIMENSION(2) :: coordSec ! longitude and latitude of the extremities of the sec
  86. INTEGER :: nb_class ! number of boundaries for density classes
  87. INTEGER, DIMENSION(nb_point_max) :: direction ! vector direction of the point in the section
  88. CHARACTER(len=40),DIMENSION(nb_class_max) :: classname ! characteristics of the class
  89. REAL(wp), DIMENSION(nb_class_max) :: zsigi ,&! in-situ density classes (99 if you don't want)
  90. zsigp ,&! potential density classes (99 if you don't want)
  91. zsal ,&! salinity classes (99 if you don't want)
  92. ztem ,&! temperature classes(99 if you don't want)
  93. zlay ! level classes (99 if you don't want)
  94. REAL(wp), DIMENSION(nb_type_class,nb_class_max) :: transport ! transport output
  95. REAL(wp) :: slopeSection ! slope of the section
  96. INTEGER :: nb_point ! number of points in the section
  97. TYPE(POINT_SECTION),DIMENSION(nb_point_max) :: listPoint ! list of points in the sections
  98. END TYPE SECTION
  99. TYPE(SECTION),DIMENSION(nb_sec_max) :: secs ! Array of sections
  100. REAL(wp), ALLOCATABLE, DIMENSION(:,:,:,:) :: transports_3d
  101. REAL(wp), ALLOCATABLE, DIMENSION(:,:,:) :: transports_2d
  102. !! $Id: diadct.F90 4578 2017-09-25 09:34:12Z ufla $
  103. CONTAINS
  104. INTEGER FUNCTION diadct_alloc()
  105. !!----------------------------------------------------------------------
  106. !! *** FUNCTION diadct_alloc ***
  107. !!----------------------------------------------------------------------
  108. INTEGER :: ierr(2)
  109. !!----------------------------------------------------------------------
  110. ALLOCATE(transports_3d(nb_3d_vars,nb_sec_max,nb_point_max,jpk), STAT=ierr(1) )
  111. ALLOCATE(transports_2d(nb_2d_vars,nb_sec_max,nb_point_max) , STAT=ierr(2) )
  112. diadct_alloc = MAXVAL( ierr )
  113. IF( diadct_alloc /= 0 ) CALL ctl_warn('diadct_alloc: failed to allocate arrays')
  114. END FUNCTION diadct_alloc
  115. SUBROUTINE dia_dct_init
  116. !!---------------------------------------------------------------------
  117. !! *** ROUTINE diadct ***
  118. !!
  119. !! ** Purpose: Read the namelist parameters
  120. !! Open output files
  121. !!
  122. !!---------------------------------------------------------------------
  123. NAMELIST/namdct/nn_dct,nn_dctwri,nn_secdebug
  124. INTEGER :: ios ! Local integer output status for namelist read
  125. IF( nn_timing == 1 ) CALL timing_start('dia_dct_init')
  126. REWIND( numnam_ref ) ! Namelist namdct in reference namelist : Diagnostic: transport through sections
  127. READ ( numnam_ref, namdct, IOSTAT = ios, ERR = 901)
  128. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namdct in reference namelist', lwp )
  129. REWIND( numnam_cfg ) ! Namelist namdct in configuration namelist : Diagnostic: transport through sections
  130. READ ( numnam_cfg, namdct, IOSTAT = ios, ERR = 902 )
  131. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namdct in configuration namelist', lwp )
  132. IF(lwm) WRITE ( numond, namdct )
  133. IF( lwp ) THEN
  134. WRITE(numout,*) " "
  135. WRITE(numout,*) "diadct_init: compute transports through sections "
  136. WRITE(numout,*) "~~~~~~~~~~~~~~~~~~~~~"
  137. WRITE(numout,*) " Frequency of computation: nn_dct = ",nn_dct
  138. WRITE(numout,*) " Frequency of write: nn_dctwri = ",nn_dctwri
  139. IF ( nn_secdebug .GE. 1 .AND. nn_secdebug .LE. nb_sec_max )THEN
  140. WRITE(numout,*)" Debug section number: ", nn_secdebug
  141. ELSE IF ( nn_secdebug == 0 )THEN ; WRITE(numout,*)" No section to debug"
  142. ELSE IF ( nn_secdebug == -1 )THEN ; WRITE(numout,*)" Debug all sections"
  143. ELSE ; WRITE(numout,*)" Wrong value for nn_secdebug : ",nn_secdebug
  144. ENDIF
  145. IF(nn_dct .GE. nn_dctwri .AND. MOD(nn_dct,nn_dctwri) .NE. 0) &
  146. & CALL ctl_stop( 'diadct: nn_dct should be smaller and a multiple of nn_dctwri' )
  147. ENDIF
  148. !Read section_ijglobal.diadct
  149. CALL readsec
  150. !open output file
  151. IF( lwm ) THEN
  152. CALL ctl_opn( numdct_vol, 'volume_transport', 'NEW', 'FORMATTED', 'SEQUENTIAL', -1, numout, .FALSE. )
  153. CALL ctl_opn( numdct_heat, 'heat_transport' , 'NEW', 'FORMATTED', 'SEQUENTIAL', -1, numout, .FALSE. )
  154. CALL ctl_opn( numdct_salt, 'salt_transport' , 'NEW', 'FORMATTED', 'SEQUENTIAL', -1, numout, .FALSE. )
  155. ENDIF
  156. ! Initialise arrays to zero
  157. transports_3d(:,:,:,:)=0.0
  158. transports_2d(:,:,:) =0.0
  159. IF( nn_timing == 1 ) CALL timing_stop('dia_dct_init')
  160. !
  161. END SUBROUTINE dia_dct_init
  162. SUBROUTINE dia_dct(kt)
  163. !!---------------------------------------------------------------------
  164. !! *** ROUTINE diadct ***
  165. !!
  166. !! Purpose :: Compute section transports and write it in numdct files
  167. !!
  168. !! Method :: All arrays initialised to zero in dct_init
  169. !! Each nn_dct time step call subroutine 'transports' for
  170. !! each section to sum the transports over each grid cell.
  171. !! Each nn_dctwri time step:
  172. !! Divide the arrays by the number of summations to gain
  173. !! an average value
  174. !! Call dia_dct_sum to sum relevant grid boxes to obtain
  175. !! totals for each class (density, depth, temp or sal)
  176. !! Call dia_dct_wri to write the transports into file
  177. !! Reinitialise all relevant arrays to zero
  178. !!---------------------------------------------------------------------
  179. !! * Arguments
  180. INTEGER,INTENT(IN) ::kt
  181. !! * Local variables
  182. INTEGER :: jsec, &! loop on sections
  183. itotal ! nb_sec_max*nb_type_class*nb_class_max
  184. LOGICAL :: lldebug =.FALSE. ! debug a section
  185. INTEGER , DIMENSION(1) :: ish ! tmp array for mpp_sum
  186. INTEGER , DIMENSION(3) :: ish2 ! "
  187. REAL(wp), POINTER, DIMENSION(:) :: zwork ! "
  188. REAL(wp), POINTER, DIMENSION(:,:,:):: zsum ! "
  189. !!---------------------------------------------------------------------
  190. IF( nn_timing == 1 ) CALL timing_start('dia_dct')
  191. IF( lk_mpp )THEN
  192. itotal = nb_sec_max*nb_type_class*nb_class_max
  193. CALL wrk_alloc( itotal , zwork )
  194. CALL wrk_alloc( nb_sec_max,nb_type_class,nb_class_max , zsum )
  195. ENDIF
  196. ! Initialise arrays
  197. zwork(:) = 0.0
  198. zsum(:,:,:) = 0.0
  199. IF( lwp .AND. kt==nit000+nn_dct-1 ) THEN
  200. WRITE(numout,*) " "
  201. WRITE(numout,*) "diadct: compute transport"
  202. WRITE(numout,*) "~~~~~~~~~~~~~~~~~~~~~~~~~"
  203. WRITE(numout,*) "nb_sec = ",nb_sec
  204. ENDIF
  205. ! Compute transport and write only at nn_dctwri
  206. IF( MOD(kt,nn_dct)==0 ) THEN
  207. DO jsec=1,nb_sec
  208. !debug this section computing ?
  209. lldebug=.FALSE.
  210. IF( (jsec==nn_secdebug .OR. nn_secdebug==-1) .AND. kt==nit000+nn_dct-1 ) lldebug=.TRUE.
  211. !Compute transport through section
  212. CALL transport(secs(jsec),lldebug,jsec)
  213. ENDDO
  214. IF( MOD(kt,nn_dctwri)==0 )THEN
  215. IF( kt==nit000+nn_dctwri-1 )WRITE(numout,*)" diadct: average transports and write at kt = ",kt
  216. !! divide arrays by nn_dctwri/nn_dct to obtain average
  217. transports_3d(:,:,:,:)=transports_3d(:,:,:,:)/(nn_dctwri/nn_dct)
  218. transports_2d(:,:,:) =transports_2d(:,:,:) /(nn_dctwri/nn_dct)
  219. ! Sum over each class
  220. DO jsec=1,nb_sec
  221. CALL dia_dct_sum(secs(jsec),jsec)
  222. ENDDO
  223. !Sum on all procs
  224. IF( lk_mpp )THEN
  225. ish(1) = nb_sec_max*nb_type_class*nb_class_max
  226. ish2 = (/nb_sec_max,nb_type_class,nb_class_max/)
  227. DO jsec=1,nb_sec ; zsum(jsec,:,:) = secs(jsec)%transport(:,:) ; ENDDO
  228. zwork(:)= RESHAPE(zsum(:,:,:), ish )
  229. CALL mpp_sum(zwork, ish(1))
  230. zsum(:,:,:)= RESHAPE(zwork,ish2)
  231. DO jsec=1,nb_sec ; secs(jsec)%transport(:,:) = zsum(jsec,:,:) ; ENDDO
  232. ENDIF
  233. !Write the transport
  234. DO jsec=1,nb_sec
  235. IF( lwm )CALL dia_dct_wri(kt,jsec,secs(jsec))
  236. !nullify transports values after writing
  237. transports_3d(:,jsec,:,:)=0.
  238. transports_2d(:,jsec,: )=0.
  239. secs(jsec)%transport(:,:)=0.
  240. ENDDO
  241. ENDIF
  242. ENDIF
  243. IF( lk_mpp )THEN
  244. itotal = nb_sec_max*nb_type_class*nb_class_max
  245. CALL wrk_dealloc( itotal , zwork )
  246. CALL wrk_dealloc( nb_sec_max,nb_type_class,nb_class_max , zsum )
  247. ENDIF
  248. IF( nn_timing == 1 ) CALL timing_stop('dia_dct')
  249. !
  250. END SUBROUTINE dia_dct
  251. SUBROUTINE readsec
  252. !!---------------------------------------------------------------------
  253. !! *** ROUTINE readsec ***
  254. !!
  255. !! ** Purpose:
  256. !! Read a binary file(section_ijglobal.diadct)
  257. !! generated by the tools "NEMOGCM/TOOLS/SECTIONS_DIADCT"
  258. !!
  259. !!
  260. !!---------------------------------------------------------------------
  261. !! * Local variables
  262. INTEGER :: iptglo , iptloc ! Global and local number of points for a section
  263. INTEGER :: isec, iiglo, ijglo, iiloc, ijloc,iost,i1 ,i2 ! temporary integer
  264. INTEGER :: jsec, jpt ! dummy loop indices
  265. INTEGER, DIMENSION(2) :: icoord
  266. CHARACTER(len=160) :: clname !filename
  267. CHARACTER(len=200) :: cltmp
  268. CHARACTER(len=200) :: clformat !automatic format
  269. TYPE(POINT_SECTION),DIMENSION(nb_point_max) ::coordtemp !contains listpoints coordinates
  270. !read in the file
  271. INTEGER, POINTER, DIMENSION(:) :: directemp !contains listpoints directions
  272. !read in the files
  273. LOGICAL :: llbon ,&!local logical
  274. lldebug !debug the section
  275. !!-------------------------------------------------------------------------------------
  276. CALL wrk_alloc( nb_point_max, directemp )
  277. !open input file
  278. !---------------
  279. CALL ctl_opn( numdct_in, 'section_ijglobal.diadct', 'OLD', 'UNFORMATTED', 'SEQUENTIAL', -1, numout, .FALSE. )
  280. !---------------
  281. !Read input file
  282. !---------------
  283. DO jsec=1,nb_sec_max !loop on the nb_sec sections
  284. IF ( jsec==nn_secdebug .OR. nn_secdebug==-1 ) &
  285. & WRITE(numout,*)'debuging for section number: ',jsec
  286. !initialization
  287. !---------------
  288. secs(jsec)%name=''
  289. secs(jsec)%llstrpond = .FALSE. ; secs(jsec)%ll_ice_section = .FALSE.
  290. secs(jsec)%ll_date_line = .FALSE. ; secs(jsec)%nb_class = 0
  291. secs(jsec)%zsigi = 99._wp ; secs(jsec)%zsigp = 99._wp
  292. secs(jsec)%zsal = 99._wp ; secs(jsec)%ztem = 99._wp
  293. secs(jsec)%zlay = 99._wp
  294. secs(jsec)%transport = 0._wp ; secs(jsec)%nb_point = 0
  295. !read section's number / name / computing choices / classes / slopeSection / points number
  296. !-----------------------------------------------------------------------------------------
  297. READ(numdct_in,iostat=iost)isec
  298. IF (iost .NE. 0 )EXIT !end of file
  299. WRITE(cltmp,'(a,i4.4,a,i4.4)')'diadct: read sections : Problem of section number: isec= ',isec,' and jsec= ',jsec
  300. IF( jsec .NE. isec ) CALL ctl_stop( cltmp )
  301. IF( jsec==nn_secdebug .OR. nn_secdebug==-1 )WRITE(numout,*)"isec ",isec
  302. READ(numdct_in)secs(jsec)%name
  303. READ(numdct_in)secs(jsec)%llstrpond
  304. READ(numdct_in)secs(jsec)%ll_ice_section
  305. READ(numdct_in)secs(jsec)%ll_date_line
  306. READ(numdct_in)secs(jsec)%coordSec
  307. READ(numdct_in)secs(jsec)%nb_class
  308. READ(numdct_in)secs(jsec)%zsigi
  309. READ(numdct_in)secs(jsec)%zsigp
  310. READ(numdct_in)secs(jsec)%zsal
  311. READ(numdct_in)secs(jsec)%ztem
  312. READ(numdct_in)secs(jsec)%zlay
  313. READ(numdct_in)secs(jsec)%slopeSection
  314. READ(numdct_in)iptglo
  315. !debug
  316. !-----
  317. IF( jsec==nn_secdebug .OR. nn_secdebug==-1 )THEN
  318. WRITE(clformat,'(a,i2,a)') '(A40,', nb_class_max,'(f8.3,1X))'
  319. WRITE(numout,*) " Section name : ",TRIM(secs(jsec)%name)
  320. WRITE(numout,*) " Compute heat and salt transport ? ",secs(jsec)%llstrpond
  321. WRITE(numout,*) " Compute ice transport ? ",secs(jsec)%ll_ice_section
  322. WRITE(numout,*) " Section crosses date-line ? ",secs(jsec)%ll_date_line
  323. WRITE(numout,*) " Slope section : ",secs(jsec)%slopeSection
  324. WRITE(numout,*) " Number of points in the section: ",iptglo
  325. WRITE(numout,*) " Number of classes ",secs(jsec)%nb_class
  326. WRITE(numout,clformat)" Insitu density classes : ",secs(jsec)%zsigi
  327. WRITE(numout,clformat)" Potential density classes : ",secs(jsec)%zsigp
  328. WRITE(numout,clformat)" Salinity classes : ",secs(jsec)%zsal
  329. WRITE(numout,clformat)" Temperature classes : ",secs(jsec)%ztem
  330. WRITE(numout,clformat)" Depth classes : ",secs(jsec)%zlay
  331. ENDIF
  332. IF( iptglo .NE. 0 )THEN
  333. !read points'coordinates and directions
  334. !--------------------------------------
  335. coordtemp(:) = POINT_SECTION(0,0) !list of points read
  336. directemp(:) = 0 !value of directions of each points
  337. DO jpt=1,iptglo
  338. READ(numdct_in)i1,i2
  339. coordtemp(jpt)%I = i1
  340. coordtemp(jpt)%J = i2
  341. ENDDO
  342. READ(numdct_in)directemp(1:iptglo)
  343. !debug
  344. !-----
  345. IF( jsec==nn_secdebug .OR. nn_secdebug==-1 )THEN
  346. WRITE(numout,*)" List of points in global domain:"
  347. DO jpt=1,iptglo
  348. WRITE(numout,*)' # I J ',jpt,coordtemp(jpt),directemp(jpt)
  349. ENDDO
  350. ENDIF
  351. !Now each proc selects only points that are in its domain:
  352. !--------------------------------------------------------
  353. iptloc = 0 !initialize number of points selected
  354. DO jpt=1,iptglo !loop on listpoint read in the file
  355. iiglo=coordtemp(jpt)%I ! global coordinates of the point
  356. ijglo=coordtemp(jpt)%J ! "
  357. IF( iiglo==jpidta .AND. nimpp==1 ) iiglo = 2
  358. iiloc=iiglo-jpizoom+1-nimpp+1 ! local coordinates of the point
  359. ijloc=ijglo-jpjzoom+1-njmpp+1 ! "
  360. !verify if the point is on the local domain:(1,nlei)*(1,nlej)
  361. IF( iiloc .GE. 1 .AND. iiloc .LE. nlei .AND. &
  362. ijloc .GE. 1 .AND. ijloc .LE. nlej )THEN
  363. iptloc = iptloc + 1 ! count local points
  364. secs(jsec)%listPoint(iptloc) = POINT_SECTION(mi0(iiglo),mj0(ijglo)) ! store local coordinates
  365. secs(jsec)%direction(iptloc) = directemp(jpt) ! store local direction
  366. ENDIF
  367. ENDDO
  368. secs(jsec)%nb_point=iptloc !store number of section's points
  369. !debug
  370. !-----
  371. IF( jsec==nn_secdebug .OR. nn_secdebug==-1 )THEN
  372. WRITE(numout,*)" List of points selected by the proc:"
  373. DO jpt = 1,iptloc
  374. iiglo = secs(jsec)%listPoint(jpt)%I + jpizoom - 1 + nimpp - 1
  375. ijglo = secs(jsec)%listPoint(jpt)%J + jpjzoom - 1 + njmpp - 1
  376. WRITE(numout,*)' # I J : ',iiglo,ijglo
  377. ENDDO
  378. ENDIF
  379. IF(jsec==nn_secdebug .AND. secs(jsec)%nb_point .NE. 0)THEN
  380. DO jpt = 1,iptloc
  381. iiglo = secs(jsec)%listPoint(jpt)%I + jpizoom - 1 + nimpp - 1
  382. ijglo = secs(jsec)%listPoint(jpt)%J + jpjzoom - 1 + njmpp - 1
  383. ENDDO
  384. ENDIF
  385. !remove redundant points between processors
  386. !------------------------------------------
  387. lldebug = .FALSE. ; IF ( jsec==nn_secdebug .OR. nn_secdebug==-1 ) lldebug = .TRUE.
  388. IF( iptloc .NE. 0 )THEN
  389. CALL removepoints(secs(jsec),'I','top_list',lldebug)
  390. CALL removepoints(secs(jsec),'I','bot_list',lldebug)
  391. CALL removepoints(secs(jsec),'J','top_list',lldebug)
  392. CALL removepoints(secs(jsec),'J','bot_list',lldebug)
  393. ENDIF
  394. IF(jsec==nn_secdebug .AND. secs(jsec)%nb_point .NE. 0)THEN
  395. DO jpt = 1,secs(jsec)%nb_point
  396. iiglo = secs(jsec)%listPoint(jpt)%I + jpizoom - 1 + nimpp - 1
  397. ijglo = secs(jsec)%listPoint(jpt)%J + jpjzoom - 1 + njmpp - 1
  398. ENDDO
  399. ENDIF
  400. !debug
  401. !-----
  402. IF( jsec==nn_secdebug .OR. nn_secdebug==-1 )THEN
  403. WRITE(numout,*)" List of points after removepoints:"
  404. iptloc = secs(jsec)%nb_point
  405. DO jpt = 1,iptloc
  406. iiglo = secs(jsec)%listPoint(jpt)%I + jpizoom - 1 + nimpp - 1
  407. ijglo = secs(jsec)%listPoint(jpt)%J + jpjzoom - 1 + njmpp - 1
  408. WRITE(numout,*)' # I J : ',iiglo,ijglo
  409. CALL FLUSH(numout)
  410. ENDDO
  411. ENDIF
  412. ELSE ! iptglo = 0
  413. IF( jsec==nn_secdebug .OR. nn_secdebug==-1 )&
  414. WRITE(numout,*)' No points for this section.'
  415. ENDIF
  416. ENDDO !end of the loop on jsec
  417. nb_sec = jsec-1 !number of section read in the file
  418. CALL wrk_dealloc( nb_point_max, directemp )
  419. !
  420. END SUBROUTINE readsec
  421. SUBROUTINE removepoints(sec,cdind,cdextr,ld_debug)
  422. !!---------------------------------------------------------------------------
  423. !! *** function removepoints
  424. !!
  425. !! ** Purpose :: Remove points which are common to 2 procs
  426. !!
  427. !----------------------------------------------------------------------------
  428. !! * arguments
  429. TYPE(SECTION),INTENT(INOUT) :: sec
  430. CHARACTER(len=1),INTENT(IN) :: cdind ! = 'I'/'J'
  431. CHARACTER(len=8),INTENT(IN) :: cdextr ! = 'top_list'/'bot_list'
  432. LOGICAL,INTENT(IN) :: ld_debug
  433. !! * Local variables
  434. INTEGER :: iextr ,& !extremity of listpoint that we verify
  435. iind ,& !coord of listpoint that we verify
  436. itest ,& !indice value of the side of the domain
  437. !where points could be redundant
  438. isgn ,& ! isgn= 1 : scan listpoint from start to end
  439. ! isgn=-1 : scan listpoint from end to start
  440. istart,iend !first and last points selected in listpoint
  441. INTEGER :: jpoint !loop on list points
  442. INTEGER, POINTER, DIMENSION(:) :: idirec !contains temporary sec%direction
  443. INTEGER, POINTER, DIMENSION(:,:) :: icoord !contains temporary sec%listpoint
  444. !----------------------------------------------------------------------------
  445. CALL wrk_alloc( nb_point_max, idirec )
  446. CALL wrk_alloc( 2, nb_point_max, icoord )
  447. IF( ld_debug )WRITE(numout,*)' -------------------------'
  448. IF( ld_debug )WRITE(numout,*)' removepoints in listpoint'
  449. !iextr=extremity of list_point that we verify
  450. IF ( cdextr=='bot_list' )THEN ; iextr=1 ; isgn=1
  451. ELSE IF ( cdextr=='top_list' )THEN ; iextr=sec%nb_point ; isgn=-1
  452. ELSE ; CALL ctl_stop("removepoints :Wrong value for cdextr")
  453. ENDIF
  454. !which coordinate shall we verify ?
  455. IF ( cdind=='I' )THEN ; itest=nlei ; iind=1
  456. ELSE IF ( cdind=='J' )THEN ; itest=nlej ; iind=2
  457. ELSE ; CALL ctl_stop("removepoints :Wrong value for cdind")
  458. ENDIF
  459. IF( ld_debug )THEN
  460. WRITE(numout,*)' case: coord/list extr/domain side'
  461. WRITE(numout,*)' ', cdind,' ',cdextr,' ',itest
  462. WRITE(numout,*)' Actual number of points: ',sec%nb_point
  463. ENDIF
  464. icoord(1,1:nb_point_max) = sec%listPoint%I
  465. icoord(2,1:nb_point_max) = sec%listPoint%J
  466. idirec = sec%direction
  467. sec%listPoint = POINT_SECTION(0,0)
  468. sec%direction = 0
  469. jpoint=iextr+isgn
  470. DO WHILE( jpoint .GE. 1 .AND. jpoint .LE. sec%nb_point )
  471. IF( icoord( iind,jpoint-isgn ) == itest .AND. icoord( iind,jpoint ) == itest )THEN ; jpoint=jpoint+isgn
  472. ELSE ; EXIT
  473. ENDIF
  474. ENDDO
  475. IF( cdextr=='bot_list')THEN ; istart=jpoint-1 ; iend=sec%nb_point
  476. ELSE ; istart=1 ; iend=jpoint+1
  477. ENDIF
  478. sec%listPoint(1:1+iend-istart)%I = icoord(1,istart:iend)
  479. sec%listPoint(1:1+iend-istart)%J = icoord(2,istart:iend)
  480. sec%direction(1:1+iend-istart) = idirec(istart:iend)
  481. sec%nb_point = iend-istart+1
  482. IF( ld_debug )THEN
  483. WRITE(numout,*)' Number of points after removepoints :',sec%nb_point
  484. WRITE(numout,*)' sec%direction after removepoints :',sec%direction(1:sec%nb_point)
  485. ENDIF
  486. CALL wrk_dealloc( nb_point_max, idirec )
  487. CALL wrk_dealloc( 2, nb_point_max, icoord )
  488. END SUBROUTINE removepoints
  489. SUBROUTINE transport(sec,ld_debug,jsec)
  490. !!-------------------------------------------------------------------------------------------
  491. !! *** ROUTINE transport ***
  492. !!
  493. !! Purpose :: Compute the transport for each point in a section
  494. !!
  495. !! Method :: Loop over each segment, and each vertical level and add the transport
  496. !! Be aware :
  497. !! One section is a sum of segments
  498. !! One segment is defined by 2 consecutive points in sec%listPoint
  499. !! All points of sec%listPoint are positioned on the F-point of the cell
  500. !!
  501. !! There are two loops:
  502. !! loop on the segment between 2 nodes
  503. !! loop on the level jk !!
  504. !!
  505. !! Output :: Arrays containing the volume,density,heat,salt transports for each i
  506. !! point in a section, summed over each nn_dct.
  507. !!
  508. !!-------------------------------------------------------------------------------------------
  509. !! * Arguments
  510. TYPE(SECTION),INTENT(INOUT) :: sec
  511. LOGICAL ,INTENT(IN) :: ld_debug
  512. INTEGER ,INTENT(IN) :: jsec ! numeric identifier of section
  513. !! * Local variables
  514. INTEGER :: jk, jseg, jclass,jl, &!loop on level/segment/classes/ice categories
  515. isgnu, isgnv !
  516. REAL(wp) :: zumid, zvmid, &!U/V velocity on a cell segment
  517. zumid_ice, zvmid_ice, &!U/V ice velocity
  518. zTnorm !transport of velocity through one cell's sides
  519. REAL(wp) :: ztn, zsn, zrhoi, zrhop, zsshn, zfsdep !temperature/salinity/potential density/ssh/depth at u/v point
  520. TYPE(POINT_SECTION) :: k
  521. !!--------------------------------------------------------
  522. IF( ld_debug )WRITE(numout,*)' Compute transport'
  523. !---------------------------!
  524. ! COMPUTE TRANSPORT !
  525. !---------------------------!
  526. IF(sec%nb_point .NE. 0)THEN
  527. !----------------------------------------------------------------------------------------------------
  528. !Compute sign for velocities:
  529. !
  530. !convention:
  531. ! non horizontal section: direction + is toward left hand of section
  532. ! horizontal section: direction + is toward north of section
  533. !
  534. !
  535. ! slopeSection < 0 slopeSection > 0 slopeSection=inf slopeSection=0
  536. ! ---------------- ----------------- --------------- --------------
  537. !
  538. ! isgnv=1 direction +
  539. ! ______ _____ ______
  540. ! | //| | | direction +
  541. ! | isgnu=1 // | |isgnu=1 |isgnu=1 /|\
  542. ! |_______ // ______| \\ | ---\ |
  543. ! | | isgnv=-1 \\ | | ---/ direction + ____________
  544. ! | | __\\| |
  545. ! | | direction + | isgnv=1
  546. !
  547. !----------------------------------------------------------------------------------------------------
  548. isgnu = 1
  549. IF( sec%slopeSection .GT. 0 ) THEN ; isgnv = -1
  550. ELSE ; isgnv = 1
  551. ENDIF
  552. IF( sec%slopeSection .GE. 9999. ) isgnv = 1
  553. IF( ld_debug )write(numout,*)"sec%slopeSection isgnu isgnv ",sec%slopeSection,isgnu,isgnv
  554. !--------------------------------------!
  555. ! LOOP ON THE SEGMENT BETWEEN 2 NODES !
  556. !--------------------------------------!
  557. DO jseg=1,MAX(sec%nb_point-1,0)
  558. !-------------------------------------------------------------------------------------------
  559. ! Select the appropriate coordinate for computing the velocity of the segment
  560. !
  561. ! CASE(0) Case (2)
  562. ! ------- --------
  563. ! listPoint(jseg) listPoint(jseg+1) listPoint(jseg) F(i,j)
  564. ! F(i,j)----------V(i+1,j)-------F(i+1,j) |
  565. ! |
  566. ! |
  567. ! |
  568. ! Case (3) U(i,j)
  569. ! -------- |
  570. ! |
  571. ! listPoint(jseg+1) F(i,j+1) |
  572. ! | |
  573. ! | |
  574. ! | listPoint(jseg+1) F(i,j-1)
  575. ! |
  576. ! |
  577. ! U(i,j+1)
  578. ! | Case(1)
  579. ! | ------
  580. ! |
  581. ! | listPoint(jseg+1) listPoint(jseg)
  582. ! | F(i-1,j)-----------V(i,j) -------f(jseg)
  583. ! listPoint(jseg) F(i,j)
  584. !
  585. !-------------------------------------------------------------------------------------------
  586. SELECT CASE( sec%direction(jseg) )
  587. CASE(0) ; k = sec%listPoint(jseg)
  588. CASE(1) ; k = POINT_SECTION(sec%listPoint(jseg)%I+1,sec%listPoint(jseg)%J)
  589. CASE(2) ; k = sec%listPoint(jseg)
  590. CASE(3) ; k = POINT_SECTION(sec%listPoint(jseg)%I,sec%listPoint(jseg)%J+1)
  591. END SELECT
  592. !---------------------------|
  593. ! LOOP ON THE LEVEL |
  594. !---------------------------|
  595. !Sum of the transport on the vertical
  596. DO jk=1,mbathy(k%I,k%J)
  597. ! compute temperature, salinity, insitu & potential density, ssh and depth at U/V point
  598. SELECT CASE( sec%direction(jseg) )
  599. CASE(0,1)
  600. ztn = interp(k%I,k%J,jk,'V',tsn(:,:,:,jp_tem) )
  601. zsn = interp(k%I,k%J,jk,'V',tsn(:,:,:,jp_sal) )
  602. zrhop = interp(k%I,k%J,jk,'V',rhop)
  603. zrhoi = interp(k%I,k%J,jk,'V',rhd*rau0+rau0)
  604. zsshn = 0.5*( sshn(k%I,k%J) + sshn(k%I,k%J+1) ) * vmask(k%I,k%J,1)
  605. CASE(2,3)
  606. ztn = interp(k%I,k%J,jk,'U',tsn(:,:,:,jp_tem) )
  607. zsn = interp(k%I,k%J,jk,'U',tsn(:,:,:,jp_sal) )
  608. zrhop = interp(k%I,k%J,jk,'U',rhop)
  609. zrhoi = interp(k%I,k%J,jk,'U',rhd*rau0+rau0)
  610. zsshn = 0.5*( sshn(k%I,k%J) + sshn(k%I+1,k%J) ) * umask(k%I,k%J,1)
  611. END SELECT
  612. zfsdep= fsdept(k%I,k%J,jk)
  613. !compute velocity with the correct direction
  614. SELECT CASE( sec%direction(jseg) )
  615. CASE(0,1)
  616. zumid=0.
  617. zvmid=isgnv*vn(k%I,k%J,jk)*vmask(k%I,k%J,jk)
  618. CASE(2,3)
  619. zumid=isgnu*un(k%I,k%J,jk)*umask(k%I,k%J,jk)
  620. zvmid=0.
  621. END SELECT
  622. !zTnorm=transport through one cell;
  623. !velocity* cell's length * cell's thickness
  624. zTnorm=zumid*e2u(k%I,k%J)* fse3u(k%I,k%J,jk)+ &
  625. zvmid*e1v(k%I,k%J)* fse3v(k%I,k%J,jk)
  626. #if ! defined key_vvl
  627. !add transport due to free surface
  628. IF( jk==1 )THEN
  629. zTnorm = zTnorm + zumid* e2u(k%I,k%J) * zsshn * umask(k%I,k%J,jk) + &
  630. zvmid* e1v(k%I,k%J) * zsshn * vmask(k%I,k%J,jk)
  631. ENDIF
  632. #endif
  633. !COMPUTE TRANSPORT
  634. transports_3d(1,jsec,jseg,jk) = transports_3d(1,jsec,jseg,jk) + zTnorm
  635. IF ( sec%llstrpond ) THEN
  636. transports_3d(2,jsec,jseg,jk) = transports_3d(2,jsec,jseg,jk) + zTnorm * ztn * zrhop * rcp
  637. transports_3d(3,jsec,jseg,jk) = transports_3d(3,jsec,jseg,jk) + zTnorm * zsn * zrhop * 0.001
  638. ENDIF
  639. ENDDO !end of loop on the level
  640. #if defined key_lim2 || defined key_lim3
  641. !ICE CASE
  642. !------------
  643. IF( sec%ll_ice_section )THEN
  644. SELECT CASE (sec%direction(jseg))
  645. CASE(0)
  646. zumid_ice = 0
  647. zvmid_ice = isgnv*0.5*(v_ice(k%I,k%J+1)+v_ice(k%I+1,k%J+1))
  648. CASE(1)
  649. zumid_ice = 0
  650. zvmid_ice = isgnv*0.5*(v_ice(k%I,k%J+1)+v_ice(k%I+1,k%J+1))
  651. CASE(2)
  652. zvmid_ice = 0
  653. zumid_ice = isgnu*0.5*(u_ice(k%I+1,k%J)+u_ice(k%I+1,k%J+1))
  654. CASE(3)
  655. zvmid_ice = 0
  656. zumid_ice = isgnu*0.5*(u_ice(k%I+1,k%J)+u_ice(k%I+1,k%J+1))
  657. END SELECT
  658. zTnorm=zumid_ice*e2u(k%I,k%J)+zvmid_ice*e1v(k%I,k%J)
  659. #if defined key_lim2
  660. transports_2d(1,jsec,jseg) = transports_2d(1,jsec,jseg) + (zTnorm)* &
  661. (1.0 - frld(sec%listPoint(jseg)%I,sec%listPoint(jseg)%J)) &
  662. *(hsnif(sec%listPoint(jseg)%I,sec%listPoint(jseg)%J) + &
  663. hicif(sec%listPoint(jseg)%I,sec%listPoint(jseg)%J))
  664. transports_2d(2,jsec,jseg) = transports_2d(2,jsec,jseg) + (zTnorm)* &
  665. (1.0 - frld(sec%listPoint(jseg)%I,sec%listPoint(jseg)%J))
  666. #endif
  667. #if defined key_lim3
  668. DO jl=1,jpl
  669. transports_2d(1,jsec,jseg) = transports_2d(1,jsec,jseg) + (zTnorm)* &
  670. a_i(sec%listPoint(jseg)%I,sec%listPoint(jseg)%J,jl) * &
  671. ( ht_i(sec%listPoint(jseg)%I,sec%listPoint(jseg)%J,jl) + &
  672. ht_s(sec%listPoint(jseg)%I,sec%listPoint(jseg)%J,jl) )
  673. transports_2d(2,jsec,jseg) = transports_2d(2,jsec,jseg) + (zTnorm)* &
  674. a_i(sec%listPoint(jseg)%I,sec%listPoint(jseg)%J,jl)
  675. ENDDO
  676. #endif
  677. ENDIF !end of ice case
  678. #endif
  679. ENDDO !end of loop on the segment
  680. ENDIF !end of sec%nb_point =0 case
  681. !
  682. END SUBROUTINE transport
  683. SUBROUTINE dia_dct_sum(sec,jsec)
  684. !!-------------------------------------------------------------
  685. !! Purpose: Average the transport over nn_dctwri time steps
  686. !! and sum over the density/salinity/temperature/depth classes
  687. !!
  688. !! Method: Sum over relevant grid cells to obtain values
  689. !! for each class
  690. !! There are several loops:
  691. !! loop on the segment between 2 nodes
  692. !! loop on the level jk
  693. !! loop on the density/temperature/salinity/level classes
  694. !! test on the density/temperature/salinity/level
  695. !!
  696. !! Note: Transport through a given section is equal to the sum of transports
  697. !! computed on each proc.
  698. !! On each proc,transport is equal to the sum of transport computed through
  699. !! segments linking each point of sec%listPoint with the next one.
  700. !!
  701. !!-------------------------------------------------------------
  702. !! * arguments
  703. TYPE(SECTION),INTENT(INOUT) :: sec
  704. INTEGER ,INTENT(IN) :: jsec ! numeric identifier of section
  705. TYPE(POINT_SECTION) :: k
  706. INTEGER :: jk,jseg,jclass ! dummy variables for looping on level/segment/classes
  707. REAL(wp) :: ztn, zsn, zrhoi, zrhop, zsshn, zfsdep ! temperature/salinity/ssh/potential density /depth at u/v point
  708. !!-------------------------------------------------------------
  709. !! Sum the relevant segments to obtain values for each class
  710. IF(sec%nb_point .NE. 0)THEN
  711. !--------------------------------------!
  712. ! LOOP ON THE SEGMENT BETWEEN 2 NODES !
  713. !--------------------------------------!
  714. DO jseg=1,MAX(sec%nb_point-1,0)
  715. !-------------------------------------------------------------------------------------------
  716. ! Select the appropriate coordinate for computing the velocity of the segment
  717. !
  718. ! CASE(0) Case (2)
  719. ! ------- --------
  720. ! listPoint(jseg) listPoint(jseg+1) listPoint(jseg) F(i,j)
  721. ! F(i,j)----------V(i+1,j)-------F(i+1,j) |
  722. ! |
  723. ! |
  724. ! |
  725. ! Case (3) U(i,j)
  726. ! -------- |
  727. ! |
  728. ! listPoint(jseg+1) F(i,j+1) |
  729. ! | |
  730. ! | |
  731. ! | listPoint(jseg+1) F(i,j-1)
  732. ! |
  733. ! |
  734. ! U(i,j+1)
  735. ! | Case(1)
  736. ! | ------
  737. ! |
  738. ! | listPoint(jseg+1) listPoint(jseg)
  739. ! | F(i-1,j)-----------V(i,j) -------f(jseg)
  740. ! listPoint(jseg) F(i,j)
  741. !
  742. !-------------------------------------------------------------------------------------------
  743. SELECT CASE( sec%direction(jseg) )
  744. CASE(0) ; k = sec%listPoint(jseg)
  745. CASE(1) ; k = POINT_SECTION(sec%listPoint(jseg)%I+1,sec%listPoint(jseg)%J)
  746. CASE(2) ; k = sec%listPoint(jseg)
  747. CASE(3) ; k = POINT_SECTION(sec%listPoint(jseg)%I,sec%listPoint(jseg)%J+1)
  748. END SELECT
  749. !---------------------------|
  750. ! LOOP ON THE LEVEL |
  751. !---------------------------|
  752. !Sum of the transport on the vertical
  753. DO jk=1,mbathy(k%I,k%J)
  754. ! compute temperature, salinity, insitu & potential density, ssh and depth at U/V point
  755. SELECT CASE( sec%direction(jseg) )
  756. CASE(0,1)
  757. ztn = interp(k%I,k%J,jk,'V',tsn(:,:,:,jp_tem) )
  758. zsn = interp(k%I,k%J,jk,'V',tsn(:,:,:,jp_sal) )
  759. zrhop = interp(k%I,k%J,jk,'V',rhop)
  760. zrhoi = interp(k%I,k%J,jk,'V',rhd*rau0+rau0)
  761. CASE(2,3)
  762. ztn = interp(k%I,k%J,jk,'U',tsn(:,:,:,jp_tem) )
  763. zsn = interp(k%I,k%J,jk,'U',tsn(:,:,:,jp_sal) )
  764. zrhop = interp(k%I,k%J,jk,'U',rhop)
  765. zrhoi = interp(k%I,k%J,jk,'U',rhd*rau0+rau0)
  766. zsshn = 0.5*( sshn(k%I,k%J) + sshn(k%I+1,k%J) ) * umask(k%I,k%J,1)
  767. END SELECT
  768. zfsdep= fsdept(k%I,k%J,jk)
  769. !-------------------------------
  770. ! LOOP ON THE DENSITY CLASSES |
  771. !-------------------------------
  772. !The computation is made for each density/temperature/salinity/depth class
  773. DO jclass=1,MAX(1,sec%nb_class-1)
  774. !----------------------------------------------!
  775. !TEST ON THE DENSITY/SALINITY/TEMPERATURE/LEVEL!
  776. !----------------------------------------------!
  777. IF ( ( &
  778. ((( zrhop .GE. (sec%zsigp(jclass)+1000. )) .AND. &
  779. ( zrhop .LE. (sec%zsigp(jclass+1)+1000. ))) .OR. &
  780. ( sec%zsigp(jclass) .EQ. 99.)) .AND. &
  781. ((( zrhoi .GE. (sec%zsigi(jclass) + 1000. )) .AND. &
  782. ( zrhoi .LE. (sec%zsigi(jclass+1)+1000. ))) .OR. &
  783. ( sec%zsigi(jclass) .EQ. 99.)) .AND. &
  784. ((( zsn .GT. sec%zsal(jclass)) .AND. &
  785. ( zsn .LE. sec%zsal(jclass+1))) .OR. &
  786. ( sec%zsal(jclass) .EQ. 99.)) .AND. &
  787. ((( ztn .GE. sec%ztem(jclass)) .AND. &
  788. ( ztn .LE. sec%ztem(jclass+1))) .OR. &
  789. ( sec%ztem(jclass) .EQ.99.)) .AND. &
  790. ((( zfsdep .GE. sec%zlay(jclass)) .AND. &
  791. ( zfsdep .LE. sec%zlay(jclass+1))) .OR. &
  792. ( sec%zlay(jclass) .EQ. 99. )) &
  793. )) THEN
  794. !SUM THE TRANSPORTS FOR EACH CLASSES FOR THE POSITIVE AND NEGATIVE DIRECTIONS
  795. !----------------------------------------------------------------------------
  796. IF (transports_3d(1,jsec,jseg,jk) .GE. 0.0) THEN
  797. sec%transport(1,jclass) = sec%transport(1,jclass)+transports_3d(1,jsec,jseg,jk)*1.E-6
  798. ELSE
  799. sec%transport(2,jclass) = sec%transport(2,jclass)+transports_3d(1,jsec,jseg,jk)*1.E-6
  800. ENDIF
  801. IF( sec%llstrpond )THEN
  802. IF ( transports_3d(2,jsec,jseg,jk) .GE. 0.0 ) THEN
  803. sec%transport(3,jclass) = sec%transport(3,jclass)+transports_3d(2,jsec,jseg,jk)
  804. ELSE
  805. sec%transport(4,jclass) = sec%transport(4,jclass)+transports_3d(2,jsec,jseg,jk)
  806. ENDIF
  807. IF ( transports_3d(3,jsec,jseg,jk) .GE. 0.0 ) THEN
  808. sec%transport(5,jclass) = sec%transport(5,jclass)+transports_3d(3,jsec,jseg,jk)
  809. ELSE
  810. sec%transport(6,jclass) = sec%transport(6,jclass)+transports_3d(3,jsec,jseg,jk)
  811. ENDIF
  812. ELSE
  813. sec%transport( 3,jclass) = 0._wp
  814. sec%transport( 4,jclass) = 0._wp
  815. sec%transport( 5,jclass) = 0._wp
  816. sec%transport( 6,jclass) = 0._wp
  817. ENDIF
  818. ENDIF ! end of test if point is in class
  819. ENDDO ! end of loop on the classes
  820. ENDDO ! loop over jk
  821. #if defined key_lim2 || defined key_lim3
  822. !ICE CASE
  823. IF( sec%ll_ice_section )THEN
  824. IF ( transports_2d(1,jsec,jseg) .GE. 0.0 ) THEN
  825. sec%transport( 7,1) = sec%transport( 7,1)+transports_2d(1,jsec,jseg)*1.E-6
  826. ELSE
  827. sec%transport( 8,1) = sec%transport( 8,1)+transports_2d(1,jsec,jseg)*1.E-6
  828. ENDIF
  829. IF ( transports_2d(3,jsec,jseg) .GE. 0.0 ) THEN
  830. sec%transport( 9,1) = sec%transport( 9,1)+transports_2d(2,jsec,jseg)*1.E-6
  831. ELSE
  832. sec%transport(10,1) = sec%transport(10,1)+transports_2d(2,jsec,jseg)*1.E-6
  833. ENDIF
  834. ENDIF !end of ice case
  835. #endif
  836. ENDDO !end of loop on the segment
  837. ELSE !if sec%nb_point =0
  838. sec%transport(1:2,:)=0.
  839. IF (sec%llstrpond) sec%transport(3:6,:)=0.
  840. IF (sec%ll_ice_section) sec%transport(7:10,:)=0.
  841. ENDIF !end of sec%nb_point =0 case
  842. END SUBROUTINE dia_dct_sum
  843. SUBROUTINE dia_dct_wri(kt,ksec,sec)
  844. !!-------------------------------------------------------------
  845. !! Write transport output in numdct
  846. !!
  847. !! Purpose: Write transports in ascii files
  848. !!
  849. !! Method:
  850. !! 1. Write volume transports in "volume_transport"
  851. !! Unit: Sv : area * Velocity / 1.e6
  852. !!
  853. !! 2. Write heat transports in "heat_transport"
  854. !! Unit: Peta W : area * Velocity * T * rhop * Cp * 1.e-15
  855. !!
  856. !! 3. Write salt transports in "salt_transport"
  857. !! Unit: 10^9 Kg/m^2/s : area * Velocity * S * rhop * 1.e-9
  858. !!
  859. !!-------------------------------------------------------------
  860. !!arguments
  861. INTEGER, INTENT(IN) :: kt ! time-step
  862. TYPE(SECTION), INTENT(INOUT) :: sec ! section to write
  863. INTEGER ,INTENT(IN) :: ksec ! section number
  864. !!local declarations
  865. INTEGER :: jclass ! Dummy loop
  866. CHARACTER(len=2) :: classe ! Classname
  867. REAL(wp) :: zbnd1,zbnd2 ! Class bounds
  868. REAL(wp) :: zslope ! section's slope coeff
  869. !
  870. REAL(wp), POINTER, DIMENSION(:):: zsumclasses ! 1D workspace
  871. !!-------------------------------------------------------------
  872. CALL wrk_alloc(nb_type_class , zsumclasses )
  873. zsumclasses(:)=0._wp
  874. zslope = sec%slopeSection
  875. DO jclass=1,MAX(1,sec%nb_class-1)
  876. classe = 'N '
  877. zbnd1 = 0._wp
  878. zbnd2 = 0._wp
  879. zsumclasses(1:nb_type_class)=zsumclasses(1:nb_type_class)+sec%transport(1:nb_type_class,jclass)
  880. !insitu density classes transports
  881. IF( ( sec%zsigi(jclass) .NE. 99._wp ) .AND. &
  882. ( sec%zsigi(jclass+1) .NE. 99._wp ) )THEN
  883. classe = 'DI '
  884. zbnd1 = sec%zsigi(jclass)
  885. zbnd2 = sec%zsigi(jclass+1)
  886. ENDIF
  887. !potential density classes transports
  888. IF( ( sec%zsigp(jclass) .NE. 99._wp ) .AND. &
  889. ( sec%zsigp(jclass+1) .NE. 99._wp ) )THEN
  890. classe = 'DP '
  891. zbnd1 = sec%zsigp(jclass)
  892. zbnd2 = sec%zsigp(jclass+1)
  893. ENDIF
  894. !depth classes transports
  895. IF( ( sec%zlay(jclass) .NE. 99._wp ) .AND. &
  896. ( sec%zlay(jclass+1) .NE. 99._wp ) )THEN
  897. classe = 'Z '
  898. zbnd1 = sec%zlay(jclass)
  899. zbnd2 = sec%zlay(jclass+1)
  900. ENDIF
  901. !salinity classes transports
  902. IF( ( sec%zsal(jclass) .NE. 99._wp ) .AND. &
  903. ( sec%zsal(jclass+1) .NE. 99._wp ) )THEN
  904. classe = 'S '
  905. zbnd1 = sec%zsal(jclass)
  906. zbnd2 = sec%zsal(jclass+1)
  907. ENDIF
  908. !temperature classes transports
  909. IF( ( sec%ztem(jclass) .NE. 99._wp ) .AND. &
  910. ( sec%ztem(jclass+1) .NE. 99._wp ) ) THEN
  911. classe = 'T '
  912. zbnd1 = sec%ztem(jclass)
  913. zbnd2 = sec%ztem(jclass+1)
  914. ENDIF
  915. !write volume transport per class
  916. WRITE(numdct_vol,118) ndastp,kt,ksec,sec%name,zslope, &
  917. jclass,classe,zbnd1,zbnd2,&
  918. sec%transport(1,jclass),sec%transport(2,jclass), &
  919. sec%transport(1,jclass)+sec%transport(2,jclass)
  920. IF( sec%llstrpond )THEN
  921. !write heat transport per class:
  922. WRITE(numdct_heat,119) ndastp,kt,ksec,sec%name,zslope, &
  923. jclass,classe,zbnd1,zbnd2,&
  924. sec%transport(3,jclass)*1.e-15,sec%transport(4,jclass)*1.e-15, &
  925. ( sec%transport(3,jclass)+sec%transport(4,jclass) )*1.e-15
  926. !write salt transport per class
  927. WRITE(numdct_salt,119) ndastp,kt,ksec,sec%name,zslope, &
  928. jclass,classe,zbnd1,zbnd2,&
  929. sec%transport(5,jclass)*1.e-9,sec%transport(6,jclass)*1.e-9,&
  930. (sec%transport(5,jclass)+sec%transport(6,jclass))*1.e-9
  931. ENDIF
  932. ENDDO
  933. zbnd1 = 0._wp
  934. zbnd2 = 0._wp
  935. jclass=0
  936. !write total volume transport
  937. WRITE(numdct_vol,118) ndastp,kt,ksec,sec%name,zslope, &
  938. jclass,"total",zbnd1,zbnd2,&
  939. zsumclasses(1),zsumclasses(2),zsumclasses(1)+zsumclasses(2)
  940. IF( sec%llstrpond )THEN
  941. !write total heat transport
  942. WRITE(numdct_heat,119) ndastp,kt,ksec,sec%name,zslope, &
  943. jclass,"total",zbnd1,zbnd2,&
  944. zsumclasses(3)*1.e-15,zsumclasses(4)*1.e-15,&
  945. (zsumclasses(3)+zsumclasses(4) )*1.e-15
  946. !write total salt transport
  947. WRITE(numdct_salt,119) ndastp,kt,ksec,sec%name,zslope, &
  948. jclass,"total",zbnd1,zbnd2,&
  949. zsumclasses(5)*1.e-9,zsumclasses(6)*1.e-9,&
  950. (zsumclasses(5)+zsumclasses(6))*1.e-9
  951. ENDIF
  952. IF ( sec%ll_ice_section) THEN
  953. !write total ice volume transport
  954. WRITE(numdct_vol,118) ndastp,kt,ksec,sec%name,zslope,&
  955. jclass,"ice_vol",zbnd1,zbnd2,&
  956. sec%transport(7,1),sec%transport(8,1),&
  957. sec%transport(7,1)+sec%transport(8,1)
  958. !write total ice surface transport
  959. WRITE(numdct_vol,118) ndastp,kt,ksec,sec%name,zslope,&
  960. jclass,"ice_surf",zbnd1,zbnd2,&
  961. sec%transport(9,1),sec%transport(10,1), &
  962. sec%transport(9,1)+sec%transport(10,1)
  963. ENDIF
  964. 118 FORMAT(I8,1X,I8,1X,I4,1X,A30,1X,f9.2,1X,I4,3X,A8,1X,2F12.4,5X,3F12.4)
  965. 119 FORMAT(I8,1X,I8,1X,I4,1X,A30,1X,f9.2,1X,I4,3X,A8,1X,2F12.4,5X,3E15.6)
  966. CALL wrk_dealloc(nb_type_class , zsumclasses )
  967. END SUBROUTINE dia_dct_wri
  968. FUNCTION interp(ki, kj, kk, cd_point, ptab)
  969. !!----------------------------------------------------------------------
  970. !!
  971. !! Purpose: compute temperature/salinity/density at U-point or V-point
  972. !! --------
  973. !!
  974. !! Method:
  975. !! ------
  976. !!
  977. !! ====> full step and partial step
  978. !!
  979. !!
  980. !! | I | I+1 | Z=temperature/salinity/density at U-poinT
  981. !! | | |
  982. !! ---------------------------------------- 1. Veritcal interpolation: compute zbis
  983. !! | | | interpolation between ptab(I,J,K) and ptab(I,J,K+1)
  984. !! | | | zbis =
  985. !! | | | [ e3w(I+1,J,K)*ptab(I,J,K) + ( e3w(I,J,K) - e3w(I+1,J,K) ) * ptab(I,J,K-1) ]
  986. !! | | | /[ e3w(I+1,J,K) + e3w(I,J,K) - e3w(I+1,J,K) ]
  987. !! | | |
  988. !! | | | 2. Horizontal interpolation: compute value at U/V point
  989. !!K-1 | ptab(I,J,K-1) | | interpolation between zbis and ptab(I+1,J,K)
  990. !! | . | |
  991. !! | . | | interp = ( 0.5*zet2*zbis + 0.5*zet1*ptab(I+1,J,K) )/(0.5*zet2+0.5*zet1)
  992. !! | . | |
  993. !! ------------------------------------------
  994. !! | . | |
  995. !! | . | |
  996. !! | . | |
  997. !!K | zbis.......U...ptab(I+1,J,K) |
  998. !! | . | |
  999. !! | ptab(I,J,K) | |
  1000. !! | |------------------|
  1001. !! | | partials |
  1002. !! | | steps |
  1003. !! -------------------------------------------
  1004. !! <----zet1------><----zet2--------->
  1005. !!
  1006. !!
  1007. !! ====> s-coordinate
  1008. !!
  1009. !! | | | 1. Compute distance between T1 and U points: SQRT( zdep1^2 + (0.5 * zet1 )^2
  1010. !! | | | Compute distance between T2 and U points: SQRT( zdep2^2 + (0.5 * zet2 )^2
  1011. !! | | ptab(I+1,J,K) |
  1012. !! | | T2 | 2. Interpolation between T1 and T2 values at U point
  1013. !! | | ^ |
  1014. !! | | | zdep2 |
  1015. !! | | | |
  1016. !! | ^ U v |
  1017. !! | | | |
  1018. !! | | zdep1 | |
  1019. !! | v | |
  1020. !! | T1 | |
  1021. !! | ptab(I,J,K) | |
  1022. !! | | |
  1023. !! | | |
  1024. !!
  1025. !! <----zet1--------><----zet2--------->
  1026. !!
  1027. !!----------------------------------------------------------------------
  1028. !*arguments
  1029. INTEGER, INTENT(IN) :: ki, kj, kk ! coordinate of point
  1030. CHARACTER(len=1), INTENT(IN) :: cd_point ! type of point (U, V)
  1031. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(IN) :: ptab ! variable to compute at (ki, kj, kk )
  1032. REAL(wp) :: interp ! interpolated variable
  1033. !*local declations
  1034. INTEGER :: ii1, ij1, ii2, ij2 ! local integer
  1035. REAL(wp):: ze3t, zfse3, zwgt1, zwgt2, zbis, zdepu ! local real
  1036. REAL(wp):: zet1, zet2 ! weight for interpolation
  1037. REAL(wp):: zdep1,zdep2 ! differences of depth
  1038. REAL(wp):: zmsk ! mask value
  1039. !!----------------------------------------------------------------------
  1040. IF( cd_point=='U' )THEN
  1041. ii1 = ki ; ij1 = kj
  1042. ii2 = ki+1 ; ij2 = kj
  1043. zet1=e1t(ii1,ij1)
  1044. zet2=e1t(ii2,ij2)
  1045. zmsk=umask(ii1,ij1,kk)
  1046. ELSE ! cd_point=='V'
  1047. ii1 = ki ; ij1 = kj
  1048. ii2 = ki ; ij2 = kj+1
  1049. zet1=e2t(ii1,ij1)
  1050. zet2=e2t(ii2,ij2)
  1051. zmsk=vmask(ii1,ij1,kk)
  1052. ENDIF
  1053. IF( ln_sco )THEN ! s-coordinate case
  1054. zdepu = ( fsdept(ii1,ij1,kk) + fsdept(ii2,ij2,kk) ) /2
  1055. zdep1 = fsdept(ii1,ij1,kk) - zdepu
  1056. zdep2 = fsdept(ii2,ij2,kk) - zdepu
  1057. ! weights
  1058. zwgt1 = SQRT( ( 0.5 * zet1 ) * ( 0.5 * zet1 ) + ( zdep1 * zdep1 ) )
  1059. zwgt2 = SQRT( ( 0.5 * zet2 ) * ( 0.5 * zet2 ) + ( zdep2 * zdep2 ) )
  1060. ! result
  1061. interp = zmsk * ( zwgt2 * ptab(ii1,ij1,kk) + zwgt1 * ptab(ii1,ij1,kk) ) / ( zwgt2 + zwgt1 )
  1062. ELSE ! full step or partial step case
  1063. #if defined key_vvl
  1064. ze3t = fse3t_n(ii2,ij2,kk) - fse3t_n(ii1,ij1,kk)
  1065. zwgt1 = ( fse3w_n(ii2,ij2,kk) - fse3w_n(ii1,ij1,kk) ) / fse3w_n(ii2,ij2,kk)
  1066. zwgt2 = ( fse3w_n(ii1,ij1,kk) - fse3w_n(ii2,ij2,kk) ) / fse3w_n(ii1,ij1,kk)
  1067. #else
  1068. ze3t = fse3t(ii2,ij2,kk) - fse3t(ii1,ij1,kk)
  1069. zwgt1 = ( fse3w(ii2,ij2,kk) - fse3w(ii1,ij1,kk) ) / fse3w(ii2,ij2,kk)
  1070. zwgt2 = ( fse3w(ii1,ij1,kk) - fse3w(ii2,ij2,kk) ) / fse3w(ii1,ij1,kk)
  1071. #endif
  1072. IF(kk .NE. 1)THEN
  1073. IF( ze3t >= 0. )THEN
  1074. ! zbis
  1075. zbis = ptab(ii2,ij2,kk) + zwgt1 * ( ptab(ii2,ij2,kk-1) - ptab(ii2,ij2,kk) )
  1076. ! result
  1077. interp = zmsk * ( zet2 * ptab(ii1,ij1,kk) + zet1 * zbis )/( zet1 + zet2 )
  1078. ELSE
  1079. ! zbis
  1080. zbis = ptab(ii1,ij1,kk) + zwgt2 * ( ptab(ii1,ij1,kk-1) - ptab(ii1,ij2,kk) )
  1081. ! result
  1082. interp = zmsk * ( zet2 * zbis + zet1 * ptab(ii2,ij2,kk) )/( zet1 + zet2 )
  1083. ENDIF
  1084. ELSE
  1085. interp = zmsk * ( zet2 * ptab(ii1,ij1,kk) + zet1 * ptab(ii2,ij2,kk) )/( zet1 + zet2 )
  1086. ENDIF
  1087. ENDIF
  1088. END FUNCTION interp
  1089. #else
  1090. !!----------------------------------------------------------------------
  1091. !! Default option : Dummy module
  1092. !!----------------------------------------------------------------------
  1093. LOGICAL, PUBLIC, PARAMETER :: lk_diadct = .FALSE. !: diamht flag
  1094. PUBLIC
  1095. !! $Id: diadct.F90 4578 2017-09-25 09:34:12Z ufla $
  1096. CONTAINS
  1097. SUBROUTINE dia_dct_init ! Dummy routine
  1098. WRITE(*,*) 'dia_dct_init: You should not have seen this print! error?', kt
  1099. END SUBROUTINE dia_dct_init
  1100. SUBROUTINE dia_dct( kt ) ! Dummy routine
  1101. INTEGER, INTENT( in ) :: kt ! ocean time-step index
  1102. WRITE(*,*) 'dia_dct: You should not have seen this print! error?', kt
  1103. END SUBROUTINE dia_dct
  1104. #endif
  1105. END MODULE diadct