cdftransportiz.f90 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. PROGRAM cdftransportiz
  2. !!---------------------------------------------------------------------
  3. !! *** PROGRAM cdftransportiz ***
  4. !!
  5. !! ** Purpose: Compute Transports across a section
  6. !! PARTIAL STEPS version
  7. !!
  8. !! ** Method: Try to avoid 3 d arrays.
  9. !! The begining and end point of the section are given in term of f-points index.
  10. !! This program computes the transport across this section for
  11. !! (1) Mass transport ( Sv)
  12. !! (2) Heat Transport (PW)
  13. !! (3) Salt Transport (kT/sec)
  14. !! (4) Freshwater Transport (Sv)
  15. !! The transport is > 0 left handside of the line
  16. !! This program use a zig-zag line going through U and V-points.
  17. !! It takes as input : VT files, gridU, gridV files.
  18. !! The mesh_mask.nc, mesh_hzr.nc are required.
  19. !! It is convenient to use an ASCII file as the standard input to give
  20. !! the name and the ii0 ii1 ij0 ij1 for each section required
  21. !! The last name of this ASCII file must be EOF
  22. !!
  23. !!
  24. !! history :
  25. !! Original : J.M. Molines (jan. 2005)
  26. !! J.M. Molines Apr 2005 : use modules
  27. !! J.M. Molines Apr 2007 : merge with Julien Jouanno version (std + file output)
  28. !! R. Dussin (Jul. 2009) : add cdf output
  29. !!---------------------------------------------------------------------
  30. !! $Rev: 257 $
  31. !! $Date: 2009-07-27 18:25:04 +0200 (Mon, 27 Jul 2009) $
  32. !! $Id: cdftransportiz.f90 257 2009-07-27 16:25:04Z forge $
  33. !!--------------------------------------------------------------
  34. !! * Modules used
  35. USE netcdf
  36. USE cdfio
  37. USE io_ezcdf
  38. IMPLICIT NONE
  39. REAL(8) :: &
  40. & ref_temp0 = 0., & ! reference temperature (in Celsius) for the transport of heat
  41. & ref_sali0 = 34.8, & ! reference salinity (in PSU) for the transport of salt
  42. & ref_temp, ref_sali, &
  43. & rU, rV
  44. CHARACTER(len=128) :: ctest, c0, c1, c2, cref1='0.', cref2='34.8'
  45. CHARACTER(len=256) :: cf_sections
  46. LOGICAL, PARAMETER :: l_save_broken_lines = .FALSE.
  47. INTEGER :: nclass !: number of depth class
  48. INTEGER ,DIMENSION (:),ALLOCATABLE :: imeter !: limit beetween depth level, in m (nclass -1)
  49. CHARACTER(len=64), DIMENSION (:),ALLOCATABLE :: cdepths
  50. INTEGER ,DIMENSION (:),ALLOCATABLE :: ilev0,ilev1 !: limit in levels ! nclass
  51. INTEGER :: jk, jc, jj, jt !: dummy loop index !LB
  52. INTEGER :: narg, iargc, istatus !: command line
  53. INTEGER :: npiglo,npjglo, npk, nt !: size of the domain !LB
  54. INTEGER :: ii0, ii1, ij0, ij1, ik, ispace
  55. INTEGER :: numin = 16
  56. INTEGER(KIND=4) :: idirx, idiry ! sense of description of the section
  57. ! broken line stuff
  58. INTEGER, PARAMETER :: jpseg=10000
  59. INTEGER :: i, j
  60. INTEGER :: n,nn,k, jseg
  61. INTEGER :: norm_u, norm_v, iist, ijst
  62. REAL(4) :: rxi0,ryj0, rxi1, ryj1
  63. REAL(4) :: ai,bi, aj,bj,d
  64. REAL(4) :: rxx(jpseg),ryy(jpseg)
  65. REAL(4), DIMENSION(jpseg) :: gla, gphi
  66. REAL(8), DIMENSION(jpseg) :: voltrp, heatrp, saltrp
  67. REAL(8) :: voltrpsum, heatrpsum, saltrpsum, frwtrpsum
  68. COMPLEX yypt(jpseg), yypti
  69. REAL(4), DIMENSION (:,:), ALLOCATABLE :: e1v, e3v ,gphiv, zv, zvt, zvs !: mask, metrics
  70. REAL(4), DIMENSION (:,:), ALLOCATABLE :: e2u, e3u ,gphiu, zu, zut, zus !: mask, metrics
  71. REAL(4), DIMENSION (:,:), ALLOCATABLE :: glamu, glamv
  72. REAL(4), DIMENSION (:), ALLOCATABLE :: gdepw, gdept
  73. REAL(4) :: rd1, rd2
  74. REAL(8), DIMENSION (:,:), ALLOCATABLE :: zwku,zwkv, zwkut,zwkvt, zwkus,zwkvs
  75. REAL(8), DIMENSION (:,:,:), ALLOCATABLE :: ztrpu, ztrpv, ztrput,ztrpvt, ztrpus,ztrpvs
  76. CHARACTER(LEN=256) :: conf_tag, cf_vt , cf_u, cf_v, csection, cf_broken_line, &
  77. & cfilvtrp='vtrp.txt', cfilhtrp='htrp.txt', cfilstrp='strp.txt'
  78. CHARACTER(LEN=256) :: cf_mm='mesh_mask.nc', cdum
  79. CHARACTER(LEN=256) ,DIMENSION(4) :: cvarname !: array of var name for output
  80. INTEGER :: nxtarg
  81. LOGICAL :: &
  82. & leiv = .TRUE., & !: weather to use Eddy Induced velocity from GM90
  83. & lcontinue = .TRUE.
  84. CHARACTER(LEN=256) :: ctim
  85. ! constants
  86. !lolo: # The density of seawater is about 1025 kg/m^3 and the specific heat is about 4000 J/(kg C)
  87. REAL(4) :: rau0=1025., rcp=3990.
  88. REAL(4), DIMENSION(:,:,:), ALLOCATABLE :: U_3D, V_3D, UEIV_3D, VEIV_3D, UT_3D, VT_3D, US_3D, VS_3D, E3V_3D, E3U_3D
  89. INTEGER :: idf_u=0, idv_u=0, idf_v=0, idv_v=0, idf_ueiv=0, idv_ueiv=0, idf_veiv=0, idv_veiv=0, &
  90. & idf_ut=0, idv_ut=0, idf_vt=0, idv_vt=0, &
  91. & idf_us=0, idv_us=0, idf_vs=0, idv_vs=0, idf_0=0, idv_0=0
  92. LOGICAL :: lfncout = .false.
  93. CHARACTER(LEN=256) :: cd_out = '.', cf_out
  94. CHARACTER(LEN=64) :: cv_u, cv_v, cv_ueiv, cv_veiv, cv_dum
  95. REAL :: ryear
  96. INTEGER :: ierr, jt_pos, idf_out, idd_t, idv_time
  97. INTEGER, DIMENSION(:) , ALLOCATABLE :: id_volu, id_heat, id_salt, id_frwt
  98. REAL(4), DIMENSION(:,:,:), ALLOCATABLE :: X_trsp ! lolo
  99. !! Read command line and output usage message if not compliant.
  100. narg= iargc()
  101. IF ( narg < 8 ) THEN
  102. PRINT *,' Usage: cdftransportiz <file_section_ASCII> <CONFTAG> <nameU> <nameV> \\'
  103. PRINT *,' <nameUeiv> <nameVeiv> <year> <DIROUT> (<z1> <z2>)'
  104. PRINT *,''
  105. PRINT *,' => files are: <CONFTAG>_VT.nc <CONFTAG>_grid_U.nc <CONFTAG>_grid_V.nc'
  106. PRINT *,' If eddy-induced velocity is not relevant, specify "0" "0" for <nameUeiv> <nameVeiv>'
  107. PRINT *,' Files mesh_mask.nc must be in te current directory'
  108. PRINT *, ''
  109. PRINT *,' In your transportiz.dat, you can specify the reference temperature and salinity to use'
  110. PRINT *,' to compute transports (defaults are 0. deg.C and 34.8 PSU).'
  111. PRINT *,' below the line with i,j coordinates, specify "ref_temp_sali: T0 S0". Ex:'
  112. PRINT *,'FRAM-STRAIT'
  113. PRINT *,'279 268 272 272'
  114. PRINT *,'ref_temp_sali: -0.5 35.'
  115. PRINT *,'...'
  116. PRINT *,''
  117. STOP
  118. ENDIF
  119. CALL getarg (1, cf_sections)
  120. CALL getarg (2, conf_tag)
  121. CALL getarg (3, cv_u)
  122. CALL getarg (4, cv_v)
  123. CALL getarg (5, cv_ueiv)
  124. CALL getarg (6, cv_veiv)
  125. CALL getarg (7, cdum) ; READ(cdum,*) ryear
  126. CALL getarg (8, cd_out)
  127. nxtarg=8
  128. nclass = narg -nxtarg + 1
  129. leiv = .TRUE.
  130. IF ( (trim(cv_ueiv) == '0').AND.(trim(cv_veiv) == '0') ) THEN
  131. leiv = .FALSE.
  132. PRINT *, ' Not taking eddy-induced velocity into account!'
  133. ELSE
  134. PRINT *, ' Taking eddy-induced velocity into account using '//trim(cv_ueiv)//' and '//trim(cv_veiv)
  135. END IF
  136. WRITE(cf_vt, '(a,"_VT.nc")') trim(conf_tag)
  137. WRITE(cf_u, '(a,"_grid_U.nc")') trim(conf_tag)
  138. WRITE(cf_v, '(a,"_grid_V.nc")') trim(conf_tag)
  139. ALLOCATE ( cdepths(0:nclass), imeter(nclass -1), ilev0(nclass), ilev1(nclass) )
  140. cdepths(0) = '0'
  141. cdepths(nclass) = 'botto'
  142. DO jk=1, nclass -1
  143. CALL getarg(nxtarg+jk,cdepths(jk))
  144. READ(cdepths(jk),*) imeter(jk)
  145. END DO
  146. npiglo= getdim (cf_vt,'x')
  147. npjglo= getdim (cf_vt,'y')
  148. npk = getdim (cf_vt,'depth')
  149. ctim = 'none'
  150. nt = getdim (cf_vt,'time',cdtrue=ctim,kstatus=istatus) !LB
  151. PRINT *, 'npiglo=', npiglo
  152. PRINT *, 'npjglo=', npjglo
  153. PRINT *, 'npk =', npk
  154. PRINT *, 'nt =', nt !LB
  155. PRINT *, ''
  156. ALLOCATE( U_3D(npiglo,npjglo,npk) , V_3D(npiglo,npjglo,npk) , UT_3D(npiglo,npjglo,npk) , VT_3D(npiglo,npjglo,npk) , &
  157. & US_3D(npiglo,npjglo,npk) , VS_3D(npiglo,npjglo,npk), E3V_3D(npiglo,npjglo,npk) , E3U_3D(npiglo,npjglo,npk) )
  158. IF ( leiv ) ALLOCATE( UEIV_3D(npiglo,npjglo,npk) , VEIV_3D(npiglo,npjglo,npk) )
  159. !! Lolo: allocating array to contain transports:
  160. ALLOCATE( X_trsp(4,nt,nclass) ) ; ! 3 transports, nt values, nclass levels
  161. ALLOCATE( id_volu(0:nclass), id_heat(0:nclass), id_salt(0:nclass), id_frwt(0:nclass) )
  162. ! Allocate arrays
  163. ALLOCATE( zu (npiglo,npjglo), zut(npiglo,npjglo), zus(npiglo,npjglo) )
  164. ALLOCATE( zv (npiglo,npjglo), zvt(npiglo,npjglo), zvs(npiglo,npjglo) )
  165. !
  166. ALLOCATE ( zwku (npiglo,npjglo), zwkut(npiglo,npjglo), zwkus(npiglo,npjglo) )
  167. ALLOCATE ( zwkv (npiglo,npjglo), zwkvt(npiglo,npjglo), zwkvs(npiglo,npjglo) )
  168. !
  169. ALLOCATE ( ztrpu (npiglo,npjglo,nclass), ztrpv (npiglo,npjglo,nclass))
  170. ALLOCATE ( ztrput(npiglo,npjglo,nclass), ztrpvt(npiglo,npjglo,nclass))
  171. ALLOCATE ( ztrpus(npiglo,npjglo,nclass), ztrpvs(npiglo,npjglo,nclass))
  172. !
  173. ALLOCATE ( e1v(npiglo,npjglo),e3v(npiglo,npjglo))
  174. ALLOCATE ( e2u(npiglo,npjglo),e3u(npiglo,npjglo))
  175. !
  176. ALLOCATE ( gphiu(npiglo,npjglo), gphiv(npiglo,npjglo) )
  177. ALLOCATE ( glamu(npiglo,npjglo), glamv(npiglo,npjglo) )
  178. ALLOCATE ( gdepw(npk), gdept(npk) )
  179. !
  180. e1v(:,:) = getvar(cf_mm, 'e1v', 1,npiglo,npjglo)
  181. e2u(:,:) = getvar(cf_mm, 'e2u', 1,npiglo,npjglo)
  182. glamv(:,:) = getvar(cf_mm, 'glamv', 1,npiglo,npjglo)
  183. glamu(:,:) = getvar(cf_mm, 'glamu', 1,npiglo,npjglo)
  184. gphiv(:,:) = getvar(cf_mm, 'gphiv', 1,npiglo,npjglo)
  185. gphiu(:,:) = getvar(cf_mm, 'gphiu', 1,npiglo,npjglo)
  186. gdepw(:) = getvare3(cf_mm, 'gdepw_1d',npk)
  187. gdept(:) = getvare3(cf_mm, 'gdept_1d',npk)
  188. DO WHILE ( lcontinue )
  189. OPEN(numin, FILE=TRIM(cf_sections), status='old')
  190. READ(numin,'(a)') csection
  191. IF (TRIM(csection) == 'EOF' ) THEN
  192. CLOSE(numin)
  193. lcontinue = .FALSE.
  194. EXIT
  195. END IF
  196. IF ( .NOT. lcontinue ) EXIT
  197. READ(numin,*) ii0, ii1, ij0, ij1
  198. WRITE(*,'(" *** Section = ",a," (",i4.4,", "i4.4,", "i4.4,", "i4.4,") ***")') TRIM(csection), ii0, ii1, ij0, ij1
  199. !PRINT*, ' =>', ii0, ii1, ij0, ij1
  200. !By defining the direction of the integration as
  201. idirx = SIGN(1,ii1-ii0) !positive to the east or if ii1=ii0
  202. idiry = SIGN(1,ij1-ij0) !positive to the north or if ij1=ij0
  203. !Then dS=(e2u*idiry,-e1v*idirx)
  204. !This will produce the following sign convention:
  205. ! West-to-est line (dx>0, dy=0)=> -My*dx (-ve for a northward flow)
  206. ! South-to-north (dy>0, dx=0)=> Mx*dy (+ve for an eastward flow)
  207. norm_u = idiry
  208. norm_v = -idirx
  209. ! Defaults:
  210. c1 = cref1 ; c2 = cref2
  211. ref_temp = ref_temp0 ; ref_sali = ref_sali0
  212. ! Should they be modified:
  213. READ(numin,'(a)') ctest
  214. IF (ctest(1:14) == 'ref_temp_sali:' ) THEN
  215. c0 = TRIM(ctest(14+2:))
  216. ispace = SCAN(TRIM(c0),' ')
  217. c1 = TRIM((c0(1:ispace-1)))
  218. c2 = TRIM((c0(ispace+1:)))
  219. READ(c1,*) ref_temp
  220. READ(c2,*) ref_sali
  221. ELSE
  222. BACKSPACE(numin)
  223. END IF
  224. PRINT *, ' => reference temperature and salinity:', REAL(ref_temp,4), REAL(ref_sali,4)
  225. ! get e3u, e3v at all levels
  226. CALL GETVAR_3D(idf_0, idv_0, cf_mm, 'e3v_0', 0, 0, E3V_3D)
  227. idf_0 = 0. ; idv_0 = 0.
  228. CALL GETVAR_3D(idf_0, idv_0, cf_mm, 'e3u_0', 0, 0, E3U_3D)
  229. DO jt = 1, nt !lolo
  230. !! -------------
  231. PRINT *, ' * [cdftransportiz] jt = ', jt, ' (', TRIM(csection),')'
  232. !! Reading 3D fields at time jt...
  233. CALL GETVAR_3D(idf_u, idv_u, cf_u, trim(cv_u), nt, jt, U_3D)
  234. CALL GETVAR_3D(idf_v, idv_v, cf_v, trim(cv_v), nt, jt, V_3D)
  235. IF ( leiv ) THEN
  236. CALL GETVAR_3D(idf_ueiv, idv_ueiv, cf_u, trim(cv_ueiv), nt, jt, UEIV_3D)
  237. CALL GETVAR_3D(idf_veiv, idv_veiv, cf_v, trim(cv_veiv), nt, jt, VEIV_3D)
  238. END IF
  239. CALL GETVAR_3D(idf_ut, idv_ut, cf_vt, 'vozout', nt, jt, UT_3D)
  240. CALL GETVAR_3D(idf_vt, idv_vt, cf_vt, 'vomevt', nt, jt, VT_3D)
  241. CALL GETVAR_3D(idf_us, idv_us, cf_vt, 'vozous', nt, jt, US_3D)
  242. CALL GETVAR_3D(idf_vs, idv_vs, cf_vt, 'vomevs', nt, jt, VS_3D)
  243. ! look for nearest level to imeter
  244. ik = 1
  245. ilev0(1) = 1
  246. ilev1(nclass) = npk-1
  247. DO jk = 1, nclass -1
  248. DO WHILE ( gdepw(ik) < imeter(jk) )
  249. ik = ik +1
  250. END DO
  251. rd1= ABS(gdepw(ik-1) - imeter(jk) )
  252. rd2= ABS(gdepw(ik) - imeter(jk) )
  253. IF ( rd2 < rd1 ) THEN
  254. ilev1(jk) = ik -1 ! t-levels
  255. ilev0(jk+1) = ik
  256. ELSE
  257. ilev1(jk) = ik -2 ! t-levels
  258. ilev0(jk+1) = ik -1
  259. END IF
  260. END DO
  261. !! compute the transport
  262. ztrpu (:,:,:)= 0
  263. ztrpv (:,:,:)= 0
  264. ztrput(:,:,:)= 0
  265. ztrpvt(:,:,:)= 0
  266. ztrpus(:,:,:)= 0
  267. ztrpvs(:,:,:)= 0
  268. DO jc = 1, nclass
  269. DO jk = ilev0(jc),ilev1(jc)
  270. ! Get velocities, temperature and salinity fluxes at jk
  271. zu (:,:) = U_3D(:,:,jk)
  272. zv (:,:) = V_3D(:,:,jk)
  273. IF ( leiv ) THEN
  274. zu(:,:) = zu(:,:) + UEIV_3D(:,:,jk)
  275. zv(:,:) = zv(:,:) + VEIV_3D(:,:,jk)
  276. END IF
  277. zut(:,:) = UT_3D(:,:,jk)
  278. zvt(:,:) = VT_3D(:,:,jk)
  279. zus(:,:) = US_3D(:,:,jk)
  280. zvs(:,:) = VS_3D(:,:,jk)
  281. e3v(:,:) = E3V_3D(:,:,jk)
  282. e3u(:,:) = E3U_3D(:,:,jk)
  283. zwku (:,:) = zu (:,:)*e2u(:,:)*e3u(:,:)
  284. zwkv (:,:) = zv (:,:)*e1v(:,:)*e3v(:,:)
  285. zwkut(:,:) = zut(:,:)*e2u(:,:)*e3u(:,:)
  286. zwkvt(:,:) = zvt(:,:)*e1v(:,:)*e3v(:,:)
  287. zwkus(:,:) = zus(:,:)*e2u(:,:)*e3u(:,:)
  288. zwkvs(:,:) = zvs(:,:)*e1v(:,:)*e3v(:,:)
  289. ! integrates vertically
  290. ztrpu (:,:,jc) = ztrpu (:,:,jc) + zwku (:,:)
  291. ztrpv (:,:,jc) = ztrpv (:,:,jc) + zwkv (:,:)
  292. ztrput(:,:,jc) = ztrput(:,:,jc) + zwkut(:,:) * rau0*rcp
  293. ztrpvt(:,:,jc) = ztrpvt(:,:,jc) + zwkvt(:,:) * rau0*rcp
  294. ztrpus(:,:,jc) = ztrpus(:,:,jc) + zwkus(:,:)
  295. ztrpvs(:,:,jc) = ztrpvs(:,:,jc) + zwkvs(:,:)
  296. END DO ! loop to next level
  297. END DO ! next class
  298. IF (jt == 1) THEN
  299. IF ( nclass > 3 ) THEN
  300. PRINT *, ' ERROR => cdftransportiz.f90 only supports 2 depths currently!!!'
  301. END IF
  302. !! Find the broken line between P1 (ii0,ij0) and P2 (ii1, ij1)
  303. !! ---------------------------------------------------------------
  304. ! ... Initialization
  305. !i0=ii0; j0=ij0; i1=ii1; j1=ij1
  306. rxi1=ii1; ryj1=ij1; rxi0=ii0; ryj0=ij0
  307. ! .. Compute equation: ryj = aj rxi + bj
  308. IF ( (rxi1 -rxi0) /= 0 ) THEN
  309. aj = (ryj1 - ryj0 ) / (rxi1 -rxi0)
  310. bj = ryj0 - aj * rxi0
  311. ELSE
  312. aj=10000.
  313. bj=0.
  314. END IF
  315. ! .. Compute equation: rxi = ai ryj + bi
  316. IF ( (ryj1 -ryj0) /= 0 ) THEN
  317. ai = (rxi1 - rxi0 ) / ( ryj1 -ryj0 )
  318. bi = rxi0 - ai * ryj0
  319. ELSE
  320. ai=10000.
  321. bi=0.
  322. END IF
  323. ! .. Compute the integer pathway:
  324. n=0
  325. ! .. Chose the strait line with the smallest slope
  326. IF (ABS(aj) <= 1 ) THEN
  327. ! ... Here, the best line is y(x)
  328. ! ... If ii1 < ii0 swap points and remember it has been swapped
  329. IF (ii1 < ii0 ) THEN
  330. i = ii0 ; j = ij0
  331. ii0 = ii1 ; ij0 = ij1
  332. ii1 = i ; ij1 = j
  333. END IF
  334. ! iist,ijst is the grid offset to pass from F point to either U/V point
  335. IF ( ij1 >= ij0 ) THEN ! line heading NE
  336. iist = 1 ; ijst = 1
  337. ELSE ! line heading SE
  338. iist = 1 ; ijst = 0
  339. END IF
  340. ! ... compute the nearest j point on the line crossing at i
  341. DO i=ii0,ii1
  342. n=n+1
  343. IF (n > jpseg) STOP 'n > jpseg !'
  344. j=NINT(aj*i + bj )
  345. yypt(n) = CMPLX(i,j)
  346. END DO
  347. ELSE
  348. ! ... Here, the best line is x(y)
  349. ! ... If ij1 < ij0 swap points and remember it has been swapped
  350. IF (ij1 < ij0 ) THEN
  351. i = ii0 ; j = ij0
  352. ii0 = ii1 ; ij0 = ij1
  353. ii1 = i ; ij1 = j
  354. END IF
  355. ! iist,ijst is the grid offset to pass from F point to either U/V point
  356. IF ( ii1 >= ii0 ) THEN
  357. iist = 1 ; ijst = 1
  358. ELSE
  359. iist = 0 ; ijst = 1
  360. END IF
  361. ! ... compute the nearest i point on the line crossing at j
  362. DO j=ij0,ij1
  363. n=n+1
  364. IF (n > jpseg) STOP 'n>jpseg !'
  365. i=NINT(ai*j + bi)
  366. yypt(n) = CMPLX(i,j)
  367. END DO
  368. END IF
  369. !!
  370. !! Look for intermediate points to be added.
  371. ! .. The final positions are saved in rxx,ryy
  372. rxx(1)=REAL(yypt(1))
  373. ryy(1)=IMAG(yypt(1))
  374. nn=1
  375. DO k=2,n
  376. ! .. distance between 2 neighbour points
  377. d=ABS(yypt(k)-yypt(k-1))
  378. ! .. intermediate points required if d > 1
  379. IF ( d > 1 ) THEN
  380. CALL interm_pt(yypt,k,ai,bi,aj,bj,yypti)
  381. nn=nn+1
  382. IF (nn > jpseg) STOP 'nn>jpseg !'
  383. rxx(nn)=REAL(yypti)
  384. ryy(nn)=IMAG(yypti)
  385. END IF
  386. nn=nn+1
  387. IF (nn > jpseg) STOP 'nn>jpseg !'
  388. rxx(nn)=REAL(yypt(k))
  389. ryy(nn)=IMAG(yypt(k))
  390. END DO
  391. IF ( l_save_broken_lines ) THEN
  392. !! LOLO: We want to save the Broken line in an ascci file for further use:
  393. WRITE(cf_broken_line,'("broken_line_",a,".dat")') trim(csection)
  394. OPEN(UNIT=19, FILE=trim(cf_broken_line), FORM='FORMATTED', RECL=256, STATUS='unknown')
  395. PRINT *, 'Saving broken line into file ', trim(cf_broken_line)
  396. WRITE(19,*)'# ji jj'
  397. DO jseg = 1, nn
  398. ii0=rxx(jseg)
  399. ij0=ryy(jseg)
  400. WRITE(19,*) ii0, ij0
  401. END DO
  402. CLOSE(19)
  403. PRINT *, ''
  404. END IF
  405. END IF !* IF ( jt == 1 )
  406. DO jc=1,nclass
  407. voltrpsum = 0.
  408. heatrpsum = 0.
  409. saltrpsum = 0.
  410. frwtrpsum = 0.
  411. DO jseg = 1, nn-1
  412. ii0=rxx(jseg)
  413. ij0=ryy(jseg)
  414. IF ( rxx(jseg) == rxx(jseg+1) ) THEN
  415. gla(jseg)=glamu(ii0,ij0+ijst) ; gphi(jseg)=gphiu(ii0,ij0+ijst)
  416. voltrp(jseg)= ztrpu (ii0,ij0+ijst,jc)*norm_u
  417. heatrp(jseg)= ztrput(ii0,ij0+ijst,jc)*norm_u
  418. saltrp(jseg)= ztrpus(ii0,ij0+ijst,jc)*norm_u
  419. ELSE IF ( ryy(jseg) == ryy(jseg+1) ) THEN
  420. gla(jseg)=glamv(ii0+iist,ij0) ; gphi(jseg)=gphiv(ii0+iist,ij0)
  421. voltrp(jseg)=ztrpv (ii0+iist,ij0,jc)*norm_v
  422. heatrp(jseg)=ztrpvt(ii0+iist,ij0,jc)*norm_v
  423. saltrp(jseg)=ztrpvs(ii0+iist,ij0,jc)*norm_v
  424. ELSE
  425. PRINT *,' ERROR :', rxx(jseg),ryy(jseg),rxx(jseg+1),ryy(jseg+1)
  426. END IF
  427. voltrpsum = voltrpsum+voltrp(jseg)
  428. heatrpsum = heatrpsum+heatrp(jseg)
  429. saltrpsum = saltrpsum+saltrp(jseg)
  430. END DO ! next segment
  431. frwtrpsum = voltrpsum - saltrpsum/ref_sali ! only valid if saltrpsum was calculated with a ref salinity of 0.!
  432. heatrpsum = heatrpsum - rau0*rcp*ref_temp*voltrpsum
  433. saltrpsum = saltrpsum - ref_sali*voltrpsum
  434. X_trsp(:,jt,jc) = (/ REAL(voltrpsum/1.e6,4), REAL(heatrpsum/1.e15,4), REAL(saltrpsum/1.e6,4), REAL(frwtrpsum/1.e6,4) /)
  435. END DO ! next class
  436. END DO ! loop on jt
  437. !! Time to create or append X_trsp into the netcdf file for current section
  438. !! -----------------------------------------------------
  439. WRITE(cf_out, '(a,"/transport_sect_",a,".nc")') trim(cd_out), trim(csection)
  440. IF ( leiv ) WRITE(cf_out, '(a,"/transport_sect_",a,"_eiv.nc")') trim(cd_out), trim(csection)
  441. id_volu = 0 ; id_heat = 0 ; id_salt = 0 ; id_frwt = 0
  442. !! LOLO netcdf
  443. INQUIRE( FILE=cf_out, EXIST=lfncout )
  444. IF ( .NOT. lfncout ) THEN
  445. !! Creating file
  446. PRINT *, ' Creating file '//trim(cf_out)//' !!!'
  447. ierr = NF90_CREATE(cf_out, NF90_CLOBBER, idf_out)
  448. ierr = NF90_DEF_DIM(idf_out, 'time', NF90_UNLIMITED, idd_t)
  449. ierr = NF90_DEF_VAR(idf_out, 'time', NF90_DOUBLE, idd_t, idv_time)
  450. ierr = NF90_DEF_VAR(idf_out, 'trsp_volu', NF90_FLOAT, (/idd_t/), id_volu(0))
  451. ierr = NF90_DEF_VAR(idf_out, 'trsp_heat', NF90_FLOAT, (/idd_t/), id_heat(0))
  452. ierr = NF90_DEF_VAR(idf_out, 'trsp_salt', NF90_FLOAT, (/idd_t/), id_salt(0))
  453. ierr = NF90_DEF_VAR(idf_out, 'trsp_frwt', NF90_FLOAT, (/idd_t/), id_frwt(0))
  454. ierr = NF90_PUT_ATT(idf_out, id_volu(0), 'long_name', 'TOTAL: Transport of volume')
  455. ierr = NF90_PUT_ATT(idf_out, id_heat(0), 'long_name', 'TOTAL: Transport of heat')
  456. ierr = NF90_PUT_ATT(idf_out, id_salt(0), 'long_name', 'TOTAL: Transport of salt')
  457. ierr = NF90_PUT_ATT(idf_out, id_frwt(0), 'long_name', 'TOTAL: Transport of liquid freshwater')
  458. ierr = NF90_PUT_ATT(idf_out, id_volu(0), 'units', 'Sv')
  459. ierr = NF90_PUT_ATT(idf_out, id_heat(0), 'units', 'PW')
  460. ierr = NF90_PUT_ATT(idf_out, id_salt(0), 'units', 'kt/s')
  461. ierr = NF90_PUT_ATT(idf_out, id_frwt(0), 'units', 'Sv')
  462. ierr = NF90_PUT_ATT(idf_out, id_heat(0), 'Tref', c1)
  463. ierr = NF90_PUT_ATT(idf_out, id_salt(0), 'Sref', c2)
  464. ierr = NF90_PUT_ATT(idf_out, id_frwt(0), 'Sref', c2)
  465. IF ( nclass > 1 ) THEN
  466. DO jc = 1, nclass
  467. WRITE(cdum,'("_",i2.2)') jc ! suffix for variable_name
  468. ierr = NF90_DEF_VAR(idf_out, 'trsp_volu'//trim(cdum), NF90_FLOAT, (/idd_t/), id_volu(jc))
  469. ierr = NF90_DEF_VAR(idf_out, 'trsp_heat'//trim(cdum), NF90_FLOAT, (/idd_t/), id_heat(jc))
  470. ierr = NF90_DEF_VAR(idf_out, 'trsp_salt'//trim(cdum), NF90_FLOAT, (/idd_t/), id_salt(jc))
  471. ierr = NF90_DEF_VAR(idf_out, 'trsp_frwt'//trim(cdum), NF90_FLOAT, (/idd_t/), id_frwt(jc))
  472. WRITE(cdum,'(f7.2,"-",f7.2,"m (t-points)")') gdept(ilev0(jc)), gdept(ilev1(jc))
  473. ierr = NF90_PUT_ATT(idf_out, id_volu(jc), 'long_name', 'Transport of volume, '//trim(cdum))
  474. ierr = NF90_PUT_ATT(idf_out, id_heat(jc), 'long_name', 'Transport of heat, '//trim(cdum))
  475. ierr = NF90_PUT_ATT(idf_out, id_salt(jc), 'long_name', 'Transport of salt, '//trim(cdum))
  476. ierr = NF90_PUT_ATT(idf_out, id_frwt(jc), 'long_name', 'Transport of liquid freshwater, '//trim(cdum))
  477. ierr = NF90_PUT_ATT(idf_out, id_volu(jc), 'units', 'Sv')
  478. ierr = NF90_PUT_ATT(idf_out, id_heat(jc), 'units', 'PW')
  479. ierr = NF90_PUT_ATT(idf_out, id_salt(jc), 'units', 'kt/s')
  480. ierr = NF90_PUT_ATT(idf_out, id_frwt(jc), 'units', 'Sv')
  481. ierr = NF90_PUT_ATT(idf_out, id_heat(jc), 'Tref', c1)
  482. ierr = NF90_PUT_ATT(idf_out, id_salt(jc), 'Sref', c2)
  483. ierr = NF90_PUT_ATT(idf_out, id_frwt(jc), 'Sref', c2)
  484. END DO
  485. END IF
  486. ierr = NF90_PUT_ATT(idf_out, NF90_GLOBAL, &
  487. & 'Info1', 'Reference temperature for heat transport is '//TRIM(c1)//' deg.C')
  488. ierr = NF90_PUT_ATT(idf_out, NF90_GLOBAL, &
  489. & 'Info2', 'Reference salinity for salt and freshwater transports is '//TRIM(c2)//' PSU')
  490. ierr = NF90_PUT_ATT(idf_out, NF90_GLOBAL, 'About', &
  491. & 'Created by BaraKuda (cdftransportiz.f90) => https://github.com/brodeau/barakuda')
  492. ierr = NF90_ENDDEF(idf_out)
  493. jt_pos = 0
  494. ELSE
  495. !! Opening already existing file
  496. ierr = NF90_OPEN (cf_out, NF90_WRITE, idf_out)
  497. !! Need IDs of variables to append... NF90_INQ_VARID
  498. ierr = NF90_INQ_VARID(idf_out, 'trsp_volu', id_volu(0))
  499. ierr = NF90_INQ_VARID(idf_out, 'trsp_heat', id_heat(0))
  500. ierr = NF90_INQ_VARID(idf_out, 'trsp_salt', id_salt(0))
  501. ierr = NF90_INQ_VARID(idf_out, 'trsp_frwt', id_frwt(0))
  502. IF ( nclass > 1 ) THEN
  503. DO jc = 1, nclass
  504. WRITE(cdum,'("_",i2.2)') jc ! suffix for variable_name
  505. ierr = NF90_INQ_VARID(idf_out, 'trsp_volu'//trim(cdum), id_volu(jc))
  506. ierr = NF90_INQ_VARID(idf_out, 'trsp_heat'//trim(cdum), id_heat(jc))
  507. ierr = NF90_INQ_VARID(idf_out, 'trsp_salt'//trim(cdum), id_salt(jc))
  508. ierr = NF90_INQ_VARID(idf_out, 'trsp_frwt'//trim(cdum), id_frwt(jc))
  509. END DO
  510. END IF
  511. ! Get ID of unlimited dimension
  512. ierr = NF90_INQUIRE(idf_out, unlimitedDimId = idv_time)
  513. ! Need to know jt_pos, record number of the last time record writen in the file
  514. ierr = NF90_INQUIRE_DIMENSION(idf_out, idv_time, name=cv_dum, len=jt_pos)
  515. END IF
  516. WRITE(*,'("Going to write record ",i4.4," to ",i4.4," into ",a)') jt_pos+1, jt_pos+nt, trim(cf_out)
  517. DO jt = 1, nt
  518. ! Writing record jt for time vector and 1d fields:
  519. ierr = NF90_PUT_VAR( idf_out, idv_time, (/ryear+1./12.*(REAL(jt)-1.+0.5)/), start=(/jt_pos+jt/), count=(/1/) )
  520. IF ( nclass == 1 ) THEN
  521. !! Default variable is the only one present (index = 1) :
  522. ierr = NF90_PUT_VAR(idf_out, id_volu(0), (/ X_trsp(1,jt,1) /), start=(/jt_pos+jt/), count=(/1/))
  523. ierr = NF90_PUT_VAR(idf_out, id_heat(0), (/ X_trsp(2,jt,1) /), start=(/jt_pos+jt/), count=(/1/))
  524. ierr = NF90_PUT_VAR(idf_out, id_salt(0), (/ X_trsp(3,jt,1) /), start=(/jt_pos+jt/), count=(/1/))
  525. ierr = NF90_PUT_VAR(idf_out, id_frwt(0), (/ X_trsp(4,jt,1) /), start=(/jt_pos+jt/), count=(/1/))
  526. ELSE
  527. !! Default variable is the sum:
  528. ierr = NF90_PUT_VAR(idf_out, id_volu(0), (/ SUM(X_trsp(1,jt,:)) /), start=(/jt_pos+jt/), count=(/1/))
  529. ierr = NF90_PUT_VAR(idf_out, id_heat(0), (/ SUM(X_trsp(2,jt,:)) /), start=(/jt_pos+jt/), count=(/1/))
  530. ierr = NF90_PUT_VAR(idf_out, id_salt(0), (/ SUM(X_trsp(3,jt,:)) /), start=(/jt_pos+jt/), count=(/1/))
  531. ierr = NF90_PUT_VAR(idf_out, id_frwt(0), (/ SUM(X_trsp(4,jt,:)) /), start=(/jt_pos+jt/), count=(/1/))
  532. DO jc = 1, nclass
  533. ierr = NF90_PUT_VAR(idf_out, id_volu(jc), (/ X_trsp(1,jt,jc) /), start=(/jt_pos+jt/), count=(/1/))
  534. ierr = NF90_PUT_VAR(idf_out, id_heat(jc), (/ X_trsp(2,jt,jc) /), start=(/jt_pos+jt/), count=(/1/))
  535. ierr = NF90_PUT_VAR(idf_out, id_salt(jc), (/ X_trsp(3,jt,jc) /), start=(/jt_pos+jt/), count=(/1/))
  536. ierr = NF90_PUT_VAR(idf_out, id_frwt(jc), (/ X_trsp(4,jt,jc) /), start=(/jt_pos+jt/), count=(/1/))
  537. END DO
  538. END IF
  539. END DO
  540. ierr = NF90_CLOSE(idf_out)
  541. PRINT *, ''
  542. END DO ! loop on sections...
  543. DEALLOCATE( X_trsp ) !lolo
  544. CONTAINS
  545. SUBROUTINE interm_pt (ydpt,k,pai,pbi,paj,pbj,ydpti)
  546. !! -----------------------------------------------------
  547. !! SUBROUTINE INTERM_PT
  548. !! ********************
  549. !!
  550. !! PURPOSE:
  551. !! --------
  552. !! Find the best intermediate points on a pathway.
  553. !!
  554. !! ARGUMENTS:
  555. !! ----------
  556. !! ydpt : complex vector of the positions of the nearest points
  557. !! k : current working index
  558. !! pai ,pbi : slope and original ordinate of x(y)
  559. !! paj ,pbj : slope and original ordinate of y(x)
  560. !! ydpti : Complex holding the position of intermediate point
  561. !!
  562. !! AUTHOR:
  563. !! -------
  564. !! 19/07/1999 : Jean-Marc MOLINES
  565. !! 14/01/2005 : J M M in F90
  566. !!
  567. !!--------------------------------------------------------------
  568. !!
  569. !! 0. Declarations:
  570. !! ----------------
  571. IMPLICIT NONE
  572. COMPLEX, INTENT(in) :: ydpt(*)
  573. COMPLEX, INTENT(out) :: ydpti
  574. REAL(4), INTENT(IN) :: pai,pbi,paj,pbj
  575. INTEGER ,INTENT(in) :: k
  576. ! ... local
  577. COMPLEX :: ylptmp1, ylptmp2
  578. REAL(4) :: za0,zb0,za1,zb1,zd1,zd2
  579. REAL(4) :: zxm,zym
  580. REAL(4) :: zxp,zyp
  581. !!
  582. !! 1. Compute intermediate points
  583. !! ------------------------------
  584. !
  585. ! ... Determines whether we use y(x) or x(y):
  586. IF (ABS(paj) <= 1) THEN
  587. ! ..... y(x)
  588. ! ... possible intermediate points:
  589. ylptmp1=ydpt(k-1)+(1.,0.)
  590. ylptmp2=ydpt(k-1)+CMPLX(0.,SIGN(1.,paj))
  591. !
  592. ! ... M is the candidate point:
  593. zxm=REAL(ylptmp1)
  594. zym=IMAG(ylptmp1)
  595. za0=paj
  596. zb0=pbj
  597. !
  598. za1=-1./za0
  599. zb1=zym - za1*zxm
  600. ! ... P is the projection of M on the strait line
  601. zxp=-(zb1-zb0)/(za1-za0)
  602. zyp=za0*zxp + zb0
  603. ! ... zd1 is the distance MP
  604. zd1=(zxm-zxp)*(zxm-zxp) + (zym-zyp)*(zym-zyp)
  605. !
  606. ! ... M is the candidate point:
  607. zxm=REAL(ylptmp2)
  608. zym=IMAG(ylptmp2)
  609. za1=-1./za0
  610. zb1=zym - za1*zxm
  611. ! ... P is the projection of M on the strait line
  612. zxp=-(zb1-zb0)/(za1-za0)
  613. zyp=za0*zxp + zb0
  614. ! ... zd2 is the distance MP
  615. zd2=(zxm-zxp)*(zxm-zxp) + (zym-zyp)*(zym-zyp)
  616. ! ... chose the smallest (zd1,zd2)
  617. IF (zd2 <= zd1) THEN
  618. ydpti=ylptmp2
  619. ELSE
  620. ydpti=ylptmp1
  621. END IF
  622. !
  623. ELSE
  624. !
  625. ! ... x(y)
  626. ylptmp1=ydpt(k-1)+CMPLX(SIGN(1.,pai),0.)
  627. ylptmp2=ydpt(k-1)+(0.,1.)
  628. zxm=REAL(ylptmp1)
  629. zym=IMAG(ylptmp1)
  630. za0=pai
  631. zb0=pbi
  632. !
  633. za1=-1./za0
  634. zb1=zxm - za1*zym
  635. zyp=-(zb1-zb0)/(za1-za0)
  636. zxp=za0*zyp + zb0
  637. zd1=(zxm-zxp)*(zxm-zxp) + (zym-zyp)*(zym-zyp)
  638. !
  639. zxm=REAL(ylptmp2)
  640. zym=IMAG(ylptmp2)
  641. za1=-1./za0
  642. zb1=zxm - za1*zym
  643. zyp=-(zb1-zb0)/(za1-za0)
  644. zxp=za0*zyp + zb0
  645. zd2=(zxm-zxp)*(zxm-zxp) + (zym-zyp)*(zym-zyp)
  646. IF (zd2 <= zd1) THEN
  647. ydpti=ylptmp2
  648. ELSE
  649. ydpti=ylptmp1
  650. END IF
  651. END IF
  652. END SUBROUTINE interm_pt
  653. END PROGRAM cdftransportiz