advectm_cfl.F90 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794
  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. ! TM5 !
  10. !-----------------------------------------------------------------------------
  11. !BOP
  12. !
  13. ! !MODULE: ADVECTM_CFL
  14. !
  15. ! !DESCRIPTION: module to check for CFL violation.
  16. !
  17. ! Exactly the same operations are performed on m as in the 'real' advection
  18. ! routines. However, rm, rxm, rym, rzm are not updated. The 'old' m is saved
  19. ! using store_masses and restored with 'restore_masses'.
  20. !\\
  21. !\\
  22. ! !INTERFACE:
  23. !
  24. MODULE ADVECTM_CFL
  25. !
  26. ! !USES:
  27. !
  28. use GO, only : gol, goErr, goPr
  29. use dims, only : nregions, maxref
  30. use dims, only : revert
  31. use dims, only : okdebug
  32. use tm5_distgrid, only : dgrid, Get_DistGrid, update_halo, update_halo_jband
  33. IMPLICIT NONE
  34. PRIVATE
  35. !
  36. ! !PUBLIC MEMBER FUNCTIONS:
  37. !
  38. public :: Init_CFL, Done_CFL
  39. public :: Check_CFL
  40. public :: Setup_MassFlow
  41. !
  42. ! !PRIVATE TYPES:
  43. !
  44. type oldmass_data
  45. real, pointer :: m(:,:,:)
  46. real, dimension(:,:,:), pointer :: am
  47. real, dimension(:,:,:), pointer :: bm
  48. real, dimension(:,:,:), pointer :: cm
  49. end type oldmass_data
  50. !
  51. ! !PRIVATE DATA MEMBERS:
  52. !
  53. integer, parameter :: max_global_iteration = 32
  54. integer, parameter :: n_operators = 3 ! xyz
  55. integer, parameter :: nsplitsteps = 6 ! xyzzyx
  56. character, parameter :: splitorder(nsplitsteps) = (/'x','y','z','z','y','x'/)
  57. character(len=*), parameter :: mname = 'advectm_cfl'
  58. integer :: global_iteration
  59. integer :: ndyn_save
  60. integer :: regionm_status(nregions)
  61. integer :: mloop_max(nregions,3) = 0 ! local CFL counters
  62. real :: xim (nregions,3) = 0.0 !
  63. logical :: cfl_ok
  64. type(oldmass_data) :: oldmass_dat(nregions)
  65. ! alternate mass array (used on row_roots, to deal with reduced grid). With and w/o halo.
  66. real, dimension(:,:,:), allocatable, target :: m_alt1
  67. real, dimension(:,:,:), allocatable :: m_alt2
  68. character :: splitorderzoom(nregions,maxref*nsplitsteps)
  69. !
  70. ! !REVISION HISTORY:
  71. ! 10 Nov 2011 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  72. !
  73. ! !REMARKS:
  74. !
  75. !EOP
  76. !------------------------------------------------------------------------
  77. CONTAINS
  78. !--------------------------------------------------------------------------
  79. ! TM5 !
  80. !--------------------------------------------------------------------------
  81. !BOP
  82. !
  83. ! !IROUTINE: INIT_CFL
  84. !
  85. ! !DESCRIPTION: initialize data for CFL
  86. !\\
  87. !\\
  88. ! !INTERFACE:
  89. !
  90. SUBROUTINE INIT_CFL
  91. !
  92. ! !USES:
  93. !
  94. use dims, only : lm, im
  95. use global_data, only : wind_dat
  96. use meteodata, only : m_dat
  97. use partools, only : isRowRoot, npe_lon
  98. use redgridZoom, only : nred
  99. !
  100. ! !REVISION HISTORY:
  101. ! 10 Nov 2011 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  102. !
  103. ! !REMARKS:
  104. !
  105. !EOP
  106. !------------------------------------------------------------------------
  107. !BOC
  108. integer :: region, imr, lmr, halo
  109. integer :: i1, i2, j1, j2
  110. ! --- begin -------------------------------
  111. DO region = 1, nregions
  112. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  113. lmr = lm(region)
  114. halo=2
  115. ALLOCATE (oldmass_dat(region)%m(i1-halo:i2+halo, j1-halo:j2+halo, lmr))
  116. halo = wind_dat(region)%halo
  117. ALLOCATE (oldmass_dat(region)%am(i1-halo:i2+halo, j1-halo:j2+halo, 0:lmr+1))
  118. ALLOCATE (oldmass_dat(region)%bm(i1-halo:i2+halo, j1-halo:j2+halo, 0:lmr+1))
  119. ALLOCATE (oldmass_dat(region)%cm(i1-halo:i2+halo, j1-halo:j2+halo, 0:lmr+1))
  120. END DO
  121. ! array to work on row_root (only if really needed)
  122. if ( nred(1)/=0 .and. (npe_lon/=1)) then
  123. if(isRowRoot)then
  124. imr = im(1)
  125. lmr = lm(1)
  126. halo=m_dat(1)%halo
  127. allocate(m_alt1( 1-halo:imr+halo, j1:j2, lmr))
  128. allocate(m_alt2( imr, j1:j2, lmr))
  129. else
  130. allocate(m_alt2(1,1,1))
  131. endif
  132. endif
  133. ! set splitorder
  134. splitorderzoom = ' '
  135. splitorderzoom(1,1:nsplitsteps) = splitorder
  136. END SUBROUTINE INIT_CFL
  137. !EOC
  138. !--------------------------------------------------------------------------
  139. ! TM5 !
  140. !--------------------------------------------------------------------------
  141. !BOP
  142. !
  143. ! !IROUTINE: DONE_CFL
  144. !
  145. ! !DESCRIPTION: deallocate data for CFL
  146. !\\
  147. !\\
  148. ! !INTERFACE:
  149. !
  150. SUBROUTINE DONE_CFL
  151. !
  152. ! !REVISION HISTORY:
  153. !
  154. !EOP
  155. !------------------------------------------------------------------------
  156. !BOC
  157. integer :: region
  158. ! info ...
  159. write (gol,'(" ")'); call goPr
  160. write (gol,'("CFL info from check_cfl:")'); call goPr
  161. write (gol,'(" x: mloop_max, xim",i4,f10.4)') mloop_max(1,1), xim(1,1); call goPr
  162. write (gol,'(" y: mloop_max, xim",i4,f10.4)') mloop_max(1,2), xim(1,2); call goPr
  163. write (gol,'(" z: mloop_max, xim",i4,f10.4)') mloop_max(1,3), xim(1,3); call goPr
  164. ! clear
  165. do region=1, nregions
  166. deallocate(oldmass_dat(region)%m )
  167. deallocate(oldmass_dat(region)%am)
  168. deallocate(oldmass_dat(region)%bm)
  169. deallocate(oldmass_dat(region)%cm)
  170. end do
  171. if (allocated(m_alt1)) deallocate(m_alt1)
  172. if (allocated(m_alt2)) deallocate(m_alt2)
  173. END SUBROUTINE DONE_CFL
  174. !EOC
  175. !--------------------------------------------------------------------------
  176. ! TM5 !
  177. !--------------------------------------------------------------------------
  178. !BOP
  179. !
  180. ! !IROUTINE: CHECK_CFL
  181. !
  182. ! !DESCRIPTION:
  183. !\\
  184. !\\
  185. ! !INTERFACE:
  186. !
  187. SUBROUTINE CHECK_CFL( t1, t2, n, status )
  188. !
  189. ! !USES:
  190. !
  191. use GO, only : TDate, IncrDate, operator(+)
  192. use global_data, only : wind_dat
  193. use dims, only : ndyn, nsrce, nconv, nchem
  194. use dims, only : nread ! <-- 'ntimestep' from rcfile, read in 'start'
  195. use datetime, only : new_valid_timestep
  196. !
  197. ! !INPUT PARAMETERS:
  198. !
  199. type(TDate), intent(in) :: t1, t2
  200. !
  201. ! !INPUT/OUTPUT PARAMETERS:
  202. !
  203. integer, intent(inout) :: n ! number of time steps: n is increased until no cfl
  204. !
  205. ! !OUTPUT PARAMETERS:
  206. !
  207. integer, intent(out) :: status
  208. !
  209. ! !REVISION HISTORY:
  210. !
  211. !EOP
  212. !------------------------------------------------------------------------
  213. !BOC
  214. character(len=*), parameter :: rname = mname//'/Check_CFL'
  215. type(TDate) :: tr(2)
  216. integer :: i, ndyn_old
  217. integer :: region
  218. real :: fraction
  219. ! --- begin -------------------------------
  220. if ( okdebug ) then
  221. write (gol,'(" checking CFL : initial timestep of ",i5," sec with ", i3," timesteps")') ndyn, n; call goPr
  222. endif
  223. ! increase number of time steps until cfl ok or maximum exceeded
  224. global_iteration = 0
  225. do
  226. ! increase number of time steps:
  227. global_iteration = global_iteration + 1
  228. ! check ...
  229. if ( global_iteration > max_global_iteration ) then
  230. write (gol,'("exceeded maximum number of time steps")'); call goErr
  231. write (gol,'("in ",a)') rname; status=1; return; call goErr
  232. end if
  233. ! save current air masses in 'oldmass_dat'
  234. call store_masses( n )
  235. ! loop over number of ndyn timesteps;
  236. ! apply advection over complete (large) time interval
  237. do i = 1, n
  238. ! small time interval
  239. tr(1) = t1 + IncrDate(sec=(i-1)*ndyn)
  240. tr(2) = t1 + IncrDate(sec= i *ndyn)
  241. ! fill am/bm/cm with balanced mass flows, eventually time interpolated
  242. call Setup_MassFlow( tr, status )
  243. IF_ERROR_RETURN(status=1)
  244. ! first half step of advection:
  245. call determine_cfl_iter(1, status) ! xyz ...
  246. IF_NOTOK_RETURN(status=1)
  247. ! second half step if first is ok:
  248. if ( cfl_ok ) then
  249. call determine_cfl_iter(1, status) ! ... zyx
  250. IF_NOTOK_RETURN(status=1)
  251. end if
  252. if ( okdebug ) then
  253. write (gol,'(" checking CFL : time step ",i2," of ",i2," ; cfl_ok : ",l1)') i, n, cfl_ok; call goPr
  254. endif
  255. ! cfl not ok ? then leave loop and decrease time step:
  256. if (.not.cfl_ok) exit
  257. ! flag ...
  258. regionm_status(:) = 0
  259. end do
  260. ! restore massa at begin of time interval
  261. call restore_masses
  262. if ( .not. cfl_ok) then
  263. ndyn_old = ndyn
  264. ! new ndyn should be a denominator of e.g. 3 hour
  265. call new_valid_timestep( ndyn, nread, nread )
  266. if ( okdebug ) then
  267. write (gol,'(" checking CFL : reducing timestep to ",i5," sec")') ndyn; call goPr
  268. endif
  269. nsrce = ndyn
  270. nconv = ndyn
  271. nchem = ndyn
  272. n = nint( real(n*ndyn_old)/real(ndyn) ) ! should work!
  273. fraction = real(ndyn)/real(ndyn_old)
  274. do region = 1, nregions
  275. wind_dat(region)%am = wind_dat(region)%am*fraction
  276. wind_dat(region)%bm = wind_dat(region)%bm*fraction
  277. wind_dat(region)%cm = wind_dat(region)%cm*fraction
  278. enddo
  279. else
  280. exit
  281. end if
  282. end do ! global_iteration
  283. ! ok
  284. status = 0
  285. end subroutine Check_CFL
  286. !EOC
  287. !--------------------------------------------------------------------------
  288. ! TM5 !
  289. !--------------------------------------------------------------------------
  290. !BOP
  291. !
  292. ! !IROUTINE: SETUP_MASSFLOW
  293. !
  294. ! !DESCRIPTION: Fill am/bm/cm :
  295. !
  296. ! o interpolate balanced mass fluxes pu/pv in time (if necessary)
  297. ! o multiply with dt; store in am/bm/cm
  298. !\\
  299. !\\
  300. ! !INTERFACE:
  301. !
  302. subroutine Setup_MassFlow( tr, status )
  303. !
  304. ! !USES:
  305. !
  306. use GO, only : TDate
  307. use meteodata, only : pu_dat, pv_dat
  308. use meteo, only : TimeInterpolation
  309. use advect, only : dynam0
  310. !
  311. ! !INPUT PARAMETERS:
  312. !
  313. type(TDate), intent(in) :: tr(2)
  314. !
  315. ! !OUTPUT PARAMETERS:
  316. !
  317. integer, intent(out) :: status
  318. !
  319. ! !REVISION HISTORY:
  320. !
  321. !EOP
  322. !------------------------------------------------------------------------
  323. !BOC
  324. character(len=*), parameter :: rname = mname//'/Setup_MassFlow'
  325. integer :: n
  326. ! --- begin ----------------------------------
  327. !
  328. ! time interpolation
  329. !
  330. do n = 1, nregions
  331. !
  332. call TimeInterpolation( pu_dat(n), tr, status )
  333. IF_ERROR_RETURN(status=1)
  334. !
  335. call TimeInterpolation( pv_dat(n), tr, status )
  336. IF_ERROR_RETURN(status=1)
  337. !
  338. end do
  339. !
  340. ! fill am/bm/cm
  341. !
  342. do n = 1, nregions
  343. ! pu/pv to am/bm/cm
  344. call dynam0( n, status )
  345. IF_NOTOK_RETURN(status=1)
  346. end do
  347. status = 0
  348. end subroutine Setup_MassFlow
  349. !EOC
  350. ! ****************************************************************
  351. ! ***
  352. ! *** mass data
  353. ! ***
  354. ! ****************************************************************
  355. !--------------------------------------------------------------------------
  356. ! TM5 !
  357. !--------------------------------------------------------------------------
  358. !BOP
  359. !
  360. ! !IROUTINE: STORE_MASSES
  361. !
  362. ! !DESCRIPTION:
  363. !\\
  364. !\\
  365. ! !INTERFACE:
  366. !
  367. SUBROUTINE STORE_MASSES(n)
  368. !
  369. ! !USES:
  370. !
  371. use dims, only : nregions, tref, lm
  372. use global_data, only : wind_dat
  373. use meteodata, only : m_dat
  374. !
  375. ! !INPUT PARAMETERS:
  376. !
  377. integer, intent(in) :: n ! number of ndym timesteps...
  378. !
  379. ! !REVISION HISTORY:
  380. ! 10 Nov 2011 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  381. !
  382. !EOP
  383. !------------------------------------------------------------------------
  384. !BOC
  385. real, dimension(:,:,:), pointer :: m, am, bm, cm
  386. integer :: region, lmr, halo
  387. integer :: i1, i2, j1, j2
  388. integer :: ntimes
  389. ! --- begin --------------------------
  390. do region = 1, nregions
  391. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  392. lmr = lm(region)
  393. oldmass_dat(region)%m = m_dat(region)%data
  394. oldmass_dat(region)%am = wind_dat(region)%am
  395. oldmass_dat(region)%bm = wind_dat(region)%bm
  396. oldmass_dat(region)%cm = wind_dat(region)%cm
  397. regionm_status(region) = 0
  398. if (revert == -1) then
  399. m => m_dat(region)%data
  400. am => wind_dat(region)%am
  401. bm => wind_dat(region)%bm
  402. cm => wind_dat(region)%cm
  403. ! backward advection (two times since xyz..zyx)
  404. ntimes = 2*n*tref(region) ! fluxes for ndyn/2 s
  405. m(i1:i2,j1:j2,1:lmr) = m( i1:i2 , j1:j2 , 1:lmr ) &
  406. - ntimes*am( i1-1:i2-1, j1:j2 , 1:lmr ) & !east
  407. + ntimes*am( i1:i2 , j1:j2 , 1:lmr ) & !west
  408. - ntimes*bm( i1:i2 , j1:j2 , 1:lmr ) & !south
  409. + ntimes*bm( i1:i2 , j1+1:j2+1, 1:lmr ) & !north
  410. - ntimes*cm( i1:i2 , j1:j2 , 0:lmr-1) & !lower
  411. + ntimes*cm( i1:i2 , j1:j2 , 1:lmr ) !upper
  412. nullify(am)
  413. nullify(bm)
  414. nullify(cm)
  415. nullify(m)
  416. endif
  417. end do
  418. END SUBROUTINE STORE_MASSES
  419. !EOC
  420. !--------------------------------------------------------------------------
  421. ! TM5 !
  422. !--------------------------------------------------------------------------
  423. !BOP
  424. !
  425. ! !IROUTINE: RESTORE_MASSES
  426. !
  427. ! !DESCRIPTION:
  428. !\\
  429. !\\
  430. ! !INTERFACE:
  431. !
  432. SUBROUTINE RESTORE_MASSES
  433. !
  434. ! !USES:
  435. !
  436. use dims, only : nregions
  437. use global_data, only : wind_dat
  438. use meteodata, only : m_dat
  439. !
  440. ! !REVISION HISTORY:
  441. !
  442. !EOP
  443. !------------------------------------------------------------------------
  444. !BOC
  445. integer :: region
  446. do region = 1, nregions
  447. m_dat(region)%data = oldmass_dat(region)%m
  448. wind_dat(region)%am = oldmass_dat(region)%am
  449. wind_dat(region)%bm = oldmass_dat(region)%bm
  450. wind_dat(region)%cm = oldmass_dat(region)%cm
  451. enddo
  452. END SUBROUTINE RESTORE_MASSES
  453. !EOC
  454. ! ****************************************************************
  455. ! ***
  456. ! *** mass advection
  457. ! ***
  458. ! ****************************************************************
  459. !--------------------------------------------------------------------------
  460. ! TM5 !
  461. !--------------------------------------------------------------------------
  462. !BOP
  463. !
  464. ! !IROUTINE: DETERMINE_CFL_ITER
  465. !
  466. ! !DESCRIPTION:
  467. !
  468. ! Determine a 'global' iteration that is needed to prevent CFL violations.
  469. ! Normally the operator splitting sequence is:
  470. ! xyz vvzyx
  471. ! xyzvvzyx vzyxxyzv
  472. ! If a CFL violation will occur anywhere, the global timestep is reduced and
  473. ! the whole sequence is called two (or more) times. The advantage is that
  474. ! 'masses' are largely restored by advection from neighbouring cells
  475. !
  476. !\\
  477. !\\
  478. ! !INTERFACE:
  479. !
  480. SUBROUTINE DETERMINE_CFL_ITER( REGION, STATUS )
  481. !
  482. ! !USES:
  483. !
  484. use dims, only: parent, tref, revert, ndyn
  485. !
  486. ! !INPUT PARAMETERS:
  487. !
  488. integer, intent(in) :: region
  489. !
  490. ! !OUTPUT PARAMETERS:
  491. !
  492. integer, intent(out) :: status
  493. !
  494. ! !REVISION HISTORY:
  495. !
  496. !EOP
  497. !------------------------------------------------------------------------
  498. !BOC
  499. character(len=*), parameter :: rname = mname//'/determine_cfl_iter'
  500. integer :: i, tref_
  501. integer, dimension(3) :: ll,uu
  502. ! set flag to signal cfl violations
  503. cfl_ok = .true.
  504. ! determine refinement factor with respect to the parent
  505. tref_ = tref(region)/tref(parent(region))
  506. do i=1,tref_
  507. call do_steps(region, status)
  508. IF_NOTOK_RETURN(status=1)
  509. if (.not. cfl_ok) return
  510. !do the remaining steps if necessary...!
  511. if (mod(regionm_status(region),n_operators) /= 0 ) then
  512. call do_steps(region, status)
  513. IF_NOTOK_RETURN(status=1)
  514. if(.not. cfl_ok) return
  515. end if
  516. end do
  517. END SUBROUTINE DETERMINE_CFL_ITER
  518. !EOC
  519. !--------------------------------------------------------------------------
  520. ! TM5 !
  521. !--------------------------------------------------------------------------
  522. !BOP
  523. !
  524. ! !IROUTINE: DO_STEPS
  525. !
  526. ! !DESCRIPTION:
  527. !\\
  528. !\\
  529. ! !INTERFACE:
  530. !
  531. subroutine do_steps(region, status)
  532. !
  533. ! !INPUT PARAMETERS:
  534. !
  535. integer, intent(in) :: region
  536. !
  537. ! !OUTPUT PARAMETERS:
  538. !
  539. integer, intent(out) :: status
  540. !
  541. ! !REVISION HISTORY:
  542. !
  543. !EOP
  544. !------------------------------------------------------------------------
  545. !BOC
  546. character(len=*), parameter :: rname = mname//'/do_steps'
  547. integer :: i123, reg, rgi, j
  548. character :: tobedone
  549. character(len=1) :: next_step, prev_step
  550. ! --- begin ---
  551. status=0
  552. if ( okdebug ) then
  553. write(gol,*) 'do_steps: region ',region
  554. call goPr
  555. end if
  556. do i123=1,n_operators
  557. next_step = splitorderzoom(region,regionm_status(region)+1)
  558. if ( regionm_status(region) /= 0 ) then
  559. prev_step = splitorderzoom(region,regionm_status(region))
  560. else
  561. prev_step = ' '
  562. end if
  563. if (okdebug) then
  564. ! it's only to make work of the code visible -- step to be done
  565. ! will be printed with capital letter (X,Y or Z)
  566. do reg=1,region
  567. tobedone = ' '
  568. if ( reg == region ) tobedone = upper(next_step)
  569. write(gol,*) 'do_steps: ',reg,': ', &
  570. splitorderzoom(reg,1:regionm_status(reg)),tobedone
  571. call goPr
  572. enddo
  573. endif
  574. tobedone = upper(next_step)
  575. select case(next_step)
  576. case('x')
  577. call advectmx
  578. case('y')
  579. call dynamvm
  580. case('z')
  581. call dynamwm
  582. case default
  583. write(gol,*)'do_steps: strange value in splitorderzoom: ', &
  584. splitorderzoom(region,regionm_status(region)) ; call goErr
  585. write(gol,*)'do_steps: (must be x, y or z)'; call goErr
  586. status=1; TRACEBACK
  587. return
  588. end select
  589. if (.not. cfl_ok) return
  590. regionm_status(region) = regionm_status(region)+1
  591. ! these statements are needed when
  592. ! more processes are involved that change rm
  593. ! for instance emissions.
  594. ! for m-advection only just leave when ready
  595. if ( mod(regionm_status(region),n_operators) == 0 ) then
  596. exit ! e.g.after zyx or xyz
  597. end if
  598. end do
  599. END SUBROUTINE DO_STEPS
  600. !EOC
  601. !--------------------------------------------------------------------------
  602. ! TM5 !
  603. !--------------------------------------------------------------------------
  604. !BOP
  605. !
  606. ! !FUNCTION: UPPER
  607. !
  608. ! !DESCRIPTION:
  609. !\\
  610. !\\
  611. ! !INTERFACE:
  612. !
  613. character function upper(xyz)
  614. !
  615. ! !INPUT PARAMETERS:
  616. !
  617. character(1), intent(in) :: xyz
  618. !
  619. ! !REVISION HISTORY:
  620. !
  621. !EOP
  622. !------------------------------------------------------------------------
  623. !BOC
  624. if (xyz=='x') then
  625. upper = 'X'
  626. else if (xyz=='y') then
  627. upper = 'Y'
  628. else if (xyz=='z') then
  629. upper = 'Z'
  630. else
  631. upper = '_'
  632. end if
  633. end function upper
  634. !EOC
  635. !--------------------------------------------------------------------------
  636. ! TM5 !
  637. !--------------------------------------------------------------------------
  638. !BOP
  639. !
  640. ! !IROUTINE: ADVECTMX
  641. !
  642. ! !DESCRIPTION: does reduced grid pre-/postprocessing and calls dynamu
  643. !
  644. !\\
  645. !\\
  646. ! !INTERFACE:
  647. !
  648. SUBROUTINE ADVECTMX
  649. !
  650. ! !USES:
  651. !
  652. use dims, only : im, jm, lm
  653. use redgridZoom, only : grid_reduced, nred, uni2red_mf, idle_xadv
  654. use global_data, only : wind_dat
  655. use meteodata, only : m_dat
  656. use partools, only : npe_lon, myid, par_broadcast
  657. !
  658. ! !REVISION HISTORY:
  659. ! written by mike botchev, march-june 1999
  660. ! 30 Jan 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  661. ! 20 Dec 2012 - P. Le Sager - fixed for reduced grid
  662. !
  663. !EOP
  664. !------------------------------------------------------------------------
  665. !BOC
  666. character(len=*), parameter :: rname = mname//'/advectmx'
  667. real, dimension(:,:,:), pointer :: m
  668. real, dimension(:,:,:), pointer :: am
  669. real, dimension(:,:,:), allocatable :: m_uni ! m backup
  670. real, dimension(:,:,:), allocatable :: am_uni ! am backup
  671. integer :: region, imr,jmr,lmr, i1, i2, j1, j2, halo, status
  672. ! Block bounds
  673. region=1
  674. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  675. lmr = lm(region)
  676. ! Transform to the reduced grid
  677. if ( grid_reduced ) then
  678. halo = m_dat(region)%halo
  679. allocate( m_uni( i1-halo:i2+halo, j1-halo:j2+halo, lmr ))
  680. halo = wind_dat(region)%halo
  681. allocate(am_uni( i1-halo:i2+halo, j1-halo:j2+halo, 0:lmr+1))
  682. am => wind_dat(region)%am
  683. m => m_dat(region)%data
  684. ! take care of BC for uniform am, so that am_uni is correct when
  685. ! updating m_uni after the call to dynamun
  686. if (npe_lon==1) then
  687. am(0,j1:j2,:) = am(im(region),j1:j2,:)
  688. else
  689. call UPDATE_HALO_JBAND(dgrid(region), am, halo, status )
  690. IF_NOTOK_RETURN(status=1)
  691. endif
  692. ! save non-reduced m and am in m_uni and am_uni:
  693. m_uni = m
  694. am_uni = am
  695. ! reduce m (simplified local routine)
  696. call uni2red(region,i1,i2,j1,j2,status)
  697. IF_NOTOK_RETURN(status=1)
  698. ! reduce am (and update halo of reduced zonal bands)
  699. call uni2red_mf(region,i1,i2,j1,j2, status)
  700. IF_NOTOK_RETURN(status=1)
  701. end if
  702. if (.not.idle_xadv) then
  703. CALL DYNAMUM (region,j1,j2,1,lmr)
  704. endif
  705. ! idle cores need to know about cfl_ok
  706. if (nred(region)/=0 .and. (npe_lon/=1)) then ! if on a row of many cores that has reduced grid
  707. call par_broadcast(cfl_ok, status, row=.true.)
  708. endif
  709. ! Transform from the reduced grid
  710. if ( grid_reduced ) then
  711. ! advection on uniform grid
  712. m_uni(i1:i2,j1:j2,1:lmr) = m_uni(i1:i2,j1:j2,1:lmr) + &
  713. am_uni(i1-1:i2-1,j1:j2,1:lmr) - am_uni(i1:i2,j1:j2,1:lmr)
  714. ! refill m with m_uni, but only boxes that have been reduced
  715. halo = m_dat(region)%halo
  716. call red2uni(region, i1, i2, j1, j2, halo, m_uni, status)
  717. IF_NOTOK_RETURN(status=1)
  718. ! recreate rm/rxm/rym/rzm by using equal masses (not m_uni)
  719. !call red2uni_em(region)
  720. ! recreate am:
  721. am = am_uni
  722. nullify(am)
  723. nullify(m)
  724. deallocate(am_uni)
  725. deallocate(m_uni)
  726. endif
  727. END SUBROUTINE ADVECTMX
  728. !EOC
  729. !--------------------------------------------------------------------------
  730. ! TM5 !
  731. !--------------------------------------------------------------------------
  732. !BOP
  733. !
  734. ! !IROUTINE: UNI2RED
  735. !
  736. ! !DESCRIPTION: transforms data (air mass only) from uniform grid to reduced grid
  737. !
  738. !\\
  739. !\\
  740. ! !INTERFACE:
  741. !
  742. subroutine uni2red(region,i1,i2,j1,j2,status)
  743. !
  744. ! !USES:
  745. !
  746. use dims, only : im,jm,lm
  747. use redgridZoom, only : nred, clustsize, jred, imredj
  748. use meteodata, only : m_dat
  749. use partools, only : isRowRoot, npe_lon
  750. use tm5_distgrid, only : dgrid, gather_j_band
  751. !
  752. ! !INPUT PARAMETERS:
  753. !
  754. integer, intent(in) :: region,i1,i2,j1,j2
  755. !
  756. ! !OUTPUT PARAMETERS:
  757. !
  758. integer, intent(out) :: status
  759. !
  760. ! !REVISION HISTORY:
  761. ! written by mike botchev, march-june 1999 ; modified by Maarten Krol, dec 2002
  762. !
  763. ! 19 Dec 2012 - P. Le Sager - modified for TM5-MP (decomposition along latitudes only)
  764. !
  765. ! !REMARKS:
  766. ! - simplified version of redgridZoom/uni2red : applied to air mass only, not to the tracers.
  767. !
  768. !EOP
  769. !------------------------------------------------------------------------
  770. !BOC
  771. character(len=*), parameter :: rname = mname//'/uni2red'
  772. real, dimension(:,:,:), pointer :: m, m_alt
  773. integer :: halo,i,ie,is,j,l,lrg,redfact,lmr,imr
  774. real :: summ
  775. ! start
  776. m => m_dat(region)%data
  777. lmr=lm(region)
  778. imr=im(region)
  779. ! Two scenarios
  780. if (npe_lon /= 1) then
  781. !
  782. ! decomposition along longitudes => work on row_root
  783. !
  784. if (nred(region)/=0) then ! some reduce grid on this tile
  785. ! gather m (need to remove i-halo)
  786. allocate(m_alt( i1:i2, j1:j2, lmr))
  787. m_alt = m(i1:i2,j1:j2,:)
  788. CALL GATHER_J_BAND(dgrid(region), m_alt, m_alt2, status, jref=j1, rowcom=.true.)
  789. IF_NOTOK_RETURN(status=1)
  790. deallocate(m_alt)
  791. if (isRowRoot) then
  792. m_alt1( 1:imr,:,:) = m_alt2
  793. m_alt1( 0,:,:) = m_alt1( imr,:,:)
  794. m_alt1( -1,:,:) = m_alt1(imr-1,:,:)
  795. do lrg=1,nred(region)
  796. j = jred(lrg,region)
  797. redfact=clustsize(j,region)
  798. do l=1,lmr
  799. do i = 1,imredj(j,region)
  800. ! the is:ie array section will be reduced to i
  801. is = (i-1)*redfact + 1
  802. ie = i*redfact
  803. summ = sum(m_alt1(is:ie,j,l))
  804. m_alt1(i,j,l) = summ
  805. end do !i
  806. end do !l
  807. enddo
  808. endif
  809. endif
  810. else
  811. !
  812. ! Reduced grid without longitudinal decomposition
  813. !
  814. do lrg=1,nred(region)
  815. j = jred(lrg,region)
  816. redfact=clustsize(j,region)
  817. do l=1,lmr
  818. do i = 1,imredj(j,region)
  819. ! the is:ie array section will be reduced to i
  820. is = (i-1)*redfact + 1
  821. ie = i*redfact
  822. summ = sum(m(is:ie,j,l))
  823. m(i,j,l) = summ
  824. end do !i
  825. end do !l
  826. enddo
  827. endif
  828. nullify(m)
  829. status=0
  830. END SUBROUTINE UNI2RED
  831. !EOC
  832. !--------------------------------------------------------------------------
  833. ! TM5 !
  834. !--------------------------------------------------------------------------
  835. !BOP
  836. !
  837. ! !IROUTINE: RED2UNI
  838. !
  839. ! !DESCRIPTION: transforms data from reduced grid back to uniform grid
  840. !
  841. !\\
  842. !\\
  843. ! !INTERFACE:
  844. !
  845. subroutine red2uni(region, i1, i2, j1, j2, halo, m_uni, status)
  846. !
  847. ! !USES:
  848. !
  849. use dims, only : im, lm
  850. use redgridZoom, only : nred, clustsize, jred, imredj
  851. use meteodata, only : m_dat
  852. use partools, only : isRowRoot, npe_lon
  853. use tm5_distgrid, only : dgrid, scatter_j_band
  854. !
  855. ! !INPUT PARAMETERS:
  856. !
  857. integer, intent(in) :: region, i1, i2, j1, j2, halo
  858. real, intent(in) :: m_uni(i1-halo:,j1-halo:,1:)
  859. !
  860. ! !OUTPUT PARAMETERS:
  861. !
  862. integer, intent(out) :: status
  863. !
  864. ! !REVISION HISTORY:
  865. ! written by mike botchev, march-june 1999
  866. ! 20 Dec 2012 - P. Le Sager - TM5-MP version
  867. !
  868. ! !REMARKS:
  869. ! - simplified version of redgridZoom/red2uni : applied to air mass only, not to the tracers
  870. !
  871. !EOP
  872. !------------------------------------------------------------------------
  873. !BOC
  874. character(len=*), parameter :: rname = mname//'_MOD_red2uni'
  875. real,dimension(:,:,:), pointer :: m, m_
  876. integer :: i, j, l, ie, is, lrg, n, redfact, lmr, imr
  877. ! start
  878. m => m_dat(region)%data
  879. lmr=lm(region)
  880. imr=im(region)
  881. ! Two scenarios
  882. if ((npe_lon /= 1).and.(nred(region)>0)) then
  883. !
  884. ! decomposition along longitudes => work on row_root
  885. !
  886. ! (1) use m_alt1 to fill m in bands that are not reduced - only if necessary
  887. if (nred(region)< (j2-j1+1)) then
  888. allocate(m_( i1:i2, j1:j2, lmr))
  889. if (isRowRoot) m_alt2 = m_alt1( 1:imr,:,:)
  890. CALL SCATTER_J_BAND(dgrid(region), m_, m_alt2, status, jref=j1, rowcom=.true.)
  891. IF_NOTOK_RETURN(status=1)
  892. m(i1:i2,j1:j2,:) = m_
  893. deallocate(m_)
  894. endif
  895. ! (2) bands with reduced grid, just use m_uni
  896. if (nred(region)/=0) then
  897. do lrg=1,nred(region)
  898. j = jred(lrg,region)
  899. m(:,j,:)= m_uni(:,j,:)
  900. end do
  901. endif
  902. ! update halo
  903. call UPDATE_HALO_JBAND(dgrid(region), m, m_dat(region)%halo, status )
  904. else
  905. !
  906. ! Reduced grid without longitudinal decomposition
  907. !
  908. do lrg=1,nred(region)
  909. j = jred(lrg,region)
  910. redfact=clustsize(j,region)
  911. m(i1:i2,j,:)= m_uni(i1:i2,j,:)
  912. m(0,j,:) = m(imr,j,:)
  913. end do
  914. endif
  915. nullify(m)
  916. status=0
  917. end subroutine red2uni
  918. !EOC
  919. !--------------------------------------------------------------------------
  920. ! TM5 !
  921. !--------------------------------------------------------------------------
  922. !BOP
  923. !
  924. ! !IROUTINE: RED2UNI_EM
  925. !
  926. ! !DESCRIPTION: transforms data from reduced grid back to uniform grid
  927. !
  928. ! ****************************************************************
  929. ! ***** COMMENTED - NOT PORTED TO TM5MP WITH NPE_LON /=1 !! ******
  930. ! ****************************************************************
  931. !
  932. !
  933. !\\
  934. !\\
  935. ! !INTERFACE:
  936. !
  937. !PLS subroutine red2uni_em(region, i1, i2, j1, j2)
  938. !PLS !
  939. !PLS ! !USES:
  940. !PLS !
  941. !PLS use dims, only : im,jm,lm
  942. !PLS use redgridZoom, only : nred, clustsize, jred, imredj
  943. !PLS use meteodata, only : m_dat
  944. !PLS !
  945. !PLS ! !INPUT PARAMETERS:
  946. !PLS !
  947. !PLS integer, intent(in) :: region, i1, i2, j1, j2
  948. !PLS !
  949. !PLS ! !REVISION HISTORY:
  950. !PLS ! written by mike botchev, march-june 1999
  951. !PLS ! 20 Dec 2012 - P. Le Sager - TM5-MP version
  952. !PLS !
  953. !PLS ! !REMARKS:
  954. !PLS ! - simplified version of redgridZoom/red2uni_em : applied to air mass only,
  955. !PLS ! no the tracers
  956. !PLS !
  957. !PLS !EOP
  958. !PLS !------------------------------------------------------------------------
  959. !PLS !BOC
  960. !PLS
  961. !PLS ! local
  962. !PLS real,dimension(:,:,:), pointer :: m
  963. !PLS integer i,ie,is,j,l,lrg,redfact,lmr
  964. !PLS real mass
  965. !PLS ! start
  966. !PLS lmr=lm(region)
  967. !PLS m => m_dat(region)%data
  968. !PLS do lrg=1,nred(region)
  969. !PLS j = jred(lrg,region)
  970. !PLS redfact=clustsize(j,region)
  971. !PLS do l=1,lmr
  972. !PLS do i = imredj(j,region),1,-1
  973. !PLS is = (i-1)*redfact + 1
  974. !PLS ie = i*redfact
  975. !PLS mass=m(i,j,l); m(is:ie,j,l)= mass/(ie-is+1)
  976. !PLS enddo
  977. !PLS m(0,j,l) = m(im(region),j,l)
  978. !PLS end do
  979. !PLS end do
  980. !PLS nullify(m)
  981. !PLS end subroutine red2uni_em
  982. !EOC
  983. !--------------------------------------------------------------------------
  984. ! TM5 !
  985. !--------------------------------------------------------------------------
  986. !BOP
  987. !
  988. ! !IROUTINE: DYNAMUM
  989. !
  990. ! !DESCRIPTION:
  991. !\\
  992. !\\
  993. ! !INTERFACE:
  994. !
  995. subroutine dynamum(region,js,je,ls,le)
  996. !
  997. ! !USES:
  998. !
  999. use dims, only : parent, im, lm, zero, one
  1000. use redgridZoom, only : grid_reduced, nred, imredj, mfl_alt1
  1001. use global_data, only : wind_dat
  1002. use meteodata, only : m_dat
  1003. use partools, only : Par_Reduce, npe_lon, par_broadcast, isRowRoot
  1004. !
  1005. ! !INPUT PARAMETERS:
  1006. !
  1007. integer,intent(in) :: region
  1008. integer,intent(in) :: js
  1009. integer,intent(in) :: je
  1010. integer,intent(in) :: ls
  1011. integer,intent(in) :: le
  1012. !
  1013. ! !REMARKS:
  1014. ! - no J-loop anymore to work on lat-lon domain decomposition [we could keep
  1015. ! the L-loop if faster]
  1016. !EOP
  1017. !------------------------------------------------------------------------
  1018. !BOC
  1019. real, dimension(:,:,:), pointer :: m, am
  1020. real, dimension(:,:,:), allocatable :: mnew, mx
  1021. integer :: i, is, j, l, n, i1, i2, j1, j2, status
  1022. integer :: lmr, nloop, iloop, iemax
  1023. integer, allocatable :: ie(:)
  1024. real :: max_alpha
  1025. real :: my_alpha, alpha, alpha2, x, rmold
  1026. logical :: cfl_okl
  1027. integer, parameter :: max_nloop = 10
  1028. ! ------------
  1029. ! Bounds
  1030. ! ------------
  1031. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2)
  1032. lmr = lm(region)
  1033. allocate(ie(j1:j2))
  1034. ! ------------
  1035. ! Work arrays
  1036. ! ------------
  1037. if ( ( grid_reduced ) .and. (npe_lon /= 1) .and. (nred(region)/=0) ) then
  1038. m => m_alt1
  1039. am => mfl_alt1
  1040. is=1
  1041. ie=im(region)
  1042. iemax=maxval(imredj(j1:j2,region))
  1043. else
  1044. m => m_dat(region)%data ! halo=2, 1:lmr
  1045. am => wind_dat(region)%am ! halo=1; 0:lmr+1
  1046. is=i1
  1047. ie=i2
  1048. iemax=i2
  1049. endif
  1050. allocate(mnew( is:iemax, j1:j2, ls:le)) ! halo=0; ls:le = 1:lmr
  1051. allocate( mx(is-1:iemax+1, j1-1:j2+1, ls:le)) ! halo=1, temp arr to store initial mass
  1052. ! ------------
  1053. ! Reduced grid & halo
  1054. ! --------------
  1055. if ( ( grid_reduced .and. npe_lon==1 ).or.(grid_reduced .and. npe_lon/=1.and.nred(region)>0)) then
  1056. ie = imredj(j1:j2,region)
  1057. do j=j1,j2
  1058. m( 0, j,:) = m(ie(j),j,:)
  1059. m(ie(j)+1, j,:) = m( 1,j,:)
  1060. end do
  1061. ! halo of am is filled in advectmx (thru uni2red_mf for reduced part)
  1062. else
  1063. CALL UPDATE_HALO_JBAND( dgrid(region), am, wind_dat(region)%halo, status)
  1064. ! IF_NOTOK_RETURN(status=1)
  1065. CALL UPDATE_HALO_JBAND( dgrid(region), m, m_dat(region)%halo, status)
  1066. ! IF_NOTOK_RETURN(status=1)
  1067. end if
  1068. ! ------------
  1069. ! Determine number of loops required to avoid CFLs
  1070. ! -----------------
  1071. nloop = 1 ! default run the loop one time!
  1072. alpha = 2.0
  1073. max_alpha = 0.0
  1074. !CMK added oct2003: nloop limit..
  1075. do while ( abs(alpha) >= one .and. nloop < max_nloop )
  1076. ! copy intial mass to temp array
  1077. do j=js,je
  1078. mx(is-1:ie(j)+1,j,:) = m(is-1:ie(j)+1,j,ls:le)
  1079. end do
  1080. xloop: do iloop = 1, nloop
  1081. cfl_okl = .true.
  1082. lloop: do l=ls,le
  1083. do j=js,je
  1084. do i=is-1,ie(j)
  1085. if (am(i,j,l)>=zero) then
  1086. my_alpha=am(i,j,l)/mx(i,j,l)
  1087. else
  1088. my_alpha=am(i,j,l)/mx(i+1,j,l)
  1089. end if
  1090. max_alpha = max(max_alpha, abs(my_alpha))
  1091. if((abs(my_alpha)>=one)) then
  1092. exit lloop
  1093. end if
  1094. end do
  1095. end do
  1096. end do lloop
  1097. if (grid_reduced .and. npe_lon/=1) then
  1098. if (nred(region)==0) then
  1099. call Par_Reduce(max_alpha, 'MAX', alpha2, status, all=.true., row=.true.)
  1100. max_alpha=alpha2
  1101. end if
  1102. if(isRowRoot)then
  1103. call Par_Reduce(max_alpha, 'MAX', alpha, status, all=.true., col=.true.)
  1104. endif
  1105. if (nred(region)==0) then
  1106. call par_broadcast(alpha, status, row=.true.)
  1107. endif
  1108. else
  1109. call Par_Reduce(max_alpha, 'MAX', alpha, status, all=.true.)
  1110. endif
  1111. if(status==1) then
  1112. write(gol,*) "error par_all_reduce";call goPr
  1113. end if
  1114. if (alpha>=one) then
  1115. cfl_okl = .false.
  1116. exit xloop
  1117. end if
  1118. ! update mass for next iteration
  1119. if (iloop/=nloop) then
  1120. ! [is:ie]
  1121. do j=js,je
  1122. mx(is:ie(j),j,:) = mx(is:ie(j),j,:) + am(is-1:ie(j)-1,j,ls:le) - am(is:ie(j),j,ls:le)
  1123. end do
  1124. ! bc
  1125. if ( ( grid_reduced .and. npe_lon==1 ).or.(grid_reduced .and. npe_lon/=1.and.nred(region)>0)) then
  1126. do j=js,je
  1127. mx( 0, j,:) = mx(ie(j),j,ls:le)
  1128. mx(ie(j)+1, j,:) = mx( 1,j,ls:le)
  1129. end do
  1130. else
  1131. call UPDATE_HALO_JBAND( dgrid(region), mx, 1, status)
  1132. ! IF_NOTOK_RETURN(status=1)
  1133. end if
  1134. end if
  1135. end do xloop
  1136. if(.not.cfl_okl) then
  1137. do j=js,je
  1138. ! reduce mass flux
  1139. am(is-1:ie(j),j,ls:le) = am(is-1:ie(j),j,ls:le)*nloop/(nloop+1)
  1140. !FASTER: am(is-1:ie,:,:) = am(is-1:ie,:,:)*(nloop/(nloop+1))
  1141. end do
  1142. if ( okdebug ) then
  1143. write(gol,*) 'dynamu: nloop increased to', nloop + 1; call goPr
  1144. write(gol,*) 'dynamu: alpha is', alpha ; call goPr
  1145. end if
  1146. nloop = nloop + 1
  1147. max_alpha = 0.0
  1148. if (nloop == max_nloop) then
  1149. ! not good solution found: set flag and return
  1150. ! note that am is restored in the calling routines
  1151. ! and m will be restored also!
  1152. cfl_ok = .false.
  1153. deallocate(mx, ie)
  1154. deallocate(mnew)
  1155. nullify(am)
  1156. nullify(m)
  1157. return
  1158. endif
  1159. end if
  1160. end do !while alpha>1
  1161. mloop_max(region,1) = max(mloop_max(region,1),nloop)
  1162. xim(region,1) = max(xim(region,1),alpha)
  1163. ! CFL loop
  1164. ! do iloop = 1,nloop
  1165. !
  1166. ! ! calculate new air mass distribution
  1167. ! mnew(is:ie,js:je,ls:le) = m(is:ie,js:je,ls:le) + am(is-1:ie-1,js:je,ls:le)-am(is:ie,js:je,ls:le)
  1168. ! m(is:ie,js:je,ls:le) = mnew(is:ie,js:je,ls:le)
  1169. !
  1170. ! end do ! iloop : SHOULD BE THE SAME AS
  1171. do j=js,je
  1172. ! calculate new air mass distribution
  1173. m(is:ie(j),j,ls:le) = m(is:ie(j),j,ls:le) + nloop*( am(is-1:ie(j)-1,j,ls:le)-am(is:ie(j),j,ls:le) )
  1174. ! restore 'old' am
  1175. am(is-1:ie(j),j,ls:le) = am(is-1:ie(j),j,ls:le)*nloop
  1176. end do
  1177. !Done
  1178. deallocate(mnew, mx, ie)
  1179. nullify(am)
  1180. nullify(m)
  1181. end subroutine dynamum
  1182. !EOC
  1183. !--------------------------------------------------------------------------
  1184. ! TM5 !
  1185. !--------------------------------------------------------------------------
  1186. !BOP
  1187. !
  1188. ! !IROUTINE: DYNAMVM
  1189. !
  1190. ! !DESCRIPTION: south-north tracer transport: calculate amount of tracer moved in a
  1191. ! south-north advection substep
  1192. !
  1193. ! method : slopes scheme
  1194. ! reference : Russel and Lerner, 1979
  1195. !\\
  1196. !\\
  1197. ! !INTERFACE:
  1198. !
  1199. SUBROUTINE DYNAMVM
  1200. !
  1201. ! !USES:
  1202. !
  1203. use dims, only : yref, zref, jm, lm
  1204. use dims, only : parent, nregions
  1205. use dims, only : zero, one
  1206. use global_data, only : wind_dat
  1207. use meteodata, only : m_dat
  1208. use chem_param, only : ntracet
  1209. use partools, only : Par_Reduce
  1210. !
  1211. ! !REVISION HISTORY:
  1212. ! programmed by mh mpi HH 23-feb-1994
  1213. ! fixed bug in calculating maximum courant number
  1214. ! mh, Thu, Feb 24, 1994 12:49:27
  1215. ! included code for limits of slopes to prevent negative tracer
  1216. ! masses mh, 20-jun-1994
  1217. !
  1218. ! zoom version written by mike botchev, march-june 1999
  1219. ! 30 Jan 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  1220. !
  1221. !EOP
  1222. !------------------------------------------------------------------------
  1223. !BOC
  1224. real, dimension(:,:,:), pointer :: m,bm
  1225. real, dimension(:,:), allocatable :: mx
  1226. real, dimension(:,:,:), allocatable :: mnew
  1227. integer :: i,j,je,js,l,n,iee,iss
  1228. integer :: lmr
  1229. integer :: yref_
  1230. real :: sfs,sfzs,sfn,sfzn
  1231. real :: my_beta, beta, max_beta
  1232. integer :: iloop, nloop
  1233. logical :: cfl_okl, SouthPole, NorthPole, SouthBorder, NorthBorder
  1234. integer :: lrg, redfact, ixe, ixs
  1235. real :: summ
  1236. integer :: i1, i2, j1, j2, jss, jee, status
  1237. integer :: is,ie,ls,le
  1238. integer, parameter :: region=1
  1239. integer, parameter :: max_nloop = 1
  1240. !--- start ---
  1241. ! compute refinement factors with respect to the parent
  1242. yref_ = yref(region)/yref(parent(region))
  1243. ! Indices
  1244. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2,&
  1245. hasSouthPole=SouthPole, hasNorthPole=NorthPole, &
  1246. hasSouthBorder=SouthBorder, hasNorthBorder=NorthBorder )
  1247. lmr = lm(region)
  1248. js = j1
  1249. je = j2
  1250. is=i1
  1251. ie=i2
  1252. ls=1
  1253. le=lmr
  1254. ! Work arrays
  1255. allocate(mnew( i1:i2, j1:j2, ls:le)) ! halo=0; ls:le = 1:lmr
  1256. m => m_dat(region)%data ! halo=2, 1:lmr
  1257. bm => wind_dat(region)%bm ! halo=1; 0:lmr+1
  1258. call UPDATE_HALO( dgrid(region), m, m_dat(region)%halo, status)
  1259. call UPDATE_HALO( dgrid(region), bm, wind_dat(region)%halo, status)
  1260. ! Reduce work domain if border of zoom region, and take care of poles
  1261. if (NorthBorder) then ! j2=jmr by design
  1262. je = j2 - yref_ + 1
  1263. if (NorthPole) je=j2-1
  1264. endif
  1265. if (SouthBorder) then ! j1=1 by design
  1266. js = j1 + yref_ - 1
  1267. if (SouthPole) js=j1+1
  1268. endif
  1269. ! indices for mass update
  1270. jss=js
  1271. jee=je
  1272. if (SouthPole) jss=js-1 ! =j1=1
  1273. if (NorthPole) jee=je+1 ! =j2=jmr
  1274. ! loop over vertical layers
  1275. LEVELS: do l=ls,le
  1276. ! compute all inner fluxes
  1277. ! f(*,j,*) is flux entering j-th cell from below?cmk
  1278. nloop = 1 ! determine nloop per layer!
  1279. beta = 2.0
  1280. max_beta = 0.0
  1281. ! allocate(mx(is:ie,js-1:je+1))
  1282. allocate(mx( i1-1:i2+1, j1-1:j2+1) )
  1283. do while(abs(beta) >= one .and. nloop <= max_nloop)
  1284. mx(is:ie,js-1:je+1) = m(is:ie,js-1:je+1,l)
  1285. xloop: do iloop = 1, nloop
  1286. cfl_okl = .true.
  1287. uloop:do j=js, je+1
  1288. do i=is, ie
  1289. if (bm(i,j,l)>=zero) then
  1290. my_beta=bm(i,j,l)/mx(i,j-1)
  1291. else
  1292. my_beta=bm(i,j,l)/mx(i,j)
  1293. end if
  1294. max_beta = max(max_beta, abs(my_beta))
  1295. if (abs(my_beta)>=one) then
  1296. exit uloop
  1297. end if
  1298. end do !i
  1299. end do uloop !j
  1300. call Par_Reduce(max_beta, 'MAX', beta, status, all=.true.)
  1301. if(status==1) then
  1302. write(gol,*) "error par_all_reduce";call goErr
  1303. end if
  1304. xim(region,2) = max(xim(region,2), beta)
  1305. if (beta>=one) then
  1306. cfl_okl = .false.
  1307. exit xloop
  1308. end if
  1309. if (iloop/=nloop) then
  1310. mx(is:ie,jss:jee) = mx(is:ie,jss:jee) + bm(is:ie,jss:jee,l) - bm(is:ie,jss+1:jee+1,l)
  1311. CALL UPDATE_HALO( dgrid(region), mx, 1, status)
  1312. end if
  1313. end do xloop
  1314. if ( .not. cfl_okl ) then
  1315. ! allow NO iterations in y-dir
  1316. cfl_ok = .false.
  1317. if ( okdebug) print *,'dynamv: ', i,j,l, beta
  1318. deallocate(mx)
  1319. deallocate(mnew)
  1320. nullify(m)
  1321. nullify(bm)
  1322. return
  1323. end if
  1324. end do !while
  1325. deallocate(mx)
  1326. mloop_max(region,2) = max(mloop_max(region,2),nloop)
  1327. ! calculate new air mass distribution, and store it in m array
  1328. do iloop = 1,nloop
  1329. mnew(is:ie,jss:jee,l) = m(is:ie,jss:jee,l) + bm(is:ie,jss:jee,l) - bm(is:ie,jss+1:jee+1,l)
  1330. m(is:ie,jss:jee,l) = mnew(is:ie,jss:jee,l)
  1331. end do
  1332. ! restore old bm's
  1333. bm(:,:,l) = bm(:,:,l)*nloop
  1334. end do LEVELS ! end of l-loop over vertical layers....
  1335. deallocate(mnew)
  1336. nullify(m)
  1337. nullify(bm)
  1338. END SUBROUTINE DYNAMVM
  1339. !EOC
  1340. !--------------------------------------------------------------------------
  1341. ! TM5 !
  1342. !--------------------------------------------------------------------------
  1343. !BOP
  1344. !
  1345. ! !IROUTINE: DYNAMWM
  1346. !
  1347. ! !DESCRIPTION: vertical tracer transport: calculate amount of tracer moved in a
  1348. ! vertical advection substep
  1349. !
  1350. ! method : slopes scheme
  1351. ! reference : Russel and Lerner, 1979
  1352. !\\
  1353. !\\
  1354. ! !INTERFACE:
  1355. !
  1356. SUBROUTINE DYNAMWM
  1357. !
  1358. ! !USES:
  1359. !
  1360. use dims, only : lm, zref
  1361. use dims, only : zbeg, zend, epsz, zero, one
  1362. use dims, only : parent
  1363. use global_data, only : wind_dat
  1364. use meteodata, only : m_dat
  1365. use partools, only : Par_Reduce
  1366. !
  1367. ! !REVISION HISTORY:
  1368. !
  1369. ! - programmed by mh, mpi HH, 1994-1995
  1370. ! - zoom version written by mike botchev, march-june 1999
  1371. ! - 1 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  1372. !
  1373. !EOP
  1374. !------------------------------------------------------------------------
  1375. !BOC
  1376. real, dimension(:,:,:), pointer :: m, cm
  1377. real, dimension(:,:,:), allocatable :: mnew, cmold, mold
  1378. real, dimension(:,:), allocatable :: gamma
  1379. integer :: i,j,l,le,lee,ls,lss,n,lmr,i1,i2,j1,j2
  1380. integer :: zref_, halo
  1381. real :: summ
  1382. real :: mxval, gam, beta, max_beta
  1383. integer :: n_advz, iter, lrg, ixs, ixe, redfact, status
  1384. integer :: is,ie,js,je
  1385. integer, parameter :: iter_limit=1 ! no iterations!
  1386. integer, parameter :: region=1
  1387. !----------- START
  1388. ! Indices & work arrays
  1389. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2,J_STRT=j1, J_STOP=j2)
  1390. lmr=lm(region)
  1391. allocate( mnew( i1-1:i2+1, j1-1:j2+1, lmr) ) ! halo=1
  1392. allocate(gamma( i1-1:i2+1, j1-1:j2+1 ) ) ! halo=1
  1393. halo = wind_dat(region)%halo
  1394. allocate(cmold( i1-halo:i2+halo, j1-halo:j2+halo, 0:lmr+1) ) ! same halo as wind_dat)
  1395. halo = m_dat(region)%halo
  1396. allocate( mold( i1-halo:i2+halo, j1-halo:j2+halo, lmr ) ) ! same halo as m_dat)
  1397. m => m_dat(region)%data
  1398. cm => wind_dat(region)%cm
  1399. is=i1 ; ie=i2 ; js=j1 ; je=j2
  1400. ! compute refinement factors with respect to the parent
  1401. zref_ = zref(region)/zref(parent(region))
  1402. ! compute ls/le -- cells is:ie,js:je:ls:le will be update
  1403. ls = zref_; le = lmr-zref_+1
  1404. if(abs(zbeg(region)-zbeg(1))<epsz) ls = 1 ! bottom
  1405. if(abs(zend(region)-zend(1))<epsz) le = lmr ! top
  1406. !
  1407. ! --- calculate new air mass distribution
  1408. !
  1409. lss = ls; lee = le
  1410. cmold=cm
  1411. mold=m
  1412. n_advz=1
  1413. cm = cmold/float(n_advz)
  1414. m = mold
  1415. ! do the iteration
  1416. advz: do iter=1,n_advz
  1417. if (abs(zbeg(region)-zbeg(1))<epsz) then
  1418. ! bottom: one-sided update of the mass
  1419. mnew(is:ie,js:je,1) = m(is:ie,js:je,1) - cm(is:ie,js:je,1)
  1420. lss = 2
  1421. end if
  1422. if (abs(zend(region)-zend(1))<epsz) then
  1423. ! top: one-sided update of the mass
  1424. mnew(is:ie,js:je,lmr) = m(is:ie,js:je,lmr) + cm(is:ie,js:je,lmr-1)
  1425. lee = lmr-1
  1426. end if
  1427. mnew(is:ie,js:je,lss:lee) = m(is:ie,js:je,lss:lee) + &
  1428. cm(is:ie,js:je,lss-1:lee-1)- &
  1429. cm(is:ie,js:je,lss:lee)
  1430. ! reset gamma
  1431. max_beta = 0.
  1432. ! compute f, pf, fx and fy
  1433. cloop: do l=lss-1,lee ! 1,lmm1
  1434. do j=j1,j2
  1435. do i=i1,i2
  1436. if(cm(i,j,l)>=zero) then
  1437. gamma(i,j)=cm(i,j,l)/m(i,j,l)
  1438. else
  1439. gamma(i,j)=cm(i,j,l)/m(i,j,l+1)
  1440. end if
  1441. max_beta = max(max_beta, abs(gamma(i,j)))
  1442. if ( abs(gamma(i,j)) >= one ) then
  1443. if ( okdebug ) then
  1444. write(gol,*) 'dynamwm: CFL violation'; call goErr
  1445. write(gol,*) ' gamma, m, cm=', max_beta, m(i,j,l), m(i,j,l+1), cm(i,j,l), &
  1446. ' in region,i,j,l: ',region,i,j,l; call goErr
  1447. endif
  1448. exit cloop
  1449. end if
  1450. end do
  1451. end do
  1452. end do cloop
  1453. call Par_Reduce(max_beta, 'MAX', beta, status, all=.true.)
  1454. xim(region,3)=max(xim(region,3), beta)
  1455. if ( beta >= one ) exit advz
  1456. ! do not allow iterations in Z
  1457. ! no CFLs upto now.....possibly in next?
  1458. m(is:ie,js:je,ls:le)=mnew(is:ie,js:je,ls:le)
  1459. enddo advz
  1460. ! if still CFL violation increase iteration counter and re-start cfl loop
  1461. ! escape is called when the number of iterations becomes too large
  1462. if ( beta >= one ) then
  1463. cfl_ok = .false.
  1464. deallocate(mnew)
  1465. deallocate(gamma)
  1466. deallocate(cmold)
  1467. deallocate(mold)
  1468. nullify(m)
  1469. nullify(cm)
  1470. return
  1471. end if
  1472. ! reset m and cm to original values:
  1473. cm = cmold/float(n_advz)
  1474. m = mold
  1475. ! do the iteration (Could get rid of mnew)
  1476. mloop_max(region,3) = max(mloop_max(region,3), n_advz)
  1477. do iter=1,n_advz
  1478. if (abs(zbeg(region)-zbeg(1))<epsz) then
  1479. ! bottom: one-sided update of the mass
  1480. mnew(is:ie,js:je,1) = m(is:ie,js:je,1) - cm(is:ie,js:je,1)
  1481. lss = 2
  1482. end if
  1483. if (abs(zend(region)-zend(1))<epsz) then
  1484. ! top: one-sided update of the mass
  1485. mnew(is:ie,js:je,lmr) = m(is:ie,js:je,lmr) + cm(is:ie,js:je,lmr-1)
  1486. lee = lmr-1
  1487. end if
  1488. mnew(is:ie,js:je,lss:lee) = m(is:ie,js:je,lss:lee) + &
  1489. cm(is:ie,js:je,lss-1:lee-1) - &
  1490. cm(is:ie,js:je,lss:lee)
  1491. ! store new air mass in m array
  1492. m(is:ie,js:je,ls:le)=mnew(is:ie,js:je,ls:le)
  1493. enddo !iter
  1494. ! finally :
  1495. ! mix according to reduced grid (to allow for the adjoint implementation!)
  1496. !cmk do l=1,lm(region)
  1497. !cmk do lrg=1,nred(region)
  1498. !cmk redfact=clustsize(lrg,region)
  1499. !cmk j = jred(lrg,region)
  1500. !cmk do i = 1,imredj(lrg,region)
  1501. !cmk ixs = (i-1)*redfact + 1
  1502. !cmk ixe = i*redfact
  1503. !cmk summ = sum(m(ixs:ixe,j,l))
  1504. !cmk m(ixs:ixe,j,l) = summ/(ixe-ixs+1)
  1505. !cmk end do ! I
  1506. !cmk end do ! lrg
  1507. !cmk end do ! l
  1508. cm=cmold ! reset cm
  1509. deallocate(mnew)
  1510. deallocate(gamma)
  1511. deallocate(cmold)
  1512. deallocate(mold)
  1513. nullify(m)
  1514. nullify(cm)
  1515. END SUBROUTINE DYNAMWM
  1516. !EOC
  1517. END MODULE ADVECTM_CFL