source: flexpart.git/src/timemanager_mpi.f90 @ ec7fc72

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

Minor cosmetic edits

  • Property mode set to 100644
File size: 32.1 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
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!*****************************************************************************
53!                                                                            *
54! Variables:                                                                 *
55! dep                .true. if either wet or dry deposition is switched on   *
56! decay(maxspec) [1/s] decay constant for radioactive decay                  *
57! drydep             .true. if dry deposition is switched on                 *
58! ideltas [s]        modelling period                                        *
59! itime [s]          actual temporal position of calculation                 *
60! ldeltat [s]        time since computation of radioact. decay of depositions*
61! loutaver [s]       averaging period for concentration calculations         *
62! loutend [s]        end of averaging for concentration calculations         *
63! loutnext [s]       next time at which output fields shall be centered      *
64! loutsample [s]     sampling interval for averaging of concentrations       *
65! loutstart [s]      start of averaging for concentration calculations       *
66! loutstep [s]       time interval for which concentrations shall be         *
67!                    calculated                                              *
68! npoint(maxpart)    index, which starting point the trajectory has          *
69!                    starting positions of trajectories                      *
70! nstop              serves as indicator for fate of particles               *
71!                    in the particle loop                                    *
72! nstop1             serves as indicator for wind fields (see getfields)     *
73! memstat            additional indicator for wind fields (see getfields)    *
74! outnum             number of samples for each concentration calculation    *
75! prob               probability of absorption at ground due to dry          *
76!                    deposition                                              *
77! wetdep             .true. if wet deposition is switched on                 *
78! weight             weight for each concentration sample (1/2 or 1)         *
79! uap(maxpart),ucp(maxpart),uzp(maxpart) = random velocities due to          *
80!                    turbulence                                              *
81! us(maxpart),vs(maxpart),ws(maxpart) = random velocities due to inter-      *
82!                    polation                                                *
83! xtra1(maxpart), ytra1(maxpart), ztra1(maxpart) =                           *
84!                    spatial positions of trajectories                       *
85!                                                                            *
86! Constants:                                                                 *
87! maxpart            maximum number of trajectories                          *
88!                                                                            *
89!*****************************************************************************
90
91  use unc_mod
92  use point_mod
93  use xmass_mod
94  use flux_mod
95  use outg_mod
96  use oh_mod
97  use par_mod
98  use com_mod
99  use mpi_mod
100  use netcdf_output_mod, only: concoutput_netcdf,concoutput_nest_netcdf,&
101       &concoutput_surf_netcdf,concoutput_surf_nest_netcdf
102
103  implicit none
104
105  logical :: reqv_state=.false. ! .true. if waiting for a MPI_Irecv to complete
106  integer :: j,ks,kp,l,n,itime=0,nstop,nstop1,memstat=0,mind
107! integer :: ksp
108  integer :: ip
109  integer :: loutnext,loutstart,loutend
110  integer :: ix,jy,ldeltat,itage,nage
111  integer :: i_nan=0,ii_nan,total_nan_intl=0  !added by mc to check instability in CBL scheme
112  integer :: numpart_tot_mpi ! for summing particles on all processes
113  real :: outnum,weight,prob(maxspec)
114  real :: decfact
115
116  real(sp) :: gridtotalunc
117  real(dep_prec) :: drygridtotalunc,wetgridtotalunc,drydeposit(maxspec)
118  real :: xold,yold,zold,xmassfract
119  real, parameter :: e_inv = 1.0/exp(1.0)
120
121! Measure time spent in timemanager
122  if (mp_measure_time) call mpif_mtime('timemanager',0)
123
124! First output for time 0
125!************************
126
127  loutnext=loutstep/2
128  outnum=0.
129  loutstart=loutnext-loutaver/2
130  loutend=loutnext+loutaver/2
131
132
133!**********************************************************************
134! Loop over the whole modelling period in time steps of mintime seconds
135!**********************************************************************
136
137
138!  itime=0
139  if (lroot) then
140  !  write(*,45) itime,numpart*mp_partgroup_np,gridtotalunc,wetgridtotalunc,drygridtotalunc
141    write(*,46) float(itime)/3600,itime,numpart*mp_partgroup_np
142   
143    if (verbosity.gt.0) then
144      write (*,*) 'timemanager> starting simulation'
145    end if
146  end if ! (lroot)
147
148!CGZ-lifetime: set lifetime to 0
149  ! checklifetime(:,:)=0
150  ! species_lifetime(:,:)=0
151  ! print*, 'Initialized lifetime'
152!CGZ-lifetime: set lifetime to 0
153
154
155
156  do itime=0,ideltas,lsynctime
157
158! Computation of wet deposition, OH reaction and mass transfer
159! between two species every lsynctime seconds
160! maybe wet depo frequency can be relaxed later but better be on safe side
161! wetdepo must be called BEFORE new fields are read in but should not
162! be called in the very beginning before any fields are loaded, or
163! before particles are in the system
164! Code may not be correct for decay of deposition
165! changed by Petra Seibert 9/02
166!********************************************************************
167
168    if (mp_dev_mode) write(*,*) 'myid, itime: ',mp_pid,itime
169   
170    if (wetdep .and. itime .ne. 0 .and. numpart .gt. 0) then
171      if (verbosity.gt.0) then
172        write (*,*) 'timemanager> call wetdepo'
173      endif
174
175      if (mp_measure_time) call mpif_mtime('wetdepo',0)
176       
177! readwind process skips this step
178      if (.not.(lmpreader.and.lmp_use_reader)) then
179        call wetdepo(itime,lsynctime,loutnext)
180      end if
181
182      if (mp_measure_time) call mpif_mtime('wetdepo',1)
183    end if
184
185    if (OHREA .and. itime .ne. 0 .and. numpart .gt. 0) then
186! readwind process skips this step
187      if (.not.(lmpreader.and.lmp_use_reader)) then
188        call ohreaction(itime,lsynctime,loutnext)
189      endif
190    end if
191
192    if (assspec .and. itime .ne. 0 .and. numpart .gt. 0) then
193      stop 'associated species not yet implemented!'
194!     call transferspec(itime,lsynctime,loutnext)
195    endif
196
197
198! compute convection for backward runs
199!*************************************
200
201    if ((ldirect.eq.-1).and.(lconvection.eq.1).and.(itime.lt.0)) then
202      if (verbosity.gt.0) then
203        write (*,*) 'timemanager> call convmix -- backward'
204      endif
205! readwind process skips this step
206      if (.not.(lmpreader.and.lmp_use_reader)) call convmix(itime)
207    endif
208
209! Get necessary wind fields if not available
210!*******************************************
211    if (verbosity.gt.0 .and. lmpreader) then
212      write (*,*) 'timemanager> call getfields'
213    endif
214
215! This time measure includes reading/MPI communication (for the reader process),
216! or MPI communication time only (for other processes)
217    if (mp_measure_time) call mpif_mtime('getfields',0)
218
219    call getfields(itime,nstop1,memstat)
220
221    if (mp_measure_time) call mpif_mtime('getfields',1)
222
223
224! Broadcast fields to all MPI processes
225! Skip if all processes have called getfields or if no new fields
226!*****************************************************************
227
228    if (mp_measure_time.and..not.(lmpreader.and.lmp_use_reader)) call mpif_mtime('getfields',0)
229
230! Version 1 (lmp_sync=.true.) uses a read-ahead process where send/recv is done
231! in sync at start of each new field time interval
232    if (lmp_sync.and.lmp_use_reader.and.memstat.gt.0) then
233      call mpif_gf_send_vars(memstat)
234      if (numbnests>0) call mpif_gf_send_vars_nest(memstat)
235! Version 2  (lmp_sync=.false., see below) is also used whenever 2 new fields are
236! read (as at first time step), in which case async send/recv is impossible.
237    else if (.not.lmp_sync.and.lmp_use_reader.and.memstat.ge.32) then
238      call mpif_gf_send_vars(memstat)
239      if (numbnests>0) call mpif_gf_send_vars_nest(memstat)
240    end if
241
242! Version 2 (lmp_sync=.false.) is for holding three fields in memory. Uses a
243! read-ahead process where sending/receiving of the 3rd fields is done in
244! the background in parallel with performing computations with fields 1&2
245!********************************************************************************
246    if (.not.lmp_sync) then
247   
248! READER PROCESS:
249      if (memstat.gt.0..and.memstat.lt.32.and.lmp_use_reader.and.lmpreader) then
250        if (mp_dev_mode) write(*,*) 'Reader process: calling mpif_gf_send_vars_async'
251        call mpif_gf_send_vars_async(memstat)
252      end if
253
254! COMPLETION CHECK:
255! Issued at start of each new field period.
256      if (memstat.ne.0.and.memstat.lt.32.and.lmp_use_reader) then
257        call mpif_gf_request
258      end if
259
260! RECVEIVING PROCESS(ES):
261      ! eso TODO: at this point we do not know if clwc/ciwc will be available
262      ! at next time step. Issue receive request anyway, cancel at mpif_gf_request
263      if (memstat.gt.0.and.lmp_use_reader.and..not.lmpreader) then
264        if (mp_dev_mode) write(*,*) 'Receiving process: calling mpif_gf_send_vars_async. PID: ', mp_pid
265        call mpif_gf_recv_vars_async(memstat)
266      end if
267
268    end if
269
270    if (mp_measure_time.and..not.(lmpreader.and.lmp_use_reader)) call mpif_mtime('getfields',1)
271
272! For validation and tests: call the function below to set all fields to simple
273! homogeneous values
274    if (mp_dev_mode) call set_fields_synthetic
275
276!*******************************************************************************
277
278    if (lmpreader.and.nstop1.gt.1) stop 'NO METEO FIELDS AVAILABLE'
279
280! Reader process goes back to top of time loop (unless simulation end)
281!*********************************************************************
282
283    if (lmpreader.and.lmp_use_reader) then
284      if (itime.lt.ideltas*ldirect) then
285        cycle
286      else
287        goto 999
288      end if
289    end if
290
291
292! Get hourly OH fields if not available
293!****************************************************
294    if (OHREA) then
295      if (verbosity.gt.0) then
296        write (*,*) 'timemanager> call gethourlyOH'
297      endif
298      call gethourlyOH(itime)
299    endif
300
301
302! Release particles
303!******************
304
305    if (verbosity.gt.0.and.lroot) then
306      write (*,*) 'timemanager>  Release particles'
307    endif
308
309    if (mdomainfill.ge.1) then
310      if (itime.eq.0) then
311        if (verbosity.gt.0) then
312          write (*,*) 'timemanager>  call init_domainfill'
313        endif
314        call init_domainfill
315      else
316        if (verbosity.gt.0.and.lroot) then
317          write (*,*) 'timemanager>  call boundcond_domainfill'
318        endif
319        call boundcond_domainfill(itime,loutend)
320      endif
321    else
322      if (verbosity.gt.0.and.lroot) then
323        print*,'call releaseparticles' 
324      endif
325      call releaseparticles(itime)
326    endif
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)
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                call concoutput_netcdf(itime,outnum,gridtotalunc,wetgridtotalunc,&
468                     &drygridtotalunc)
469              else
470                call concoutput(itime,outnum,gridtotalunc,wetgridtotalunc,drygridtotalunc)
471              endif
472            else
473! zero arrays on non-root processes
474              gridunc(:,:,:,:,:,:,:)=0.
475              creceptor(:,:)=0.
476            end if
477          else
478            if (lroot) then
479              if (lnetcdfout.eq.1) then
480                call concoutput_surf_netcdf(itime,outnum,gridtotalunc,wetgridtotalunc,&
481                     &drygridtotalunc)
482              else
483                call concoutput_surf(itime,outnum,gridtotalunc,wetgridtotalunc,drygridtotalunc)
484              end if
485            else
486! zero arrays on non-root processes
487              gridunc(:,:,:,:,:,:,:)=0.
488              creceptor(:,:)=0.
489            endif
490          endif
491          if (mp_measure_time) call mpif_mtime('iotime',1)
492
493          if (nested_output.eq.1) then
494
495! MPI: Root process collects/sums nested grids
496!*********************************************
497            call mpif_tm_reduce_grid_nest
498 
499           if (mp_measure_time) call mpif_mtime('iotime',0)
500
501            if (lnetcdfout.eq.0) then
502              if (surf_only.ne.1) then
503
504                if (lroot) then
505                  call concoutput_nest(itime,outnum)
506                else
507                  griduncn(:,:,:,:,:,:,:)=0.
508                end if
509
510              else  ! :TODO: check for zeroing in the netcdf module
511                call concoutput_surf_nest(itime,outnum)
512
513              end if
514
515            else
516
517              if (surf_only.ne.1) then
518                if (lroot) then             
519                  call concoutput_nest_netcdf(itime,outnum)
520                else
521                  griduncn(:,:,:,:,:,:,:)=0.
522                end if
523              else
524                if (lroot) then
525                  call concoutput_surf_nest_netcdf(itime,outnum)
526                else
527                  griduncn(:,:,:,:,:,:,:)=0.
528                end if
529              endif
530
531
532            end if
533          end if
534         
535
536          outnum=0.
537        endif
538        if ((iout.eq.4).or.(iout.eq.5)) call plumetraj(itime)
539        if (iflux.eq.1) call fluxoutput(itime)
540        if (mp_measure_time) call mpif_mtime('iotime',1)
541
542
543! Decide whether to write an estimate of the number of particles released,
544! or exact number (require MPI reduce operation)
545        numpart_tot_mpi = numpart*mp_partgroup_np
546
547        if (mp_exact_numpart.and..not.(lmpreader.and.lmp_use_reader)) then
548          call MPI_Reduce(numpart, numpart_tot_mpi, 1, MPI_INTEGER, MPI_SUM, id_root, &
549               & mp_comm_used, mp_ierr)
550        endif
551       
552        !CGZ-lifetime: output species lifetime
553        if (lroot) then
554        !   write(*,*) 'Overview species lifetime in days', &
555        !        real((species_lifetime(:,1)/species_lifetime(:,2))/real(3600.0*24.0))
556        !   write(*,*) 'all info:',species_lifetime
557          write(*,45) itime,numpart_tot_mpi,gridtotalunc,&
558               &wetgridtotalunc,drygridtotalunc
559        !   if (verbosity.gt.0) then
560        !     write (*,*) 'timemanager> starting simulation'
561        !   end if
562        end if
563
56445      format(i13,' SECONDS SIMULATED: ',i13, ' PARTICLES:    Uncertainty: ',3f7.3)
56546      format(' Simulated ',f7.1,' hours (',i13,' s), ',i13, ' particles')
566        if (ipout.ge.1) then
567          do ip=0, mp_partgroup_np-1
568            if (ip.eq.mp_partid) call partoutput(itime) ! dump particle positions
569            call mpif_mpi_barrier
570          end do
571        end if
572
573        loutnext=loutnext+loutstep
574        loutstart=loutnext-loutaver/2
575        loutend=loutnext+loutaver/2
576        if (itime.eq.loutstart) then
577          weight=0.5
578          outnum=outnum+weight
579          call conccalc(itime,weight)
580        endif
581
582
583! Check, whether particles are to be split:
584! If so, create new particles and attribute all information from the old
585! particles also to the new ones; old and new particles both get half the
586! mass of the old ones
587!************************************************************************
588       
589        if (ldirect*itime.ge.ldirect*itsplit) then
590          n=numpart
591          do j=1,numpart
592            if (ldirect*itime.ge.ldirect*itrasplit(j)) then
593!                if (n.lt.maxpart) then
594              if (n.lt.maxpart_mpi) then
595                n=n+1
596                itrasplit(j)=2*(itrasplit(j)-itramem(j))+itramem(j)
597                itrasplit(n)=itrasplit(j)
598                itramem(n)=itramem(j)
599                itra1(n)=itra1(j)
600                idt(n)=idt(j)
601                npoint(n)=npoint(j)
602                nclass(n)=nclass(j)
603                xtra1(n)=xtra1(j)
604                ytra1(n)=ytra1(j)
605                ztra1(n)=ztra1(j)
606                uap(n)=uap(j)
607                ucp(n)=ucp(j)
608                uzp(n)=uzp(j)
609                us(n)=us(j)
610                vs(n)=vs(j)
611                ws(n)=ws(j)
612                cbt(n)=cbt(j)
613                do ks=1,nspec
614                  xmass1(j,ks)=xmass1(j,ks)/2.
615                  xmass1(n,ks)=xmass1(j,ks)
616                end do
617              endif
618            endif
619          end do
620          numpart=n
621        endif
622      endif
623    endif
624   
625
626    if (itime.eq.ideltas) exit         ! almost finished
627
628! Compute interval since radioactive decay of deposited mass was computed
629!************************************************************************
630
631    if (itime.lt.loutnext) then
632      ldeltat=itime-(loutnext-loutstep)
633    else                                  ! first half of next interval
634      ldeltat=itime-loutnext
635    endif
636
637
638! Loop over all particles
639!************************
640    if (mp_measure_time) call mpif_mtime('partloop1',0)
641
642!--------------------------------------------------------------------------------
643! various variables for testing reason of CBL scheme, by mc
644    well_mixed_vector=0. !erase vector to test well mixed condition: modified by mc
645    well_mixed_norm=0.   !erase normalization to test well mixed condition: modified by mc
646    avg_ol=0.
647    avg_wst=0.
648    avg_h=0.
649    avg_air_dens=0.  !erase vector to obtain air density at particle positions: modified by mc
650!--------------------------------------------------------------------------------
651
652    do j=1,numpart
653
654! If integration step is due, do it
655!**********************************
656
657      if (itra1(j).eq.itime) then
658
659        if (ioutputforeachrelease.eq.1) then
660          kp=npoint(j)
661        else
662          kp=1
663        endif
664! Determine age class of the particle
665        itage=abs(itra1(j)-itramem(j))
666        do nage=1,nageclass
667          if (itage.lt.lage(nage)) exit
668        end do
669
670! Initialize newly released particle
671!***********************************
672
673        if ((itramem(j).eq.itime).or.(itime.eq.0)) &
674             call initialize(itime,idt(j),uap(j),ucp(j),uzp(j), &
675             us(j),vs(j),ws(j),xtra1(j),ytra1(j),ztra1(j),cbt(j))
676
677! Memorize particle positions
678!****************************
679
680        xold=xtra1(j)
681        yold=ytra1(j)
682        zold=ztra1(j)
683
684! Integrate Lagevin equation for lsynctime seconds
685!*************************************************
686
687        if (mp_measure_time) call mpif_mtime('advance',0)
688
689        call advance(itime,npoint(j),idt(j),uap(j),ucp(j),uzp(j), &
690             us(j),vs(j),ws(j),nstop,xtra1(j),ytra1(j),ztra1(j),prob, &
691             cbt(j))
692
693        if (mp_measure_time) call mpif_mtime('advance',1)
694
695
696! Calculate the gross fluxes across layer interfaces
697!***************************************************
698
699        if (iflux.eq.1) call calcfluxes(nage,j,xold,yold,zold)
700
701
702! Determine, when next time step is due
703! If trajectory is terminated, mark it
704!**************************************
705
706        if (nstop.gt.1) then
707          if (linit_cond.ge.1) call initial_cond_calc(itime,j)
708          itra1(j)=-999999999
709        else
710          itra1(j)=itime+lsynctime
711
712
713! Dry deposition and radioactive decay for each species
714! Also check maximum (of all species) of initial mass remaining on the particle;
715! if it is below a threshold value, terminate particle
716!*****************************************************************************
717
718          xmassfract=0.
719          do ks=1,nspec
720            if (decay(ks).gt.0.) then             ! radioactive decay
721              decfact=exp(-real(abs(lsynctime))*decay(ks))
722            else
723              decfact=1.
724            endif
725
726            if (DRYDEPSPEC(ks)) then        ! dry deposition
727              drydeposit(ks)=xmass1(j,ks)*prob(ks)*decfact
728              xmass1(j,ks)=xmass1(j,ks)*(1.-prob(ks))*decfact
729              if (decay(ks).gt.0.) then   ! correct for decay (see wetdepo)
730                drydeposit(ks)=drydeposit(ks)* &
731                     exp(real(abs(ldeltat))*decay(ks))
732              endif
733            else                           ! no dry deposition
734              xmass1(j,ks)=xmass1(j,ks)*decfact
735            endif
736
737
738            if (mdomainfill.eq.0) then
739              if (xmass(npoint(j),ks).gt.0.)then
740                   xmassfract=max(xmassfract,real(npart(npoint(j)))* &
741                   xmass1(j,ks)/xmass(npoint(j),ks))
742                   
743                   !CGZ-lifetime: Check mass fraction left/save lifetime
744                   ! if(lroot.and.real(npart(npoint(j)))*xmass1(j,ks)/xmass(npoint(j),ks).lt.e_inv.and.checklifetime(j,ks).eq.0.)then
745                       !Mass below 1% of initial >register lifetime
746                   !     checklifetime(j,ks)=abs(itra1(j)-itramem(j))
747
748                   !     species_lifetime(ks,1)=species_lifetime(ks,1)+abs(itra1(j)-itramem(j))
749                   !     species_lifetime(ks,2)= species_lifetime(ks,2)+1
750                   ! endif
751                   !CGZ-lifetime: Check mass fraction left/save lifetime
752                   
753              endif
754            else
755              xmassfract=1.
756            endif
757          end do
758
759          if (xmassfract.lt.minmass) then ! .and. sum(real(npart(npoint(j)))*xmass1(j,:)).lt.1.0) then   ! terminate all particles carrying less mass
760          !            print*,'terminated particle ',j,' for small mass (', sum(real(npart(npoint(j)))* &
761          !         xmass1(j,:)), ' of ', sum(xmass(npoint(j),:)),')'
762            itra1(j)=-999999999
763          endif
764
765!        Sabine Eckhardt, June 2008
766!        don't create depofield for backward runs
767          if (DRYDEP.AND.(ldirect.eq.1)) then
768            call drydepokernel(nclass(j),drydeposit,real(xtra1(j)), &
769                 real(ytra1(j)),nage,kp)
770            if (nested_output.eq.1) call drydepokernel_nest( &
771                 nclass(j),drydeposit,real(xtra1(j)),real(ytra1(j)), &
772                 nage,kp)
773          endif
774
775! Terminate trajectories that are older than maximum allowed age
776!***************************************************************
777
778          if (abs(itra1(j)-itramem(j)).ge.lage(nageclass)) then
779            if (linit_cond.ge.1) &
780                 call initial_cond_calc(itime+lsynctime,j)
781            itra1(j)=-999999999
782            !print*, 'terminated particle ',j,'for age'
783          endif
784        endif
785
786      endif
787
788    end do ! j=1, numpart
789
790    if(mp_measure_time) call mpif_mtime('partloop1',1)
791
792
793! Added by mc: counter of "unstable" particle velocity during a time scale
794!   of maximumtl=20 minutes (defined in com_mod)
795
796    total_nan_intl=0
797    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)
798    sum_nan_count(i_nan)=nan_count
799    if (i_nan > maxtl/lsynctime) i_nan=1 !lsynctime must be <= maxtl
800    do ii_nan=1, (maxtl/lsynctime)
801      total_nan_intl=total_nan_intl+sum_nan_count(ii_nan)
802    end do
803
804! Output to keep track of the numerical instabilities in CBL simulation
805! and if they are compromising the final result (or not):
806    if (cblflag.eq.1) print *,j,itime,'nan_synctime',nan_count,'nan_tl',total_nan_intl 
807
808
809  end do ! itime=0,ideltas,lsynctime
810
811
812! Complete the calculation of initial conditions for particles not yet terminated
813!*****************************************************************************
814
815! eso :TODO: this not implemented yet (transfer particles to PID 0 or rewrite)
816! the tools to do this are already in mpi_mod.f90
817  if (lroot) then
818    do j=1,numpart
819      if (linit_cond.ge.1) call initial_cond_calc(itime,j)
820    end do
821  end if
822
823
824  if (ipout.eq.2) then
825! MPI process 0 creates the file, the other processes append to it
826    do ip=0, mp_partgroup_np-1
827      if (ip.eq.mp_partid) then
828        !if (mp_dbg_mode) write(*,*) 'call partoutput(itime), proc, mp_partid',ip,mp_partid
829        call partoutput(itime)    ! dump particle positions
830      end if
831      call mpif_mpi_barrier
832    end do
833  end if
834
835! eso :TODO: MPI
836  if (linit_cond.ge.1.and.lroot) call initial_cond_output(itime)   ! dump initial cond. field
837
838
839! De-allocate memory and end
840!***************************
841
842999 if (iflux.eq.1) then
843    deallocate(flux)
844  endif
845  if (OHREA) then
846    deallocate(OH_field,OH_hourly,lonOH,latOH,altOH)
847  endif
848  if (ldirect.gt.0) then
849    deallocate(drygridunc,wetgridunc)
850  endif
851  deallocate(gridunc)
852  deallocate(xpoint1,xpoint2,ypoint1,ypoint2,zpoint1,zpoint2,xmass, checklifetime)
853  deallocate(ireleasestart,ireleaseend,npart,kindz)
854  deallocate(xmasssave)
855  if (nested_output.eq.1) then
856    deallocate(orooutn, arean, volumen)
857    if (ldirect.gt.0) then
858      deallocate(griduncn,drygriduncn,wetgriduncn)
859    endif
860  endif
861  deallocate(outheight,outheighthalf)
862  deallocate(oroout, area, volume)
863
864  if (mp_measure_time) call mpif_mtime('timemanager',1)
865
866end subroutine timemanager
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG