advectx__slopes.F90 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  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 (test/=0) then; TRACEBACK; action; return; end if
  5. #define IF_ERROR_RETURN(action) if (test> 0) then; TRACEBACK; action; return; end if
  6. !
  7. #include "tm5.inc"
  8. !
  9. !-----------------------------------------------------------------------------
  10. ! TM5 !
  11. !-----------------------------------------------------------------------------
  12. !BOP
  13. !
  14. ! !MODULE: ADVECTX
  15. !
  16. ! !DESCRIPTION:
  17. !\\
  18. !\\
  19. ! !INTERFACE:
  20. !
  21. MODULE ADVECTX
  22. !
  23. ! !USES:
  24. !
  25. USE GO, ONLY : gol, goPr, goErr
  26. USE TM5_DISTGRID, ONLY : DGRID, GET_DISTGRID, REDUCE, UPDATE_HALO_JBAND
  27. USE PARTOOLS, ONLY : isRoot, npe_lon
  28. IMPLICIT NONE
  29. PRIVATE
  30. !
  31. ! !PUBLIC MEMBER FUNCTIONS:
  32. !
  33. PUBLIC :: advectxzoom
  34. !
  35. ! !PRIVATE DATA MEMBERS:
  36. !
  37. character(len=*), parameter :: mname='advectx'
  38. !
  39. ! !REVISION HISTORY:
  40. ! 1 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  41. ! 9 Jan 2013 - P. Le Sager - works with reduced grid
  42. !
  43. ! !REMARKS:
  44. !
  45. !EOP
  46. !------------------------------------------------------------------------
  47. CONTAINS
  48. !--------------------------------------------------------------------------
  49. ! TM5 !
  50. !--------------------------------------------------------------------------
  51. !BOP
  52. !
  53. ! !IROUTINE: ADVECTXZOOM
  54. !
  55. ! !DESCRIPTION: set parameters for advectx
  56. !\\
  57. !\\
  58. ! !INTERFACE:
  59. !
  60. SUBROUTINE ADVECTXZOOM( REGION, TEST )
  61. ! !USES:
  62. !
  63. !
  64. use dims, only : lm
  65. #ifdef with_budgets
  66. use budget_global, only : sum_advection
  67. #endif
  68. use global_data, only : mass_dat, wind_dat
  69. !
  70. ! !INPUT PARAMETERS:
  71. !
  72. integer, intent(in) :: region
  73. !
  74. ! !OUTPUT PARAMETERS:
  75. !
  76. integer, intent(out) :: test
  77. !
  78. ! !REVISION HISTORY:
  79. ! written by patrick berkvens and mike botchev, march-june 1999
  80. ! updated and modified by MK, dec 2002
  81. ! 1 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  82. !
  83. ! !REMARKS:
  84. !
  85. !EOP
  86. !------------------------------------------------------------------------
  87. !BOC
  88. character(len=*), parameter :: rname = mname//'/advectxzoom'
  89. integer :: i1, j1, i2, j2, istat, lmr
  90. real :: sum_old, sum_new
  91. !-------------- start
  92. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  93. lmr = lm(region)
  94. #ifdef with_budgets
  95. ! total mass tracer #1
  96. call REDUCE( dgrid(region), mass_dat(region)%rm(:,:,:,1), mass_dat(region)%halo, 'SUM', sum_old, istat)
  97. #endif
  98. CALL ADVECTX_WORK(region, j1, j2, 1, lmr, test)
  99. IF_NOTOK_RETURN(test=1)
  100. #ifdef with_budgets
  101. call REDUCE( dgrid(region), mass_dat(region)%rm(:,:,:,1), mass_dat(region)%halo, 'SUM', sum_new, istat)
  102. if( isRoot ) then
  103. sum_advection(region) = sum_advection(region) + sum_new - sum_old
  104. end if
  105. #endif
  106. test=0
  107. END SUBROUTINE ADVECTXZOOM
  108. !EOC
  109. !--------------------------------------------------------------------------
  110. ! TM5 !
  111. !--------------------------------------------------------------------------
  112. !BOP
  113. !
  114. ! !IROUTINE: ADVECTX_WORK
  115. !
  116. ! !DESCRIPTION: makes reduced grid pre-/postprocessing, call dynamu
  117. !\\
  118. !\\
  119. ! !INTERFACE:
  120. !
  121. SUBROUTINE ADVECTX_WORK( region, js, je, ls, le, test)
  122. !
  123. ! !USES:
  124. !
  125. use dims, only : im, jm, lm
  126. use redgridZoom, only : grid_reduced, nred, uni2red, uni2red_mf, red2uni, idle_xadv
  127. use global_data, only : wind_dat, mass_dat
  128. use meteodata , only : m_dat
  129. use chem_param, only : ntracet
  130. !
  131. ! !INPUT PARAMETERS:
  132. !
  133. integer,intent(in) :: region
  134. integer,intent(in) :: js
  135. integer,intent(in) :: je
  136. integer,intent(in) :: ls
  137. integer,intent(in) :: le
  138. !
  139. ! !OUTPUT PARAMETERS:
  140. !
  141. integer, intent(out) :: test
  142. !
  143. ! !REVISION HISTORY:
  144. !
  145. ! written by mike botchev, march-june 1999
  146. ! 1 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  147. !
  148. !EOP
  149. !------------------------------------------------------------------------
  150. !BOC
  151. character(len=*), parameter :: rname = mname//'/advectx_work'
  152. real, dimension(:,:,:), pointer :: m
  153. real, dimension(:,:,:), pointer :: am
  154. real, dimension(:,:,:), allocatable :: m_uni ! for reduced grid...
  155. real, dimension(:,:,:), allocatable :: am_uni ! for reduced grid...
  156. real :: mxval
  157. integer,dimension(3) :: mxloc
  158. integer :: imr, jmr, lmr, i1, i2, j1, j2, halo
  159. ! --------- START
  160. #ifndef slopes
  161. test=1
  162. TRACEBACK
  163. return
  164. #endif
  165. ! Transform to the reduced grid
  166. if ( grid_reduced ) then
  167. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  168. lmr = lm(region)
  169. imr = im(region)
  170. halo = m_dat(region)%halo
  171. allocate( m_uni( i1-halo:i2+halo, j1-halo:j2+halo, lmr ))
  172. halo = wind_dat(region)%halo
  173. allocate(am_uni( i1-halo:i2+halo, j1-halo:j2+halo, 0:lmr+1))
  174. am => wind_dat(region)%am
  175. m => m_dat(region)%data
  176. ! take care of BC for uniform am, so that am_uni is correct when
  177. ! updating m_uni after the call to dynamun
  178. if (npe_lon==1) then
  179. am(-1:0,j1:j2,:) = am(imr-1:imr,j1:j2,:)
  180. am(i2+1,j1:j2,:) = am( 1,j1:j2,:)
  181. else
  182. call UPDATE_HALO_JBAND(dgrid(region), am, halo, test )
  183. IF_NOTOK_RETURN(test=1)
  184. endif
  185. ! save non-reduced m and am in m_uni and am_uni:
  186. m_uni = m
  187. am_uni = am
  188. ! reduce m
  189. call uni2red(region,i1,i2,j1,j2,test)
  190. IF_NOTOK_RETURN(test=1)
  191. ! reduce am (and update halo of reduced zonal bands)
  192. call uni2red_mf( region,i1,i2,j1,j2,test )
  193. IF_NOTOK_RETURN(test=1)
  194. end if
  195. ! transport
  196. if (.not.idle_xadv) then
  197. CALL DYNAMU (region,js,je,ls,le, test)
  198. IF_NOTOK_RETURN(test=1)
  199. endif
  200. ! Transform from reduced to uniform grid
  201. if ( grid_reduced ) then
  202. ! advection on uniform grid
  203. m_uni(i1:i2,j1:j2,1:lmr) = m_uni(i1:i2,j1:j2,1:lmr) + &
  204. am_uni(i1-1:i2-1,j1:j2,1:lmr) - am_uni(i1:i2,j1:j2,1:lmr)
  205. ! redistribute rm,rxm,rym,rzm by using m_uni and m
  206. halo = m_dat(region)%halo
  207. call red2uni(region, i1, i2, j1, j2, halo, m_uni, test)
  208. ! recreate rm/rxm/rym/rzm by using equal masses (not m_uni)
  209. !call red2uni_em(region)
  210. ! recreate am:
  211. am = am_uni
  212. nullify(am)
  213. nullify(m)
  214. deallocate(am_uni)
  215. deallocate(m_uni)
  216. endif
  217. test=0
  218. END SUBROUTINE ADVECTX_WORK
  219. !EOC
  220. !--------------------------------------------------------------------------
  221. ! TM5 !
  222. !--------------------------------------------------------------------------
  223. !BOP
  224. !
  225. ! !IROUTINE: DYNAMU
  226. !
  227. ! !DESCRIPTION: east-west tracer transport: calculate amount of tracer moved in an east-west
  228. ! advection substep
  229. !
  230. ! method : slopes scheme
  231. ! reference : Russel and Lerner, 1979
  232. !\\
  233. !\\
  234. ! !INTERFACE:
  235. !
  236. SUBROUTINE DYNAMU( region, js, je, ls, le, test)
  237. !
  238. ! !USES:
  239. !
  240. use dims, only : okdebug, nregions, parent
  241. use dims, only : im, jm, lm, xref, yref, zref, tref
  242. use dims, only : zero, one, xi, nxi, nloop_max, limits, xcyc
  243. use redgridZoom, only : grid_reduced, nred, imredj
  244. use redgridZoom, only : mfl_alt1, m_alt1, rm_alt1, rxm_alt1, rym_alt1, rzm_alt1
  245. use global_data, only : wind_dat, mass_dat
  246. use meteodata , only : m_dat
  247. #ifdef with_budgets
  248. use budget_global, only : budget_flux, apply_budget_global_flux
  249. use budget_global, only : iflux1, iflux2, jflux1, jflux2
  250. #endif
  251. use chem_param, only : ntracet, ra
  252. use partools, only : par_reduce, isRowRoot
  253. !
  254. ! !INPUT PARAMETERS:
  255. !
  256. integer,intent(in) :: region
  257. integer,intent(in) :: js
  258. integer,intent(in) :: je
  259. integer,intent(in) :: ls
  260. integer,intent(in) :: le
  261. !
  262. ! !OUTPUT PARAMETERS:
  263. !
  264. integer, intent(out) :: test
  265. !
  266. ! !REVISION HISTORY:
  267. ! programmed by mh, mpi HH 1994-1995
  268. ! zoom version written by mike botchev, march-june 1999
  269. ! 1 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  270. !
  271. !EOP
  272. !------------------------------------------------------------------------
  273. !BOC
  274. character(len=*), parameter :: rname = mname//'/dynamu'
  275. real, dimension(:,:,:,:), pointer :: rm, rxm, rym, rzm
  276. real, dimension(:,:,:), pointer :: m, am
  277. real, dimension(:), allocatable :: f, pf, fy, fz, mnew, mx
  278. real, dimension(:,:), allocatable :: wrk2
  279. integer, allocatable :: ie(:)
  280. integer :: i, is, j, l, n, offsetn
  281. integer :: i1, i2, j1, j2
  282. logical :: WestBorder, EastBorder
  283. integer :: imr, jmr, lmr, tref_, xref_, yref_, zref_, ic, iloop, iemax
  284. integer :: nloop(jm(region),lm(region))
  285. real :: min_one, max_one, min_all, max_all
  286. real :: my_alpha, alpha, max_alpha, alphamax, x, rmold
  287. logical :: cfl_ok
  288. integer, parameter :: max_nloop = 50
  289. integer :: ns, ne, jss, jee, iie
  290. real :: l_xi, g_xi, l_nl, g_nl
  291. character(len=2) :: sloop
  292. !------------- Start
  293. ! ------------
  294. ! Bounds
  295. ! ------------
  296. CALL GET_DISTGRID( dgrid(region), &
  297. I_STRT=i1, I_STOP=i2, &
  298. J_STRT=j1, J_STOP=j2, &
  299. hasWestBorder=WestBorder, hasEastBorder=EastBorder )
  300. lmr = lm(region)
  301. imr = im(region)
  302. allocate(ie(j1:j2))
  303. ! ------------
  304. ! Work arrays
  305. ! ------------
  306. if ( ( grid_reduced ) .and. (npe_lon /= 1) .and. (nred(region)/=0) ) then
  307. am => mfl_alt1
  308. m => m_alt1
  309. rm => rm_alt1
  310. rxm => rxm_alt1
  311. rym => rym_alt1
  312. rzm => rzm_alt1
  313. is=1
  314. ie=imr
  315. iemax=maxval(imredj(j1:j2,region))
  316. else
  317. am => wind_dat(region)%am
  318. m => m_dat(region)%data
  319. rm => mass_dat(region)%rm
  320. rxm => mass_dat(region)%rxm
  321. rym => mass_dat(region)%rym
  322. rzm => mass_dat(region)%rzm
  323. is=i1
  324. ie=i2
  325. iemax=i2
  326. endif
  327. allocate( f( is-1:iemax+1 )) ! halo=1
  328. allocate( pf( is-1:iemax+1 )) ! halo=1
  329. allocate( fy( is-1:iemax+1 )) ! halo=1
  330. allocate( fz( is-1:iemax+1 )) ! halo=1
  331. allocate( mx( is-2:iemax+2 )) ! halo=2 (was 1)
  332. allocate(mnew( is-1:iemax+1 )) ! halo=1 (was 0)
  333. allocate(wrk2( is-2:iemax+2, ntracet )) ! halo=2
  334. ! ------------
  335. ! Reduced grid & halo
  336. ! --------------
  337. if ( ( grid_reduced .and. npe_lon==1 ).or.(grid_reduced .and. npe_lon/=1.and.nred(region)>0)) then
  338. ie = imredj(j1:j2,region)
  339. do j=j1,j2
  340. iie=ie(j)
  341. m( -1:0, j,:) = m(iie-1:iie,j,:)
  342. rm( -1:0, j,:,:) = rm(iie-1:iie,j,:,:)
  343. rxm( -1:0, j,:,:) = rxm(iie-1:iie,j,:,:)
  344. rym( -1:0, j,:,:) = rym(iie-1:iie,j,:,:)
  345. rzm( -1:0, j,:,:) = rzm(iie-1:iie,j,:,:)
  346. m(iie+1:iie+2, j,:) = m(1:2,j,:)
  347. rm(iie+1:iie+2, j,:,:) = rm(1:2,j,:,:)
  348. rxm(iie+1:iie+2, j,:,:) = rxm(1:2,j,:,:)
  349. rym(iie+1:iie+2, j,:,:) = rym(1:2,j,:,:)
  350. rzm(iie+1:iie+2, j,:,:) = rzm(1:2,j,:,:)
  351. end do
  352. ! halo of am is filled in advectx_work (thru uni2red_mf for reduced part)
  353. else
  354. CALL UPDATE_HALO_JBAND( dgrid(region), am, wind_dat(region)%halo, test)
  355. CALL UPDATE_HALO_JBAND( dgrid(region), m, m_dat(region)%halo, test)
  356. CALL UPDATE_HALO_JBAND( dgrid(region), rm, mass_dat(region)%halo, test)
  357. CALL UPDATE_HALO_JBAND( dgrid(region), rxm, mass_dat(region)%halo, test)
  358. CALL UPDATE_HALO_JBAND( dgrid(region), rym, mass_dat(region)%halo, test)
  359. CALL UPDATE_HALO_JBAND( dgrid(region), rzm, mass_dat(region)%halo, test)
  360. end if
  361. ! if requested limit zonal slopes such that no negative tracer masses
  362. ! should occur
  363. if ( limits ) then
  364. do n = 1, ntracet
  365. do l = ls, le
  366. do j = js, je
  367. do i = is - 1, ie(j) + 1
  368. rxm(i,j,l,n) = max (min (rxm(i,j,l,n), rm(i,j,l,n)), -rm(i,j,l,n))
  369. end do
  370. end do
  371. end do
  372. end do
  373. end if
  374. ! init stat holders
  375. l_nl = 0.0
  376. l_xi = 0.0 ! max alpha
  377. ! ================= Find number of iterations needed
  378. LATBAND: DO l= ls, le ! work in 1D, so final nloop can differ with latitude and levels
  379. DO j = js, je
  380. iie = ie(j)
  381. ! Determine number of loops required to avoid CFLs...
  382. nloop(j,l) = 1 ! default run the loop one time!
  383. alpha = 2.0
  384. max_alpha = 0.0
  385. do while ( abs(alpha) >= one .and. nloop(j,l) < max_nloop )
  386. ! copy initial mass to temp array
  387. mx(is-2:iie+2) = m(is-2:iie+2,j,l)
  388. xloop: do iloop = 1, nloop(j,l)
  389. cfl_ok = .true.
  390. indloop : do i=is-1,iie
  391. if (am(i,j,l)>=zero) then
  392. my_alpha=am(i,j,l)/mx(i)
  393. else
  394. my_alpha=am(i,j,l)/mx(i+1)
  395. end if
  396. max_alpha = max(max_alpha, abs(my_alpha))
  397. if((abs(my_alpha)>=one)) exit indloop
  398. end do indloop
  399. ! sync
  400. if (grid_reduced .and. npe_lon/=1.and.nred(region)>0) then
  401. alpha=max_alpha
  402. else
  403. call Par_Reduce(max_alpha, 'MAX', alpha, test, all=.true., row=.true.)
  404. endif
  405. if (alpha>=one) then
  406. cfl_ok = .false.
  407. exit xloop
  408. end if
  409. ! cfl ok, then update mass for next iteration if any
  410. if(iloop/=nloop(j,l)) then
  411. ! is:iie updated
  412. ! is-1, iie+1 are BC, and also updated (assumption that
  413. ! xcyc(region)==1), so we do not need to call update halo
  414. ! every other iteration.
  415. mx(is-1:iie+1) = mx(is-1:iie+1) + am(is-2:iie,j,l) - am(is-1:iie+1,j,l)
  416. if (modulo(iloop,2)==0) then
  417. if ( ( grid_reduced .and. npe_lon==1 ).or.(grid_reduced .and. npe_lon/=1.and.nred(region)>0)) then
  418. mx( -1:0) = mx(iie-1:iie)
  419. mx(iie+1:iie+2) = mx( 1:2)
  420. else
  421. call UPDATE_HALO_JBAND( dgrid(region), mx, 2, test)
  422. end if
  423. end if
  424. end if
  425. end do xloop
  426. ! CLF not ok : reduce mass flux
  427. if(.not.cfl_ok) then
  428. am(is-2:iie+1,j,l) = am(is-2:iie+1,j,l)*nloop(j,l)/(nloop(j,l)+1)
  429. nloop(j,l) = nloop(j,l) + 1
  430. max_alpha = 0.0
  431. if (nloop(j,l) == max_nloop) then
  432. write(gol,*)'nloop too high'; call goErr
  433. test=1; TRACEBACK
  434. return
  435. end if
  436. end if
  437. end do !while alpha>1
  438. l_xi = MAX (l_xi, alpha)
  439. end DO
  440. end DO LATBAND
  441. ! ================= UPDATE MASSES
  442. LATBAND2: DO l= ls, le
  443. DO j = js, je
  444. iie = ie(j)
  445. CFL: do iloop = 1,nloop(j,l)
  446. ! calculate new air mass distribution
  447. mnew(is-1:iie+1) = m(is-1:iie+1,j,l) + am(is-2:iie,j,l)-am(is-1:iie+1,j,l)
  448. ! loop over tracers
  449. TRAC: do n=1,ntracet
  450. ! calculate fluxes for rm,rxm,rym,rzm
  451. do i=is-1,iie
  452. if (am(i,j,l)>=zero) then
  453. alpha = am(i,j,l)/m(i,j,l)
  454. f(i) = alpha*(rm(i,j,l,n)+(one-alpha)*rxm(i,j,l,n))
  455. pf(i) = am(i,j,l)*(alpha*alpha*rxm(i,j,l,n) - 3.*f(i))
  456. fy(i) = alpha*rym(i,j,l,n)
  457. fz(i) = alpha*rzm(i,j,l,n)
  458. else
  459. alpha = am(i,j,l)/m(i+1,j,l)
  460. f(i) = alpha*(rm(i+1,j,l,n)-(one+alpha)*rxm(i+1,j,l,n))
  461. pf(i) = am(i,j,l)*(alpha*alpha*rxm(i+1,j,l,n) - 3.*f(i))
  462. fy(i) = alpha*rym(i+1,j,l,n)
  463. fz(i) = alpha*rzm(i+1,j,l,n)
  464. end if
  465. !xi(region,1)=max(xi(region,1),abs(alpha))
  466. end do
  467. #ifdef with_budgets
  468. !
  469. ! add up flux budget!
  470. ! FIXME: note that this woukd be wrong if grid is reduced, so set it to
  471. ! a quiet NaN (but possible only with F2003)
  472. !
  473. if ( apply_budget_global_flux ) then
  474. if ( (iflux1(region)-1 >= is) .and. (iflux1(region)-1 <= iie) ) then
  475. budget_flux(region)%flux_x1(j,l,n) = budget_flux(region)%flux_x1(j,l,n) &
  476. + f(iflux1(region)-1)*1e3/ra(n) ! moles
  477. endif
  478. if ( (iflux2(region)-1 >= is) .and. (iflux2(region)-1 <= iie) ) then
  479. budget_flux(region)%flux_x2(j,l,n) = budget_flux(region)%flux_x2(j,l,n) &
  480. + f(iflux2(region)-1)*1e3/ra(n)
  481. endif
  482. end if
  483. #endif
  484. !
  485. ! calculate new tracer mass, and tracer mass slopes
  486. !
  487. do i=is, iie
  488. rm(i,j,l,n) = rm(i,j,l,n) + (f(i-1)-f(i))
  489. rxm(i,j,l,n) = rxm(i,j,l,n) + (pf(i-1)-pf(i) &
  490. - (am(i-1,j,l)-am(i,j,l))*rxm(i,j,l,n) &
  491. + 3.*((am(i-1,j,l)+am(i,j,l))*rm(i,j,l,n) &
  492. - (f(i-1)+f(i))*m(i,j,l)))/mnew(i)
  493. !CMK: apply limits again: might be in nloop!
  494. if ( limits ) rxm(i,j,l,n) = &
  495. max(min(rxm(i,j,l,n),rm(i,j,l,n)),-rm(i,j,l,n))
  496. rym(i,j,l,n) = rym(i,j,l,n) + (fy(i-1)-fy(i))
  497. rzm(i,j,l,n) = rzm(i,j,l,n) + (fz(i-1)-fz(i))
  498. end do
  499. end do TRAC ! end of n-loop
  500. ! store new air mass in m array
  501. m(is-1:iie+1,j,l)=mnew(is-1:iie+1)
  502. ! update anything that changes and may be used with +/- index shift in next iloop
  503. if(iloop/=nloop(j,l)) then
  504. if ( ( grid_reduced .and. npe_lon==1 ).or.(grid_reduced .and. npe_lon/=1.and.nred(region)>0)) then
  505. m( -1:0, j,:) = m(iie-1:iie,j,:)
  506. rm( -1:0, j,:,:) = rm(iie-1:iie,j,:,:)
  507. rxm( -1:0, j,:,:) = rxm(iie-1:iie,j,:,:)
  508. rym( -1:0, j,:,:) = rym(iie-1:iie,j,:,:)
  509. rzm( -1:0, j,:,:) = rzm(iie-1:iie,j,:,:)
  510. m(iie+1:iie+2, j,:) = m(1:2,j,:)
  511. rm(iie+1:iie+2, j,:,:) = rm(1:2,j,:,:)
  512. rxm(iie+1:iie+2, j,:,:) = rxm(1:2,j,:,:)
  513. rym(iie+1:iie+2, j,:,:) = rym(1:2,j,:,:)
  514. rzm(iie+1:iie+2, j,:,:) = rzm(1:2,j,:,:)
  515. else
  516. wrk2 = rm(:,j,l,:)
  517. CALL UPDATE_HALO_JBAND( dgrid(region), wrk2, mass_dat(region)%halo, test)
  518. rm(:,j,l,:) = wrk2
  519. wrk2 = rxm(:,j,l,:)
  520. CALL UPDATE_HALO_JBAND( dgrid(region), wrk2, mass_dat(region)%halo, test)
  521. rxm(:,j,l,:) = wrk2
  522. wrk2 = rym(:,j,l,:)
  523. CALL UPDATE_HALO_JBAND( dgrid(region), wrk2, mass_dat(region)%halo, test)
  524. rym(:,j,l,:) = wrk2
  525. wrk2 = rzm(:,j,l,:)
  526. CALL UPDATE_HALO_JBAND( dgrid(region), wrk2, mass_dat(region)%halo, test)
  527. rzm(:,j,l,:) = wrk2
  528. end if
  529. end if
  530. end do CFL ! iloop
  531. ! restore 'old' am
  532. am(is-2:iie+1,j,l) = am(is-2:iie+1,j,l)*nloop(j,l)
  533. enddo
  534. enddo LATBAND2
  535. ! store algo info
  536. l_nl = REAL(maxval(nloop(js:je,ls:le)))
  537. if (grid_reduced .and. npe_lon/=1) then
  538. if (nred(region)==0) then
  539. call Par_Reduce(l_nl, 'MAX', g_nl, test, all=.false., row=.true.)
  540. l_nl=g_nl
  541. end if
  542. if(isRowRoot)then
  543. call Par_Reduce(l_nl, 'MAX', g_nl, test, all=.false., col=.true.)
  544. endif
  545. else
  546. call Par_Reduce(l_nl, 'MAX', g_nl, test, all=.false.)
  547. endif
  548. if (grid_reduced .and. npe_lon/=1) then
  549. if (nred(region)==0) then
  550. call Par_Reduce(l_xi, 'MAX', g_xi, test, all=.false., row=.true.)
  551. l_xi=g_xi
  552. end if
  553. if(isRowRoot)then
  554. call Par_Reduce(l_xi, 'MAX', g_xi, test, all=.false., col=.true.)
  555. endif
  556. else
  557. call Par_Reduce(l_xi, 'MAX', g_xi, test, all=.false.)
  558. endif
  559. deallocate(f)
  560. deallocate(pf)
  561. deallocate(fy)
  562. deallocate(fz)
  563. deallocate(mnew)
  564. deallocate(mx, wrk2)
  565. deallocate(ie)
  566. if ( isRoot ) then
  567. nloop_max(region,1) = max (nloop_max(region,1), nint (g_nl))
  568. xi(region,1) = max (xi(region,1), g_xi)
  569. end if
  570. nullify(am)
  571. nullify(m)
  572. nullify(rm)
  573. nullify(rxm)
  574. nullify(rym)
  575. nullify(rzm)
  576. test=0
  577. END SUBROUTINE DYNAMU
  578. !EOC
  579. END MODULE ADVECTX