From 2d7717b12556da7b12bfb09b176d092e07997f59 Mon Sep 17 00:00:00 2001 From: ronesy <rlt@nilu.no> Date: Thu, 25 Apr 2024 21:11:47 +0200 Subject: [PATCH] Changes to make the parallelization of receptoroutput more efficient and correction to restart a run using partoutput Former-commit-id: f50831436f74aeed3ab189eccaa6c593927250cf --- src/FLEXPART.f90 | 5 +- src/chemistry_mod.f90 | 112 ++++++++++++------------------- src/com_mod.f90 | 6 +- src/emissions_mod.f90 | 83 ++++++++++++----------- src/gitversion.txt | 1 + src/initdomain_mod.f90 | 27 +++++--- src/netcdf_output_mod.f90 | 14 +++- src/readoptions_mod.f90 | 4 +- src/receptor_mod.f90 | 137 ++++++++++++++++++++------------------ src/timemanager_mod.f90 | 24 ++++--- src/totals_mod.f90 | 1 + 11 files changed, 212 insertions(+), 202 deletions(-) create mode 100644 src/gitversion.txt diff --git a/src/FLEXPART.f90 b/src/FLEXPART.f90 index e6d865e6..7a20ec48 100644 --- a/src/FLEXPART.f90 +++ b/src/FLEXPART.f90 @@ -44,7 +44,7 @@ program flexpart real :: s_timemanager character(len=256) :: & inline_options ! pathfile, flexversion, arg2 - character(len=256) :: gitversion_tmp="undefined" + character(len=256) :: gitversion_tmp="8d9c680 Mon Apr 22 15:37:39 2024 +0200" ! Keeping track of the total running time of FLEXPART, printed out at the end. !***************************************************************************** @@ -300,11 +300,10 @@ subroutine read_options_and_initialise_flexpart numreceptor=0 numsatreceptor=0 nlayermax=1 - ! NOTE: need to change to calc receptors conc without netcdf #ifdef USE_NCF call readreceptors_satellite - call readreceptors #endif + call readreceptors ! Read the landuse inventory !*************************** diff --git a/src/chemistry_mod.f90 b/src/chemistry_mod.f90 index 19abd5f2..403b9890 100644 --- a/src/chemistry_mod.f90 +++ b/src/chemistry_mod.f90 @@ -373,11 +373,13 @@ module chemistry_mod integer :: jrx, jry real(kind=dp) :: jul !! testing - character(len=4) :: atime - character(len=20) :: frmt - real, dimension(nxjr,nyjr) :: jscalar +! character(len=4) :: atime +! character(len=20) :: frmt +! real, dimension(nxjr,nyjr) :: jscalar, sza_grid - jscalar(:,:)=1. + !! testing +! jscalar(:,:)=1. +! sza_grid(:,:)=0. ! current hour of simulation curhour=itime/3600 @@ -397,7 +399,7 @@ module chemistry_mod dt2=float(memCLtime(2)-interp_time) dtt=1./(dt1+dt2) !! testing - print*, 'getchemhourly: dt1, dt2, dtt = ',dt1,dt2,dtt +! print*, 'getchemhourly: dt1, dt2, dtt = ',dt1,dt2,dtt do nr=1,nreagent write(*,*) 'Interpolating fields for reagent: ',reagents(nr) clfield_cur(:,:,:,nr)=(dt2*CL_field(:,:,:,nr,1) + dt1*CL_field(:,:,:,nr,2))*dtt @@ -410,13 +412,15 @@ module chemistry_mod do jy=1,nyCL ! jrate_average dimensions given as grid midpoints jry=int((latCL(jy)-(latjr(1)-0.5*dyjr))/dyjr)+1 + jry=min(jry,nyCL) !! testing - if (kz.eq.1.and.jy.lt.10) print*, 'latCL, latjr = ',latCL(jy), latjr(jry) +! if (kz.eq.1.and.jy.lt.10) print*, 'latCL, latjr = ',latCL(jy), latjr(jry) do ix=1,nxCL ! jrate_average dimensions given as grid midpoints jrx=int((lonCL(ix)-(lonjr(1)-0.5*dxjr))/dxjr)+1 + jrx=min(jrx,nxCL) !! testing - if (kz.eq.1.and.jy.lt.10.and.ix.lt.10) print*, 'lonCL, lonjr = ',lonCL(ix), lonjr(jrx) +! if (kz.eq.1.and.jy.lt.10.and.ix.lt.10) print*, 'lonCL, lonjr = ',lonCL(ix), lonjr(jrx) ! solar zenith angle sza=zenithangle(latjr(jry),lonjr(jrx),jjjjmmdd,hhmmss) ! calculate J(O1D) (jrate) @@ -427,7 +431,10 @@ module chemistry_mod if(jrate_cur.gt.0.) then clfield_cur(ix,jy,kz,nr)=clfield_cur(ix,jy,kz,nr)*jrate/jrate_cur !! testing - if (kz.eq.1) jscalar(ix,jy)=jrate/jrate_cur +! if (kz.eq.1) then +! jscalar(ix,jy)=jrate/jrate_cur +! sza_grid(ix,jy)=sza +! endif endif end do end do @@ -439,29 +446,27 @@ module chemistry_mod endif ! curhour !! testing - write(frmt,fmt='(A,I4,A)') '(',nxCL,'(E14.6))' - write(atime,fmt='(I4.4)') curhour - open(600,file=path(2)(1:length(2))//'clfield_'//atime//'.txt',action='write',status='replace') - do kz=1,nzCL - do jy=1,nyCL - write(600,fmt=frmt) clfield_cur(:,jy,kz,1) - end do - end do - close(600) - write(frmt,fmt='(A,I4,A)') '(',nxjr,'(E14.6))' - open(600,file=path(2)(1:length(2))//'jscalar_'//atime//'.txt',action='write',status='replace') - do jy=1,nyjr - write(600,fmt=frmt) jscalar(:,jy) - end do - close(600) - if (itime.eq.0) then - write(frmt,fmt='(A,I4,A)') '(',nxjr,'(E14.6))' - open(600,file=path(2)(1:length(2))//'javerage_'//atime//'.txt',action='write',status='replace') - do jy=1,nyjr - write(600,fmt=frmt) jrate_average(:,jy,1) - end do - endif - close(600) +! write(frmt,fmt='(A,I4,A)') '(',nxCL,'(E14.6))' +! write(atime,fmt='(I4.4)') curhour +! open(600,file=path(2)(1:length(2))//'clfield_'//atime//'.txt',action='write',status='replace') +! do kz=1,nzCL +! do jy=1,nyCL +! write(600,fmt=frmt) clfield_cur(:,jy,kz,1) +! end do +! end do +! close(600) +! write(frmt,fmt='(A,I4,A)') '(',nxjr,'(E14.6))' +! open(600,file=path(2)(1:length(2))//'jscalar_'//atime//'.txt',action='write',status='replace') +! do jy=1,nyjr +! write(600,fmt=frmt) jscalar(:,jy) +! end do +! close(600) +! write(frmt,fmt='(A,I4,A)') '(',nxjr,'(E14.6))' +! open(600,file=path(2)(1:length(2))//'sza_'//atime//'.txt',action='write',status='replace') +! do jy=1,nyjr +! write(600,fmt=frmt) sza_grid(:,jy) +! end do +! close(600) end subroutine getchemhourly @@ -521,15 +526,15 @@ module chemistry_mod #ifdef _OPENMP allocate( chem_loss_tmp(nreagent,nspec,numthreads) ) chem_loss_tmp(:,:,:) = 0d0 -#endif +#endif + ! Loop over particles !***************************************** !$OMP PARALLEL & !$OMP PRIVATE(ii,jpart,ngrid,j,xtn,ytn,ix,jy, & !$OMP xlon,ylat,clx,cly,clz,clzm,kz,altCLtop,dz1,dz2,dzz,nr,i, & -!$OMP cl_cur,indz,temp,ks,clrate,restmass,clreacted,ithread) -! !$OMP REDUCTION(+:chem_loss) +!$OMP cl_cur,indz,temp,ks,clrate,restmass,clreacted,ithread) #ifdef _OPENMP ithread = OMP_GET_THREAD_NUM()+1 ! Starts with 1 @@ -576,8 +581,8 @@ module chemistry_mod endif ! get position in the chem field ! assumes chem field dimensions given as grid midpoints - clx=min(nxCL, int((xlon-(lonCL(1)-0.5*dxCL))/dxCL)+1) - cly=min(nyCL, int((ylat-(latCL(1)-0.5*dyCL))/dyCL)+1) + clx=min(nxCL,int((xlon-(lonCL(1)-0.5*dxCL))/dxCL)+1) + cly=min(nyCL,int((ylat-(latCL(1)-0.5*dyCL))/dyCL)+1) ! get the level of the chem field for the particle ! z is the z-coord of the trajectory above model orography in metres @@ -655,11 +660,11 @@ module chemistry_mod !$OMP END DO !$OMP END PARALLEL - + #ifdef _OPENMP do ithread=1,numthreads chem_loss(:,:) = chem_loss(:,:)+chem_loss_tmp(:,:,ithread) - end do + end do deallocate( chem_loss_tmp ) #endif @@ -848,37 +853,6 @@ module chemistry_mod end function zenithangle - function find_minloc(n,vect,val) result(ind) - - !***************************************************************************** - ! * - ! This function returns index of a vector corresponding to the closest * - ! value to variable val * - ! * - ! Author: R. Thompson, Mar 2024 * - ! * - !***************************************************************************** - - implicit none - - integer, intent(in) :: n - real, dimension(n), intent(in) :: vect - real, intent(in) :: val - integer :: i, ind - real :: diff, diff_min - - diff_min=huge(1.0) - - ind=0 - do i=1,n - diff=abs(vect(i)-val) - if ( diff.lt.diff_min ) then - diff_min=diff - ind=i - endif - end do - - end function find_minloc end module chemistry_mod diff --git a/src/com_mod.f90 b/src/com_mod.f90 index 1a7957d4..3d1eec5e 100644 --- a/src/com_mod.f90 +++ b/src/com_mod.f90 @@ -419,7 +419,7 @@ module com_mod real, allocatable, dimension(:) :: xkreceptor,nnreceptor character(len=16), allocatable, dimension(:) :: receptorname integer :: cpointer(maxrecsample) - integer :: numreceptor + integer :: numreceptor, numcurrec ! satellite receptors real, allocatable, dimension(:) :: xsatellite,ysatellite @@ -429,7 +429,7 @@ module com_mod real, allocatable, dimension(:,:,:) :: csatellite, csatuncert real, allocatable, dimension(:,:) :: xksatellite, nnsatellite character(len=16), allocatable, dimension(:) :: satellitename - integer :: numsatreceptor, nlayermax, numsatellite + integer :: numsatreceptor, nlayermax, numsatellite, numcursat integer, allocatable, dimension(:) :: nnsatlayer integer :: csatpointer(maxrecsample) @@ -437,7 +437,9 @@ module com_mod ! creceptor concentrations at receptor points ! receptorarea area of 1*1 grid cell at receptor point ! numreceptor number of receptors (non-satellite) + ! numcurrec number of receptors in current time interval (updated each time interval) ! numsatreceptor number of satellite receptors (aka. retrievals) + ! numcursat number of satellite receptors in current time interval (updated each time interval) ! numsatellite number of satellite instruments ! nlayermax max number of vertical layers in satellite retrievals ! nnsatlayer actual number of vertical layers for each satellite diff --git a/src/emissions_mod.f90 b/src/emissions_mod.f90 index e0414708..775b894a 100644 --- a/src/emissions_mod.f90 +++ b/src/emissions_mod.f90 @@ -69,13 +69,11 @@ module emissions_mod character(len=20) :: frmt real :: em_frac real, allocatable, dimension(:,:,:) :: em_neg -#ifdef _OPENMP real, allocatable, dimension(:,:) :: tot_em_up_tmp real, allocatable, dimension(:,:,:,:) :: mass_field_tmp, em_neg_tmp -#endif real :: f_m logical :: lexist - integer, parameter :: unittest=120 +! integer, parameter :: unittest=120 ! fraction of stored emissions that is released in a time step @@ -91,31 +89,28 @@ module emissions_mod dt2=float(memtime(2)-itime) dtt=1./(dt1+dt2) + tot_em_up(:) = 0. + ! estimate mass in PBL from particle positions !********************************************** + mass_field(:,:,:) = 0. allocate( em_neg(nspec-1,nxem,nyem) ) -#ifdef _OPENMP +#if _OPENMP allocate( mass_field_tmp(nspec,nxem,nyem,numthreads)) allocate( em_neg_tmp(nspec-1,nxem,nyem,numthreads)) allocate( tot_em_up_tmp(nspec,numthreads) ) -#endif - -!$OMP PARALLEL -!$OMP WORKSHARE mass_field_tmp(:,:,:,:) = 0. em_neg_tmp(:,:,:,:) = 0. tot_em_up_tmp(:,:) = 0. +#endif tot_em_up(:) = 0. mass_field(:,:,:) = 0. em_neg(:,:,:) = 0. -!$OMP END WORKSHARE -!$OMP END PARALLEL !$OMP PARALLEL & !$OMP PRIVATE(ii,xlon,ylat,em_ix,em_jy,ix,jy,ixp,jyp,ddx,ddy, & -!$OMP rddx,rddy,p1,p2,p3,p4,mm,hm,hmixi,ks,ithread) & -!$OMP SHARED(em_cond,mass_field_tmp) +!$OMP rddx,rddy,p1,p2,p3,p4,mm,hm,hmixi,ks,ithread) #ifdef _OPENMP ithread = OMP_GET_THREAD_NUM()+1 ! Starts with 1 @@ -124,8 +119,6 @@ module emissions_mod #endif !$OMP DO - -! REDUCTION(+:mass_field) do ii=1,count%alive ! loop over all particles xlon=xlon0+part(ii)%xlon*dx @@ -135,7 +128,7 @@ module emissions_mod em_ix=min(nxem, int((xlon-(lonem(1)-0.5*dxem))/dxem)+1) em_jy=min(nyem, int((ylat-(latem(1)-0.5*dyem))/dyem)+1) !! testing - if (ii.lt.20) print*, 'lonem, lon, latem, lat = ',lonem(em_ix),xlon,latem(em_jy),ylat +! if (ii.lt.20) print*, 'lonem, lon, latem, lat = ',lonem(em_ix),xlon,latem(em_jy),ylat ! interpolate to particle position ix=int(part(ii)%xlon) @@ -180,10 +173,13 @@ module emissions_mod !$OMP END DO !$OMP END PARALLEL - ! Manual reduction of mass_field +#ifdef _OPENMP + ! manual reduction of mass_field do ithread=1,numthreads mass_field(:,:,:) = mass_field(:,:,:)+mass_field_tmp(:,:,:,ithread) - end do + end do +#endif + f_m = exp(-1.*real(lsynctime)/tau_ipm) ! estimate emissions for each particle @@ -191,8 +187,7 @@ module emissions_mod !$OMP PARALLEL & !$OMP PRIVATE(ii,xlon,ylat,em_ix,em_jy, & -!$OMP ks,em_cur,tmp,ithread) & -!$OMP SHARED(em_cond,tot_em_up_tmp,em_neg_tmp) +!$OMP ks,em_cur,tmp,ithread) #ifdef _OPENMP ithread = OMP_GET_THREAD_NUM()+1 ! Starts with 1 @@ -200,8 +195,7 @@ module emissions_mod ithread = 1 #endif -!$OMP DO -! REDUCTION(+:tot_em_up,em_neg) +!$OMP DO do ii=1,count%alive ! loop over particles if (.not.em_cond(ii)) cycle ! skip particles not in PBL @@ -233,9 +227,13 @@ module emissions_mod if (-1.*tmp.gt.mass(ii,ks)) then tmp = tmp + mass(ii,ks) ! subtract mass from atmosphere by setting it to zero below +#ifdef _OPENMP tot_em_up_tmp(ks,ithread) = tot_em_up_tmp(ks,ithread) - real(mass(ii,ks),kind=dp) +#else + tot_em_up(ks) = tot_em_up(ks) - real(mass(ii,ks),kind=dp) +#endif mass(ii,ks) = 0. - ! add remaining uptake to em_neg + ! add remaining uptake to em_neg #ifdef _OPENMP em_neg_tmp(ks-1,em_ix,em_jy,ithread) = em_neg_tmp(ks-1,em_ix,em_jy,ithread) + & tmp/mass(ii,1)*mass_field(1,em_ix,em_jy) @@ -245,11 +243,19 @@ module emissions_mod #endif else mass(ii,ks)=mass(ii,ks)+tmp +#ifdef _OPENMP tot_em_up_tmp(ks,ithread) = tot_em_up_tmp(ks,ithread) + real(tmp,kind=dp) +#else + tot_em_up(ks) = tot_em_up(ks) + real(tmp,kind=dp) +#endif endif else mass(ii,ks)=mass(ii,ks)+tmp +#ifdef _OPENMP tot_em_up_tmp(ks,ithread) = tot_em_up_tmp(ks,ithread) + real(tmp,kind=dp) +#else + tot_em_up(ks) = tot_em_up(ks) + real(tmp,kind=dp) +#endif endif ! negative emissions end do ! nspec @@ -279,14 +285,13 @@ module emissions_mod !$OMP END DO !$OMP END PARALLEL + ! manual reduction of em_neg and tot_em_up #ifdef _OPENMP do ithread=1,numthreads em_neg(:,:,:) = em_neg(:,:,:)+em_neg_tmp(:,:,:,ithread) tot_em_up(:) = tot_em_up(:) + tot_em_up_tmp(:,ithread) - end do - deallocate( mass_field_tmp,em_neg_tmp,tot_em_up_tmp ) -#else - tot_em_up(:) = tot_em_up_tmp(:,1) + end do + deallocate( mass_field_tmp, em_neg_tmp, tot_em_up_tmp ) #endif ! update for negative emissions @@ -305,18 +310,18 @@ module emissions_mod !$OMP END PARALLEL !! test - inquire(file=path(2)(1:length(2))//'mass_field.txt',exist=lexist) - write(*,*) 'emissions: lexist = ',lexist - if (lexist) then - open(unittest,file=path(2)(1:length(2))//'mass_field.txt',ACCESS='APPEND',STATUS='OLD') - else - open(unittest,file=path(2)(1:length(2))//'mass_field.txt',STATUS='NEW') - endif - write(frmt, '(A, I4, A)') '(', nxem, 'E12.3)' - do jy=1,nyem-1 - write(unittest,frmt) (mass_field(2,ix,jy),ix=1,nxem) - end do - close(unittest) +! inquire(file=path(2)(1:length(2))//'mass_field.txt',exist=lexist) +! write(*,*) 'emissions: lexist = ',lexist +! if (lexist) then +! open(unittest,file=path(2)(1:length(2))//'mass_field.txt',ACCESS='APPEND',STATUS='OLD') +! else +! open(unittest,file=path(2)(1:length(2))//'mass_field.txt',STATUS='NEW') +! endif +! write(frmt, '(A, I4, A)') '(', nxem, 'E12.3)' +! do jy=1,nyem-1 +! write(unittest,frmt) (mass_field(2,ix,jy),ix=1,nxem) +! end do +! close(unittest) !! end subroutine emissions @@ -572,7 +577,7 @@ module emissions_mod allocate( em_field(nspec-1,nxem,nyem,2) ) em_field(:,:,:,:)=0. allocate( em_res(nspec-1,nxem,nyem) ) - if (ipin.eq.1) then + if (ipin.eq.2) then ! read residual emissions from end of previous run write(*,*) 'Reading residual emissions from previous run' call em_res_read diff --git a/src/gitversion.txt b/src/gitversion.txt new file mode 100644 index 00000000..bc95db4e --- /dev/null +++ b/src/gitversion.txt @@ -0,0 +1 @@ +8d9c680 Mon Apr 22 15:37:39 2024 +0200 diff --git a/src/initdomain_mod.f90 b/src/initdomain_mod.f90 index e5a8b710..0ea8502d 100644 --- a/src/initdomain_mod.f90 +++ b/src/initdomain_mod.f90 @@ -536,9 +536,18 @@ module initdomain_mod endif endif - ! Exit here if resuming a run from particle dump - !*********************************************** - if (gdomainfill.and.ipin.ne.0) return + ! If resuming a run from particle dump + ! calculate total mass each species then exit + !******************************************** + if (gdomainfill.and.ipin.ne.0) then + write(*,*) 'Initialising particles from partoutput' + tot_mass(:)=0. + do ks=2,nspec + tot_mass(ks)=sum(mass(1:count%alive,ks)) + write(*,'(A,E12.4,A)') 'Species '//species(ks)//': ',tot_mass(ks),' (kg)' + end do + return + endif ! Allocate fields used within this subroutine !********************************************* @@ -550,7 +559,6 @@ module initdomain_mod ! Do not release particles twice (i.e., not at both in the leftmost and rightmost ! grid cell) for a global domain !***************************************************************************** - write(*,*) 'init_domainfill: nx_we(2), nx-2 = ',nx_we(2), nx-2 if (xglobal) nx_we(2)=min(nx_we(2),nx-2) write(*,*) 'init_domainfill: nx_we, ny_sn = ',nx_we, ny_sn @@ -741,10 +749,10 @@ module initdomain_mod ! poles), distribute the particles randomly. When only few particles are ! left distribute them randomly - if ((ncolumn.gt.20).and.(ncolumn-j.gt.20)) then + if ((ncolumn.gt.20)) then !.and.(ncolumn-j.gt.20)) then pnew=pnew-deltacol - else if (ncolumn.gt.20) then - pnew=pnew-ran1(idummy,0)*(pnew-pp(nz)) +! else if (ncolumn.gt.20) then +! pnew=pnew-ran1(idummy,0)*(pnew-pp(nz)) else pnew=pp(1)-ran1(idummy,0)*(pp(1)-pp(nz)) endif @@ -871,6 +879,8 @@ module initdomain_mod ! Assumes lon and lat dimensions are midpoints ixm=int((xl-(lonini(1,indxn)-0.5*dxini(indxn)))/dxini(indxn))+1 jym=int((yl-(latini(1,indxn)-0.5*dyini(indxn)))/dyini(indxn))+1 + ixm=min(ixm,nxini(indxn)) + jym=min(jym,nyini(indxn)) !! testing if (jj.eq.1.and.jy.lt.5.and.ix.lt.5) then print*, 'init_domainfill: lonini, xl, latini, yl = ',lonini(ixm,indxn),xl,latini(jym,indxn),yl @@ -970,9 +980,6 @@ module initdomain_mod ! Total mass each species !************************ - if (.not.allocated(tot_mass)) then - allocate( tot_mass(nspec) ) - endif tot_mass(:)=0. do ks=2,nspec tot_mass(ks)=sum(mass(1:count%alive,ks)) diff --git a/src/netcdf_output_mod.f90 b/src/netcdf_output_mod.f90 index e3d36b66..d6be602c 100644 --- a/src/netcdf_output_mod.f90 +++ b/src/netcdf_output_mod.f90 @@ -2436,7 +2436,7 @@ subroutine readpartpositions_netcdf(ibtime,ibdate) endif ! Open partoutput_end.nc file - call nf90_err(nf90_open(trim('partoutput_end.nc'), mode=NF90_NOWRITE,ncid=ncidend)) + call nf90_err(nf90_open(path(2)(1:length(2))//trim('partoutput_end.nc'), mode=NF90_NOWRITE,ncid=ncidend)) ! Take the positions of the particles at the last timestep in the file ! It needs to be the same as given in the COMMAND file, this is arbitrary @@ -2467,6 +2467,9 @@ subroutine readpartpositions_netcdf(ibtime,ibdate) error stop endif + !! testing +! print*, 'readpartpositions_netcdf: julin, julcommand = ',julin, julcommand + ! Then the particle dimension call nf90_err(nf90_inq_dimid(ncid=ncidend,name='particle',dimid=pIDend)) call nf90_err(nf90_inquire_dimension(ncid=ncidend,dimid=pIDend,len=plen)) @@ -2510,7 +2513,9 @@ subroutine readpartpositions_netcdf(ibtime,ibdate) do i=1,plen if (part(i)%z.lt.0) then call terminate_particle(i,0) - write(*,*) 'Particle ',i,'is not alive in the restart file.' + if (mdomainfill.eq.0) then + write(*,*) 'Particle ',i,'is not alive in the restart file.' + endif iterminate=iterminate+1 endif part(i)%nclass=min(int(ran1(idummy,0)*real(nclassunc))+1, & @@ -2523,6 +2528,11 @@ subroutine readpartpositions_netcdf(ibtime,ibdate) call nf90_err(nf90_close(ncidend)) + !! testing +! print*, 'readpartpositions_netcdf: number alive = ',count%alive +! print*, 'readpartpositions_netcdf: range(part%z) = ',minval(part(1:count%alive)%z),maxval(part(1:count%alive)%z) +! print*, 'readpartpositions_netcdf: part(1)%tstart = ',part(1)%tstart + end subroutine readpartpositions_netcdf subroutine readinitconditions_netcdf() diff --git a/src/readoptions_mod.f90 b/src/readoptions_mod.f90 index 2f2ab8ed..ff0971ef 100644 --- a/src/readoptions_mod.f90 +++ b/src/readoptions_mod.f90 @@ -1969,7 +1969,7 @@ subroutine readreceptors lon=-999.9 read(unitreceptor,receptors,iostat=ios) if ((lon.lt.-900).or.(ios.ne.0)) exit - if ((time.lt.bdate).or.(time.gt.edate)) cycle ! skip receptors not in simulation window + if ((time.lt.bdate).or.(time.ge.edate)) cycle ! skip receptors not in simulation window j=j+1 end do numreceptor=j @@ -1992,7 +1992,7 @@ subroutine readreceptors lon=-999.9 read(unitreceptor,receptors,iostat=ios) if ((lon.lt.-900).or.(ios.ne.0)) exit ! read error - if ((time.lt.bdate).or.(time.gt.edate)) cycle ! skip receptors not in simulation window + if ((time.lt.bdate).or.(time.ge.edate)) cycle ! skip receptors not in simulation window j=j+1 receptorname(j)=receptor xreceptor(j)=(lon-xlon0)/dx ! transform to grid coordinates diff --git a/src/receptor_mod.f90 b/src/receptor_mod.f90 index dad99ec7..0883b60b 100644 --- a/src/receptor_mod.f90 +++ b/src/receptor_mod.f90 @@ -133,6 +133,9 @@ module receptor_mod call receptorcalc(itime,weight,lrecoutstart,lrecoutend,recoutnum,recoutnumsat) endif + !! testing + print*, 'receptor_mod: itime, lrecoutstart, lrecoutend = ',itime, lrecoutstart, lrecoutend + if ((itime.eq.lrecoutend).and.(any(recoutnum.gt.0.).or.any(recoutnumsat.gt.0.))) then ! output receptor concentrations @@ -174,8 +177,8 @@ module receptor_mod endif !! testing - print*, 'receptor_mod: concvar_id = ',concvar_id - print*, 'receptor_mod: satvar_id = ',satvar_id +! print*, 'receptor_mod: concvar_id = ',concvar_id +! print*, 'receptor_mod: satvar_id = ',satvar_id ! Initialize variables @@ -188,7 +191,7 @@ module receptor_mod #endif !! testing - print*, 'receptor_mod: nthread = ',nthreads +! print*, 'receptor_mod: nthread = ',nthreads allocate(densityoutrecept(nlayermax)) allocate(nnrec(maxrecsample,nlayermax),& @@ -222,6 +225,8 @@ module receptor_mod ! Loop over general receptors !**************************** + + write(*,fmt='(A,1X,I8,1X,A,1X,I3)') 'Number of receptors output at itime ',itime,'is',numcurrec !$OMP PARALLEL & !$OMP PRIVATE(n,k,nn,nr,ix,jy,ixp,jyp,ddx,ddy,rddx,rddy,p1,p2,p3,p4,indz,indzp,il,dz1,dz2,dz, & @@ -232,29 +237,22 @@ module receptor_mod #else thread=1 #endif - !! testing - print*, 'receptor_mod: thread = ',thread nr=0 !$OMP DO - do n=1,numreceptor + do k=1,numcurrec - if ((treceptor(n).lt.lrecoutstart).or. & - (treceptor(n).ge.lrecoutend)) cycle ! skip if not in current sampling time interval + if (cpointer(k).eq.0.) cycle - ! find indice to creceptor, xkreceptor, and nnreceptor - do k=1,maxrecsample - if (cpointer(k).eq.n) exit - end do + ! number of the receptor + n=cpointer(k) ! counter of receptor values this time interval nr=nr+1 nr_omp(thread)=nr !! testing - if (n.lt.40) then - print*, 'receptor_mod: n, thread, nr, cpointer(k), rpointer = ',n, thread, nr, cpointer(k), rpointer - endif +! print*, 'receptor_mod: n, thread, nr, cpointer(k), rpointer = ',n, thread, nr, cpointer(k), rpointer if (((.not.llcmoutput).and.(iout.eq.2)).or.& (llcmoutput.and.((iout.eq.1).or.(iout.eq.3).or.(iout.eq.5)))) then @@ -356,7 +354,7 @@ module receptor_mod timerec_omp(nr,thread)=treceptor(n) namerec_omp(nr,thread)=receptorname(n) - end do ! numreceptor + end do ! numcurrec !$OMP END DO !$OMP END PARALLEL @@ -364,7 +362,7 @@ module receptor_mod nr=1 do ithread=1,nthreads !! testing - print*, 'receptor_mod: nr_omp(ithread) = ',nr_omp(ithread) +! print*, 'receptor_mod: nr_omp(ithread) = ',nr_omp(ithread) if (nr_omp(ithread).eq.0) cycle crec(:,nr:(nr+nr_omp(ithread)-1),1)=crec_omp(:,1:nr_omp(ithread),1,ithread) cunc(:,nr:(nr+nr_omp(ithread)-1),1)=cunc_omp(:,1:nr_omp(ithread),1,ithread) @@ -377,7 +375,7 @@ module receptor_mod namerec(nr:(nr+nr_omp(ithread)-1))=namerec_omp(1:nr_omp(ithread),ithread) nr=nr+nr_omp(ithread) !! testing - print*, 'receptor_mod: nr = ',nr +! print*, 'receptor_mod: nr = ',nr end do ! total number of receptors to write this interval @@ -397,8 +395,8 @@ module receptor_mod rpointer=rpointer+nr !! testing - print*, 'receptor_mod: nr_omp = ',nr_omp - print*, 'receptor_mod: rpointer = ',rpointer +! print*, 'receptor_mod: nr_omp = ',nr_omp +! print*, 'receptor_mod: rpointer = ',rpointer ! Loop over satellites !********************* @@ -413,6 +411,8 @@ module receptor_mod cunc_omp(:,:,:,:)=0. nr_omp(:)=0 + write(*,fmt='(A,1X,I8,1X,A,1X,I3)') 'Number of satellite receptors output at itime ',itime,'is',numcursat + !$OMP PARALLEL & !$OMP PRIVATE(n,nr,nn,nchar,k,ix,jy,ixp,jyp,ddx,ddy,rddx,rddy,p1,p2,p3,p4,kz,numsatlayer,zmid,indz,indzp, & !$OMP il,dz1,dz2,dz,ind,rho_p,rhoi,densityoutrecept,ks,thread) @@ -423,27 +423,21 @@ module receptor_mod thread=1 #endif - !! testing - print*, 'receptor_mod: satellites, thread = ',thread - nr=0 !$OMP DO - do n=1,numsatreceptor + do k=1,numcursat - if ((tsatellite(n).lt.lrecoutstart).or. & - (tsatellite(n).ge.lrecoutend)) cycle ! skip if not in current sampling time interval + if (csatpointer(k).eq.0) cycle - ! find indice to csatellite, xksatellite, and nnsatellite - do k=1,maxrecsample - if (csatpointer(k).eq.n) exit - end do + ! number of satellite receptor + n=csatpointer(k) ! counter of receptor values this time interval nr=nr+1 nr_omp(thread)=nr !! testing - print*, 'receptor_mod: n, thread, nr, csatpointer(k) = ',n, thread, nr, csatpointer(k) +! print*, 'receptor_mod: n, thread, nr, csatpointer(k) = ',n, thread, nr, csatpointer(k) ! get actual number vertical layers for this retrieval do nn=1,numsatellite @@ -544,7 +538,7 @@ module receptor_mod timerec_omp(nr,thread)=tsatellite(n) namerec_omp(nr,thread)=satellitename(n) - end do ! numsatreceptor + end do ! numcursat !$OMP END DO !$OMP END PARALLEL @@ -552,7 +546,7 @@ module receptor_mod nr=1 do ithread=1,nthreads !! testing - print*, 'receptor_mod: satellites, nr_omp(ithread) = ',nr_omp(ithread) +! print*, 'receptor_mod: satellites, nr_omp(ithread) = ',nr_omp(ithread) if (nr_omp(ithread).eq.0) cycle crec(:,nr:nr+nr_omp(ithread)-1,:)=crec_omp(:,1:nr_omp(ithread),:,ithread) cunc(:,nr:nr+nr_omp(ithread)-1,:)=cunc_omp(:,1:nr_omp(ithread),:,ithread) @@ -565,7 +559,7 @@ module receptor_mod namerec(nr:nr+nr_omp(ithread)-1)=namerec_omp(1:nr_omp(ithread),ithread) nr=nr+nr_omp(ithread) !! testing - print*, 'receptor_mod: satellites, nr = ',nr +! print*, 'receptor_mod: satellites, nr = ',nr end do ! total number of receptors to write this interval @@ -585,8 +579,8 @@ module receptor_mod spointer=spointer+nr !! testing - print*, 'receptor_mod: satellites, nr_omp = ',nr_omp - print*, 'receptor_mod: spointer = ',spointer +! print*, 'receptor_mod: satellites, nr_omp = ',nr_omp +! print*, 'receptor_mod: spointer = ',spointer ! close files if (lnetcdfout.eq.1) then @@ -600,9 +594,6 @@ module receptor_mod #endif endif - ! Reinitialization - !***************** - deallocate(densityoutrecept) deallocate(crec,cunc,nnrec,xkrec) deallocate(crec_omp,cunc_omp,nnrec_omp,xkrec_omp) @@ -610,17 +601,6 @@ module receptor_mod deallocate(lonrec_omp,latrec_omp,altrec_omp,timerec_omp,namerec_omp) deallocate(nr_omp) - creceptor(:,:)=0. - crecuncert(:,:)=0. - nnreceptor(:)=0. - xkreceptor(:)=0. - if (numsatreceptor.gt.0) then - csatellite(:,:,:)=0. - csatuncert(:,:,:)=0. - nnsatellite(:,:)=0. - xksatellite(:,:)=0. - endif - ! End of receptor output !*********************** @@ -629,6 +609,27 @@ module receptor_mod endif ! output receptor conc + endif ! receptor output + + if (itime.eq.lrecoutend) then + + ! Reinitialize + !************* + + creceptor(:,:)=0. + crecuncert(:,:)=0. + nnreceptor(:)=0. + xkreceptor(:)=0. + if (numsatreceptor.gt.0) then + csatellite(:,:,:)=0. + csatuncert(:,:,:)=0. + nnsatellite(:,:)=0. + xksatellite(:,:)=0. + endif + + recoutnum(:)=0. + recoutnumsat(:,:)=0. + ! Update output timesteps !************************ lrecoutnext=lrecoutnext+lrecoutstep @@ -640,7 +641,7 @@ module receptor_mod call receptorcalc(itime,weight,lrecoutstart,lrecoutend,recoutnum,recoutnumsat) endif - endif ! calculate receptors + endif end subroutine receptoroutput @@ -711,13 +712,14 @@ module receptor_mod !******************** ! pointer for creceptor, xkreceptor and nnreceptor + numcurrec=0 cpointer(:)=0 k=0 do n=1,numreceptor if ((treceptor(n).lt.lrecoutstart).or. & - (treceptor(n).gt.lrecoutend)) cycle ! skip if not in current sampling time interval + (treceptor(n).ge.lrecoutend)) cycle ! skip if not in current sampling time interval ! update pointer k=k+1 @@ -727,8 +729,8 @@ module receptor_mod endif cpointer(k)=n - !! test - print*, 'receptorcalc: n, receptorname(n) = ',n, receptorname(n) + !! testing +! print*, 'receptorcalc: n, receptorname(n) = ',n, receptorname(n) ! Reset concentrations for new receptor conc(:)=0. @@ -746,14 +748,12 @@ module receptor_mod endif h=hxmax*hymax*hzmax - !! test + !! testing ! print*, 'receptorcalc: rec_ff = ',rec_ff ! Estimate concentration at receptor !*********************************** -!! TO DO: replace ATOMIC with j variable with dim of thread - !$OMP PARALLEL & !$OMP PRIVATE(i,itage,hz,zd,hx,xd,hy,yd,h,r2,xkern,ks) & !$OMP SHARED(j,unc,conc) & @@ -816,7 +816,7 @@ module receptor_mod do ks=ks_start,nspec if (llcmoutput) then - ! special case CTM output use mass ratio species to airtracer + ! special case LCM output use mass ratio species to airtracer ! species 1 is always airtracer conc(ks)=conc(ks) + mass(i,ks)/mass(i,1) * & weight * xkern @@ -852,7 +852,10 @@ module receptor_mod recoutnum(k)=recoutnum(k)+weight endif - !! test + ! update number receptors this time interval + numcurrec=k + + !! testing ! print*, 'receptorcalc: j, conc, xksum = ',j, conc(2), xksum ! print*, 'receptorcalc: n, k, cpointer(k) = ',n, k, cpointer(k) ! print*, 'receptorcalc: nnreceptor(k) = ',nnreceptor(k) @@ -866,15 +869,16 @@ module receptor_mod !********************* ! pointer for csatellite, xksatellite and nnsatellite + numcursat=0 csatpointer(:)=0 k=0 do n=1,numsatreceptor if ((tsatellite(n).lt.lrecoutstart).or. & - (tsatellite(n).gt.lrecoutend)) cycle ! skip if not in current sampling time interval + (tsatellite(n).ge.lrecoutend)) cycle ! skip if not in current sampling time interval - !! test + !! testing ! print*, 'receptorcalc: lrecoutstart, lrecoutend, tsatellite(n) = ',lrecoutstart, lrecoutend, tsatellite(n) ! update pointer @@ -894,7 +898,7 @@ module receptor_mod endif end do - !! test + !! testing ! print*, 'receptorcalc: n, satellitename(n) = ',n, satellitename(n) do kz=1,numsatlayer @@ -921,7 +925,7 @@ module receptor_mod h=hxsat*hysat*(0.5*hz) - !! test + !! testing ! print*, 'zmid, hz, eta =',zmid, hz, eta !$OMP PARALLEL & @@ -959,7 +963,7 @@ module receptor_mod do ks=ks_start,nspec if (llcmoutput) then - ! special case CTM output use mass ratio species to airtracer + ! special case LCM output use mass ratio species to airtracer ! species 1 is always airtracer conc(ks)=conc(ks) + mass(i,ks)/mass(i,1) * & weight * xkern @@ -995,7 +999,7 @@ module receptor_mod recoutnumsat(kz,k)=recoutnumsat(kz,k)+weight endif - !! test + !! testing ! print*, 'receptorcalc: for satellite: j, conc, xksum = ',j, conc(2), xksum ! print*, 'receptorcalc: n, k, csatpointer(k) = ',n, k, csatpointer(k) ! print*, 'receptorcalc: nnsatellite(:,k) = ',nnsatellite(:,k) @@ -1003,6 +1007,9 @@ module receptor_mod end do ! numsatlayer + ! update current number of satellite receptors this time interval + numcursat=k + end do ! numsatreceptor end subroutine receptorcalc diff --git a/src/timemanager_mod.f90 b/src/timemanager_mod.f90 index 0871a411..931477c1 100644 --- a/src/timemanager_mod.f90 +++ b/src/timemanager_mod.f90 @@ -304,6 +304,19 @@ subroutine timemanager else call init_domainfill endif + if (ipin.eq.2) then + ! Particles initialized from partoutput +#ifdef ETA +!$OMP PARALLEL PRIVATE(i,j) +!$OMP DO + do i=1,count%alive + j=count%ialive(i) + call update_z_to_zeta(itime,j) + end do +!$OMP END DO +!$OMP END PARALLEL +#endif + endif else call boundcond_domainfill(itime,loutend) endif @@ -704,17 +717,8 @@ subroutine timemanager #ifdef USE_NCF if ((mdomainfill.eq.1).and.(llcmoutput)) then - - if (.not.allocated(tot_mass)) then - allocate( tot_mass(nspec) ) - tot_mass(:)=0. - endif - do ks=1,nspec - do i=1,count%alive - j=count%ialive(i) - tot_mass(ks)=tot_mass(ks)+real(mass(j,ks),kind=dp) - end do + tot_mass(ks)=sum(real(mass(1:count%alive,ks),kind=dp)) end do call totals_write(itime) endif diff --git a/src/totals_mod.f90 b/src/totals_mod.f90 index 912593cd..65491241 100644 --- a/src/totals_mod.f90 +++ b/src/totals_mod.f90 @@ -44,6 +44,7 @@ module totals_mod if (stat.ne.0) error stop "Could not allocate totals arrays" chem_loss(:,:)=0. + allocate( tot_mass(nspec) ) allocate( tot_em_up(nspec) ) allocate( tot_em_field(nspec) ) allocate( tot_em_res(nspec) ) -- GitLab