advect.F90 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. !### macro's #####################################################
  2. !
  3. #define TRACEBACK write (gol,'("in ",a," (",a,", line",i5,")")') rname, __FILE__, __LINE__; call goErr
  4. #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
  5. #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if
  6. !
  7. #include "tm5.inc"
  8. !
  9. !#################################################################
  10. MODULE ADVECT
  11. use GO, only : gol, goPr, goErr
  12. implicit none
  13. private
  14. public :: Advect_Init, Advect_Done
  15. public :: dynam0
  16. ! --- const --------------------------------------
  17. character(len=*), parameter :: mname = 'advect'
  18. CONTAINS
  19. ! ================================================================
  20. subroutine Advect_Init( status )
  21. use dims , only : nregions
  22. use Meteo, only : Set
  23. use Meteodata, only : sp1_dat, sp2_dat, sp_dat
  24. #ifdef with_prism
  25. use MeteoData, only : tsp_dat
  26. #endif
  27. use MeteoData, only : mfu_dat, mfv_dat, mfw_dat
  28. use MeteoData, only : pu_dat, pv_dat, pw_dat
  29. ! --- in/out --------------------------------
  30. integer, intent(out) :: status
  31. ! --- const ------------------------------
  32. character(len=*), parameter :: rname = mname//'/Advect_Init'
  33. ! --- local --------------------------------
  34. integer :: n
  35. ! --- begin --------------------------------
  36. ! loop over all (zoom) regions:
  37. do n = 1, nregions
  38. ! surface pressures and mass fluxes for advection
  39. call Set( sp_dat(n), status, used=.true. )
  40. call Set( sp1_dat(n), status, used=.true. )
  41. call Set( sp2_dat(n), status, used=.true. )
  42. #ifdef with_prism
  43. call Set( tsp_dat(n), status, used=.true. )
  44. #endif
  45. call Set( mfu_dat(n), status, used=.true. )
  46. call Set( mfv_dat(n), status, used=.true. )
  47. call Set( mfw_dat(n), status, used=.true. )
  48. call Set( pu_dat(n), status, used=.true. )
  49. call Set( pv_dat(n), status, used=.true. )
  50. call Set( pw_dat(n), status, used=.true. )
  51. end do ! regions
  52. ! ok
  53. status = 0
  54. end subroutine Advect_Init
  55. ! ***
  56. subroutine Advect_Done( status )
  57. ! --- in/out --------------------------------
  58. integer, intent(out) :: status
  59. ! --- const ------------------------------
  60. character(len=*), parameter :: rname = mname//'/Advect_Done'
  61. ! --- begin --------------------------------
  62. ! nothing to be done
  63. ! ok
  64. status = 0
  65. end subroutine Advect_Done
  66. ! ================================================================
  67. !-----------------------------------------------------------------------
  68. !
  69. !**** dynam0 - calculates vertical massfluxes v 9.1
  70. !
  71. ! programmed by mh mpi HH 1-oct-1991
  72. !
  73. ! purpose
  74. ! -------
  75. ! This sr is CALLed each time after new massfluxes are read in.
  76. ! Calculate the new air-masses in each grid box from the
  77. ! surface pressure.
  78. ! Calculate the amount of air moved in each advection substep,
  79. ! also in the vertical direction.
  80. !
  81. ! interface
  82. ! ---------
  83. ! CALL dynam0
  84. !
  85. ! method
  86. ! ------
  87. ! integrate air conservation equation in the vertical direction
  88. ! in order to obtain the vertical massfluxes.
  89. !
  90. ! externals
  91. ! ---------
  92. ! none
  93. !
  94. ! reference
  95. ! ---------
  96. ! see manual
  97. !
  98. ! modified by mk (1999) for zoom version.
  99. ! 25 Jan 2012 - P. Le Sager - adapted for MPI lat-lon domain decomposition
  100. !
  101. !-----------------------------------------------------------------------
  102. SUBROUTINE DYNAM0(region, status)
  103. use dims, only : im, jm, lm, ndyn, tref, zero, bt, xcyc
  104. use global_data, only : wind_dat
  105. use meteodata , only : pu_dat, pv_dat
  106. use tm5_distgrid, only : dgrid, Get_DistGrid, update_halo
  107. ! in/output
  108. integer,intent(in) :: region
  109. integer,intent(out) :: status
  110. ! local
  111. real, dimension(:,:,:), pointer :: pu,pv,am,bm,cm
  112. real, dimension(:,:), allocatable :: pit
  113. real, dimension(:,:,:), allocatable :: sd
  114. real, dimension(:,:,:), allocatable :: conv_adv
  115. real :: dtu, dtv, dtw
  116. integer :: i, j, l, lmr, i1, i2, j1, j2
  117. character(len=*), parameter :: rname = mname//'/dynam0'
  118. ! start
  119. call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2 , J_STRT=j1, J_STOP=j2 )
  120. allocate( pit(i1:i2, j1:j2 ) )
  121. allocate( sd(i1:i2, j1:j2, lm(region)-1) )
  122. allocate( conv_adv(i1:i2, j1:j2, lm(region) ) )
  123. ! leave if fluxes are not in use:
  124. if ( .not. pu_dat(region)%used ) return
  125. if ( .not. pv_dat(region)%used ) return
  126. ! set pointers:
  127. pu => pu_dat(region)%data
  128. pv => pv_dat(region)%data
  129. am => wind_dat(region)%am
  130. bm => wind_dat(region)%bm
  131. cm => wind_dat(region)%cm
  132. !---- length of advection substeps (in seconds) in the three directions
  133. dtu=ndyn/(2.*tref(region)) ! again removed the revert! cmk
  134. dtv=ndyn/(2.*tref(region))
  135. dtw=ndyn/(2.*tref(region))
  136. ! number of levels in this region:
  137. lmr = lm(region)
  138. ! init to zero:
  139. am = zero
  140. bm = zero
  141. cm = zero
  142. ! update pu and pv before using them
  143. CALL UPDATE_HALO( dgrid(region), pu_dat(region)%data, pu_dat(region)%halo, status)
  144. IF_NOTOK_RETURN(status=1)
  145. CALL UPDATE_HALO( dgrid(region), pv_dat(region)%data, pv_dat(region)%halo, status)
  146. IF_NOTOK_RETURN(status=1)
  147. !
  148. ! compute conv_adv, the horizontal mass convergence
  149. ! the arrays pu and pv contain the horizontal air mass fluxes crossing
  150. ! the grid box boundaries. pu(i,j,l) is the eastward mass flux in kg/sec
  151. ! at the eastern edge of box i,j,l; pv(i,j,l) is the northward
  152. ! mass flux at the southern edge of box i,j,l
  153. !
  154. do l=1,lmr
  155. do j=j1, j2
  156. do i=i1, i2
  157. conv_adv(i,j,l)=pu(i-1,j,l)-pu(i,j,l)+pv(i,j,l)-pv(i,j+1,l)
  158. end do
  159. end do
  160. end do
  161. !
  162. ! compute pit, the vertically integrated conv_adv
  163. !
  164. do j=j1, j2
  165. do i=i1, i2
  166. pit(i,j)=conv_adv(i,j,1)
  167. do l=2,lmr
  168. pit(i,j)=pit(i,j)+conv_adv(i,j,l)
  169. end do
  170. !
  171. ! compute the vertical massflux on the box boundaries (in kg/s)
  172. !mk in the hybrid system, the tendency in ps is given by bt. Bt is
  173. !mk already normalized. Now distribute pit such that the new mass
  174. !mk distribution after advection exactly matches the
  175. !mk exactly coincides with the distribution that is obtained
  176. !mk from the new surface pressure.
  177. !
  178. sd(i,j,lmr-1)=conv_adv(i,j,lmr) - (bt(lmr)-bt(lmr+1))*pit(i,j)
  179. do l=lmr-2,1,-1
  180. sd(i,j,l)=sd(i,j,l+1)+conv_adv(i,j,l+1)-(bt(l+1)-bt(l+2))*pit(i,j)
  181. end do
  182. end do
  183. end do
  184. !
  185. ! compute amount of air moved each advection substep, am, bm or cm (kg)
  186. !
  187. ! am(i,j,l) is the amount of air moved eastward at the eastern
  188. ! boundary of grid box i,j,l
  189. ! compute cm
  190. ! cm(i,j,l) is the amount of air moved in upward direction at the
  191. ! upper boundary of grid box i,j,l
  192. ! compute bm
  193. ! bm(i,j,l) is the amount of air moved northward at the southern
  194. ! boundary of grid box i,j,l
  195. !
  196. do l= 1, lmr
  197. do j= j1, j2
  198. do i= i1-1, i2
  199. am(i,j,l)=dtu*pu(i,j,l)
  200. end do
  201. end do
  202. end do
  203. do l= 1, lmr
  204. do j= j1, j2+1
  205. do i= i1, i2
  206. bm(i,j,l)=dtv*pv(i,j,l)
  207. end do
  208. end do
  209. end do
  210. do l= 1, lmr-1
  211. do j= j1, j2
  212. do i= i1, i2
  213. cm(i,j,l)=-dtw*sd(i,j,l)
  214. end do
  215. end do
  216. end do
  217. CALL UPDATE_HALO( dgrid(region), am, wind_dat(region)%halo, status)
  218. IF_NOTOK_RETURN(status=1)
  219. nullify(pu)
  220. nullify(pv)
  221. nullify(am)
  222. nullify(bm)
  223. nullify(cm)
  224. deallocate( pit, sd, conv_adv)
  225. END SUBROUTINE DYNAM0
  226. end module advect