source: flexpart.git/src/timemanager_mpi.f90 @ 20963b1

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

Backwards deposition for the MPI version

  • Property mode set to 100644
File size: 34.9 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 timemanager(metdata_format)
23
24!*****************************************************************************
25!                                                                            *
26! Handles the computation of trajectories, i.e. determines which             *
27! trajectories have to be computed at what time.                             *
28! Manages dry+wet deposition routines, radioactive decay and the computation *
29! of concentrations.                                                         *
30!                                                                            *
31!     Author: A. Stohl                                                       *
32!                                                                            *
33!     20 May 1996                                                            *
34!                                                                            *
35!*****************************************************************************
36!  Changes, Bernd C. Krueger, Feb. 2001:                                     *
37!        Call of convmix when new windfield is read                          *
38!------------------------------------                                        *
39!  Changes Petra Seibert, Sept 2002                                          *
40!     fix wet scavenging problem                                             *
41!     Code may not be correct for decay of deposition!                       *
42!  Changes Petra Seibert, Nov 2002                                           *
43!     call convection BEFORE new fields are read in BWD mode                 *
44!  Changes Caroline Forster, Feb 2005                                        *
45!   new interface between flexpart and convection scheme                     *
46!   Emanuel's latest subroutine convect43c.f is used                         *
47!  Changes Stefan Henne, Harald Sodemann, 2013-2014                          *
48!   added netcdf output code                                                 *
49!  Changes Espen Sollum 2014                                                 *
50!   MPI version                                                              *
51!   Variables uap,ucp,uzp,us,vs,ws,cbt now in module com_mod                 *
52!  Unified ECMWF and GFS builds                                              *
53!   Marian Harustak, 12.5.2017                                               *
54!   - Added passing of metdata_format as it was needed by called routines    *
55!*****************************************************************************
56!                                                                            *
57! Variables:                                                                 *
58! dep                .true. if either wet or dry deposition is switched on   *
59! decay(maxspec) [1/s] decay constant for radioactive decay                  *
60! drydep             .true. if dry deposition is switched on                 *
61! ideltas [s]        modelling period                                        *
62! itime [s]          actual temporal position of calculation                 *
63! ldeltat [s]        time since computation of radioact. decay of depositions*
64! loutaver [s]       averaging period for concentration calculations         *
65! loutend [s]        end of averaging for concentration calculations         *
66! loutnext [s]       next time at which output fields shall be centered      *
67! loutsample [s]     sampling interval for averaging of concentrations       *
68! loutstart [s]      start of averaging for concentration calculations       *
69! loutstep [s]       time interval for which concentrations shall be         *
70!                    calculated                                              *
71! npoint(maxpart)    index, which starting point the trajectory has          *
72!                    starting positions of trajectories                      *
73! nstop              serves as indicator for fate of particles               *
74!                    in the particle loop                                    *
75! nstop1             serves as indicator for wind fields (see getfields)     *
76! memstat            additional indicator for wind fields (see getfields)    *
77! outnum             number of samples for each concentration calculation    *
78! prob               probability of absorption at ground due to dry          *
79!                    deposition                                              *
80! wetdep             .true. if wet deposition is switched on                 *
81! weight             weight for each concentration sample (1/2 or 1)         *
82! uap(maxpart),ucp(maxpart),uzp(maxpart) = random velocities due to          *
83!                    turbulence                                              *
84! us(maxpart),vs(maxpart),ws(maxpart) = random velocities due to inter-      *
85!                    polation                                                *
86! xtra1(maxpart), ytra1(maxpart), ztra1(maxpart) =                           *
87!                    spatial positions of trajectories                       *
88! metdata_format     format of metdata (ecmwf/gfs)                           *
89!                                                                            *
90! Constants:                                                                 *
91! maxpart            maximum number of trajectories                          *
92!                                                                            *
93!*****************************************************************************
94
95  use unc_mod
96  use point_mod
97  use xmass_mod
98  use flux_mod
99  use outg_mod
100  use oh_mod
101  use par_mod
102  use com_mod
103  use mpi_mod
104#ifdef USE_NCF
105  use netcdf_output_mod, only: concoutput_netcdf,concoutput_nest_netcdf,&
106       &concoutput_surf_netcdf,concoutput_surf_nest_netcdf
107#endif
108
109  implicit none
110
111  integer :: metdata_format
112  logical :: reqv_state=.false. ! .true. if waiting for a MPI_Irecv to complete
113  integer :: j,ks,kp,l,n,itime=0,nstop,nstop1,memstat=0
114! integer :: ksp
115  integer :: ip
116  integer :: loutnext,loutstart,loutend
117  integer :: ix,jy,ldeltat,itage,nage,idummy
118  integer :: i_nan=0,ii_nan,total_nan_intl=0  !added by mc to check instability in CBL scheme
119  integer :: numpart_tot_mpi ! for summing particles on all processes
120  real :: outnum,weight,prob(maxspec), prob_rec(maxspec), decfact,wetscav
121
122  real(sp) :: gridtotalunc
123  real(dep_prec) :: drygridtotalunc=0_dep_prec,wetgridtotalunc=0_dep_prec,&
124       & drydeposit(maxspec)=0_dep_prec
125  real :: xold,yold,zold,xmassfract
126  real :: grfraction(3)
127  real, parameter :: e_inv = 1.0/exp(1.0)
128
129! Measure time spent in timemanager
130  if (mp_measure_time) call mpif_mtime('timemanager',0)
131
132! First output for time 0
133!************************
134
135  loutnext=loutstep/2
136  outnum=0.
137  loutstart=loutnext-loutaver/2
138  loutend=loutnext+loutaver/2
139
140
141!**********************************************************************
142! Loop over the whole modelling period in time steps of mintime seconds
143!**********************************************************************
144
145
146  if (lroot.or.mp_dev_mode) then
147  !  write(*,45) itime,numpart*mp_partgroup_np,gridtotalunc,wetgridtotalunc,drygridtotalunc
148    write(*,46) float(itime)/3600,itime,numpart*mp_partgroup_np
149   
150    if (verbosity.gt.0) then
151      write (*,*) 'timemanager> starting simulation'
152    end if
153  end if ! (lroot)
154
155!CGZ-lifetime: set lifetime to 0
156  ! checklifetime(:,:)=0
157  ! species_lifetime(:,:)=0
158  ! print*, 'Initialized lifetime'
159!CGZ-lifetime: set lifetime to 0
160
161  if (.not.lusekerneloutput) write(*,*) 'Not using the kernel'
162  if (turboff) write(*,*) 'Turbulence switched off'
163
164
165  do itime=0,ideltas,lsynctime
166   
167
168! Computation of wet deposition, OH reaction and mass transfer
169! between two species every lsynctime seconds
170! maybe wet depo frequency can be relaxed later but better be on safe side
171! wetdepo must be called BEFORE new fields are read in but should not
172! be called in the very beginning before any fields are loaded, or
173! before particles are in the system
174! Code may not be correct for decay of deposition
175! changed by Petra Seibert 9/02
176!********************************************************************
177
178    if (mp_dbg_mode) write(*,*) 'myid, itime: ',mp_pid,itime
179   
180    if (WETDEP .and. itime .ne. 0 .and. numpart .gt. 0) then
181      if (verbosity.gt.0) then
182        write (*,*) 'timemanager> call wetdepo'
183      endif
184
185      if (mp_measure_time) call mpif_mtime('wetdepo',0)
186       
187! readwind process skips this step
188      if (.not.(lmpreader.and.lmp_use_reader)) then
189        call wetdepo(itime,lsynctime,loutnext)
190      end if
191
192      if (mp_measure_time) call mpif_mtime('wetdepo',1)
193    end if
194
195    if (OHREA .and. itime .ne. 0 .and. numpart .gt. 0) then
196! readwind process skips this step
197      if (.not.(lmpreader.and.lmp_use_reader)) then
198        call ohreaction(itime,lsynctime,loutnext)
199      endif
200    end if
201
202    if (assspec .and. itime .ne. 0 .and. numpart .gt. 0) then
203      stop 'associated species not yet implemented!'
204!     call transferspec(itime,lsynctime,loutnext)
205    endif
206
207
208! compute convection for backward runs
209!*************************************
210
211    if ((ldirect.eq.-1).and.(lconvection.eq.1).and.(itime.lt.0)) then
212      if (verbosity.gt.0) then
213        write (*,*) 'timemanager> call convmix -- backward'
214      endif
215! readwind process skips this step
216      if (.not.(lmpreader.and.lmp_use_reader)) call convmix(itime,metdata_format)
217    endif
218
219! Get necessary wind fields if not available
220!*******************************************
221    if (verbosity.gt.0 .and. lmpreader) then
222      write (*,*) 'timemanager> call getfields'
223    endif
224
225! This time measure includes reading/MPI communication (for the reader process),
226! or MPI communication time only (for other processes)
227    if (mp_measure_time) call mpif_mtime('getfields',0)
228
229    call getfields(itime,nstop1,memstat,metdata_format)
230
231    if (mp_measure_time) call mpif_mtime('getfields',1)
232
233
234! Broadcast fields to all MPI processes
235! Skip if all processes have called getfields or if no new fields
236!*****************************************************************
237
238    if (mp_measure_time.and..not.(lmpreader.and.lmp_use_reader)) call mpif_mtime('getfields',0)
239
240! Two approaches to MPI getfields is implemented:
241! Version 1 (lmp_sync=.true.) uses a read-ahead process where send/recv is done
242! in sync at start of each new field time interval
243!
244! Version 2 (lmp_sync=.false.) is for holding three fields in memory. Uses a
245! read-ahead process where sending/receiving of the 3rd fields is done in
246! the background in parallel with performing computations with fields 1&2
247!********************************************************************************
248
249    if (lmp_sync.and.lmp_use_reader.and.memstat.gt.0) then
250      call mpif_gf_send_vars(memstat)
251      if (numbnests>0) call mpif_gf_send_vars_nest(memstat)
252! Version 2  (lmp_sync=.false.) is also used whenever 2 new fields are
253! read (as at first time step), in which case async send/recv is impossible.
254    else if (.not.lmp_sync.and.lmp_use_reader.and.memstat.ge.32) then
255      call mpif_gf_send_vars(memstat)
256      if (numbnests>0) call mpif_gf_send_vars_nest(memstat)
257    end if
258
259    if (.not.lmp_sync) then
260   
261! Reader process:
262      if (memstat.gt.0..and.memstat.lt.32.and.lmp_use_reader.and.lmpreader) then
263        if (mp_dev_mode) write(*,*) 'Reader process: calling mpif_gf_send_vars_async'
264        call mpif_gf_send_vars_async(memstat)
265        if (numbnests>0) call mpif_gf_send_vars_nest_async(memstat)
266      end if
267
268! Completion check:
269! Issued at start of each new field period.
270      if (memstat.ne.0.and.memstat.lt.32.and.lmp_use_reader) then
271        call mpif_gf_request
272      end if
273
274! Recveiving process(es):
275! eso TODO: at this point we do not know if clwc/ciwc will be available
276! at next time step. Issue receive request anyway, cancel at mpif_gf_request
277      if (memstat.gt.0.and.lmp_use_reader.and..not.lmpreader) then
278        if (mp_dev_mode) write(*,*) 'Receiving process: calling mpif_gf_send_vars_async. PID: ', mp_pid
279        call mpif_gf_recv_vars_async(memstat)
280        if (numbnests>0) call mpif_gf_recv_vars_nest_async(memstat)
281      end if
282
283    end if
284
285    if (mp_measure_time.and..not.(lmpreader.and.lmp_use_reader)) call mpif_mtime('getfields',1)
286
287! For validation and tests: call the function below to set all fields to simple
288! homogeneous values
289!    if (mp_dev_mode) call set_fields_synthetic
290
291!*******************************************************************************
292
293    if (lmpreader.and.nstop1.gt.1) stop 'NO METEO FIELDS AVAILABLE'
294
295! Reader process goes back to top of time loop (unless simulation end)
296!*********************************************************************
297
298    if (lmpreader.and.lmp_use_reader) then
299      if (itime.lt.ideltas*ldirect) then
300        cycle
301      else
302        goto 999
303      end if
304    end if
305
306
307! Get hourly OH fields if not available
308!****************************************************
309    if (OHREA) then
310      if (verbosity.gt.0) then
311        write (*,*) 'timemanager> call gethourlyOH'
312      endif
313      call gethourlyOH(itime)
314    endif
315
316
317! Release particles
318!******************
319
320    if (verbosity.gt.0.and.lroot) then
321      write (*,*) 'timemanager>  Release particles'
322    endif
323
324    if (mdomainfill.ge.1) then
325      if (itime.eq.0) then
326        if (verbosity.gt.0) then
327          write (*,*) 'timemanager>  call init_domainfill'
328        endif
329        call init_domainfill
330      else
331        if (verbosity.gt.0.and.lroot) then
332          write (*,*) 'timemanager>  call boundcond_domainfill'
333        endif
334        call boundcond_domainfill(itime,loutend)
335      endif
336    else
337      if (verbosity.gt.0.and.lroot) then
338        print*,'call releaseparticles' 
339      endif
340      call releaseparticles(itime)
341    endif
342
343
344! Check if particles should be redistributed among processes
345!***********************************************************
346    call mpif_calculate_part_redist(itime)
347
348
349! Compute convective mixing for forward runs
350! for backward runs it is done before next windfield is read in
351!**************************************************************
352
353    if ((ldirect.eq.1).and.(lconvection.eq.1)) then
354      if (verbosity.gt.0) then
355        write (*,*) 'timemanager> call convmix -- forward'
356      endif
357      call convmix(itime,metdata_format)
358    endif
359
360! If middle of averaging period of output fields is reached, accumulated
361! deposited mass radioactively decays
362!***********************************************************************
363
364    if (DEP.and.(itime.eq.loutnext).and.(ldirect.gt.0)) then
365      do ks=1,nspec
366        do kp=1,maxpointspec_act
367          if (decay(ks).gt.0.) then ! TODO move this statement up 2 levels
368            do nage=1,nageclass
369              do l=1,nclassunc
370! Mother output grid
371                do jy=0,numygrid-1
372                  do ix=0,numxgrid-1
373                    wetgridunc(ix,jy,ks,kp,l,nage)= &
374                         wetgridunc(ix,jy,ks,kp,l,nage)* &
375                         exp(-1.*outstep*decay(ks))
376                    drygridunc(ix,jy,ks,kp,l,nage)= &
377                         drygridunc(ix,jy,ks,kp,l,nage)* &
378                         exp(-1.*outstep*decay(ks))
379                  end do
380                end do
381! Nested output grid
382                if (nested_output.eq.1) then
383                  do jy=0,numygridn-1
384                    do ix=0,numxgridn-1
385                      wetgriduncn(ix,jy,ks,kp,l,nage)= &
386                           wetgriduncn(ix,jy,ks,kp,l,nage)* &
387                           exp(-1.*outstep*decay(ks))
388                      drygriduncn(ix,jy,ks,kp,l,nage)= &
389                           drygriduncn(ix,jy,ks,kp,l,nage)* &
390                           exp(-1.*outstep*decay(ks))
391                    end do
392                  end do
393                endif
394              end do
395            end do
396          endif
397        end do
398      end do
399    endif
400
401
402!!! CHANGE: These lines may be switched on to check the conservation
403!!! of mass within FLEXPART
404!   if (itime.eq.loutnext) then
405!   do 247 ksp=1, nspec
406!   do 247 kp=1, maxpointspec_act
407!47         xm(ksp,kp)=0.
408
409!   do 249 ksp=1, nspec
410!     do 249 j=1,numpart
411!          if (ioutputforeachrelease.eq.1) then
412!            kp=npoint(j)
413!          else
414!            kp=1
415!          endif
416!       if (itra1(j).eq.itime) then
417!          xm(ksp,kp)=xm(ksp,kp)+xmass1(j,ksp)
418!         write(*,*) 'xmass: ',xmass1(j,ksp),j,ksp,nspec
419!       endif
420!49     continue
421!  do 248 ksp=1,nspec
422!  do 248 kp=1,maxpointspec_act
423!  xm_depw(ksp,kp)=0.
424!  xm_depd(ksp,kp)=0.
425!     do 248 nage=1,nageclass
426!       do 248 ix=0,numxgrid-1
427!         do 248 jy=0,numygrid-1
428!           do 248 l=1,nclassunc
429!              xm_depw(ksp,kp)=xm_depw(ksp,kp)
430!    +                  +wetgridunc(ix,jy,ksp,kp,l,nage)
431!48                 xm_depd(ksp,kp)=xm_depd(ksp,kp)
432!    +                  +drygridunc(ix,jy,ksp,kp,l,nage)
433!             do 246 ksp=1,nspec
434!46                    write(88,'(2i10,3e12.3)')
435!    +              itime,ksp,(xm(ksp,kp),kp=1,maxpointspec_act),
436!    +                (xm_depw(ksp,kp),kp=1,maxpointspec_act),
437!    +                (xm_depd(ksp,kp),kp=1,maxpointspec_act)
438!  endif
439!!! CHANGE
440
441
442
443
444! Check whether concentrations are to be calculated
445!**************************************************
446
447    if ((ldirect*itime.ge.ldirect*loutstart).and. &
448         (ldirect*itime.le.ldirect*loutend)) then ! add to grid
449      if (mod(itime-loutstart,loutsample).eq.0) then
450
451! If we are exactly at the start or end of the concentration averaging interval,
452! give only half the weight to this sample
453!*****************************************************************************
454
455        if ((itime.eq.loutstart).or.(itime.eq.loutend)) then
456          weight=0.5
457        else
458          weight=1.0
459        endif
460        outnum=outnum+weight
461
462        call conccalc(itime,weight)
463
464      endif
465
466! :TODO: MPI output of particle positions;  each process sequentially
467!   access the same file
468      if ((mquasilag.eq.1).and.(itime.eq.(loutstart+loutend)/2)) &
469           call partoutput_short(itime)    ! dump particle positions in extremely compressed format
470
471
472! Output and reinitialization of grid
473! If necessary, first sample of new grid is also taken
474!*****************************************************
475
476      if ((itime.eq.loutend).and.(outnum.gt.0.)) then
477        if ((iout.le.3.).or.(iout.eq.5)) then
478
479! MPI: Root process collects/sums grids
480!**************************************
481          call mpif_tm_reduce_grid
482
483          if (mp_measure_time) call mpif_mtime('iotime',0)
484          if (surf_only.ne.1) then
485            if (lroot) then
486              if (lnetcdfout.eq.1) then
487#ifdef USE_NCF
488                call concoutput_netcdf(itime,outnum,gridtotalunc,wetgridtotalunc,&
489                     &drygridtotalunc)
490#endif
491              else
492                call concoutput(itime,outnum,gridtotalunc,wetgridtotalunc,drygridtotalunc)
493              endif
494            else
495! zero arrays on non-root processes
496              gridunc(:,:,:,:,:,:,:)=0.
497              creceptor(:,:)=0.
498            end if
499          else
500            if (lroot) then
501              if (lnetcdfout.eq.1) then
502#ifdef USE_NCF
503                call concoutput_surf_netcdf(itime,outnum,gridtotalunc,wetgridtotalunc,&
504                     &drygridtotalunc)
505#endif
506              else
507                call concoutput_surf(itime,outnum,gridtotalunc,wetgridtotalunc,drygridtotalunc)
508              end if
509            else
510! zero arrays on non-root processes
511              gridunc(:,:,:,:,:,:,:)=0.
512              creceptor(:,:)=0.
513            endif
514          endif
515          if (mp_measure_time) call mpif_mtime('iotime',1)
516
517          if (nested_output.eq.1) then
518
519! MPI: Root process collects/sums nested grids
520!*********************************************
521            call mpif_tm_reduce_grid_nest
522 
523            if (mp_measure_time) call mpif_mtime('iotime',0)
524
525            if (lnetcdfout.eq.0) then
526              if (surf_only.ne.1) then
527
528                if (lroot) then
529                  call concoutput_nest(itime,outnum)
530                else
531                  griduncn(:,:,:,:,:,:,:)=0.
532                end if
533
534              else  ! :TODO: check for zeroing in the netcdf module
535                call concoutput_surf_nest(itime,outnum)
536              end if
537            else
538#ifdef USE_NCF
539              if (surf_only.ne.1) then
540                if (lroot) then             
541                  call concoutput_nest_netcdf(itime,outnum)
542                else
543                  griduncn(:,:,:,:,:,:,:)=0.
544                end if
545              else
546                if (lroot) then
547                  call concoutput_surf_nest_netcdf(itime,outnum)
548                else
549                  griduncn(:,:,:,:,:,:,:)=0.
550                end if
551              endif
552#endif
553            end if
554          end if
555          outnum=0.
556        endif
557        if ((iout.eq.4).or.(iout.eq.5)) call plumetraj(itime)
558        if (iflux.eq.1) call fluxoutput(itime)
559        if (mp_measure_time) call mpif_mtime('iotime',1)
560
561
562! Decide whether to write an estimate of the number of particles released,
563! or exact number (require MPI reduce operation)
564        if (mp_dbg_mode) then
565          numpart_tot_mpi = numpart
566        else
567          numpart_tot_mpi = numpart*mp_partgroup_np
568        end if
569
570        if (mp_exact_numpart.and..not.(lmpreader.and.lmp_use_reader).and.&
571             &.not.mp_dbg_mode) then
572          call MPI_Reduce(numpart, numpart_tot_mpi, 1, MPI_INTEGER, MPI_SUM, id_root, &
573               & mp_comm_used, mp_ierr)
574        endif
575       
576        !CGZ-lifetime: output species lifetime
577        if (lroot.or.mp_dbg_mode) then
578        !   write(*,*) 'Overview species lifetime in days', &
579        !        real((species_lifetime(:,1)/species_lifetime(:,2))/real(3600.0*24.0))
580        !   write(*,*) 'all info:',species_lifetime
581          write(*,45) itime,numpart_tot_mpi,gridtotalunc,&
582               &wetgridtotalunc,drygridtotalunc
583        !   if (verbosity.gt.0) then
584        !     write (*,*) 'timemanager> starting simulation'
585        !   end if
586        end if
587
588        ! Write number of particles for all processes
589        if (mp_dev_mode) write(*,*) "PID, itime, numpart", mp_pid,itime,numpart
590
591
59245      format(i13,' SECONDS SIMULATED: ',i13, ' PARTICLES:    Uncertainty: ',3f7.3)
59346      format(' Simulated ',f7.1,' hours (',i13,' s), ',i13, ' particles')
594        if (ipout.ge.1) then
595          do ip=0, mp_partgroup_np-1
596            if (ip.eq.mp_partid) call partoutput(itime) ! dump particle positions
597            call mpif_mpi_barrier
598          end do
599        end if
600
601        loutnext=loutnext+loutstep
602        loutstart=loutnext-loutaver/2
603        loutend=loutnext+loutaver/2
604        if (itime.eq.loutstart) then
605          weight=0.5
606          outnum=outnum+weight
607          call conccalc(itime,weight)
608        endif
609
610
611! Check, whether particles are to be split:
612! If so, create new particles and attribute all information from the old
613! particles also to the new ones; old and new particles both get half the
614! mass of the old ones
615!************************************************************************
616       
617        if (ldirect*itime.ge.ldirect*itsplit) then
618          n=numpart
619          do j=1,numpart
620            if (ldirect*itime.ge.ldirect*itrasplit(j)) then
621!                if (n.lt.maxpart) then
622              if (n.lt.maxpart_mpi) then
623                n=n+1
624                itrasplit(j)=2*(itrasplit(j)-itramem(j))+itramem(j)
625                itrasplit(n)=itrasplit(j)
626                itramem(n)=itramem(j)
627                itra1(n)=itra1(j)
628                idt(n)=idt(j)
629                npoint(n)=npoint(j)
630                nclass(n)=nclass(j)
631                xtra1(n)=xtra1(j)
632                ytra1(n)=ytra1(j)
633                ztra1(n)=ztra1(j)
634                uap(n)=uap(j)
635                ucp(n)=ucp(j)
636                uzp(n)=uzp(j)
637                us(n)=us(j)
638                vs(n)=vs(j)
639                ws(n)=ws(j)
640                cbt(n)=cbt(j)
641                do ks=1,nspec
642                  xmass1(j,ks)=xmass1(j,ks)/2.
643                  xmass1(n,ks)=xmass1(j,ks)
644                end do
645              endif
646            endif
647          end do
648          numpart=n
649        endif
650      endif
651    endif
652   
653
654    if (itime.eq.ideltas) exit         ! almost finished
655
656! Compute interval since radioactive decay of deposited mass was computed
657!************************************************************************
658
659    if (itime.lt.loutnext) then
660      ldeltat=itime-(loutnext-loutstep)
661    else                                  ! first half of next interval
662      ldeltat=itime-loutnext
663    endif
664
665
666! Loop over all particles
667!************************
668    if (mp_measure_time) call mpif_mtime('partloop1',0)
669
670!--------------------------------------------------------------------------------
671! various variables for testing reason of CBL scheme, by mc
672    well_mixed_vector=0. !erase vector to test well mixed condition: modified by mc
673    well_mixed_norm=0.   !erase normalization to test well mixed condition: modified by mc
674    avg_ol=0.
675    avg_wst=0.
676    avg_h=0.
677    avg_air_dens=0.  !erase vector to obtain air density at particle positions: modified by mc
678!--------------------------------------------------------------------------------
679
680    do j=1,numpart
681
682! If integration step is due, do it
683!**********************************
684
685      if (itra1(j).eq.itime) then
686
687        if (ioutputforeachrelease.eq.1) then
688          kp=npoint(j)
689        else
690          kp=1
691        endif
692! Determine age class of the particle
693        itage=abs(itra1(j)-itramem(j))
694        do nage=1,nageclass
695          if (itage.lt.lage(nage)) exit
696        end do
697
698! Initialize newly released particle
699!***********************************
700
701        if ((itramem(j).eq.itime).or.(itime.eq.0)) &
702             call initialize(itime,idt(j),uap(j),ucp(j),uzp(j), &
703             us(j),vs(j),ws(j),xtra1(j),ytra1(j),ztra1(j),cbt(j))
704
705! Memorize particle positions
706!****************************
707
708        xold=xtra1(j)
709        yold=ytra1(j)
710        zold=ztra1(j)
711
712   
713  ! RECEPTOR: dry/wet depovel
714  !****************************
715  ! Before the particle is moved
716  ! the calculation of the scavenged mass shall only be done once after release
717  ! xscav_frac1 was initialised with a negative value
718
719      if  (DRYBKDEP) then
720       do ks=1,nspec
721         if  ((xscav_frac1(j,ks).lt.0)) then
722            call get_vdep_prob(itime,xtra1(j),ytra1(j),ztra1(j),prob_rec)
723            if (DRYDEPSPEC(ks)) then        ! dry deposition
724               xscav_frac1(j,ks)=prob_rec(ks)
725             else
726                xmass1(j,ks)=0.
727                xscav_frac1(j,ks)=0.
728             endif
729         endif
730        enddo
731       endif
732
733       if (WETBKDEP) then
734       do ks=1,nspec
735         if  ((xscav_frac1(j,ks).lt.0)) then
736            call get_wetscav(itime,lsynctime,loutnext,j,ks,grfraction,idummy,idummy,wetscav)
737            if (wetscav.gt.0) then
738                xscav_frac1(j,ks)=wetscav* &
739                       (zpoint2(npoint(j))-zpoint1(npoint(j)))*grfraction(1)
740            else
741                xmass1(j,ks)=0.
742                xscav_frac1(j,ks)=0.
743            endif
744         endif
745        enddo
746       endif
747
748! Integrate Lagevin equation for lsynctime seconds
749!*************************************************
750
751        if (mp_measure_time) call mpif_mtime('advance',0)
752
753        call advance(itime,npoint(j),idt(j),uap(j),ucp(j),uzp(j), &
754             us(j),vs(j),ws(j),nstop,xtra1(j),ytra1(j),ztra1(j),prob, &
755             cbt(j))
756
757        if (mp_measure_time) call mpif_mtime('advance',1)
758
759
760! Calculate the gross fluxes across layer interfaces
761!***************************************************
762
763        if (iflux.eq.1) call calcfluxes(nage,j,xold,yold,zold)
764
765
766! Determine, when next time step is due
767! If trajectory is terminated, mark it
768!**************************************
769
770        if (nstop.gt.1) then
771          if (linit_cond.ge.1) call initial_cond_calc(itime,j)
772          itra1(j)=-999999999
773        else
774          itra1(j)=itime+lsynctime
775
776
777! Dry deposition and radioactive decay for each species
778! Also check maximum (of all species) of initial mass remaining on the particle;
779! if it is below a threshold value, terminate particle
780!*****************************************************************************
781
782          xmassfract=0.
783          do ks=1,nspec
784            if (decay(ks).gt.0.) then             ! radioactive decay
785              decfact=exp(-real(abs(lsynctime))*decay(ks))
786            else
787              decfact=1.
788            endif
789
790            if (DRYDEPSPEC(ks)) then        ! dry deposition
791              drydeposit(ks)=xmass1(j,ks)*prob(ks)*decfact
792              xmass1(j,ks)=xmass1(j,ks)*(1.-prob(ks))*decfact
793              if (decay(ks).gt.0.) then   ! correct for decay (see wetdepo)
794                drydeposit(ks)=drydeposit(ks)* &
795                     exp(real(abs(ldeltat))*decay(ks))
796              endif
797            else                           ! no dry deposition
798              xmass1(j,ks)=xmass1(j,ks)*decfact
799            endif
800
801! Skip check on mass fraction when npoint represents particle number
802            if (mdomainfill.eq.0.and.mquasilag.eq.0) then
803              if (xmass(npoint(j),ks).gt.0.)then
804                   xmassfract=max(xmassfract,real(npart(npoint(j)))* &
805                   xmass1(j,ks)/xmass(npoint(j),ks))
806                   
807                   !CGZ-lifetime: Check mass fraction left/save lifetime
808                   ! if(lroot.and.real(npart(npoint(j)))*xmass1(j,ks)/xmass(npoint(j),ks).lt.e_inv.and.checklifetime(j,ks).eq.0.)then
809                       !Mass below 1% of initial >register lifetime
810                   !     checklifetime(j,ks)=abs(itra1(j)-itramem(j))
811
812                   !     species_lifetime(ks,1)=species_lifetime(ks,1)+abs(itra1(j)-itramem(j))
813                   !     species_lifetime(ks,2)= species_lifetime(ks,2)+1
814                   ! endif
815                   !CGZ-lifetime: Check mass fraction left/save lifetime
816                   
817              endif
818            else
819              xmassfract=1.0
820            endif
821          end do
822
823          if (xmassfract.lt.minmass) then ! .and. sum(real(npart(npoint(j)))*xmass1(j,:)).lt.1.0) then   ! terminate all particles carrying less mass
824          !            print*,'terminated particle ',j,' for small mass (', sum(real(npart(npoint(j)))* &
825          !         xmass1(j,:)), ' of ', sum(xmass(npoint(j),:)),')'
826            itra1(j)=-999999999
827            if (verbosity.gt.0) then
828              print*,'terminated particle ',j,' for small mass'
829            endif
830          endif
831
832!        Sabine Eckhardt, June 2008
833!        don't create depofield for backward runs
834          if (DRYDEP.AND.(ldirect.eq.1)) then
835            call drydepokernel(nclass(j),drydeposit,real(xtra1(j)), &
836                 real(ytra1(j)),nage,kp)
837            if (nested_output.eq.1) call drydepokernel_nest( &
838                 nclass(j),drydeposit,real(xtra1(j)),real(ytra1(j)), &
839                 nage,kp)
840          endif
841
842! Terminate trajectories that are older than maximum allowed age
843!***************************************************************
844
845          if (abs(itra1(j)-itramem(j)).ge.lage(nageclass)) then
846            if (linit_cond.ge.1) &
847                 call initial_cond_calc(itime+lsynctime,j)
848            itra1(j)=-999999999
849            if (verbosity.gt.0) then
850              print*, 'terminated particle ',j,'for age'
851            endif
852          endif
853        endif
854
855      endif
856
857    end do ! j=1, numpart
858
859    if(mp_measure_time) call mpif_mtime('partloop1',1)
860
861
862! Counter of "unstable" particle velocity during a time scale
863! of maximumtl=20 minutes (defined in com_mod)
864!************************************************************
865    total_nan_intl=0
866    i_nan=i_nan+1 ! added by mc to count nan during a time of maxtl (i.e. maximum tl fixed here to 20 minutes, see com_mod)
867    sum_nan_count(i_nan)=nan_count
868    if (i_nan > maxtl/lsynctime) i_nan=1 !lsynctime must be <= maxtl
869    do ii_nan=1, (maxtl/lsynctime)
870      total_nan_intl=total_nan_intl+sum_nan_count(ii_nan)
871    end do
872
873! Output to keep track of the numerical instabilities in CBL simulation
874! and if they are compromising the final result (or not):
875    if (cblflag.eq.1) print *,j,itime,'nan_synctime',nan_count,'nan_tl',total_nan_intl 
876
877
878  end do ! itime=0,ideltas,lsynctime
879
880
881! Complete the calculation of initial conditions for particles not yet terminated
882!*****************************************************************************
883
884! eso :TODO: this not implemented yet (transfer particles to PID 0 or rewrite)
885! the tools to do this are already in mpi_mod.f90
886  if (lroot) then
887    do j=1,numpart
888      if (linit_cond.ge.1) call initial_cond_calc(itime,j)
889    end do
890  end if
891
892
893  if (ipout.eq.2) then
894! MPI process 0 creates the file, the other processes append to it
895    do ip=0, mp_partgroup_np-1
896      if (ip.eq.mp_partid) then
897        !if (mp_dbg_mode) write(*,*) 'call partoutput(itime), proc, mp_partid',ip,mp_partid
898        call partoutput(itime)    ! dump particle positions
899      end if
900      call mpif_mpi_barrier
901    end do
902  end if
903
904! eso :TODO: MPI
905  if (linit_cond.ge.1.and.lroot) call initial_cond_output(itime)   ! dump initial cond. field
906
907
908! De-allocate memory and end
909!***************************
910
911999 if (iflux.eq.1) then
912    deallocate(flux)
913  endif
914  if (OHREA) then
915    deallocate(OH_field,OH_hourly,lonOH,latOH,altOH)
916  endif
917  if (ldirect.gt.0) then
918    deallocate(drygridunc,wetgridunc)
919  endif
920  deallocate(gridunc)
921  deallocate(xpoint1,xpoint2,ypoint1,ypoint2,zpoint1,zpoint2,xmass)
922  if (allocated(checklifetime)) deallocate(checklifetime)
923  deallocate(ireleasestart,ireleaseend,npart,kindz)
924  deallocate(xmasssave)
925  if (nested_output.eq.1) then
926    deallocate(orooutn, arean, volumen)
927    if (ldirect.gt.0) then
928      deallocate(griduncn,drygriduncn,wetgriduncn)
929    endif
930  endif
931  deallocate(outheight,outheighthalf)
932  deallocate(oroout, area, volume)
933
934  if (mp_measure_time) call mpif_mtime('timemanager',1)
935
936end subroutine timemanager
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG