source: flexpart.git/src/advance.f90 @ 420423c

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

code included to interpolate hmix

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