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

univie
Last change on this file since c0884a8 was c0884a8, checked in by pesei <petra seibert at univie ac at>, 6 years ago

replace CTBTO code for checking type of GRIB

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