source: flexpart.git/src/timemanager_mpi.f90 @ 3481cc1

10.4.1_peseiGFS_025bugfixes+enhancementsdevrelease-10release-10.4.1scaling-bug
Last change on this file since 3481cc1 was 3481cc1, checked in by Ignacio Pisso <ip@…>, 4 years ago

move license from headers to a different file

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