source: flexpart.git/src/advance.f90 @ e52967c

10.4.1_peseiGFS_025bugfixes+enhancementsdevrelease-10release-10.4.1scaling-bugunivie
Last change on this file since e52967c was e52967c, checked in by Espen Sollum ATMOS <eso@…>, 7 years ago

Quick fix for segmentation fault when particle is at north pole

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