source: branches/flexpart91_hasod/src_parallel/advance.f90 @ 8

Last change on this file since 8 was 8, checked in by hasod, 11 years ago

Added parallel version of Flexpart91

File size: 29.2 KB
Line 
1!**********************************************************************
2! Copyright 1998,1999,2000,2001,2002,2005,2007,2008,2009,2010         *
3! Andreas Stohl, Petra Seibert, A. Frank, Gerhard Wotawa,             *
4! Caroline Forster, Sabine Eckhardt, John Burkhart, Harald Sodemann   *
5!                                                                     *
6! This file is part of FLEXPART.                                      *
7!                                                                     *
8! FLEXPART is free software: you can redistribute it and/or modify    *
9! it under the terms of the GNU General Public License as published by*
10! the Free Software Foundation, either version 3 of the License, or   *
11! (at your option) any later version.                                 *
12!                                                                     *
13! FLEXPART is distributed in the hope that it will be useful,         *
14! but WITHOUT ANY WARRANTY; without even the implied warranty of      *
15! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       *
16! GNU General Public License for more details.                        *
17!                                                                     *
18! You should have received a copy of the GNU General Public License   *
19! along with FLEXPART.  If not, see <http://www.gnu.org/licenses/>.   *
20!**********************************************************************
21
22subroutine advance(pj, itime,nrelpoint,ldt,up,vp,wp, &
23       usigold,vsigold,wsigold,nstop,xt,yt,zt,prob,icbt)
24  !                     i    i  i/oi/oi/o
25  !  i/o     i/o     i/o     o  i/oi/oi/o i/o  i/o
26  !*****************************************************************************
27  !                                                                            *
28  !  Calculation of turbulent particle trajectories utilizing a                *
29  !  zero-acceleration scheme, which is corrected by a numerically more        *
30  !  accurate Petterssen scheme whenever possible.                             *
31  !                                                                            *
32  !  Particle positions are read in, incremented, and returned to the calling  *
33  !  program.                                                                  *
34  !                                                                            *
35  !  In different regions of the atmosphere (PBL vs. free troposphere),        *
36  !  different parameters are needed for advection, parameterizing turbulent   *
37  !  velocities, etc. For efficiency, different interpolation routines have    *
38  !  been written for these different cases, with the disadvantage that there  *
39  !  exist several routines doing almost the same. They all share the          *
40  !  included file 'interpol_mod'. The following                               *
41  !  interpolation routines are used:                                          *
42  !                                                                            *
43  !  interpol_all(_nests)     interpolates everything (called inside the PBL)  *
44  !  interpol_misslev(_nests) if a particle moves vertically in the PBL,       *
45  !                           additional parameters are interpolated if it     *
46  !                           crosses a model level                            *
47  !  interpol_wind(_nests)    interpolates the wind and determines the         *
48  !                           standard deviation of the wind (called outside   *
49  !                           PBL) also interpolates potential vorticity       *
50  !  interpol_wind_short(_nests) only interpolates the wind (needed for the    *
51  !                           Petterssen scheme)                               *
52  !  interpol_vdep(_nests)    interpolates deposition velocities               *
53  !                                                                            *
54  !                                                                            *
55  !     Author: A. Stohl                                                       *
56  !                                                                            *
57  !     16 December 1997                                                       *
58  !                                                                            *
59  !  Changes:                                                                  *
60  !                                                                            *
61  !  8 April 2000: Deep convection parameterization                            *
62  !                                                                            *
63  !  May 2002: Petterssen scheme introduced                                    *
64  !                                                                            *
65  !*****************************************************************************
66  !                                                                            *
67  ! Variables:                                                                 *
68  ! icbt               1 if particle not transferred to forbidden state,       *
69  !                    else -1                                                 *
70  ! dawsave            accumulated displacement in along-wind direction        *
71  ! dcwsave            accumulated displacement in cross-wind direction        *
72  ! dxsave             accumulated displacement in longitude                   *
73  ! dysave             accumulated displacement in latitude                    *
74  ! h [m]              Mixing height                                           *
75  ! lwindinterv [s]    time interval between two wind fields                   *
76  ! itime [s]          time at which this subroutine is entered                *
77  ! itimec [s]         actual time, which is incremented in this subroutine    *
78  ! href [m]           height for which dry deposition velocity is calculated  *
79  ! ladvance [s]       Total integration time period                           *
80  ! ldirect            1 forward, -1 backward                                  *
81  ! ldt [s]            Time step for the next integration                      *
82  ! lsynctime [s]      Synchronisation interval of FLEXPART                    *
83  ! ngrid              index which grid is to be used                          *
84  ! nrand              index for a variable to be picked from rannumb          *
85  ! nstop              if > 1 particle has left domain and must be stopped     *
86  ! prob               probability of absorption due to dry deposition         *
87  ! rannumb(maxrand)   normally distributed random variables                   *
88  ! rhoa               air density                                             *
89  ! rhograd            vertical gradient of the air density                    *
90  ! up,vp,wp           random velocities due to turbulence (along wind, cross  *
91  !                    wind, vertical wind                                     *
92  ! usig,vsig,wsig     mesoscale wind fluctuations                             *
93  ! usigold,vsigold,wsigold  like usig, etc., but for the last time step       *
94  ! vdepo              Deposition velocities for all species                   *
95  ! xt,yt,zt           Particle position                                       *
96  !                                                                            *
97  !*****************************************************************************
98
99  use point_mod
100  use par_mod
101  use com_mod
102  use interpol_mod
103  use hanna_mod
104  use cmapf_mod
105  use random_mod, only : ran3_advance
106  ! reads: ran3_advance
107  ! writes:
108
109  implicit none
110
111  real(kind=dp) :: xt,yt
112  real :: zt,xts,yts,weight
113  integer, intent(in) :: pj
114  integer :: itime,itimec,nstop,ldt,i,j,k,nrand,loop,memindnext
115  integer :: ngr,nix,njy,ks,nsp,nrelpoint
116  real :: dz,dz1,dz2,xlon,ylat,xpol,ypol,gridsize
117  real :: ru,rv,rw,dt,ux,vy,cosfact,xtn,ytn,tropop
118  real :: prob(maxspec),up,vp,wp,dxsave,dysave,dawsave
119  real :: dcwsave
120  real :: usigold,vsigold,wsigold,r,rs
121  real :: uold,vold,wold,vdepo(maxspec)
122  !real uprof(nzmax),vprof(nzmax),wprof(nzmax)
123  !real usigprof(nzmax),vsigprof(nzmax),wsigprof(nzmax)
124  !real rhoprof(nzmax),rhogradprof(nzmax)
125  real :: rhoa,rhograd,delz,dtf,rhoaux,dtftlw,uxscale,wpscale
126  integer(kind=2) :: icbt
127  real,parameter :: eps=nxmax/3.e5,eps2=1.e-9
128
129
130  !!! CHANGE: TEST OF THE WELL-MIXED CRITERION
131  !  integer,parameter :: iclass=10
132  !  real(kind=dp) :: zacc,tacc,t(iclass),th(0:iclass),hsave
133  !  logical dump
134  !  save zacc,tacc,t,th,hsave,dump
135  !!! CHANGE
136
137  integer :: idummy = -7
138  real    :: settling = 0.
139
140
141  !!! CHANGE: TEST OF THE WELL-MIXED CRITERION
142  !if (idummy.eq.-7) then
143  !open(550,file='WELLMIXEDTEST')
144  !do 17 i=0,iclass
145  !7      th(i)=real(i)/real(iclass)
146  !endif
147  !!! CHANGE
148
149
150  nstop=0
151  do i=1,nmixz
152    indzindicator(i)=.true.
153  end do
154
155
156  if (DRYDEP) then    ! reset probability for deposition
157    do ks=1,nspec
158      depoindicator(ks)=.true.
159      prob(ks)=0.
160    end do
161  endif
162
163  dxsave=0.           ! reset position displacements
164  dysave=0.           ! due to mean wind
165  dawsave=0.          ! and turbulent wind
166  dcwsave=0.
167
168  itimec=itime
169
170  nrand=int(ran3_advance(pj) * real(maxrand-1)) + 1
171
172
173  ! Determine whether lat/long grid or polarstereographic projection
174  ! is to be used
175  ! Furthermore, determine which nesting level to be used
176  !*****************************************************************
177
178  if (nglobal.and.(yt.gt.switchnorthg)) then
179    ngrid=-1
180  else if (sglobal.and.(yt.lt.switchsouthg)) then
181    ngrid=-2
182  else
183    ngrid=0
184    do j=numbnests,1,-1
185      if ((xt.gt.xln(j)+eps).and.(xt.lt.xrn(j)-eps).and. &
186           (yt.gt.yln(j)+eps).and.(yt.lt.yrn(j)-eps)) then
187        ngrid=j
188        goto 23
189      endif
190    end do
19123   continue
192  endif
193
194
195  !***************************
196  ! Interpolate necessary data
197  !***************************
198
199  if (abs(itime-memtime(1)).lt.abs(itime-memtime(2))) then
200    memindnext=1
201  else
202    memindnext=2
203  endif
204
205  ! Determine nested grid coordinates
206  !**********************************
207
208  if (ngrid.gt.0) then
209    xtn=(real(xt)-xln(ngrid))*xresoln(ngrid)
210    ytn=(real(yt)-yln(ngrid))*yresoln(ngrid)
211    ix=int(xtn)
212    jy=int(ytn)
213    nix=nint(xtn)
214    njy=nint(ytn)
215  else
216    ix=int(xt)
217    jy=int(yt)
218    nix=nint(xt)
219    njy=nint(yt)
220  endif
221  ixp=ix+1
222  jyp=jy+1
223
224
225  ! Compute maximum mixing height around particle position
226  !*******************************************************
227
228  h=0.
229  if (ngrid.le.0) then
230    do k=1,2
231      do j=jy,jyp
232        do i=ix,ixp
233          if (hmix(i,j,1,k).gt.h) h=hmix(i,j,1,k)
234        end do
235      end do
236    end do
237    tropop=tropopause(nix,njy,1,1)
238  else
239    do k=1,2
240      do j=jy,jyp
241        do i=ix,ixp
242          if (hmixn(i,j,1,k,ngrid).gt.h) h=hmixn(i,j,1,k,ngrid)
243        end do
244      end do
245    end do
246    tropop=tropopausen(nix,njy,1,1,ngrid)
247  endif
248
249  zeta=zt/h
250
251
252
253  !*************************************************************
254  ! If particle is in the PBL, interpolate once and then make a
255  ! time loop until end of interval is reached
256  !*************************************************************
257
258  if (zeta.le.1.) then
259
260  ! BEGIN TIME LOOP
261  !================
262
263    loop=0
264100   loop=loop+1
265      if (method.eq.1) then
266        ldt=min(ldt,abs(lsynctime-itimec+itime))
267        itimec=itimec+ldt*ldirect
268      else
269        ldt=abs(lsynctime)
270        itimec=itime+lsynctime
271      endif
272      dt=real(ldt)
273
274      zeta=zt/h
275
276
277      if (loop.eq.1) then
278        if (ngrid.le.0) then
279          xts=real(xt)
280          yts=real(yt)
281          call interpol_all(itime,xts,yts,zt)
282        else
283          call interpol_all_nests(itime,xtn,ytn,zt)
284        endif
285
286      else
287
288
289  ! Determine the level below the current position for u,v,rho
290  !***********************************************************
291
292        do i=2,nz
293          if (height(i).gt.zt) then
294            indz=i-1
295            indzp=i
296            goto 6
297          endif
298        end do
2996       continue
300
301  ! If one of the levels necessary is not yet available,
302  ! calculate it
303  !*****************************************************
304
305        do i=indz,indzp
306          if (indzindicator(i)) then
307            if (ngrid.le.0) then
308              call interpol_misslev(i)
309            else
310              call interpol_misslev_nests(i)
311            endif
312          endif
313        end do
314      endif
315
316
317  ! Vertical interpolation of u,v,w,rho and drhodz
318  !***********************************************
319
320  ! Vertical distance to the level below and above current position
321  ! both in terms of (u,v) and (w) fields
322  !****************************************************************
323
324      dz=1./(height(indzp)-height(indz))
325      dz1=(zt-height(indz))*dz
326      dz2=(height(indzp)-zt)*dz
327
328      u=dz1*uprof(indzp)+dz2*uprof(indz)
329      v=dz1*vprof(indzp)+dz2*vprof(indz)
330      w=dz1*wprof(indzp)+dz2*wprof(indz)
331      rhoa=dz1*rhoprof(indzp)+dz2*rhoprof(indz)
332      rhograd=dz1*rhogradprof(indzp)+dz2*rhogradprof(indz)
333
334
335  ! Compute the turbulent disturbances
336  ! Determine the sigmas and the timescales
337  !****************************************
338
339      if (turbswitch) then
340        call hanna(zt)
341      else
342        call hanna1(zt)
343      endif
344
345
346  !*****************************************
347  ! Determine the new diffusivity velocities
348  !*****************************************
349
350  ! Horizontal components
351  !**********************
352
353      if (nrand+1.gt.maxrand) nrand=1
354      if (dt/tlu.lt..5) then
355        up=(1.-dt/tlu)*up+rannumb(nrand)*sigu*sqrt(2.*dt/tlu)
356      else
357        ru=exp(-dt/tlu)
358        up=ru*up+rannumb(nrand)*sigu*sqrt(1.-ru**2)
359      endif
360      if (dt/tlv.lt..5) then
361        vp=(1.-dt/tlv)*vp+rannumb(nrand+1)*sigv*sqrt(2.*dt/tlv)
362      else
363        rv=exp(-dt/tlv)
364        vp=rv*vp+rannumb(nrand+1)*sigv*sqrt(1.-rv**2)
365      endif
366      nrand=nrand+2
367
368
369      if (nrand+ifine.gt.maxrand) nrand=1
370      rhoaux=rhograd/rhoa
371      dtf=dt*fine
372
373      dtftlw=dtf/tlw
374
375  ! Loop over ifine short time steps for vertical component
376  !********************************************************
377
378      do i=1,ifine
379
380  ! Determine the drift velocity and density correction velocity
381  !*************************************************************
382
383        if (turbswitch) then
384          if (dtftlw.lt..5) then
385            wp=((1.-dtftlw)*wp+rannumb(nrand+i)*sqrt(2.*dtftlw) &
386                 +dtf*(dsigwdz+rhoaux*sigw))*real(icbt)
387          else
388            rw=exp(-dtftlw)
389            wp=(rw*wp+rannumb(nrand+i)*sqrt(1.-rw**2) &
390                 +tlw*(1.-rw)*(dsigwdz+rhoaux*sigw))*real(icbt)
391          endif
392          delz=wp*sigw*dtf
393        else
394          rw=exp(-dtftlw)
395          wp=(rw*wp+rannumb(nrand+i)*sqrt(1.-rw**2)*sigw &
396               +tlw*(1.-rw)*(dsigw2dz+rhoaux*sigw**2))*real(icbt)
397          delz=wp*dtf
398        endif
399
400  !****************************************************
401  ! Compute turbulent vertical displacement of particle
402  !****************************************************
403
404        if (abs(delz).gt.h) delz=mod(delz,h)
405
406  ! Determine if particle transfers to a "forbidden state" below the ground
407  ! or above the mixing height
408  !************************************************************************
409
410        if (delz.lt.-zt) then         ! reflection at ground
411          icbt=-1
412          zt=-zt-delz
413        else if (delz.gt.(h-zt)) then ! reflection at h
414          icbt=-1
415          zt=-zt-delz+2.*h
416        else                         ! no reflection
417          icbt=1
418          zt=zt+delz
419        endif
420
421        if (i.ne.ifine) then
422          zeta=zt/h
423          call hanna_short(zt)
424        endif
425
426      end do
427      nrand=nrand+i
428
429  ! Determine time step for next integration
430  !*****************************************
431
432      if (turbswitch) then
433        ldt=int(min(tlw,h/max(2.*abs(wp*sigw),1.e-5), &
434             0.5/abs(dsigwdz))*ctl)
435      else
436        ldt=int(min(tlw,h/max(2.*abs(wp),1.e-5))*ctl)
437      endif
438      ldt=max(ldt,mintime)
439
440
441  ! If particle represents only a single species, add gravitational settling
442  ! velocity. The settling velocity is zero for gases, or if particle
443  ! represents more than one species
444  !*************************************************************************
445
446      if (mdomainfill.eq.0) then
447        do nsp=1,nspec
448          if (xmass(nrelpoint,nsp).gt.eps2) goto 887
449        end do
450887     nsp=min(nsp,nspec)
451!!$        if (density(nsp).gt.0.) &
452!!$             call get_settling(itime,xts,yts,zt,nsp,settling)    !old
453        if (density(nsp).gt.0.) &
454             call get_settling(itime,real(xt),real(yt),zt,nsp,settling)  !bugfix
455        w=w+settling
456      endif
457
458  ! Horizontal displacements during time step dt are small real values compared
459  ! to the position; adding the two, would result in large numerical errors.
460  ! Thus, displacements are accumulated during lsynctime and are added to the
461  ! position at the end
462  !****************************************************************************
463
464      dxsave=dxsave+u*dt
465      dysave=dysave+v*dt
466      dawsave=dawsave+up*dt
467      dcwsave=dcwsave+vp*dt
468      zt=zt+w*dt*real(ldirect)
469
470      if (zt.gt.h) then
471        if (itimec.eq.itime+lsynctime) goto 99
472        goto 700    ! complete the current interval above PBL
473      endif
474
475
476  !!! CHANGE: TEST OF THE WELL-MIXED CRITERION
477  !!! These lines may be switched on to test the well-mixed criterion
478  !if (zt.le.h) then
479  !  zacc=zacc+zt/h*dt
480  !  hsave=hsave+h*dt
481  !  tacc=tacc+dt
482  !  do 67 i=1,iclass
483  !    if ((zt/h.gt.th(i-1)).and.(zt/h.le.th(i)))
484  !    +    t(i)=t(i)+dt
485  !7        continue
486  !endif
487  !if ((mod(itime,10800).eq.0).and.dump) then
488  ! dump=.false.
489  ! write(550,'(i6,12f10.3)') itime,hsave/tacc,zacc/tacc,
490  !    + (t(i)/tacc*real(iclass),i=1,iclass)
491  !  zacc=0.
492  !  tacc=0.
493  !  do 68 i=1,iclass
494  !8        t(i)=0.
495  !  hsave=0.
496  !endif
497  !if (mod(itime,10800).ne.0) dump=.true.
498  !!! CHANGE
499
500
501  ! Determine probability of deposition
502  !************************************
503
504      if ((DRYDEP).and.(zt.lt.2.*href)) then
505        do ks=1,nspec
506          if (DRYDEPSPEC(ks)) then
507            if (depoindicator(ks)) then
508              if (ngrid.le.0) then
509                call interpol_vdep(ks,vdepo(ks))
510              else
511                call interpol_vdep_nests(ks,vdepo(ks))
512              endif
513            endif
514  ! correction by Petra Seibert, 10 April 2001
515  !   this formulation means that prob(n) = 1 - f(0)*...*f(n)
516  !   where f(n) is the exponential term
517               prob(ks)=1.+(prob(ks)-1.)* &
518                    exp(-vdepo(ks)*abs(dt)/(2.*href))
519          endif
520        end do
521      endif
522
523      if (zt.lt.0.) zt=min(h-eps2,-1.*zt)    ! if particle below ground -> reflection
524
525      if (itimec.eq.(itime+lsynctime)) then
526        usig=0.5*(usigprof(indzp)+usigprof(indz))
527        vsig=0.5*(vsigprof(indzp)+vsigprof(indz))
528        wsig=0.5*(wsigprof(indzp)+wsigprof(indz))
529        goto 99  ! finished
530      endif
531      goto 100
532
533  ! END TIME LOOP
534  !==============
535
536
537  endif
538
539
540
541  !**********************************************************
542  ! For all particles that are outside the PBL, make a single
543  ! time step. Only horizontal turbulent disturbances are
544  ! calculated. Vertical disturbances are reset.
545  !**********************************************************
546
547
548  ! Interpolate the wind
549  !*********************
550
551700   continue
552  if (ngrid.le.0) then
553    xts=real(xt)
554    yts=real(yt)
555    call interpol_wind(itime,xts,yts,zt)
556  else
557    call interpol_wind_nests(itime,xtn,ytn,zt)
558  endif
559
560
561  ! Compute everything for above the PBL
562
563  ! Assume constant, uncorrelated, turbulent perturbations
564  ! In the stratosphere, use a small vertical diffusivity d_strat,
565  ! in the troposphere, use a larger horizontal diffusivity d_trop.
566  ! Turbulent velocity scales are determined based on sqrt(d_trop/dt)
567  !******************************************************************
568
569  ldt=abs(lsynctime-itimec+itime)
570  dt=real(ldt)
571
572  if (zt.lt.tropop) then  ! in the troposphere
573    uxscale=sqrt(2.*d_trop/dt)
574    if (nrand+1.gt.maxrand) nrand=1
575    ux=rannumb(nrand)*uxscale
576    vy=rannumb(nrand+1)*uxscale
577    nrand=nrand+2
578    wp=0.
579  else if (zt.lt.tropop+1000.) then     ! just above the tropopause: make transition
580    weight=(zt-tropop)/1000.
581    uxscale=sqrt(2.*d_trop/dt*(1.-weight))
582    if (nrand+2.gt.maxrand) nrand=1
583    ux=rannumb(nrand)*uxscale
584    vy=rannumb(nrand+1)*uxscale
585    wpscale=sqrt(2.*d_strat/dt*weight)
586    wp=rannumb(nrand+2)*wpscale+d_strat/1000.
587    nrand=nrand+3
588  else                 ! in the stratosphere
589    if (nrand.gt.maxrand) nrand=1
590    ux=0.
591    vy=0.
592    wpscale=sqrt(2.*d_strat/dt)
593    wp=rannumb(nrand)*wpscale
594    nrand=nrand+1
595  endif
596
597
598  ! If particle represents only a single species, add gravitational settling
599  ! velocity. The settling velocity is zero for gases
600  !*************************************************************************
601
602
603
604    if (mdomainfill.eq.0) then
605      do nsp=1,nspec
606        if (xmass(nrelpoint,nsp).gt.eps2) goto 888
607      end do
608888   nsp=min(nsp,nspec)
609!!$      if (density(nsp).gt.0.) &
610!!$           call get_settling(itime,xts,yts,zt,nsp,settling)    !old
611      if (density(nsp).gt.0.) &
612           call get_settling(itime,real(xt),real(yt),zt,nsp,settling)  !bugfix
613      w=w+settling
614    endif
615
616  ! Calculate position at time step itime+lsynctime
617  !************************************************
618
619  dxsave=dxsave+(u+ux)*dt
620  dysave=dysave+(v+vy)*dt
621  zt=zt+(w+wp)*dt*real(ldirect)
622  if (zt.lt.0.) zt=min(h-eps2,-1.*zt)    ! if particle below ground -> reflection
623
62499   continue
625
626
627
628  !****************************************************************
629  ! Add mesoscale random disturbances
630  ! This is done only once for the whole lsynctime interval to save
631  ! computation time
632  !****************************************************************
633
634
635  ! Mesoscale wind velocity fluctuations are obtained by scaling
636  ! with the standard deviation of the grid-scale winds surrounding
637  ! the particle location, multiplied by a factor turbmesoscale.
638  ! The autocorrelation time constant is taken as half the
639  ! time interval between wind fields
640  !****************************************************************
641
642  r=exp(-2.*real(abs(lsynctime))/real(lwindinterv))
643  rs=sqrt(1.-r**2)
644  if (nrand+2.gt.maxrand) nrand=1
645  usigold=r*usigold+rs*rannumb(nrand)*usig*turbmesoscale
646  vsigold=r*vsigold+rs*rannumb(nrand+1)*vsig*turbmesoscale
647  wsigold=r*wsigold+rs*rannumb(nrand+2)*wsig*turbmesoscale
648
649  dxsave=dxsave+usigold*real(lsynctime)
650  dysave=dysave+vsigold*real(lsynctime)
651
652  zt=zt+wsigold*real(lsynctime)
653  if (zt.lt.0.) zt=-1.*zt    ! if particle below ground -> refletion
654
655  !*************************************************************
656  ! Transform along and cross wind components to xy coordinates,
657  ! add them to u and v, transform u,v to grid units/second
658  ! and calculate new position
659  !*************************************************************
660
661  call windalign(dxsave,dysave,dawsave,dcwsave,ux,vy)
662  dxsave=dxsave+ux
663  dysave=dysave+vy
664  if (ngrid.ge.0) then
665    cosfact=dxconst/cos((real(yt)*dy+ylat0)*pi180)
666    xt=xt+real(dxsave*cosfact*real(ldirect),kind=dp)
667    yt=yt+real(dysave*dyconst*real(ldirect),kind=dp)
668  else if (ngrid.eq.-1) then      ! around north pole
669    xlon=xlon0+real(xt)*dx
670    ylat=ylat0+real(yt)*dy
671    call cll2xy(northpolemap,ylat,xlon,xpol,ypol)
672    gridsize=1000.*cgszll(northpolemap,ylat,xlon)
673    dxsave=dxsave/gridsize
674    dysave=dysave/gridsize
675    xpol=xpol+dxsave*real(ldirect)
676    ypol=ypol+dysave*real(ldirect)
677    call cxy2ll(northpolemap,xpol,ypol,ylat,xlon)
678    xt=(xlon-xlon0)/dx
679    yt=(ylat-ylat0)/dy
680  else if (ngrid.eq.-2) then    ! around south pole
681    xlon=xlon0+real(xt)*dx
682    ylat=ylat0+real(yt)*dy
683    call cll2xy(southpolemap,ylat,xlon,xpol,ypol)
684    gridsize=1000.*cgszll(southpolemap,ylat,xlon)
685    dxsave=dxsave/gridsize
686    dysave=dysave/gridsize
687    xpol=xpol+dxsave*real(ldirect)
688    ypol=ypol+dysave*real(ldirect)
689    call cxy2ll(southpolemap,xpol,ypol,ylat,xlon)
690    xt=(xlon-xlon0)/dx
691    yt=(ylat-ylat0)/dy
692  endif
693
694
695  ! If global data are available, use cyclic boundary condition
696  !************************************************************
697
698  if (xglobal) then
699    if (xt.ge.real(nxmin1)) xt=xt-real(nxmin1)
700    if (xt.lt.0.) xt=xt+real(nxmin1)
701    if (xt.le.eps) xt=eps
702    if (abs(xt-real(nxmin1)).le.eps) xt=real(nxmin1)-eps
703  endif
704
705
706  ! Check position: If trajectory outside model domain, terminate it
707  !*****************************************************************
708
709  if ((xt.lt.0.).or.(xt.ge.real(nxmin1)).or.(yt.lt.0.).or. &
710       (yt.ge.real(nymin1))) then
711    nstop=3
712    return
713  endif
714
715  ! If particle above highest model level, set it back into the domain
716  !*******************************************************************
717
718  if (zt.ge.height(nz)) zt=height(nz)-100.*eps
719
720
721  !************************************************************************
722  ! Now we could finish, as this was done in FLEXPART versions up to 4.0.
723  ! However, truncation errors of the advection can be significantly
724  ! reduced by doing one iteration of the Petterssen scheme, if this is
725  ! possible.
726  ! Note that this is applied only to the grid-scale winds, not to
727  ! the turbulent winds.
728  !************************************************************************
729
730  ! The Petterssen scheme can only applied with long time steps (only then u
731  ! is the "old" wind as required by the scheme); otherwise do nothing
732  !*************************************************************************
733
734  if (ldt.ne.abs(lsynctime)) return
735
736  ! The Petterssen scheme can only be applied if the ending time of the time step
737  ! (itime+ldt*ldirect) is still between the two wind fields held in memory;
738  ! otherwise do nothing
739  !******************************************************************************
740
741  if (abs(itime+ldt*ldirect).gt.abs(memtime(2))) return
742
743  ! Apply it also only if starting and ending point of current time step are on
744  ! the same grid; otherwise do nothing
745  !*****************************************************************************
746  if (nglobal.and.(yt.gt.switchnorthg)) then
747    ngr=-1
748  else if (sglobal.and.(yt.lt.switchsouthg)) then
749    ngr=-2
750  else
751    ngr=0
752    do j=numbnests,1,-1
753      if ((xt.gt.xln(j)+eps).and.(xt.lt.xrn(j)-eps).and. &
754           (yt.gt.yln(j)+eps).and.(yt.lt.yrn(j)-eps)) then
755        ngr=j
756        goto 43
757      endif
758    end do
75943   continue
760  endif
761
762  if (ngr.ne.ngrid) return
763
764  ! Determine nested grid coordinates
765  !**********************************
766
767  if (ngrid.gt.0) then
768    xtn=(real(xt)-xln(ngrid))*xresoln(ngrid)
769    ytn=(real(yt)-yln(ngrid))*yresoln(ngrid)
770    ix=int(xtn)
771    jy=int(ytn)
772  else
773    ix=int(xt)
774    jy=int(yt)
775  endif
776  ixp=ix+1
777  jyp=jy+1
778
779
780  ! Memorize the old wind
781  !**********************
782
783  uold=u
784  vold=v
785  wold=w
786
787  ! Interpolate wind at new position and time
788  !******************************************
789
790  if (ngrid.le.0) then
791    xts=real(xt)
792    yts=real(yt)
793    call interpol_wind_short(itime+ldt*ldirect,xts,yts,zt)
794  else
795    call interpol_wind_short_nests(itime+ldt*ldirect,xtn,ytn,zt)
796  endif
797
798  if (mdomainfill.eq.0) then
799    do nsp=1,nspec
800      if (xmass(nrelpoint,nsp).gt.eps2) goto 889
801    end do
802889   nsp=min(nsp,nspec)
803!!$    if (density(nsp).gt.0.) &
804!!$         call get_settling(itime+ldt,xts,yts,zt,nsp,settling)    !old
805    if (density(nsp).gt.0.) &
806         call get_settling(itime+ldt,real(xt),real(yt),zt,nsp,settling)  !bugfix
807    w=w+settling
808  endif
809
810
811  ! Determine the difference vector between new and old wind
812  ! (use half of it to correct position according to Petterssen)
813  !*************************************************************
814
815  u=(u-uold)/2.
816  v=(v-vold)/2.
817  w=(w-wold)/2.
818
819
820  ! Finally, correct the old position
821  !**********************************
822
823  zt=zt+w*real(ldt*ldirect)
824  if (zt.lt.0.) zt=min(h-eps2,-1.*zt)    ! if particle below ground -> reflection
825  if (ngrid.ge.0) then
826    cosfact=dxconst/cos((real(yt)*dy+ylat0)*pi180)
827    xt=xt+real(u*cosfact*real(ldt*ldirect),kind=dp)
828    yt=yt+real(v*dyconst*real(ldt*ldirect),kind=dp)
829  else if (ngrid.eq.-1) then      ! around north pole
830    xlon=xlon0+real(xt)*dx
831    ylat=ylat0+real(yt)*dy
832    call cll2xy(northpolemap,ylat,xlon,xpol,ypol)
833    gridsize=1000.*cgszll(northpolemap,ylat,xlon)
834    u=u/gridsize
835    v=v/gridsize
836    xpol=xpol+u*real(ldt*ldirect)
837    ypol=ypol+v*real(ldt*ldirect)
838    call cxy2ll(northpolemap,xpol,ypol,ylat,xlon)
839    xt=(xlon-xlon0)/dx
840    yt=(ylat-ylat0)/dy
841  else if (ngrid.eq.-2) then    ! around south pole
842    xlon=xlon0+real(xt)*dx
843    ylat=ylat0+real(yt)*dy
844    call cll2xy(southpolemap,ylat,xlon,xpol,ypol)
845    gridsize=1000.*cgszll(southpolemap,ylat,xlon)
846    u=u/gridsize
847    v=v/gridsize
848    xpol=xpol+u*real(ldt*ldirect)
849    ypol=ypol+v*real(ldt*ldirect)
850    call cxy2ll(southpolemap,xpol,ypol,ylat,xlon)
851    xt=(xlon-xlon0)/dx
852    yt=(ylat-ylat0)/dy
853  endif
854
855  ! If global data are available, use cyclic boundary condition
856  !************************************************************
857
858  if (xglobal) then
859    if (xt.ge.real(nxmin1)) xt=xt-real(nxmin1)
860    if (xt.lt.0.) xt=xt+real(nxmin1)
861    if (xt.le.eps) xt=eps
862    if (abs(xt-real(nxmin1)).le.eps) xt=real(nxmin1)-eps
863  endif
864
865  ! Check position: If trajectory outside model domain, terminate it
866  !*****************************************************************
867
868  if ((xt.lt.0.).or.(xt.ge.real(nxmin1)).or.(yt.lt.0.).or. &
869       (yt.ge.real(nymin1))) then
870    nstop=3
871    return
872  endif
873
874  ! If particle above highest model level, set it back into the domain
875  !*******************************************************************
876
877  if (zt.ge.height(nz)) zt=height(nz)-100.*eps
878
879
880end subroutine advance
881
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG