flodom.F90 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. MODULE flodom
  2. !!======================================================================
  3. !! *** MODULE flodom ***
  4. !! Ocean floats : domain
  5. !!======================================================================
  6. !! History : OPA ! 1998-07 (Y.Drillet, CLIPPER) Original code
  7. !! NEMO_3.3.1 ! 2011-09 (C.Bricaud,S.Law-Chune Mercator-Ocean):
  8. ! add Ariane convention, Comsecitc changes
  9. !!----------------------------------------------------------------------
  10. #if defined key_floats || defined key_esopa
  11. !!----------------------------------------------------------------------
  12. !! 'key_floats' float trajectories
  13. !!----------------------------------------------------------------------
  14. !! flo_dom : initialization of floats
  15. !! add_new_floats : add new floats (long/lat/depth)
  16. !! add_new_ariane_floats : add new floats with araine convention (i/j/k)
  17. !! findmesh : compute index of position
  18. !! dstnce : compute distance between face mesh and floats
  19. !!----------------------------------------------------------------------
  20. USE oce ! ocean dynamics and tracers
  21. USE dom_oce ! ocean space and time domain
  22. USE flo_oce ! ocean drifting floats
  23. USE in_out_manager ! I/O manager
  24. USE lib_mpp ! distribued memory computing library
  25. IMPLICIT NONE
  26. PRIVATE
  27. PUBLIC flo_dom ! routine called by floats.F90
  28. PUBLIC flo_dom_alloc ! Routine called in floats.F90
  29. CHARACTER (len=21) :: clname1 = 'init_float' ! floats initialisation filename
  30. CHARACTER (len=21) :: clname2 = 'init_float_ariane' ! ariane floats initialisation filename
  31. INTEGER , ALLOCATABLE, DIMENSION(:) :: iimfl, ijmfl, ikmfl ! index mesh of floats
  32. INTEGER , ALLOCATABLE, DIMENSION(:) :: idomfl, ivtest, ihtest ! -
  33. REAL(wp), ALLOCATABLE, DIMENSION(:) :: zgifl, zgjfl, zgkfl ! distances in indexes
  34. !! * Substitutions
  35. # include "domzgr_substitute.h90"
  36. !!----------------------------------------------------------------------
  37. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  38. !! $Id: flodom.F90 3294 2012-01-28 16:44:18Z rblod $
  39. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  40. !!----------------------------------------------------------------------
  41. CONTAINS
  42. SUBROUTINE flo_dom
  43. !! ---------------------------------------------------------------------
  44. !! *** ROUTINE flo_dom ***
  45. !!
  46. !! ** Purpose : Initialisation of floats
  47. !!
  48. !! ** Method : We put the floats in the domain with the latitude,
  49. !! the longitude (degree) and the depth (m).
  50. !!----------------------------------------------------------------------
  51. INTEGER :: jfl ! dummy loop
  52. INTEGER :: inum ! logical unit for file read
  53. !!---------------------------------------------------------------------
  54. ! Initialisation with the geographical position or restart
  55. IF(lwp) WRITE(numout,*) 'flo_dom : compute initial position of floats'
  56. IF(lwp) WRITE(numout,*) '~~~~~~~~'
  57. IF(lwp) WRITE(numout,*) ' jpnfl = ',jpnfl
  58. !-------------------------!
  59. ! FLOAT RESTART FILE READ !
  60. !-------------------------!
  61. IF( ln_rstflo )THEN
  62. IF(lwp) WRITE(numout,*) ' float restart file read'
  63. ! open the restart file
  64. !----------------------
  65. CALL ctl_opn( inum, 'restart_float', 'OLD', 'FORMATTED', 'SEQUENTIAL', -1, numout, lwp )
  66. ! read of the restart file
  67. READ(inum,*) ( tpifl (jfl), jfl=1, jpnrstflo), &
  68. ( tpjfl (jfl), jfl=1, jpnrstflo), &
  69. ( tpkfl (jfl), jfl=1, jpnrstflo), &
  70. ( nisobfl(jfl), jfl=1, jpnrstflo), &
  71. ( ngrpfl (jfl), jfl=1, jpnrstflo)
  72. CLOSE(inum)
  73. ! if we want a surface drift ( like PROVOR floats )
  74. IF( ln_argo ) nisobfl(1:jpnrstflo) = 0
  75. ! It is possible to add new floats.
  76. !---------------------------------
  77. IF( jpnfl > jpnrstflo )THEN
  78. IF(lwp) WRITE(numout,*) ' add new floats'
  79. IF( ln_ariane )THEN !Add new floats with ariane convention
  80. CALL flo_add_new_ariane_floats(jpnrstflo+1,jpnfl)
  81. ELSE !Add new floats with long/lat convention
  82. CALL flo_add_new_floats(jpnrstflo+1,jpnfl)
  83. ENDIF
  84. ENDIF
  85. !--------------------------------------!
  86. ! FLOAT INITILISATION: NO RESTART FILE !
  87. !--------------------------------------!
  88. ELSE !ln_rstflo
  89. IF( ln_ariane )THEN !Add new floats with ariane convention
  90. CALL flo_add_new_ariane_floats(1,jpnfl)
  91. ELSE !Add new floats with long/lat convention
  92. CALL flo_add_new_floats(1,jpnfl)
  93. ENDIF
  94. ENDIF
  95. END SUBROUTINE flo_dom
  96. SUBROUTINE flo_add_new_floats(kfl_start, kfl_end)
  97. !! -------------------------------------------------------------
  98. !! *** SUBROUTINE add_new_arianefloats ***
  99. !!
  100. !! ** Purpose :
  101. !!
  102. !! First initialisation of floats
  103. !! the initials positions of floats are written in a file
  104. !! with a variable to know if it is a isobar float a number
  105. !! to identified who want the trajectories of this float and
  106. !! an index for the number of the float
  107. !! open the init file
  108. !!
  109. !! ** Method :
  110. !!----------------------------------------------------------------------
  111. INTEGER, INTENT(in) :: kfl_start, kfl_end
  112. !!
  113. INTEGER :: inum ! file unit
  114. INTEGER :: jfl,ji, jj, jk ! dummy loop indices
  115. INTEGER :: itrash ! trash var for reading
  116. INTEGER :: ifl ! number of floats to read
  117. REAL(wp) :: zdxab, zdyad
  118. LOGICAL :: llinmesh
  119. CHARACTER(len=80) :: cltmp
  120. !!---------------------------------------------------------------------
  121. ifl = kfl_end-kfl_start+1
  122. ! we get the init values
  123. !-----------------------
  124. CALL ctl_opn( inum , clname1, 'OLD', 'FORMATTED', 'SEQUENTIAL', -1, numout, lwp )
  125. DO jfl = kfl_start,kfl_end
  126. READ(inum,*) flxx(jfl),flyy(jfl),flzz(jfl), nisobfl(jfl),ngrpfl(jfl),itrash
  127. if(lwp)write(numout,*)'read:',jfl,flxx(jfl),flyy(jfl),flzz(jfl), nisobfl(jfl),ngrpfl(jfl),itrash ; call flush(numout)
  128. END DO
  129. CLOSE(inum)
  130. ! Test to find the grid point coordonate with the geographical position
  131. !----------------------------------------------------------------------
  132. DO jfl = kfl_start,kfl_end
  133. ihtest(jfl) = 0
  134. ivtest(jfl) = 0
  135. ikmfl(jfl) = 0
  136. # if defined key_mpp_mpi
  137. DO ji = MAX(nldi,2), nlei
  138. DO jj = MAX(nldj,2), nlej ! NO vector opt.
  139. # else
  140. DO ji = 2, jpi
  141. DO jj = 2, jpj ! NO vector opt.
  142. # endif
  143. ! For each float we find the indexes of the mesh
  144. CALL flo_findmesh(glamf(ji-1,jj-1),gphif(ji-1,jj-1), &
  145. glamf(ji-1,jj ),gphif(ji-1,jj ), &
  146. glamf(ji ,jj ),gphif(ji ,jj ), &
  147. glamf(ji ,jj-1),gphif(ji ,jj-1), &
  148. flxx(jfl) ,flyy(jfl) , &
  149. glamt(ji ,jj ),gphit(ji ,jj ), llinmesh)
  150. IF( llinmesh )THEN
  151. iimfl(jfl) = ji
  152. ijmfl(jfl) = jj
  153. ihtest(jfl) = ihtest(jfl)+1
  154. DO jk = 1, jpk-1
  155. IF( (fsdepw(ji,jj,jk) <= flzz(jfl)) .AND. (fsdepw(ji,jj,jk+1) > flzz(jfl)) ) THEN
  156. ikmfl(jfl) = jk
  157. ivtest(jfl) = ivtest(jfl) + 1
  158. ENDIF
  159. END DO
  160. ENDIF
  161. END DO
  162. END DO
  163. ! If the float is in a mesh computed by an other processor we put iimfl=ijmfl=-1
  164. IF( ihtest(jfl) == 0 ) THEN
  165. iimfl(jfl) = -1
  166. ijmfl(jfl) = -1
  167. ENDIF
  168. END DO
  169. !Test if each float is in one and only one proc
  170. !----------------------------------------------
  171. IF( lk_mpp ) THEN
  172. CALL mpp_sum(ihtest,jpnfl)
  173. CALL mpp_sum(ivtest,jpnfl)
  174. ENDIF
  175. DO jfl = kfl_start,kfl_end
  176. IF( (ihtest(jfl) > 1 ) .OR. ( ivtest(jfl) > 1) ) THEN
  177. WRITE(cltmp,'(A10,i4.4,A20)' )'THE FLOAT',jfl,' IS NOT IN ONLY ONE MESH'
  178. CALL ctl_stop('STOP',TRIM(cltmp) )
  179. ENDIF
  180. IF( (ihtest(jfl) == 0) ) THEN
  181. WRITE(cltmp,'(A10,i4.4,A20)' )'THE FLOAT',jfl,' IS IN NO MESH'
  182. CALL ctl_stop('STOP',TRIM(cltmp) )
  183. ENDIF
  184. END DO
  185. ! We compute the distance between the float and the face of the mesh
  186. !-------------------------------------------------------------------
  187. DO jfl = kfl_start,kfl_end
  188. ! Made only if the float is in the domain of the processor
  189. IF( (iimfl(jfl) >= 0) .AND. (ijmfl(jfl) >= 0) ) THEN
  190. ! TEST TO KNOW IF THE FLOAT IS NOT INITIALISED IN THE COAST
  191. idomfl(jfl) = 0
  192. IF( tmask(iimfl(jfl),ijmfl(jfl),ikmfl(jfl)) == 0. ) idomfl(jfl) = 1
  193. ! Computation of the distance between the float and the faces of the mesh
  194. ! zdxab
  195. ! .
  196. ! B----.---------C
  197. ! | . |
  198. ! |<------>flo |
  199. ! | ^ |
  200. ! | |.....|....zdyad
  201. ! | | |
  202. ! A--------|-----D
  203. !
  204. zdxab = flo_dstnce( flxx(jfl), flyy(jfl), glamf(iimfl(jfl)-1,ijmfl(jfl)-1), flyy(jfl) )
  205. zdyad = flo_dstnce( flxx(jfl), flyy(jfl), flxx(jfl), gphif(iimfl(jfl)-1,ijmfl(jfl)-1) )
  206. ! Translation of this distances (in meter) in indexes
  207. zgifl(jfl)= (iimfl(jfl)-0.5) + zdxab/e1u(iimfl(jfl)-1,ijmfl(jfl)) + (mig(1)-jpizoom)
  208. zgjfl(jfl)= (ijmfl(jfl)-0.5) + zdyad/e2v(iimfl(jfl),ijmfl(jfl)-1) + (mjg(1)-jpjzoom)
  209. zgkfl(jfl) = (( fsdepw(iimfl(jfl),ijmfl(jfl),ikmfl(jfl)+1) - flzz(jfl) )* ikmfl(jfl)) &
  210. & / ( fsdepw(iimfl(jfl),ijmfl(jfl),ikmfl(jfl)+1) &
  211. & - fsdepw(iimfl(jfl),ijmfl(jfl),ikmfl(jfl) ) ) &
  212. & + (( flzz(jfl)-fsdepw(iimfl(jfl),ijmfl(jfl),ikmfl(jfl)) ) *(ikmfl(jfl)+1)) &
  213. & / ( fsdepw(iimfl(jfl),ijmfl(jfl),ikmfl(jfl)+1) &
  214. & - fsdepw(iimfl(jfl),ijmfl(jfl),ikmfl(jfl)) )
  215. ELSE
  216. zgifl(jfl) = 0.e0
  217. zgjfl(jfl) = 0.e0
  218. zgkfl(jfl) = 0.e0
  219. ENDIF
  220. END DO
  221. ! The sum of all the arrays zgifl, zgjfl, zgkfl give 3 arrays with the positions of all the floats.
  222. IF( lk_mpp ) THEN
  223. CALL mpp_sum( zgjfl, ifl ) ! sums over the global domain
  224. CALL mpp_sum( zgkfl, ifl )
  225. ENDIF
  226. DO jfl = kfl_start,kfl_end
  227. tpifl(jfl) = zgifl(jfl)
  228. tpjfl(jfl) = zgjfl(jfl)
  229. tpkfl(jfl) = zgkfl(jfl)
  230. END DO
  231. ! WARNING : initial position not in the sea
  232. IF( .NOT. ln_rstflo ) THEN
  233. DO jfl = kfl_start,kfl_end
  234. IF( idomfl(jfl) == 1 ) THEN
  235. IF(lwp) WRITE(numout,*)'*****************************'
  236. IF(lwp) WRITE(numout,*)'!!!!!!! WARNING !!!!!!!!!!'
  237. IF(lwp) WRITE(numout,*)'*****************************'
  238. IF(lwp) WRITE(numout,*)'The float number',jfl,'is out of the sea.'
  239. IF(lwp) WRITE(numout,*)'geographical position',flxx(jfl),flyy(jfl),flzz(jfl)
  240. IF(lwp) WRITE(numout,*)'index position',tpifl(jfl),tpjfl(jfl),tpkfl(jfl)
  241. ENDIF
  242. END DO
  243. ENDIF
  244. END SUBROUTINE flo_add_new_floats
  245. SUBROUTINE flo_add_new_ariane_floats(kfl_start, kfl_end)
  246. !! -------------------------------------------------------------
  247. !! *** SUBROUTINE add_new_arianefloats ***
  248. !!
  249. !! ** Purpose :
  250. !! First initialisation of floats with ariane convention
  251. !!
  252. !! The indexes are read directly from file (warning ariane
  253. !! convention, are refered to
  254. !! U,V,W grids - and not T-)
  255. !! The isobar advection is managed with the sign of tpkfl ( >0 -> 3D
  256. !! advection, <0 -> 2D)
  257. !! Some variables are not read, as - gl : time index; 4th
  258. !! column
  259. !! - transport : transport ; 5th
  260. !! column
  261. !! and paste in the jtrash var
  262. !! At the end, ones need to replace the indexes on T grid
  263. !! RMQ : there is no float groups identification !
  264. !!
  265. !!
  266. !! ** Method :
  267. !!----------------------------------------------------------------------
  268. INTEGER, INTENT(in) :: kfl_start, kfl_end
  269. !!
  270. INTEGER :: inum ! file unit
  271. INTEGER :: ierr, ifl
  272. INTEGER :: jfl, jfl1 ! dummy loop indices
  273. INTEGER :: itrash ! trash var for reading
  274. CHARACTER(len=80) :: cltmp
  275. !!----------------------------------------------------------------------
  276. nisobfl(kfl_start:kfl_end) = 1 ! we assume that by default we want 3D advection
  277. ifl = kfl_end - kfl_start + 1 ! number of floats to read
  278. ! we check that the number of floats in the init_file are consistant with the namelist
  279. IF( lwp ) THEN
  280. jfl1=0
  281. ierr=0
  282. CALL ctl_opn( inum, clname2, 'OLD', 'FORMATTED', 'SEQUENTIAL', 1, numout, .TRUE., 1 )
  283. DO WHILE (ierr .EQ. 0)
  284. jfl1=jfl1+1
  285. READ(inum,*, iostat=ierr)
  286. END DO
  287. CLOSE(inum)
  288. IF( (jfl1-1) .NE. ifl )THEN
  289. WRITE(cltmp,'(A25,A20,A3,i4.4,A10,i4.4)')"the number of floats in ",TRIM(clname2), &
  290. " = ",jfl1," is not equal to jfl= ",ifl
  291. CALL ctl_stop('STOP',TRIM(cltmp) )
  292. ENDIF
  293. ENDIF
  294. ! we get the init values
  295. CALL ctl_opn( inum, clname2, 'OLD', 'FORMATTED', 'SEQUENTIAL', 1, numout, .TRUE., 1 )
  296. DO jfl = kfl_start, kfl_end
  297. READ(inum,*) tpifl(jfl),tpjfl(jfl),tpkfl(jfl),itrash, itrash
  298. IF ( tpkfl(jfl) .LT. 0. ) nisobfl(jfl) = 0 !set the 2D advection according to init_float
  299. ngrpfl(jfl)=jfl
  300. END DO
  301. ! conversion from ariane index to T grid index
  302. tpkfl(kfl_start:kfl_end) = abs(tpkfl)-0.5 ! reversed vertical axis
  303. tpifl(kfl_start:kfl_end) = tpifl+0.5
  304. tpjfl(kfl_start:kfl_end) = tpjfl+0.5
  305. END SUBROUTINE flo_add_new_ariane_floats
  306. SUBROUTINE flo_findmesh( pax, pay, pbx, pby, &
  307. pcx, pcy, pdx, pdy, &
  308. px ,py ,ptx, pty, ldinmesh )
  309. !! -------------------------------------------------------------
  310. !! *** ROUTINE findmesh ***
  311. !!
  312. !! ** Purpose : Find the index of mesh for the point spx spy
  313. !!
  314. !! ** Method :
  315. !!----------------------------------------------------------------------
  316. REAL(wp) :: &
  317. pax, pay, pbx, pby, & ! ???
  318. pcx, pcy, pdx, pdy, & ! ???
  319. px, py, & ! longitude and latitude
  320. ptx, pty ! ???
  321. LOGICAL :: ldinmesh ! ???
  322. !!
  323. REAL(wp) :: zabt, zbct, zcdt, zdat, zabpt, zbcpt, zcdpt, zdapt
  324. !!---------------------------------------------------------------------
  325. !! Statement function
  326. REAL(wp) :: fsline
  327. REAL(wp) :: psax, psay, psbx, psby, psx, psy
  328. fsline( psax, psay, psbx, psby, psx, psy ) = psy * ( psbx - psax ) &
  329. & - psx * ( psby - psay ) &
  330. & + psax * psby - psay * psbx
  331. !!---------------------------------------------------------------------
  332. ! 4 semi plane defined by the 4 points and including the T point
  333. zabt = fsline(pax,pay,pbx,pby,ptx,pty)
  334. zbct = fsline(pbx,pby,pcx,pcy,ptx,pty)
  335. zcdt = fsline(pcx,pcy,pdx,pdy,ptx,pty)
  336. zdat = fsline(pdx,pdy,pax,pay,ptx,pty)
  337. ! 4 semi plane defined by the 4 points and including the extrememity
  338. zabpt = fsline(pax,pay,pbx,pby,px,py)
  339. zbcpt = fsline(pbx,pby,pcx,pcy,px,py)
  340. zcdpt = fsline(pcx,pcy,pdx,pdy,px,py)
  341. zdapt = fsline(pdx,pdy,pax,pay,px,py)
  342. ! We compare the semi plane T with the semi plane including the point
  343. ! to know if it is in this mesh.
  344. ! For numerical reasons it is possible that for a point which is on
  345. ! the line we don't have exactly zero with fsline function. We want
  346. ! that a point can't be in 2 mesh in the same time, so we put the
  347. ! coefficient to zero if it is smaller than 1.E-12
  348. IF( ABS(zabpt) <= 1.E-12 ) zabpt = 0.
  349. IF( ABS(zbcpt) <= 1.E-12 ) zbcpt = 0.
  350. IF( ABS(zcdpt) <= 1.E-12 ) zcdpt = 0.
  351. IF( ABS(zdapt) <= 1.E-12 ) zdapt = 0.
  352. IF( (zabt*zabpt > 0.) .AND. (zbct*zbcpt >= 0. ) .AND. ( zcdt*zcdpt >= 0. ) .AND. ( zdat*zdapt > 0. ) &
  353. .AND. ( px <= MAX(pcx,pdx) ) .AND. ( px >= MIN(pax,pbx) ) &
  354. .AND. ( py <= MAX(pby,pcy) ) .AND. ( py >= MIN(pay,pdy) ) ) THEN
  355. ldinmesh=.TRUE.
  356. ELSE
  357. ldinmesh=.FALSE.
  358. ENDIF
  359. !
  360. END SUBROUTINE flo_findmesh
  361. FUNCTION flo_dstnce( pla1, phi1, pla2, phi2 )
  362. !! -------------------------------------------------------------
  363. !! *** Function dstnce ***
  364. !!
  365. !! ** Purpose : returns distance (in m) between two geographical
  366. !! points
  367. !! ** Method :
  368. !!----------------------------------------------------------------------
  369. REAL(wp), INTENT(in) :: pla1, phi1, pla2, phi2 ! ???
  370. !!
  371. REAL(wp) :: dly1, dly2, dlx1, dlx2, dlx, dls, dld, dpi
  372. REAL(wp) :: flo_dstnce
  373. !!---------------------------------------------------------------------
  374. !
  375. dpi = 2._wp * ASIN(1._wp)
  376. dls = dpi / 180._wp
  377. dly1 = phi1 * dls
  378. dly2 = phi2 * dls
  379. dlx1 = pla1 * dls
  380. dlx2 = pla2 * dls
  381. !
  382. dlx = SIN(dly1) * SIN(dly2) + COS(dly1) * COS(dly2) * COS(dlx2-dlx1)
  383. !
  384. IF( ABS(dlx) > 1.0_wp ) dlx = 1.0_wp
  385. !
  386. dld = ATAN(DSQRT( 1._wp * ( 1._wp-dlx )/( 1._wp+dlx ) )) * 222.24_wp / dls
  387. flo_dstnce = dld * 1000._wp
  388. !
  389. END FUNCTION flo_dstnce
  390. INTEGER FUNCTION flo_dom_alloc()
  391. !!----------------------------------------------------------------------
  392. !! *** FUNCTION flo_dom_alloc ***
  393. !!----------------------------------------------------------------------
  394. ALLOCATE( iimfl(jpnfl) , ijmfl(jpnfl) , ikmfl(jpnfl) , &
  395. idomfl(jpnfl), ivtest(jpnfl), ihtest(jpnfl), &
  396. zgifl(jpnfl) , zgjfl(jpnfl) , zgkfl(jpnfl) , STAT=flo_dom_alloc )
  397. !
  398. IF( lk_mpp ) CALL mpp_sum ( flo_dom_alloc )
  399. IF( flo_dom_alloc /= 0 ) CALL ctl_warn('flo_dom_alloc: failed to allocate arrays')
  400. END FUNCTION flo_dom_alloc
  401. #else
  402. !!----------------------------------------------------------------------
  403. !! Default option Empty module
  404. !!----------------------------------------------------------------------
  405. CONTAINS
  406. SUBROUTINE flo_dom ! Empty routine
  407. WRITE(*,*) 'flo_dom: : You should not have seen this print! error?'
  408. END SUBROUTINE flo_dom
  409. #endif
  410. !!======================================================================
  411. END MODULE flodom