source: flexpart.git/src/advance.f90 @ 8a65cb0

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

Added code, makefile for dev branch

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