source: flexpart.git/src/advance.f90 @ 94735e2

10.4.1_peseiGFS_025bugfixes+enhancementsdevrelease-10release-10.4.1scaling-bugunivie
Last change on this file since 94735e2 was 94735e2, checked in by Sabine <sabine.eckhardt@…>, 7 years ago

added switch turboff to run FLEXPART without turbulence

  • Property mode set to 100644
File size: 34.5 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(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
106
107  implicit none
108
109  real(kind=dp) :: xt,yt
110  real :: zt,xts,yts,weight
111  integer :: itime,itimec,nstop,ldt,i,j,k,nrand,loop,memindnext,mind
112  integer :: ngr,nix,njy,ks,nsp,nrelpoint
113  real :: dz,dz1,dz2,xlon,ylat,xpol,ypol,gridsize
114  real :: ru,rv,rw,dt,ux,vy,cosfact,xtn,ytn,tropop
115  real :: prob(maxspec),up,vp,wp,dxsave,dysave,dawsave
116  real :: dcwsave
117  real :: usigold,vsigold,wsigold,r,rs
118  real :: uold,vold,wold,vdepo(maxspec)
119  real :: h1(2)
120  !real uprof(nzmax),vprof(nzmax),wprof(nzmax)
121  !real usigprof(nzmax),vsigprof(nzmax),wsigprof(nzmax)
122  !real rhoprof(nzmax),rhogradprof(nzmax)
123  real :: rhoa,rhograd,delz,dtf,rhoaux,dtftlw,uxscale,wpscale
124  integer(kind=2) :: icbt
125  real,parameter :: eps=nxmax/3.e5,eps2=1.e-9
126  real :: ptot_lhh,Q_lhh,phi_lhh,ath,bth !modified by mc
127  real :: old_wp_buf,dcas,dcas1,del_test !added by mc
128  integer :: i_well,jj,flagrein !test well mixed: modified by mc
129
130
131  !!! CHANGE: TEST OF THE WELL-MIXED CRITERION
132  !  integer,parameter :: iclass=10
133  !  real(kind=dp) :: zacc,tacc,t(iclass),th(0:iclass),hsave
134  !  logical dump
135  !  save zacc,tacc,t,th,hsave,dump
136  !!! CHANGE
137
138  integer :: idummy = -7
139  real    :: settling = 0.
140
141
142  !!! CHANGE: TEST OF THE WELL-MIXED CRITERION
143  !if (idummy.eq.-7) then
144  !open(550,file='WELLMIXEDTEST')
145  !do 17 i=0,iclass
146  !7      th(i)=real(i)/real(iclass)
147  !endif
148  !!! CHANGE
149
150
151  nstop=0
152  do i=1,nmixz
153    indzindicator(i)=.true.
154  end do
155
156
157  if (DRYDEP) then    ! reset probability for deposition
158    do ks=1,nspec
159      depoindicator(ks)=.true.
160      prob(ks)=0.
161    end do
162  endif
163
164  dxsave=0.           ! reset position displacements
165  dysave=0.           ! due to mean wind
166  dawsave=0.          ! and turbulent wind
167  dcwsave=0.
168
169  itimec=itime
170
171  nrand=int(ran3(idummy)*real(maxrand-1))+1
172
173
174  ! Determine whether lat/long grid or polarstereographic projection
175  ! is to be used
176  ! Furthermore, determine which nesting level to be used
177  !*****************************************************************
178
179  if (nglobal.and.(yt.gt.switchnorthg)) then
180    ngrid=-1
181  else if (sglobal.and.(yt.lt.switchsouthg)) then
182    ngrid=-2
183  else
184    ngrid=0
185    do j=numbnests,1,-1
186      if ((xt.gt.xln(j)+eps).and.(xt.lt.xrn(j)-eps).and. &
187           (yt.gt.yln(j)+eps).and.(yt.lt.yrn(j)-eps)) then
188        ngrid=j
189        goto 23
190      endif
191    end do
19223   continue
193  endif
194
195
196  !***************************
197  ! Interpolate necessary data
198  !***************************
199
200  if (abs(itime-memtime(1)).lt.abs(itime-memtime(2))) then
201    memindnext=1
202  else
203    memindnext=2
204  endif
205
206  ! Determine nested grid coordinates
207  !**********************************
208
209  if (ngrid.gt.0) then
210    xtn=(xt-xln(ngrid))*xresoln(ngrid)
211    ytn=(yt-yln(ngrid))*yresoln(ngrid)
212    ix=int(xtn)
213    jy=int(ytn)
214    nix=nint(xtn)
215    njy=nint(ytn)
216  else
217    ix=int(xt)
218    jy=int(yt)
219    nix=nint(xt)
220    njy=nint(yt)
221  endif
222  ixp=ix+1
223  jyp=jy+1
224
225
226 ! Determine the lower left corner and its distance to the current position
227  !*************************************************************************
228
229  ddx=xt-real(ix)
230  ddy=yt-real(jy)
231  rddx=1.-ddx
232  rddy=1.-ddy
233  p1=rddx*rddy
234  p2=ddx*rddy
235  p3=rddx*ddy
236  p4=ddx*ddy
237
238 ! Calculate variables for time interpolation
239  !*******************************************
240
241  dt1=real(itime-memtime(1))
242  dt2=real(memtime(2)-itime)
243  dtt=1./(dt1+dt2)
244
245  ! Compute maximum mixing height around particle position
246  !*******************************************************
247
248  h=0.
249  if (ngrid.le.0) then
250    do k=1,2
251       mind=memind(k) ! eso: compatibility with 3-field version
252       if (interpolhmix) then
253             h1(k)=p1*hmix(ix ,jy ,1,mind) &
254                 + p2*hmix(ixp,jy ,1,mind) &
255                 + p3*hmix(ix ,jyp,1,mind) &
256                 + p4*hmix(ixp,jyp,1,mind)
257        else
258          do j=jy,jyp
259            do i=ix,ixp
260               if (hmix(i,j,1,mind).gt.h) h=hmix(i,j,1,mind)
261            end do
262          end do
263        endif
264    end do
265    tropop=tropopause(nix,njy,1,1)
266  else
267    do k=1,2
268      mind=memind(k)
269      do j=jy,jyp
270        do i=ix,ixp
271          if (hmixn(i,j,1,mind,ngrid).gt.h) h=hmixn(i,j,1,mind,ngrid)
272        end do
273      end do
274    end do
275    tropop=tropopausen(nix,njy,1,1,ngrid)
276  endif
277
278  if (interpolhmix) h=(h1(1)*dt2+h1(2)*dt1)*dtt
279  zeta=zt/h
280
281
282
283  !*************************************************************
284  ! If particle is in the PBL, interpolate once and then make a
285  ! time loop until end of interval is reached
286  !*************************************************************
287
288  if (zeta.le.1.) then
289
290  ! BEGIN TIME LOOP
291  !================
292
293    loop=0
294100   loop=loop+1
295      if (method.eq.1) then
296        ldt=min(ldt,abs(lsynctime-itimec+itime))
297        itimec=itimec+ldt*ldirect
298      else
299        ldt=abs(lsynctime)
300        itimec=itime+lsynctime
301      endif
302      dt=real(ldt)
303
304      zeta=zt/h
305
306
307      if (loop.eq.1) then
308        if (ngrid.le.0) then
309          xts=real(xt)
310          yts=real(yt)
311          call interpol_all(itime,xts,yts,zt)
312        else
313          call interpol_all_nests(itime,xtn,ytn,zt)
314        endif
315
316      else
317
318
319  ! Determine the level below the current position for u,v,rho
320  !***********************************************************
321
322        do i=2,nz
323          if (height(i).gt.zt) then
324            indz=i-1
325            indzp=i
326            goto 6
327          endif
328        end do
3296       continue
330
331  ! If one of the levels necessary is not yet available,
332  ! calculate it
333  !*****************************************************
334
335        do i=indz,indzp
336          if (indzindicator(i)) then
337            if (ngrid.le.0) then
338              call interpol_misslev(i)
339            else
340              call interpol_misslev_nests(i)
341            endif
342          endif
343        end do
344      endif
345
346
347  ! Vertical interpolation of u,v,w,rho and drhodz
348  !***********************************************
349
350  ! Vertical distance to the level below and above current position
351  ! both in terms of (u,v) and (w) fields
352  !****************************************************************
353
354      dz=1./(height(indzp)-height(indz))
355      dz1=(zt-height(indz))*dz
356      dz2=(height(indzp)-zt)*dz
357
358      u=dz1*uprof(indzp)+dz2*uprof(indz)
359      v=dz1*vprof(indzp)+dz2*vprof(indz)
360      w=dz1*wprof(indzp)+dz2*wprof(indz)
361      rhoa=dz1*rhoprof(indzp)+dz2*rhoprof(indz)
362      rhograd=dz1*rhogradprof(indzp)+dz2*rhogradprof(indz)
363
364
365  ! Compute the turbulent disturbances
366  ! Determine the sigmas and the timescales
367  !****************************************
368
369      if (turbswitch) then
370        call hanna(zt)
371      else
372        call hanna1(zt)
373      endif
374
375
376  !*****************************************
377  ! Determine the new diffusivity velocities
378  !*****************************************
379
380  ! Horizontal components
381  !**********************
382
383      if (nrand+1.gt.maxrand) nrand=1
384      if (dt/tlu.lt..5) then
385        up=(1.-dt/tlu)*up+rannumb(nrand)*sigu*sqrt(2.*dt/tlu)
386      else
387        ru=exp(-dt/tlu)
388        up=ru*up+rannumb(nrand)*sigu*sqrt(1.-ru**2)
389      endif
390      if (dt/tlv.lt..5) then
391        vp=(1.-dt/tlv)*vp+rannumb(nrand+1)*sigv*sqrt(2.*dt/tlv)
392      else
393        rv=exp(-dt/tlv)
394        vp=rv*vp+rannumb(nrand+1)*sigv*sqrt(1.-rv**2)
395      endif
396      nrand=nrand+2
397
398
399      if (nrand+ifine.gt.maxrand) nrand=1
400      rhoaux=rhograd/rhoa
401      dtf=dt*fine
402
403      dtftlw=dtf/tlw
404
405  ! Loop over ifine short time steps for vertical component
406  !********************************************************
407
408      do i=1,ifine
409
410  ! Determine the drift velocity and density correction velocity
411  !*************************************************************
412
413        if (turbswitch) then
414          if (dtftlw.lt..5) then
415  !*************************************************************
416  !************** CBL options added by mc see routine cblf90 ***
417            if (cblflag.eq.1) then  !modified by mc
418              if (-h/ol.gt.5) then  !modified by mc
419              !if (ol.lt.0.) then   !modified by mc 
420              !if (ol.gt.0.) then   !modified by mc : for test
421                  !print  *,zt,wp,ath,bth,tlw,dtf,'prima'
422                  flagrein=0
423                  nrand=nrand+1
424                  old_wp_buf=wp
425                  call cbl(wp,zt,ust,wst,h,rhoa,rhograd,sigw,dsigwdz,tlw,ptot_lhh,Q_lhh,phi_lhh,ath,bth,ol,flagrein) !inside the routine for inverse time
426                  wp=(wp+ath*dtf+bth*rannumb(nrand)*sqrt(dtf))*real(icbt)
427                  ! wp=(wp+ath*dtf+bth*gasdev2(mydum)*sqrt(dtf))*real(icbt)
428                  delz=wp*dtf
429                  if (flagrein.eq.1) then
430                      call re_initialize_particle(zt,ust,wst,h,sigw,old_wp_buf,nrand,ol)
431                      wp=old_wp_buf
432                      delz=wp*dtf
433                      nan_count=nan_count+1
434                  end if
435                  !print  *,zt,wp,ath,bth,tlw,dtf,rannumb(nrand+i),icbt
436                  !pause                 
437              else
438                  nrand=nrand+1
439                  old_wp_buf=wp
440                  ath=-wp/tlw+sigw*dsigwdz+wp*wp/sigw*dsigwdz+sigw*sigw/rhoa*rhograd  !1-note for inverse time should be -wp/tlw*ldirect+... calculated for wp=-wp
441                                                                                      !2-but since ldirect =-1 for inverse time and this must be calculated for (-wp) and
442                                                                                      !3-the gaussian pdf is symmetric (i.e. pdf(w)=pdf(-w) ldirect can be discarded
443                  bth=sigw*rannumb(nrand)*sqrt(2.*dtftlw)
444                  wp=(wp+ath*dtf+bth)*real(icbt) 
445                  delz=wp*dtf
446                  del_test=(1.-wp)/wp !catch infinity value
447                  if (isnan(wp).or.isnan(del_test)) then
448                      nrand=nrand+1                     
449                      wp=sigw*rannumb(nrand)
450                      delz=wp*dtf
451                      nan_count2=nan_count2+1
452                      !print *,'NaN coutner equal to:', nan_count,'reduce ifine if this number became a non-negligible fraction of the particle number'
453                  end if 
454              end if
455  !******************** END CBL option *******************************           
456  !*******************************************************************           
457            else
458                 wp=((1.-dtftlw)*wp+rannumb(nrand+i)*sqrt(2.*dtftlw) &
459                 +dtf*(dsigwdz+rhoaux*sigw))*real(icbt)
460                 delz=wp*sigw*dtf
461            end if
462          else
463            rw=exp(-dtftlw)
464            wp=(rw*wp+rannumb(nrand+i)*sqrt(1.-rw**2) &
465                 +tlw*(1.-rw)*(dsigwdz+rhoaux*sigw))*real(icbt)
466            delz=wp*sigw*dtf
467          endif
468         
469        else
470          rw=exp(-dtftlw)
471          wp=(rw*wp+rannumb(nrand+i)*sqrt(1.-rw**2)*sigw &
472               +tlw*(1.-rw)*(dsigw2dz+rhoaux*sigw**2))*real(icbt)
473          delz=wp*dtf
474        endif
475
476        if (turboff) then
477!sec switch off turbulence
478          up=0.0
479          vp=0.0
480          wp=0.0
481          delz=0.
482        endif
483
484  !****************************************************
485  ! Compute turbulent vertical displacement of particle
486  !****************************************************
487
488        if (abs(delz).gt.h) delz=mod(delz,h)
489
490  ! Determine if particle transfers to a "forbidden state" below the ground
491  ! or above the mixing height
492  !************************************************************************
493
494        if (delz.lt.-zt) then         ! reflection at ground
495          icbt=-1
496          zt=-zt-delz
497        else if (delz.gt.(h-zt)) then ! reflection at h
498          icbt=-1
499          zt=-zt-delz+2.*h
500        else                         ! no reflection
501          icbt=1
502          zt=zt+delz
503        endif
504
505        if (i.ne.ifine) then
506          zeta=zt/h
507          call hanna_short(zt)
508        endif
509
510      end do
511      if (cblflag.ne.1) nrand=nrand+i
512
513  ! Determine time step for next integration
514  !*****************************************
515
516      if (turbswitch) then
517        ldt=int(min(tlw,h/max(2.*abs(wp*sigw),1.e-5), &
518             0.5/abs(dsigwdz))*ctl)
519      else
520        ldt=int(min(tlw,h/max(2.*abs(wp),1.e-5))*ctl)
521      endif
522      ldt=max(ldt,mintime)
523
524
525  ! If particle represents only a single species, add gravitational settling
526  ! velocity. The settling velocity is zero for gases, or if particle
527  ! represents more than one species
528  !*************************************************************************
529
530      if (mdomainfill.eq.0) then
531! ESO 05.2015  Changed this to fix MQUASILAG option, where nrelpoint is
532!              particle number and thus xmass array goes out of bounds
533!        do nsp=1,nspec
534!           if (xmass(nrelpoint,nsp).gt.eps2) goto 887
535!         end do
536! 887     nsp=min(nsp,nspec)
537        if (nspec.eq.1.and.density(1).gt.0.) then
538          call get_settling(itime,real(xt),real(yt),zt,nspec,settling)  !bugfix
539        end if
540        w=w+settling
541      endif
542
543  ! Horizontal displacements during time step dt are small real values compared
544  ! to the position; adding the two, would result in large numerical errors.
545  ! Thus, displacements are accumulated during lsynctime and are added to the
546  ! position at the end
547  !****************************************************************************
548
549      dxsave=dxsave+u*dt
550      dysave=dysave+v*dt
551      dawsave=dawsave+up*dt
552      dcwsave=dcwsave+vp*dt
553      zt=zt+w*dt*real(ldirect)
554
555      ! HSO/AL: Particle managed to go over highest level -> interpolation error in goto 700
556      !          alias interpol_wind (division by zero)
557      if (zt.ge.height(nz)) zt=height(nz)-100.*eps
558
559      if (zt.gt.h) then
560        if (itimec.eq.itime+lsynctime) goto 99
561        goto 700    ! complete the current interval above PBL
562      endif
563
564
565  !!! CHANGE: TEST OF THE WELL-MIXED CRITERION
566  !!! These lines may be switched on to test the well-mixed criterion
567  !if (zt.le.h) then
568  !  zacc=zacc+zt/h*dt
569  !  hsave=hsave+h*dt
570  !  tacc=tacc+dt
571  !  do 67 i=1,iclass
572  !    if ((zt/h.gt.th(i-1)).and.(zt/h.le.th(i)))
573  !    +    t(i)=t(i)+dt
574  !7        continue
575  !endif
576  !if ((mod(itime,10800).eq.0).and.dump) then
577  ! dump=.false.
578  ! write(550,'(i6,12f10.3)') itime,hsave/tacc,zacc/tacc,
579  !    + (t(i)/tacc*real(iclass),i=1,iclass)
580  !  zacc=0.
581  !  tacc=0.
582  !  do 68 i=1,iclass
583  !8        t(i)=0.
584  !  hsave=0.
585  !endif
586  !if (mod(itime,10800).ne.0) dump=.true.
587  !!! CHANGE
588     
589  ! Determine probability of deposition
590  !************************************
591
592      if ((DRYDEP).and.(zt.lt.2.*href)) then
593        do ks=1,nspec
594          if (DRYDEPSPEC(ks)) then
595            if (depoindicator(ks)) then
596              if (ngrid.le.0) then
597                call interpol_vdep(ks,vdepo(ks))
598              else
599                call interpol_vdep_nests(ks,vdepo(ks))
600              endif
601            endif
602  ! correction by Petra Seibert, 10 April 2001
603  !   this formulation means that prob(n) = 1 - f(0)*...*f(n)
604  !   where f(n) is the exponential term
605               prob(ks)=1.+(prob(ks)-1.)* &
606                    exp(-vdepo(ks)*abs(dt)/(2.*href))
607          endif
608        end do
609      endif
610
611      if (zt.lt.0.) zt=min(h-eps2,-1.*zt)    ! if particle below ground -> reflection
612
613      if (itimec.eq.(itime+lsynctime)) then
614        usig=0.5*(usigprof(indzp)+usigprof(indz))
615        vsig=0.5*(vsigprof(indzp)+vsigprof(indz))
616        wsig=0.5*(wsigprof(indzp)+wsigprof(indz))
617        goto 99  ! finished
618      endif
619      goto 100
620
621  ! END TIME LOOP
622  !==============
623
624
625  endif
626
627
628
629  !**********************************************************
630  ! For all particles that are outside the PBL, make a single
631  ! time step. Only horizontal turbulent disturbances are
632  ! calculated. Vertical disturbances are reset.
633  !**********************************************************
634
635
636  ! Interpolate the wind
637  !*********************
638
639700   continue
640  if (ngrid.le.0) then
641    xts=real(xt)
642    yts=real(yt)
643    call interpol_wind(itime,xts,yts,zt)
644  else
645    call interpol_wind_nests(itime,xtn,ytn,zt)
646  endif
647
648
649  ! Compute everything for above the PBL
650
651  ! Assume constant, uncorrelated, turbulent perturbations
652  ! In the stratosphere, use a small vertical diffusivity d_strat,
653  ! in the troposphere, use a larger horizontal diffusivity d_trop.
654  ! Turbulent velocity scales are determined based on sqrt(d_trop/dt)
655  !******************************************************************
656
657  ldt=abs(lsynctime-itimec+itime)
658  dt=real(ldt)
659
660  if (zt.lt.tropop) then  ! in the troposphere
661    uxscale=sqrt(2.*d_trop/dt)
662    if (nrand+1.gt.maxrand) nrand=1
663    ux=rannumb(nrand)*uxscale
664    vy=rannumb(nrand+1)*uxscale
665    nrand=nrand+2
666    wp=0.
667  else if (zt.lt.tropop+1000.) then     ! just above the tropopause: make transition
668    weight=(zt-tropop)/1000.
669    uxscale=sqrt(2.*d_trop/dt*(1.-weight))
670    if (nrand+2.gt.maxrand) nrand=1
671    ux=rannumb(nrand)*uxscale
672    vy=rannumb(nrand+1)*uxscale
673    wpscale=sqrt(2.*d_strat/dt*weight)
674    wp=rannumb(nrand+2)*wpscale+d_strat/1000.
675    nrand=nrand+3
676  else                 ! in the stratosphere
677    if (nrand.gt.maxrand) nrand=1
678    ux=0.
679    vy=0.
680    wpscale=sqrt(2.*d_strat/dt)
681    wp=rannumb(nrand)*wpscale
682    nrand=nrand+1
683  endif
684
685  if (turboff) then
686!sec switch off turbulence
687    ux=0.0
688    vy=0.0
689    wp=0.0
690  endif
691
692  ! If particle represents only a single species, add gravitational settling
693  ! velocity. The settling velocity is zero for gases
694  !*************************************************************************
695
696
697
698    if (mdomainfill.eq.0) then
699! ESO 05.2015  Changed this to fix MQUASILAG option, where nrelpoint is
700!              particle number and thus xmass array goes out of bounds
701
702!      do nsp=1,nspec
703!         if (xmass(nrelpoint,nsp).gt.eps2) goto 888
704!       end do
705! 888   nsp=min(nsp,nspec)
706!        if (density(nsp).gt.0.) then
707      if (nspec.eq.1.and.density(1).gt.0.) then
708        call get_settling(itime,real(xt),real(yt),zt,nspec,settling)  !bugfix
709      end if
710      w=w+settling
711    endif
712
713  ! Calculate position at time step itime+lsynctime
714  !************************************************
715
716  dxsave=dxsave+(u+ux)*dt
717  dysave=dysave+(v+vy)*dt
718  zt=zt+(w+wp)*dt*real(ldirect)
719  if (zt.lt.0.) zt=min(h-eps2,-1.*zt)    ! if particle below ground -> reflection
720
72199   continue
722
723
724
725  !****************************************************************
726  ! Add mesoscale random disturbances
727  ! This is done only once for the whole lsynctime interval to save
728  ! computation time
729  !****************************************************************
730
731
732  ! Mesoscale wind velocity fluctuations are obtained by scaling
733  ! with the standard deviation of the grid-scale winds surrounding
734  ! the particle location, multiplied by a factor turbmesoscale.
735  ! The autocorrelation time constant is taken as half the
736  ! time interval between wind fields
737  !****************************************************************
738
739  r=exp(-2.*real(abs(lsynctime))/real(lwindinterv))
740  rs=sqrt(1.-r**2)
741  if (nrand+2.gt.maxrand) nrand=1
742  usigold=r*usigold+rs*rannumb(nrand)*usig*turbmesoscale
743  vsigold=r*vsigold+rs*rannumb(nrand+1)*vsig*turbmesoscale
744  wsigold=r*wsigold+rs*rannumb(nrand+2)*wsig*turbmesoscale
745
746  dxsave=dxsave+usigold*real(lsynctime)
747  dysave=dysave+vsigold*real(lsynctime)
748
749  zt=zt+wsigold*real(lsynctime)
750  if (zt.lt.0.) zt=-1.*zt    ! if particle below ground -> refletion
751
752  !*************************************************************
753  ! Transform along and cross wind components to xy coordinates,
754  ! add them to u and v, transform u,v to grid units/second
755  ! and calculate new position
756  !*************************************************************
757
758  call windalign(dxsave,dysave,dawsave,dcwsave,ux,vy)
759  dxsave=dxsave+ux   ! comment by mc: comment this line to stop the particles horizontally for test reasons
760  dysave=dysave+vy
761  if (ngrid.ge.0) then
762    cosfact=dxconst/cos((yt*dy+ylat0)*pi180)
763    xt=xt+real(dxsave*cosfact*real(ldirect),kind=dp)
764    yt=yt+real(dysave*dyconst*real(ldirect),kind=dp)
765  else if (ngrid.eq.-1) then      ! around north pole
766    xlon=xlon0+xt*dx                                !comment by mc: compute old particle position
767    ylat=ylat0+yt*dy
768    call cll2xy(northpolemap,ylat,xlon,xpol,ypol)   !convert old particle position in polar stereographic
769    gridsize=1000.*cgszll(northpolemap,ylat,xlon)   !calculate size in m of grid element in polar stereographic coordinate
770    dxsave=dxsave/gridsize                          !increment from meter to grdi unit
771    dysave=dysave/gridsize
772    xpol=xpol+dxsave*real(ldirect)                  !position in grid unit polar stereographic
773    ypol=ypol+dysave*real(ldirect)
774    call cxy2ll(northpolemap,xpol,ypol,ylat,xlon)  !convert to lat long coordinate
775    xt=(xlon-xlon0)/dx                             !convert to grid units in lat long coordinate, comment by mc
776    yt=(ylat-ylat0)/dy
777  else if (ngrid.eq.-2) then    ! around south pole
778    xlon=xlon0+xt*dx
779    ylat=ylat0+yt*dy
780    call cll2xy(southpolemap,ylat,xlon,xpol,ypol)
781    gridsize=1000.*cgszll(southpolemap,ylat,xlon)
782    dxsave=dxsave/gridsize
783    dysave=dysave/gridsize
784    xpol=xpol+dxsave*real(ldirect)
785    ypol=ypol+dysave*real(ldirect)
786    call cxy2ll(southpolemap,xpol,ypol,ylat,xlon)
787    xt=(xlon-xlon0)/dx
788    yt=(ylat-ylat0)/dy
789  endif
790
791
792  ! If global data are available, use cyclic boundary condition
793  !************************************************************
794
795  if (xglobal) then
796    if (xt.ge.real(nxmin1)) xt=xt-real(nxmin1)
797    if (xt.lt.0.) xt=xt+real(nxmin1)
798    if (xt.le.eps) xt=eps
799    if (abs(xt-real(nxmin1)).le.eps) xt=real(nxmin1)-eps
800  endif
801
802  ! HSO/AL: Prevent particles from disappearing at the pole
803  !******************************************************************
804
805  if ( yt.lt.0. ) then
806    xt=mod(xt+180.,360.)
807    yt=-yt
808  else if ( yt.gt.real(nymin1) ) then
809    xt=mod(xt+180.,360.)
810    yt=2*real(nymin1)-yt
811  endif
812
813  ! Check position: If trajectory outside model domain, terminate it
814  !*****************************************************************
815
816  if ((xt.lt.0.).or.(xt.ge.real(nxmin1)).or.(yt.lt.0.).or. &
817       (yt.gt.real(nymin1))) then
818    nstop=3
819    return
820  endif
821
822  ! If particle above highest model level, set it back into the domain
823  !*******************************************************************
824
825  if (zt.ge.height(nz)) zt=height(nz)-100.*eps
826
827
828  !************************************************************************
829  ! Now we could finish, as this was done in FLEXPART versions up to 4.0.
830  ! However, truncation errors of the advection can be significantly
831  ! reduced by doing one iteration of the Petterssen scheme, if this is
832  ! possible.
833  ! Note that this is applied only to the grid-scale winds, not to
834  ! the turbulent winds.
835  !************************************************************************
836
837  ! The Petterssen scheme can only applied with long time steps (only then u
838  ! is the "old" wind as required by the scheme); otherwise do nothing
839  !*************************************************************************
840
841  if (ldt.ne.abs(lsynctime)) return
842
843  ! The Petterssen scheme can only be applied if the ending time of the time step
844  ! (itime+ldt*ldirect) is still between the two wind fields held in memory;
845  ! otherwise do nothing
846  !******************************************************************************
847
848  if (abs(itime+ldt*ldirect).gt.abs(memtime(2))) return
849
850  ! Apply it also only if starting and ending point of current time step are on
851  ! the same grid; otherwise do nothing
852  !*****************************************************************************
853  if (nglobal.and.(yt.gt.switchnorthg)) then
854    ngr=-1
855  else if (sglobal.and.(yt.lt.switchsouthg)) then
856    ngr=-2
857  else
858    ngr=0
859    do j=numbnests,1,-1
860      if ((xt.gt.xln(j)+eps).and.(xt.lt.xrn(j)-eps).and. &
861           (yt.gt.yln(j)+eps).and.(yt.lt.yrn(j)-eps)) then
862        ngr=j
863        goto 43
864      endif
865    end do
86643   continue
867  endif
868
869  if (ngr.ne.ngrid) return
870
871  ! Determine nested grid coordinates
872  !**********************************
873
874  if (ngrid.gt.0) then
875    xtn=(xt-xln(ngrid))*xresoln(ngrid)
876    ytn=(yt-yln(ngrid))*yresoln(ngrid)
877    ix=int(xtn)
878    jy=int(ytn)
879  else
880    ix=int(xt)
881    jy=int(yt)
882  endif
883  ixp=ix+1
884  jyp=jy+1
885
886
887  ! Memorize the old wind
888  !**********************
889
890  uold=u
891  vold=v
892  wold=w
893
894  ! Interpolate wind at new position and time
895  !******************************************
896
897  if (ngrid.le.0) then
898    xts=real(xt)
899    yts=real(yt)
900    call interpol_wind_short(itime+ldt*ldirect,xts,yts,zt)
901  else
902    call interpol_wind_short_nests(itime+ldt*ldirect,xtn,ytn,zt)
903  endif
904
905  if (mdomainfill.eq.0) then
906! ESO 05.2015  Changed this to fix MQUASILAG option, where nrelpoint is
907!              particle number and thus xmass array goes out of bounds
908!    do nsp=1,nspec
909!       if (xmass(nrelpoint,nsp).gt.eps2) goto 889
910!     end do
911! 889   nsp=min(nsp,nspec)
912!      if (density(nsp).gt.0.) then
913    if (nspec.eq.1.and.density(1).gt.0.) then
914      call get_settling(itime+ldt,real(xt),real(yt),zt,nspec,settling)  !bugfix
915    end if
916    w=w+settling
917  endif
918
919
920  ! Determine the difference vector between new and old wind
921  ! (use half of it to correct position according to Petterssen)
922  !*************************************************************
923
924  u=(u-uold)/2.
925  v=(v-vold)/2.
926  w=(w-wold)/2.
927
928
929  ! Finally, correct the old position
930  !**********************************
931
932  zt=zt+w*real(ldt*ldirect)
933  if (zt.lt.0.) zt=min(h-eps2,-1.*zt)    ! if particle below ground -> reflection
934  if (ngrid.ge.0) then
935    cosfact=dxconst/cos((yt*dy+ylat0)*pi180)
936    xt=xt+real(u*cosfact*real(ldt*ldirect),kind=dp)
937    yt=yt+real(v*dyconst*real(ldt*ldirect),kind=dp)
938  else if (ngrid.eq.-1) then      ! around north pole
939    xlon=xlon0+xt*dx
940    ylat=ylat0+yt*dy
941    call cll2xy(northpolemap,ylat,xlon,xpol,ypol)
942    gridsize=1000.*cgszll(northpolemap,ylat,xlon)
943    u=u/gridsize
944    v=v/gridsize
945    xpol=xpol+u*real(ldt*ldirect)
946    ypol=ypol+v*real(ldt*ldirect)
947    call cxy2ll(northpolemap,xpol,ypol,ylat,xlon)
948    xt=(xlon-xlon0)/dx
949    yt=(ylat-ylat0)/dy
950  else if (ngrid.eq.-2) then    ! around south pole
951    xlon=xlon0+xt*dx
952    ylat=ylat0+yt*dy
953    call cll2xy(southpolemap,ylat,xlon,xpol,ypol)
954    gridsize=1000.*cgszll(southpolemap,ylat,xlon)
955    u=u/gridsize
956    v=v/gridsize
957    xpol=xpol+u*real(ldt*ldirect)
958    ypol=ypol+v*real(ldt*ldirect)
959    call cxy2ll(southpolemap,xpol,ypol,ylat,xlon)
960    xt=(xlon-xlon0)/dx
961    yt=(ylat-ylat0)/dy
962  endif
963
964  ! If global data are available, use cyclic boundary condition
965  !************************************************************
966
967  if (xglobal) then
968    if (xt.ge.real(nxmin1)) xt=xt-real(nxmin1)
969    if (xt.lt.0.) xt=xt+real(nxmin1)
970    if (xt.le.eps) xt=eps
971    if (abs(xt-real(nxmin1)).le.eps) xt=real(nxmin1)-eps
972  endif
973
974  ! HSO/AL: Prevent particles from disappearing at the pole
975  !******************************************************************
976
977  if ( yt.lt.0. ) then
978    xt=mod(xt+180.,360.)
979    yt=-yt
980  else if ( yt.gt.real(nymin1) ) then
981    xt=mod(xt+180.,360.)
982    yt=2*real(nymin1)-yt
983  endif
984
985  ! Check position: If trajectory outside model domain, terminate it
986  !*****************************************************************
987
988  if ((xt.lt.0.).or.(xt.ge.real(nxmin1)).or.(yt.lt.0.).or. &
989       (yt.gt.real(nymin1))) then
990    nstop=3
991    return
992  endif
993
994  ! If particle above highest model level, set it back into the domain
995  !*******************************************************************
996
997  if (zt.ge.height(nz)) zt=height(nz)-100.*eps
998
999
1000end subroutine advance
1001
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG