geo2ocean.f90 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. MODULE geo2ocean
  2. !!======================================================================
  3. !! *** MODULE geo2ocean ***
  4. !! Ocean mesh : ???
  5. !!======================================================================
  6. !! History : OPA ! 07-1996 (O. Marti) Original code
  7. !! NEMO 1.0 ! 02-2008 (G. Madec) F90: Free form
  8. !! 3.0 !
  9. !!----------------------------------------------------------------------
  10. !!----------------------------------------------------------------------
  11. !! repcmo :
  12. !! angle :
  13. !! geo2oce :
  14. !!----------------------------------------------------------------------
  15. USE dom_oce ! mesh and scale factors
  16. USE phycst ! physical constants
  17. USE par_kind ! precision
  18. USE lbclnk
  19. IMPLICIT NONE
  20. PRIVATE
  21. PUBLIC rot_rep
  22. REAL(wp), DIMENSION(jpi,jpj) :: &
  23. gsint, gcost, & ! cos/sin between model grid lines and NP direction at T point
  24. gsinu, gcosu, & ! cos/sin between model grid lines and NP direction at U point
  25. gsinv, gcosv, & ! cos/sin between model grid lines and NP direction at V point
  26. gsinf, gcosf ! cos/sin between model grid lines and NP direction at F point
  27. LOGICAL :: lmust_init = .TRUE. !: used to initialize the cos/sin variables (se above)
  28. !! * Substitutions
  29. !!----------------------------------------------------------------------
  30. !! NEMO/OPA 3.0 , LOCEAN-IPSL (2008)
  31. !! $Id: geo2ocean.F90 1833 2010-04-13 17:44:52Z smasson $
  32. !! Software governed by the CeCILL licence (modipsl/doc/NEMO_CeCILL.txt)
  33. !!----------------------------------------------------------------------
  34. CONTAINS
  35. SUBROUTINE rot_rep ( pxin, pyin, cd_type, cdtodo, prot )
  36. !!----------------------------------------------------------------------
  37. !! *** ROUTINE rot_rep ***
  38. !!
  39. !! ** Purpose : Rotate the Repere: Change vector componantes between
  40. !! geographic grid <--> stretched coordinates grid.
  41. !!
  42. !! History :
  43. !! 9.2 ! 07-04 (S. Masson)
  44. !! (O. Marti ) Original code (repere and repcmo)
  45. !!----------------------------------------------------------------------
  46. REAL(wp), DIMENSION(jpi,jpj), INTENT( IN ) :: pxin, pyin ! vector componantes
  47. CHARACTER(len=1), INTENT( IN ) :: cd_type ! define the nature of pt2d array grid-points
  48. CHARACTER(len=5), INTENT( IN ) :: cdtodo ! specify the work to do:
  49. !! ! 'en->i' east-north componantes to model i componante
  50. !! ! 'en->j' east-north componantes to model j componante
  51. !! ! 'ij->e' model i-j componantes to east componante
  52. !! ! 'ij->n' model i-j componantes to east componante
  53. REAL(wp), DIMENSION(jpi,jpj), INTENT(out) :: prot
  54. !!----------------------------------------------------------------------
  55. ! Initialization of gsin* and gcos* at first call
  56. ! -----------------------------------------------
  57. IF( lmust_init ) THEN
  58. CALL angle ! initialization of the transformation
  59. lmust_init = .FALSE.
  60. ENDIF
  61. SELECT CASE (cdtodo)
  62. CASE ('en->i') ! 'en->i' est-north componantes to model i componante
  63. SELECT CASE (cd_type)
  64. CASE ('T') ; prot(:,:) = pxin(:,:) * gcost(:,:) + pyin(:,:) * gsint(:,:)
  65. CASE ('U') ; prot(:,:) = pxin(:,:) * gcosu(:,:) + pyin(:,:) * gsinu(:,:)
  66. CASE ('V') ; prot(:,:) = pxin(:,:) * gcosv(:,:) + pyin(:,:) * gsinv(:,:)
  67. CASE ('F') ; prot(:,:) = pxin(:,:) * gcosf(:,:) + pyin(:,:) * gsinf(:,:)
  68. CASE DEFAULT ; STOP 'Only T, U, V and F grid points are coded'
  69. END SELECT
  70. CASE ('en->j') ! 'en->j' est-north componantes to model j componante
  71. SELECT CASE (cd_type)
  72. CASE ('T') ; prot(:,:) = pyin(:,:) * gcost(:,:) - pxin(:,:) * gsint(:,:)
  73. CASE ('U') ; prot(:,:) = pyin(:,:) * gcosu(:,:) - pxin(:,:) * gsinu(:,:)
  74. CASE ('V') ; prot(:,:) = pyin(:,:) * gcosv(:,:) - pxin(:,:) * gsinv(:,:)
  75. CASE ('F') ; prot(:,:) = pyin(:,:) * gcosf(:,:) - pxin(:,:) * gsinf(:,:)
  76. CASE DEFAULT ; STOP 'Only T, U, V and F grid points are coded'
  77. END SELECT
  78. CASE ('ij->e') ! 'ij->e' model i-j componantes to est componante
  79. SELECT CASE (cd_type)
  80. CASE ('T') ; prot(:,:) = pxin(:,:) * gcost(:,:) - pyin(:,:) * gsint(:,:)
  81. CASE ('U') ; prot(:,:) = pxin(:,:) * gcosu(:,:) - pyin(:,:) * gsinu(:,:)
  82. CASE ('V') ; prot(:,:) = pxin(:,:) * gcosv(:,:) - pyin(:,:) * gsinv(:,:)
  83. CASE ('F') ; prot(:,:) = pxin(:,:) * gcosf(:,:) - pyin(:,:) * gsinf(:,:)
  84. CASE DEFAULT ; STOP 'Only T, U, V and F grid points are coded'
  85. END SELECT
  86. CASE ('ij->n') ! 'ij->n' model i-j componantes to est componante
  87. SELECT CASE (cd_type)
  88. CASE ('T') ; prot(:,:) = pyin(:,:) * gcost(:,:) + pxin(:,:) * gsint(:,:)
  89. CASE ('U') ; prot(:,:) = pyin(:,:) * gcosu(:,:) + pxin(:,:) * gsinu(:,:)
  90. CASE ('V') ; prot(:,:) = pyin(:,:) * gcosv(:,:) + pxin(:,:) * gsinv(:,:)
  91. CASE ('F') ; prot(:,:) = pyin(:,:) * gcosf(:,:) + pxin(:,:) * gsinf(:,:)
  92. CASE DEFAULT ; STOP 'Only T, U, V and F grid points are coded'
  93. END SELECT
  94. CASE DEFAULT ; STOP 'rot_rep: Syntax Error in the definition of cdtodo'
  95. END SELECT
  96. END SUBROUTINE rot_rep
  97. SUBROUTINE angle
  98. !!----------------------------------------------------------------------
  99. !! *** ROUTINE angle ***
  100. !!
  101. !! ** Purpose : Compute angles between model grid lines and the North direction
  102. !!
  103. !! ** Method :
  104. !!
  105. !! ** Action : Compute (gsint, gcost, gsinu, gcosu, gsinv, gcosv, gsinf, gcosf) arrays:
  106. !! sinus and cosinus of the angle between the north-south axe and the
  107. !! j-direction at t, u, v and f-points
  108. !!
  109. !! History :
  110. !! 7.0 ! 96-07 (O. Marti ) Original code
  111. !! 8.0 ! 98-06 (G. Madec )
  112. !! 8.5 ! 98-06 (G. Madec ) Free form, F90 + opt.
  113. !! 9.2 ! 07-04 (S. Masson) Add T, F points and bugfix in cos lateral boundary
  114. !!----------------------------------------------------------------------
  115. INTEGER :: ji, jj ! dummy loop indices
  116. !!
  117. REAL(wp) :: &
  118. zlam, zphi, & ! temporary scalars
  119. zlan, zphh, & ! " "
  120. zxnpt, zynpt, znnpt, & ! x,y components and norm of the vector: T point to North Pole
  121. zxnpu, zynpu, znnpu, & ! x,y components and norm of the vector: U point to North Pole
  122. zxnpv, zynpv, znnpv, & ! x,y components and norm of the vector: V point to North Pole
  123. zxnpf, zynpf, znnpf, & ! x,y components and norm of the vector: F point to North Pole
  124. zxvvt, zyvvt, znvvt, & ! x,y components and norm of the vector: between V points below and above a T point
  125. zxffu, zyffu, znffu, & ! x,y components and norm of the vector: between F points below and above a U point
  126. zxffv, zyffv, znffv, & ! x,y components and norm of the vector: between F points left and right a V point
  127. zxuuf, zyuuf, znuuf ! x,y components and norm of the vector: between U points below and above a F point
  128. !!----------------------------------------------------------------------
  129. ! ============================= !
  130. ! Compute the cosinus and sinus !
  131. ! ============================= !
  132. ! (computation done on the north stereographic polar plane)
  133. DO jj = 2, (jpj-1)
  134. !CDIR NOVERRCHK
  135. DO ji = 2, jpi ! vector opt.
  136. ! north pole direction & modulous (at t-point)
  137. zlam = glamt(ji,jj)
  138. zphi = gphit(ji,jj)
  139. zxnpt = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. )
  140. zynpt = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. )
  141. znnpt = zxnpt*zxnpt + zynpt*zynpt
  142. ! north pole direction & modulous (at u-point)
  143. zlam = glamu(ji,jj)
  144. zphi = gphiu(ji,jj)
  145. zxnpu = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. )
  146. zynpu = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. )
  147. znnpu = zxnpu*zxnpu + zynpu*zynpu
  148. ! north pole direction & modulous (at v-point)
  149. zlam = glamv(ji,jj)
  150. zphi = gphiv(ji,jj)
  151. zxnpv = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. )
  152. zynpv = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. )
  153. znnpv = zxnpv*zxnpv + zynpv*zynpv
  154. ! north pole direction & modulous (at f-point)
  155. zlam = glamf(ji,jj)
  156. zphi = gphif(ji,jj)
  157. zxnpf = 0. - 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. )
  158. zynpf = 0. - 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. )
  159. znnpf = zxnpf*zxnpf + zynpf*zynpf
  160. ! j-direction: v-point segment direction (around t-point)
  161. zlam = glamv(ji,jj )
  162. zphi = gphiv(ji,jj )
  163. zlan = glamv(ji,jj-1)
  164. zphh = gphiv(ji,jj-1)
  165. zxvvt = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) &
  166. & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. )
  167. zyvvt = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) &
  168. & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. )
  169. znvvt = SQRT( znnpt * ( zxvvt*zxvvt + zyvvt*zyvvt ) )
  170. znvvt = MAX( znvvt, 1.e-14 )
  171. ! j-direction: f-point segment direction (around u-point)
  172. zlam = glamf(ji,jj )
  173. zphi = gphif(ji,jj )
  174. zlan = glamf(ji,jj-1)
  175. zphh = gphif(ji,jj-1)
  176. zxffu = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) &
  177. & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. )
  178. zyffu = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) &
  179. & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. )
  180. znffu = SQRT( znnpu * ( zxffu*zxffu + zyffu*zyffu ) )
  181. znffu = MAX( znffu, 1.e-14 )
  182. ! i-direction: f-point segment direction (around v-point)
  183. zlam = glamf(ji ,jj)
  184. zphi = gphif(ji ,jj)
  185. zlan = glamf(ji-1,jj)
  186. zphh = gphif(ji-1,jj)
  187. zxffv = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) &
  188. & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. )
  189. zyffv = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) &
  190. & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. )
  191. znffv = SQRT( znnpv * ( zxffv*zxffv + zyffv*zyffv ) )
  192. znffv = MAX( znffv, 1.e-14 )
  193. ! j-direction: u-point segment direction (around f-point)
  194. zlam = glamu(ji,jj+1)
  195. zphi = gphiu(ji,jj+1)
  196. zlan = glamu(ji,jj )
  197. zphh = gphiu(ji,jj )
  198. zxuuf = 2. * COS( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) &
  199. & - 2. * COS( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. )
  200. zyuuf = 2. * SIN( rad*zlam ) * TAN( rpi/4. - rad*zphi/2. ) &
  201. & - 2. * SIN( rad*zlan ) * TAN( rpi/4. - rad*zphh/2. )
  202. znuuf = SQRT( znnpf * ( zxuuf*zxuuf + zyuuf*zyuuf ) )
  203. znuuf = MAX( znuuf, 1.e-14 )
  204. ! cosinus and sinus using scalar and vectorial products
  205. gsint(ji,jj) = ( zxnpt*zyvvt - zynpt*zxvvt ) / znvvt
  206. gcost(ji,jj) = ( zxnpt*zxvvt + zynpt*zyvvt ) / znvvt
  207. gsinu(ji,jj) = ( zxnpu*zyffu - zynpu*zxffu ) / znffu
  208. gcosu(ji,jj) = ( zxnpu*zxffu + zynpu*zyffu ) / znffu
  209. gsinf(ji,jj) = ( zxnpf*zyuuf - zynpf*zxuuf ) / znuuf
  210. gcosf(ji,jj) = ( zxnpf*zxuuf + zynpf*zyuuf ) / znuuf
  211. ! (caution, rotation of 90 degres)
  212. gsinv(ji,jj) = ( zxnpv*zxffv + zynpv*zyffv ) / znffv
  213. gcosv(ji,jj) =-( zxnpv*zyffv - zynpv*zxffv ) / znffv
  214. END DO
  215. END DO
  216. ! =============== !
  217. ! Geographic mesh !
  218. ! =============== !
  219. DO jj = 2, (jpj-1)
  220. DO ji = 2, jpi ! vector opt.
  221. IF( MOD( ABS( glamv(ji,jj) - glamv(ji,jj-1) ), 360. ) < 1.e-8 ) THEN
  222. gsint(ji,jj) = 0.
  223. gcost(ji,jj) = 1.
  224. ENDIF
  225. IF( MOD( ABS( glamf(ji,jj) - glamf(ji,jj-1) ), 360. ) < 1.e-8 ) THEN
  226. gsinu(ji,jj) = 0.
  227. gcosu(ji,jj) = 1.
  228. ENDIF
  229. IF( ABS( gphif(ji,jj) - gphif(ji-1,jj) ) < 1.e-8 ) THEN
  230. gsinv(ji,jj) = 0.
  231. gcosv(ji,jj) = 1.
  232. ENDIF
  233. IF( MOD( ABS( glamu(ji,jj) - glamu(ji,jj+1) ), 360. ) < 1.e-8 ) THEN
  234. gsinf(ji,jj) = 0.
  235. gcosf(ji,jj) = 1.
  236. ENDIF
  237. END DO
  238. END DO
  239. ! =========================== !
  240. ! Lateral boundary conditions !
  241. ! =========================== !
  242. ! lateral boundary cond.: T-, U-, V-, F-pts, sgn
  243. CALL lbc_lnk( gcost, 'T', -1._wp ) ; CALL lbc_lnk( gsint, 'T', -1._wp )
  244. CALL lbc_lnk( gcosu, 'U', -1._wp ) ; CALL lbc_lnk( gsinu, 'U', -1._wp )
  245. CALL lbc_lnk( gcosv, 'V', -1._wp ) ; CALL lbc_lnk( gsinv, 'V', -1._wp )
  246. CALL lbc_lnk( gcosf, 'F', -1._wp ) ; CALL lbc_lnk( gsinf, 'F', -1._wp )
  247. END SUBROUTINE angle
  248. END MODULE geo2ocean