source: flexpart.git/src/timemanager_mpi.f90 @ 5b34509

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

Merged changes from CTBTO project

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