source: branches/jerome/src_flexwrf_v3.1/releaseparticles_reg.f90 @ 16

Last change on this file since 16 was 16, checked in by jebri, 10 years ago

sources for flexwrf v3.1

File size: 18.7 KB
Line 
1!***********************************************************************
2!* Copyright 2012,2013                                                *
3!* Jerome Brioude, Delia Arnold, Andreas Stohl, Wayne Angevine,       *
4!* John Burkhart, Massimo Cassiani, Adam Dingwell, Richard C Easter, Sabine Eckhardt,*
5!* Stephanie Evan, Jerome D Fast, Don Morton, Ignacio Pisso,          *
6!* Petra Seibert, Gerard Wotawa, Caroline Forster, Harald Sodemann,   *
7!*                                                                     *
8!* This file is part of FLEXPART WRF                                   *
9!*                                                                     *
10!* FLEXPART is free software: you can redistribute it and/or modify    *
11!* it under the terms of the GNU General Public License as published by*
12!* the Free Software Foundation, either version 3 of the License, or   *
13!* (at your option) any later version.                                 *
14!*                                                                     *
15!* FLEXPART is distributed in the hope that it will be useful,         *
16!* but WITHOUT ANY WARRANTY; without even the implied warranty of      *
17!* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       *
18!* GNU General Public License for more details.                        *
19!*                                                                     *
20!* You should have received a copy of the GNU General Public License   *
21!* along with FLEXPART.  If not, see <http://www.gnu.org/licenses/>.   *
22!***********************************************************************
23
24      subroutine releaseparticles_reg(itime)
25!                                   o
26!*******************************************************************************
27!                                                                              *
28!     This subroutine releases particles from the release locations.           *
29!                                                                              *
30!     Note:  This is the FLEXPART_WRF version of subroutine gridcheck.         *
31!            The computational grid is the WRF x-y grid rather than lat-lon.   *
32!                                                                              *
33!     It searches for a "vacant" storage space and assigns all particle        *
34!     information to that space. A space is vacant either when no particle     *
35!     is yet assigned to it, or when it's particle is expired and, thus,       *
36!     the storage space is made available to a new particle.                   *
37!                                                                              *
38!     Author: A. Stohl                                                         *
39!     29 June 2002                                                             *
40!                                                                              *
41!     14 Nov 2005, R. Easter - use xyindex_to_ll_wrf to get lat,lon            *
42!     July 2012, J. Brioude: regular lat/lon grid coordinates                  *
43!*******************************************************************************
44!                                                                              *
45! Variables:                                                                   *
46! itime [s]            current time                                            *
47! ireleasestart, ireleaseend          start and end times of all releases      *
48! npart(maxpoint)      number of particles to be released in total             *
49! numrel               number of particles to be released during this time step*
50!                                                                              *
51!*******************************************************************************
52
53  use par_mod
54  use com_mod
55  use point_mod
56!  use xmass_mod
57
58!      include 'includepar'
59!      include 'includecom'
60
61      real :: xaux,yaux,zaux,ran1,rfraction
62!,xmasssave(maxpoint)
63      real :: topo,rhoaux(2),r,t,rhoout,ddx,ddy,rddx,rddy,p1,p2,p3,p4
64      real :: dz1,dz2,dz,xtn,ytn,xlonav,timecorrect(maxspec),press,pressold
65      real :: presspart,average_timecorrect,xlon,ylat,x1,y1
66      real :: dumx, dumy, ylatav,xaux2,yaux2
67      real,parameter :: eps=1.e-8
68      integer :: itime,numrel,i,j,k,n,ix,jy,ixp,jyp,ipart,minpart,ii
69      integer :: indz,indzp,kz,ngrid
70      integer :: nweeks,ndayofweek,nhour,jjjjmmdd,ihmmss,mm
71  real(kind=dp) :: juldate,julmonday,jul,jullocal,juldiff
72
73  integer :: idummy = -7
74!      save idummy,xmasssave
75!      data idummy/-7/,xmasssave/maxpoint*0./
76
77
78
79! Determine the actual date and time in Greenwich (i.e., UTC + correction for daylight savings time)
80!***************************************************************************************************
81
82      julmonday=juldate(19000101,0)          ! this is a Monday
83  jul=bdate+real(itime,kind=dp)/86400._dp    ! this is the current day
84
85      call caldate(jul,jjjjmmdd,ihmmss)
86      mm=(jjjjmmdd-10000*(jjjjmmdd/10000))/100
87  if ((mm.ge.4).and.(mm.le.9)) jul=jul+1._dp/24._dp   ! daylight savings time in summer
88         
89
90! For every release point, check whether we are in the release time interval
91!***************************************************************************
92      minpart=1
93!    print*,'test rel time',itime,itra1(2),itra1(2000),itra1(4000)
94      do i=1,numpoint
95!           print*,'numpoint',numpoint,itime,ireleasestart(i)     
96        if ((itime.ge.ireleasestart(i)).and.   &         ! are we within release interval?
97        (itime.le.ireleaseend(i))) then
98
99! Determine the local day and time
100!*********************************
101
102! FLEXPART_WRF - use this routine to get lat,lon
103!         xlonav=xlon0+(xpoint2(i)+xpoint1(i))/2.*dx  ! longitude needed to determine local time
104          dumx = (xpoint2(i)+xpoint1(i))*0.5
105          dumy = (ypoint2(i)+ypoint1(i))*0.5
106          call xyindex_to_ll_wrf( 0, dumx, dumy, xlonav, ylatav )
107
108          if (xlonav.lt.-180.) xlonav=xlonav+360.
109          if (xlonav.gt.180.) xlonav=xlonav-360.
110      jullocal=jul+real(xlonav,kind=dp)/360._dp   ! correct approximately for time zone to obtain local time
111
112      juldiff=jullocal-julmonday
113      nweeks=int(juldiff/7._dp)
114      juldiff=juldiff-real(nweeks,kind=dp)*7._dp
115      ndayofweek=int(juldiff)+1              ! this is the current day of week, starting with Monday
116      nhour=nint((juldiff-real(ndayofweek-1,kind=dp))*24._dp)    ! this is the current hour
117      if (nhour.eq.0) then
118        nhour=24
119        ndayofweek=ndayofweek-1
120        if (ndayofweek.eq.0) ndayofweek=7
121      endif
122
123! Calculate a species- and time-dependent correction factor, distinguishing between
124! area (those with release starting at surface) and point (release starting above surface) sources
125! Also, calculate an average time correction factor (species independent)
126!*************************************************************************************************
127          average_timecorrect=0.
128          do k=1,nspec
129            if (zpoint1(i).gt.0.5) then      ! point source
130              timecorrect(k)=point_hour(k,nhour)*point_dow(k,ndayofweek)
131            else                             ! area source
132              timecorrect(k)=area_hour(k,nhour)*area_dow(k,ndayofweek)
133            endif
134            average_timecorrect=average_timecorrect+timecorrect(k)
135           enddo
136          average_timecorrect=average_timecorrect/real(nspec)
137
138! Determine number of particles to be released this time; at start and at end of release,
139! only half the particles are released
140!****************************************************************************************
141
142          if (ireleasestart(i).ne.ireleaseend(i)) then
143            rfraction=abs(real(npart(i))*real(lsynctime)/ &
144            real(ireleaseend(i)-ireleasestart(i)))
145            if ((itime.eq.ireleasestart(i)).or. &
146            (itime.eq.ireleaseend(i))) rfraction=rfraction/2.
147
148! Take the species-average time correction factor in order to scale the
149! number of particles released this time
150!**********************************************************************
151            rfraction=rfraction*average_timecorrect
152
153            rfraction=rfraction+xmasssave(i)  ! number to be released at this time
154!            rfraction=rfraction+xmasssave(1)  ! number to be released at this time
155            numrel=int(rfraction)
156            xmasssave(i)=rfraction-real(numrel)
157!            xmasssave(1)=rfraction-real(numrel)
158          else
159            numrel=npart(i)
160          endif
161
162!          xaux=xpoint2(i)-xpoint1(i)
163!          yaux=ypoint2(i)-ypoint1(i)
164          xaux2=xpoint22(i)-xpoint12(i)
165          yaux2=ypoint22(i)-ypoint12(i)
166          zaux=zpoint2(i)-zpoint1(i)
167!           print*,'numrel',numrel,numpart
168          do j=1,numrel                       ! loop over particles to be released this time
169            do ipart=minpart,maxpart          ! search for free storage space
170! If a free storage space is found, attribute everything to this array element
171!*****************************************************************************
172
173              if (itra1(ipart).ne.itime) then   
174               
175! Particle coordinates are determined by using a random position within the release volume
176!*****************************************************************************************
177!              print*,'empty',ipart,itra1(ipart),itime
178! Determine horizontal particle position
179!***************************************
180
181!                xtra1(ipart)=xpoint1(i)+ran1(idummy)*xaux
182                xlon=xpoint12(i)+ran1(idummy)*xaux2
183                ylat=ypoint12(i)+ran1(idummy)*yaux2
184!JB: a tester
185!       print*,'map_std',map_stdlon
186        call ll_to_xymeter_wrf(xlon,ylat,x1,y1)
187                xtra1(ipart)=(x1-xmet0)/dx
188                ytra1(ipart)=(y1-ymet0)/dy
189
190                if (xglobal) then
191                  if (xtra1(ipart).gt.real(nxmin1)) xtra1(ipart)= &
192                  xtra1(ipart)-real(nxmin1)
193                  if (xtra1(ipart).lt.0.) xtra1(ipart)= &
194                  xtra1(ipart)+real(nxmin1)
195                endif
196!                ytra1(ipart)=ypoint1(i)+ran1(idummy)*yaux
197
198! Assign mass to particle: Total mass divided by total number of particles.
199! Time variation has partly been taken into account already by a species-average
200! correction factor, by which the number of particles released this time has been
201! scaled. Adjust the mass per particle by the species-dependent time correction factor
202! divided by the species-average one 
203!*************************************************************************************
204
205                do k=1,nspec
206                  xmass1(ipart,k)=xmass(i,k)/real(npart(i)) &
207                  *timecorrect(k)/average_timecorrect
208                enddo
209! Assign certain properties to particle
210!**************************************
211
212                nclass(ipart)=min(int(ran1(idummy)*real(nclassunc))+1, &
213                nclassunc)
214                numparticlecount=numparticlecount+1
215                if (mquasilag.eq.0) then
216                  npoint(ipart)=i
217                else
218                  npoint(ipart)=numparticlecount
219                endif
220                idt(ipart)=mintime               ! first time step
221                itra1(ipart)=itime
222                itramem(ipart)=itra1(ipart)
223                itrasplit(ipart)=itra1(ipart)+ldirect*itsplit
224
225
226! Determine vertical particle position
227!*************************************
228
229                ztra1(ipart)=zpoint1(i)+ran1(idummy)*zaux
230!          print*,'ipart 1',ipart,ztra1(ipart)
231! Interpolation of topography and density
232!****************************************
233
234! Determine the nest we are in
235!*****************************
236
237                ngrid=0
238                do k=numbnests,1,-1
239                  if ((xtra1(ipart).gt.xln(k)+eps).and. &
240                  (xtra1(ipart).lt.xrn(k)-eps).and. &
241                  (ytra1(ipart).gt.yln(k)+eps).and. &
242                  (ytra1(ipart).lt.yrn(k)-eps)) then
243                    ngrid=k
244                    goto 43
245                  endif
246                enddo
24743              continue
248
249! Determine (nested) grid coordinates and auxiliary parameters used for interpolation
250!************************************************************************************
251
252                if (ngrid.gt.0) then
253                  xtn=(xtra1(ipart)-xln(ngrid))*xresoln(ngrid)
254                  ytn=(ytra1(ipart)-yln(ngrid))*yresoln(ngrid)
255                  ix=int(xtn)
256                  jy=int(ytn)
257                  ddy=ytn-real(jy)
258                  ddx=xtn-real(ix)
259                else
260                  ix=int(xtra1(ipart))
261                  jy=int(ytra1(ipart))
262                  ddy=ytra1(ipart)-real(jy)
263                  ddx=xtra1(ipart)-real(ix)
264                endif
265                ixp=ix+1
266                jyp=jy+1
267                rddx=1.-ddx
268                rddy=1.-ddy
269                p1=rddx*rddy
270                p2=ddx*rddy
271                p3=rddx*ddy
272                p4=ddx*ddy
273
274            if (ngrid.gt.0) then
275              topo=p1*oron(ix ,jy ,ngrid) &
276                   + p2*oron(ixp,jy ,ngrid) &
277                   + p3*oron(ix ,jyp,ngrid) &
278                   + p4*oron(ixp,jyp,ngrid)
279            else
280              topo=p1*oro(ix ,jy) &
281                   + p2*oro(ixp,jy) &
282                   + p3*oro(ix ,jyp) &
283                   + p4*oro(ixp,jyp)
284            endif
285
286! If starting height is in pressure coordinates, retrieve pressure profile and convert zpart1 to meters
287!******************************************************************************************************
288            if (kindz(i).eq.3) then
289              presspart=ztra1(ipart)
290              do kz=1,nz
291                if (ngrid.gt.0) then
292                  r=p1*rhon(ix ,jy ,kz,2,ngrid) &
293                       +p2*rhon(ixp,jy ,kz,2,ngrid) &
294                       +p3*rhon(ix ,jyp,kz,2,ngrid) &
295                       +p4*rhon(ixp,jyp,kz,2,ngrid)
296                  t=p1*ttn(ix ,jy ,kz,2,ngrid) &
297                       +p2*ttn(ixp,jy ,kz,2,ngrid) &
298                       +p3*ttn(ix ,jyp,kz,2,ngrid) &
299                       +p4*ttn(ixp,jyp,kz,2,ngrid)
300                else
301                  r=p1*rho(ix ,jy ,kz,2) &
302                       +p2*rho(ixp,jy ,kz,2) &
303                       +p3*rho(ix ,jyp,kz,2) &
304                       +p4*rho(ixp,jyp,kz,2)
305                  t=p1*tt(ix ,jy ,kz,2) &
306                       +p2*tt(ixp,jy ,kz,2) &
307                       +p3*tt(ix ,jyp,kz,2) &
308                       +p4*tt(ixp,jyp,kz,2)
309                endif
310                press=r*r_air*t/100.
311                if (kz.eq.1) pressold=press
312
313                    if (press.lt.presspart) then
314                      if (kz.eq.1) then
315                        ztra1(ipart)=height(1)/2.
316                      else
317                        dz1=pressold-presspart
318                        dz2=presspart-press
319                        ztra1(ipart)=(height(kz-1)*dz2+height(kz)*dz1) &
320                        /(dz1+dz2)
321                      endif
322                      goto 71
323                    endif
324                    pressold=press
325              end do
32671                continue
327                endif
328
329! If release positions are given in meters above sea level, subtract the
330! topography from the starting height
331!***********************************************************************
332
333                if (kindz(i).eq.2) ztra1(ipart)=ztra1(ipart)-topo
334                if (ztra1(ipart).lt.eps) ztra1(ipart)=eps   ! Minimum starting height is eps
335                if (ztra1(ipart).gt.height(nz)-0.5) ztra1(ipart)= &
336                height(nz)-0.5 ! Maximum starting height is uppermost level - 0.5 meters
337
338
339
340! For special simulations, multiply particle concentration air density;
341! Simply take the 2nd field in memory to do this (accurate enough)
342!***********************************************************************
343!AF IND_SOURCE switches between different units for concentrations at the source
344!Af    NOTE that in backward simulations the release of particles takes place at the
345!Af         receptor and the sampling at the source.
346!Af          1="mass"
347!Af          2="mass mixing ratio"
348!Af IND_RECEPTOR switches between different units for concentrations at the receptor
349!Af          1="mass"
350!Af          2="mass mixing ratio"
351
352!Af switches for the releasefile:
353!Af IND_REL =  1 : xmass * rho
354!Af IND_REL =  0 : xmass * 1
355
356!Af ind_rel is defined in readcommand.f
357
358                if (ind_rel .eq. 1) then
359
360! Interpolate the air density
361!****************************
362
363                  do ii=2,nz
364                    if (height(ii).gt.ztra1(ipart)) then
365                      indz=ii-1
366                      indzp=ii
367                      goto 6
368                    endif
369                  enddo
3706                 continue
371
372                  dz1=ztra1(ipart)-height(indz)
373                  dz2=height(indzp)-ztra1(ipart)
374                  dz=1./(dz1+dz2)
375
376                  if (ngrid.gt.0) then
377                    do n=1,2
378                      rhoaux(n)=p1*rhon(ix ,jy ,indz+n-1,2,ngrid) &
379                               +p2*rhon(ixp,jy ,indz+n-1,2,ngrid) &
380                               +p3*rhon(ix ,jyp,indz+n-1,2,ngrid) &
381                               +p4*rhon(ixp,jyp,indz+n-1,2,ngrid)
382                  enddo
383                  else
384                    do n=1,2
385                      rhoaux(n)=p1*rho(ix ,jy ,indz+n-1,2) &
386                               +p2*rho(ixp,jy ,indz+n-1,2) &
387                               +p3*rho(ix ,jyp,indz+n-1,2) &
388                               +p4*rho(ixp,jyp,indz+n-1,2)
389                  enddo
390                  endif
391                  rhoout=(dz2*rhoaux(1)+dz1*rhoaux(2))*dz
392
393
394! Multiply "mass" (i.e., mass mixing ratio in forward runs) with density
395!********************************************************************
396
397                  do k=1,nspec
398                  xmass1(ipart,k)=xmass1(ipart,k)*rhoout
399                   enddo
400                endif
401
402
403
404                numpart=max(numpart,ipart)
405                goto 34      ! Storage space has been found, stop searching
406              endif
407        end do
408
409            if (ipart.gt.maxpart) goto 996
41034          minpart=ipart+1
411      end do
412      endif
413  end do
414!       print*,'numpart in rel',numpart
415!         print*,'test rel0',npoint(5139),npoint(6002),npoint(100003)
416!           print*,'numpart release',numpart,ipart,maxpart
417
418      return
419
420996   continue
421      write(*,*) '#####################################################'
422      write(*,*) '#### FLEXPART MODEL SUBROUTINE RELEASEPARTICLES: ####'
423      write(*,*) '####                                             ####'
424      write(*,*) '#### ERROR - TOTAL NUMBER OF PARTICLES REQUIRED  ####'
425      write(*,*) '#### EXCEEDS THE MAXIMUM ALLOWED NUMBER. REDUCE  ####'
426      write(*,*) '#### EITHER NUMBER OF PARTICLES PER RELEASE POINT####'
427      write(*,*) '#### OR REDUCE NUMBER OF RELEASE POINTS.         ####'
428      write(*,*) '#####################################################'
429      stop
430
431end subroutine releaseparticles_reg
432
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG