coast_dist.F90 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. MODULE coastdist
  2. USE utils
  3. USE netcdf
  4. IMPLICIT NONE
  5. PUBLIC
  6. CONTAINS
  7. SUBROUTINE coast_dist_weight( presto )
  8. !!----------------------------------------------------------------------
  9. !! *** ROUTINE coast_dist_weight ***
  10. !!
  11. !! ** Purpose: Weight restoration coefficient by distance to coast
  12. !!
  13. !! ** Method: 1) Calculate distance to coast
  14. !! 2) Reduce resto with 1000km of coast
  15. !!
  16. IMPLICIT NONE
  17. REAL(wp), DIMENSION(jpi,jpj), INTENT( inout ) :: presto
  18. REAL(wp), DIMENSION(jpi,jpj) :: zdct
  19. REAL(wp) :: zinfl = 1000.e3_wp ! Distance of influence of coast line (could be
  20. ! a namelist setting)
  21. INTEGER :: jj, ji ! dummy loop indices
  22. CALL cofdis( zdct )
  23. DO jj = 1, jpj
  24. DO ji = 1, jpi
  25. zdct(ji,jj) = MIN( zinfl, zdct(ji,jj) )
  26. presto(ji,jj) = presto(ji, jj) * 0.5_wp * ( 1._wp - COS( rpi*zdct(ji,jj)/zinfl) )
  27. END DO
  28. END DO
  29. END SUBROUTINE coast_dist_weight
  30. SUBROUTINE cofdis( pdct )
  31. !!----------------------------------------------------------------------
  32. !! *** ROUTINE cofdis ***
  33. !!
  34. !! ** Purpose : Compute the distance between ocean T-points and the
  35. !! ocean model coastlines.
  36. !!
  37. !! ** Method : For each model level, the distance-to-coast is
  38. !! computed as follows :
  39. !! - The coastline is defined as the serie of U-,V-,F-points
  40. !! that are at the ocean-land bound.
  41. !! - For each ocean T-point, the distance-to-coast is then
  42. !! computed as the smallest distance (on the sphere) between the
  43. !! T-point and all the coastline points.
  44. !! - For land T-points, the distance-to-coast is set to zero.
  45. !!
  46. !! ** Action : - pdct, distance to the coastline (argument)
  47. !! - NetCDF file 'dist.coast.nc'
  48. !!----------------------------------------------------------------------
  49. !!
  50. REAL(wp), DIMENSION(jpi,jpj), INTENT( out ) :: pdct ! distance to the coastline
  51. !!
  52. INTEGER :: ji, jj, jl ! dummy loop indices
  53. INTEGER :: iju, ijt, icoast, itime, ierr, icot ! local integers
  54. CHARACTER (len=32) :: clname ! local name
  55. REAL(wp) :: zdate0 ! local scalar
  56. REAL(wp), POINTER, DIMENSION(:,:) :: zxt, zyt, zzt, zmask
  57. REAL(wp), POINTER, DIMENSION(: ) :: zxc, zyc, zzc, zdis ! temporary workspace
  58. LOGICAL , ALLOCATABLE, DIMENSION(:,:) :: llcotu, llcotv, llcotf ! 2D logical workspace
  59. !!----------------------------------------------------------------------
  60. !
  61. ALLOCATE( zxt(jpi,jpj) , zyt(jpi,jpj) , zzt(jpi,jpj) , zmask(jpi,jpj) )
  62. ALLOCATE(zxc(3*jpi*jpj), zyc(3*jpi*jpj), zzc(3*jpi*jpj), zdis(3*jpi*jpj) )
  63. ALLOCATE( llcotu(jpi,jpj), llcotv(jpi,jpj), llcotf(jpi,jpj) )
  64. ALLOCATE( gphiu(jpi,jpj), gphiv(jpi,jpj), gphif(jpi,jpj) )
  65. ALLOCATE( glamu(jpi,jpj), glamv(jpi,jpj), glamf(jpi,jpj), glamt(jpi,jpj) )
  66. ALLOCATE( umask(jpi,jpj), vmask(jpi,jpj), fmask(jpi,jpj) )
  67. !
  68. CALL check_nf90( nf90_get_var( ncin, gphit_id, gphit, (/ 1,1 /), (/ jpi, jpj /) ) )
  69. CALL check_nf90( nf90_get_var( ncin, gphiu_id, gphiu, (/ 1,1 /), (/ jpi, jpj /) ) )
  70. CALL check_nf90( nf90_get_var( ncin, gphiv_id, gphiv, (/ 1,1 /), (/ jpi, jpj /) ) )
  71. CALL check_nf90( nf90_get_var( ncin, gphif_id, gphif, (/ 1,1 /), (/ jpi, jpj /) ) )
  72. CALL check_nf90( nf90_get_var( ncin, glamt_id, glamt, (/ 1,1 /), (/ jpi, jpj /) ) )
  73. CALL check_nf90( nf90_get_var( ncin, glamu_id, glamu, (/ 1,1 /), (/ jpi, jpj /) ) )
  74. CALL check_nf90( nf90_get_var( ncin, glamv_id, glamv, (/ 1,1 /), (/ jpi, jpj /) ) )
  75. CALL check_nf90( nf90_get_var( ncin, glamf_id, glamf, (/ 1,1 /), (/ jpi, jpj /) ) )
  76. CALL check_nf90( nf90_get_var( ncin, tmask_id, tmask, (/ 1,1 /), (/ jpi, jpj /) ) )
  77. CALL check_nf90( nf90_get_var( ncin, umask_id, umask, (/ 1,1 /), (/ jpi, jpj /) ) )
  78. CALL check_nf90( nf90_get_var( ncin, vmask_id, vmask, (/ 1,1 /), (/ jpi, jpj /) ) )
  79. CALL check_nf90( nf90_get_var( ncin, fmask_id, fmask, (/ 1,1 /), (/ jpi, jpj /) ) )
  80. pdct(:,:) = 0._wp
  81. zxt(:,:) = COS( rad * gphit(:,:) ) * COS( rad * glamt(:,:) )
  82. zyt(:,:) = COS( rad * gphit(:,:) ) * SIN( rad * glamt(:,:) )
  83. zzt(:,:) = SIN( rad * gphit(:,:) )
  84. ! Define the coastline points (U, V and F)
  85. DO jj = 2, jpj-1
  86. DO ji = 2, jpi-1
  87. zmask(ji,jj) = ( tmask(ji,jj+1) + tmask(ji+1,jj+1) &
  88. & + tmask(ji,jj ) + tmask(ji+1,jj ) )
  89. llcotu(ji,jj) = ( tmask(ji,jj ) + tmask(ji+1,jj ) == 1._wp )
  90. llcotv(ji,jj) = ( tmask(ji,jj ) + tmask(ji ,jj+1) == 1._wp )
  91. llcotf(ji,jj) = ( zmask(ji,jj) > 0._wp ) .AND. ( zmask(ji,jj) < 4._wp )
  92. END DO
  93. END DO
  94. ! Lateral boundaries conditions
  95. llcotu(:, 1 ) = umask(:, 2 ) == 1
  96. llcotu(:,jpj) = umask(:,jpj-1) == 1
  97. llcotv(:, 1 ) = vmask(:, 2 ) == 1
  98. llcotv(:,jpj) = vmask(:,jpj-1) == 1
  99. llcotf(:, 1 ) = fmask(:, 2 ) == 1
  100. llcotf(:,jpj) = fmask(:,jpj-1) == 1
  101. IF( jperio == 1 .OR. jperio == 4 .OR. jperio == 6 ) THEN
  102. llcotu( 1 ,:) = llcotu(jpi-1,:)
  103. llcotu(jpi,:) = llcotu( 2 ,:)
  104. llcotv( 1 ,:) = llcotv(jpi-1,:)
  105. llcotv(jpi,:) = llcotv( 2 ,:)
  106. llcotf( 1 ,:) = llcotf(jpi-1,:)
  107. llcotf(jpi,:) = llcotf( 2 ,:)
  108. ELSE
  109. llcotu( 1 ,:) = umask( 2 ,:) == 1
  110. llcotu(jpi,:) = umask(jpi-1,:) == 1
  111. llcotv( 1 ,:) = vmask( 2 ,:) == 1
  112. llcotv(jpi,:) = vmask(jpi-1,:) == 1
  113. llcotf( 1 ,:) = fmask( 2 ,:) == 1
  114. llcotf(jpi,:) = fmask(jpi-1,:) == 1
  115. ENDIF
  116. IF( jperio == 3 .OR. jperio == 4 ) THEN
  117. DO ji = 1, jpi-1
  118. iju = jpi - ji + 1
  119. llcotu(ji,jpj ) = llcotu(iju,jpj-2)
  120. llcotf(ji,jpj-1) = llcotf(iju,jpj-2)
  121. llcotf(ji,jpj ) = llcotf(iju,jpj-3)
  122. END DO
  123. DO ji = jpi/2, jpi-1
  124. iju = jpi - ji + 1
  125. llcotu(ji,jpj-1) = llcotu(iju,jpj-1)
  126. END DO
  127. DO ji = 2, jpi
  128. ijt = jpi - ji + 2
  129. llcotv(ji,jpj-1) = llcotv(ijt,jpj-2)
  130. llcotv(ji,jpj ) = llcotv(ijt,jpj-3)
  131. END DO
  132. ENDIF
  133. IF( jperio == 5 .OR. jperio == 6 ) THEN
  134. DO ji = 1, jpi-1
  135. iju = jpi - ji
  136. llcotu(ji,jpj ) = llcotu(iju,jpj-1)
  137. llcotf(ji,jpj ) = llcotf(iju,jpj-2)
  138. END DO
  139. DO ji = jpi/2, jpi-1
  140. iju = jpi - ji
  141. llcotf(ji,jpj-1) = llcotf(iju,jpj-1)
  142. END DO
  143. DO ji = 1, jpi
  144. ijt = jpi - ji + 1
  145. llcotv(ji,jpj ) = llcotv(ijt,jpj-1)
  146. END DO
  147. DO ji = jpi/2+1, jpi
  148. ijt = jpi - ji + 1
  149. llcotv(ji,jpj-1) = llcotv(ijt,jpj-1)
  150. END DO
  151. ENDIF
  152. ! Compute cartesian coordinates of coastline points
  153. ! and the number of coastline points
  154. icoast = 0
  155. DO jj = 1, jpj
  156. DO ji = 1, jpi
  157. IF( llcotf(ji,jj) ) THEN
  158. icoast = icoast + 1
  159. zxc(icoast) = COS( rad*gphif(ji,jj) ) * COS( rad*glamf(ji,jj) )
  160. zyc(icoast) = COS( rad*gphif(ji,jj) ) * SIN( rad*glamf(ji,jj) )
  161. zzc(icoast) = SIN( rad*gphif(ji,jj) )
  162. ENDIF
  163. IF( llcotu(ji,jj) ) THEN
  164. icoast = icoast+1
  165. zxc(icoast) = COS( rad*gphiu(ji,jj) ) * COS( rad*glamu(ji,jj) )
  166. zyc(icoast) = COS( rad*gphiu(ji,jj) ) * SIN( rad*glamu(ji,jj) )
  167. zzc(icoast) = SIN( rad*gphiu(ji,jj) )
  168. ENDIF
  169. IF( llcotv(ji,jj) ) THEN
  170. icoast = icoast+1
  171. zxc(icoast) = COS( rad*gphiv(ji,jj) ) * COS( rad*glamv(ji,jj) )
  172. zyc(icoast) = COS( rad*gphiv(ji,jj) ) * SIN( rad*glamv(ji,jj) )
  173. zzc(icoast) = SIN( rad*gphiv(ji,jj) )
  174. ENDIF
  175. END DO
  176. END DO
  177. ! Distance for the T-points
  178. DO jj = 1, jpj
  179. DO ji = 1, jpi
  180. IF( tmask(ji,jj) == 0._wp ) THEN
  181. pdct(ji,jj) = 0._wp
  182. ELSE
  183. DO jl = 1, icoast
  184. zdis(jl) = ( zxt(ji,jj) - zxc(jl) )**2 &
  185. & + ( zyt(ji,jj) - zyc(jl) )**2 &
  186. & + ( zzt(ji,jj) - zzc(jl) )**2
  187. END DO
  188. pdct(ji,jj) = ra * SQRT( MINVAL( zdis(1:icoast) ) )
  189. ENDIF
  190. END DO
  191. END DO
  192. DEALLOCATE( zxt , zyt , zzt , zmask )
  193. DEALLOCATE(zxc, zyc, zzc, zdis )
  194. DEALLOCATE( llcotu, llcotv, llcotf )
  195. DEALLOCATE( gphiu, gphiv, gphif )
  196. DEALLOCATE( glamu, glamv, glamf, glamt )
  197. DEALLOCATE( umask, vmask, fmask )
  198. END SUBROUTINE cofdis
  199. END MODULE coastdist