From 12dd3e347d95892ca09358d0cd673912164524cb Mon Sep 17 00:00:00 2001 From: Marco de Bruine Date: Fri, 3 Jul 2020 14:13:06 +0200 Subject: [PATCH] 3D emission and namelist options; emission switch (l_emission) and vertical upper limit to apply emission (kemis) --- src/modemisdata.f90 | 18 ++++++--- src/modemission.f90 | 93 +++++++++++++++++++++++++++++++++------------ 2 files changed, 82 insertions(+), 29 deletions(-) diff --git a/src/modemisdata.f90 b/src/modemisdata.f90 index 6ed95b0d..dd60ebfc 100644 --- a/src/modemisdata.f90 +++ b/src/modemisdata.f90 @@ -34,15 +34,23 @@ module modemisdata implicit none save - real, allocatable :: & - svemis_a (:,:,:), & - svemis_b (:,:,:) + ! Namelist variables + + logical :: l_emission = .false. + integer :: kemis = -1 + + ! Main variables + real, allocatable :: svemis (:,:,:,:,:) + ! TODO INTEGRATION WITH MODCHEM, possibly switch? ! For example, nchem, firstchem etc, but also structure for species ! 'location', i.e. switch scalar field represents which species? - character (len = 3), dimension(4) :: svlist = (/'nr', 'qr', 'co2', 'ch4' /) - logical, dimension(4) :: emislist = (/.false., .false., .true., .false./) + character (len = 3), dimension(1) :: svlist = (/'co2' /) + logical, dimension(1) :: emislist = (/.true./) + +! character (len = 3), dimension(4) :: svlist = (/'nr', 'qr', 'co2', 'ch4' /) +! logical, dimension(4) :: emislist = (/.false., .false., .true., .false./) end module modemisdata diff --git a/src/modemission.f90 b/src/modemission.f90 index 9b3b2c15..9e85029d 100644 --- a/src/modemission.f90 +++ b/src/modemission.f90 @@ -32,30 +32,64 @@ module modemission subroutine initemission - use modglobal, only : i2, j2, nsv + use modglobal, only : i2, j2,kmax, nsv, ifnamopt, fname_options + use modmpi, only : myid, comm3d, mpi_logical, mpi_integer use moddatetime, only : datex, prevday, nextday implicit none + + ! Auxiliary variables + integer :: ierr + + ! --- Read & broadcast namelist EMISSION ----------------------------------- + namelist/NAMEMISSION/ l_emission, kemis + + if (myid == 0) then + + open(ifnamopt, file=fname_options, status='old', iostat=ierr) + read(ifnamopt, NAMEMISSION, iostat=ierr) + + if (ierr > 0) then + print *, 'iostat error: ', ierr + stop 'ERROR: Problem in namoptions NAMEMISSION' + endif + + write(6, NAMEMISSION) + close(ifnamopt) + + endif + + call mpi_bcast(l_emission, 1, mpi_logical, 0, comm3d, ierr) + call mpi_bcast(kemis, 1, mpi_integer, 0, comm3d, ierr) - allocate(svemis_a(i2,j2,nsv)) - allocate(svemis_b(i2,j2,nsv)) + ! --- Local pre-calculations and settings + if (.not. (l_emission)) return + + if (kemis == -1) kemis = kmax + + ! --- Read emission files for first time step ---------------------------------- + + ! Two hourly emission fields are loaded at all times: + ! (1) before model time, t_field < t_model, "in-the-past" + ! (2) ahead of model time, t_field > t_model, "in-the-future" + allocate(svemis(i2, j2, kemis, nsv, 2)) if (datex(5) >= 30) then - call reademission( datex(1), datex(2), datex(3), datex(4), svemis_a) + call reademission( datex(1), datex(2), datex(3), datex(4), svemis(:,:,:,:,1)) if (datex(4) == 23) then - call reademission(nextday(1), nextday(2), nextday(3), 0, svemis_b) + call reademission(nextday(1), nextday(2), nextday(3), 0, svemis(:,:,:,:,2)) else - call reademission( datex(1), datex(2), datex(3), datex(4)+1, svemis_b) + call reademission( datex(1), datex(2), datex(3), datex(4)+1, svemis(:,:,:,:,2)) endif else - call reademission( datex(1), datex(2), datex(3), datex(4), svemis_b) + call reademission( datex(1), datex(2), datex(3), datex(4), svemis(:,:,:,:,2)) if (datex(4) == 0) then - call reademission(prevday(1), prevday(2), prevday(3), 23, svemis_a) + call reademission(prevday(1), prevday(2), prevday(3), 23, svemis(:,:,:,:,1)) else - call reademission( datex(1), datex(2), datex(3), datex(4)-1, svemis_a) + call reademission( datex(1), datex(2), datex(3), datex(4)-1, svemis(:,:,:,:,1)) endif endif @@ -77,7 +111,7 @@ subroutine reademission(iyear, imonth, iday, ihour, emisfield) implicit none integer, intent(in) :: iyear, imonth, iday, ihour - real, intent(out) :: emisfield(i2,j2,nsv) + real, intent(out) :: emisfield(i2, j2, kemis, nsv) integer, parameter :: ndim = 3 integer :: start(ndim), count(ndim) @@ -94,12 +128,12 @@ subroutine reademission(iyear, imonth, iday, ihour, emisfield) do isv = 1, nsv if (emislist(isv)) then - call check( nf90_open( svlist(isv)//'_emis_'//sdatetime//'.nc', IOR(NF90_NOWRITE, NF90_MPIIO), & + call check( nf90_open( svlist(isv)//'_emis_'//sdatetime//'_3d.nc', IOR(NF90_NOWRITE, NF90_MPIIO), & ncid, comm = comm3d, info = MPI_INFO_NULL) ) call check( nf90_inq_varid( ncid, svlist(isv), varid) ) - call check( nf90_get_var ( ncid, varid, emisfield(2:i1,2:j1,isv), & - start = (/1 + myidx * imax, 1 + myidy * jmax, 1/), & - count = (/imax, jmax, 1/) ) ) + call check( nf90_get_var ( ncid, varid, emisfield(2:i1,2:j1,1:kemis,isv), & + start = (/1 + myidx * imax, 1 + myidy * jmax, 1, 1/), & + count = (/imax, jmax, kemis, 1/) ) ) call check( nf90_close( ncid ) ) endif @@ -128,8 +162,8 @@ subroutine emission ! gridbx size and air density AND apply a factor of 1e6. ! ! TODO - ! 1. MDB Align properly with non-chem tracers, i.e. cloud scalars from e.g. - ! microphysics. + ! 1. MDB Align properly with "non-emitted" tracers, i.e. cloud scalars from e.g. + ! microphysics/chemistry ! ---------------------------------------------------------------------- use modfields, only : svp @@ -141,17 +175,26 @@ subroutine emission implicit none + integer :: k + real :: emistime_s, emistime_e ! Emission timers real, parameter :: div3600 = 1./3600. ! Quick division - + + if (.not. (l_emission)) return + ! -------------------------------------------------------------------------- ! Interpolate and apply emission ! -------------------------------------------------------------------------- emistime_s = mod(rtimee + 1800., 3600.)*div3600 - svp(2:i1,2:j1,1,1:nsv) = svp(2:i1,2:j1,1,1:nsv) + & - ((1. - emistime_s)*svemis_a(2:i1, 2:j1, 1:nsv) + & - emistime_s *svemis_b(2:i1, 2:j1, 1:nsv))/(3600.*rhof(1)*dzf(1)*dx*dy*1e-6) + ! MdB NOTE : Better way to do this? Problem is the broadcasting of 1D arrays + ! rhof and dzf to svemis. For now, loop over k. + + do k = 1,kemis + svp(2:i1, 2:j1, k, 1:nsv) = svp(2:i1, 2:j1, k, 1:nsv) + & + ((1. - emistime_s)*svemis(2:i1, 2:j1, k, 1:nsv, 1) + & + emistime_s *svemis(2:i1, 2:j1, k, 1:nsv, 2))/(3600.*rhof(k)*dzf(k)*dx*dy*1e-6) + end do ! -------------------------------------------------------------------------- ! Read emission files when neccesary, i.e. simulation reaches half hour mark @@ -163,13 +206,13 @@ subroutine emission if ( emistime_e < emistime_s ) then ! Transfer data from 'ahead-of-modeltime' field to 'past-modeltime' field - svemis_a = svemis_b + svemis(:,:,:,:,1) = svemis(:,:,:,:,2) ! Read new 'ahead-of-modeltime' emission field if ( datex(4) == 23 ) then - call reademission(nextday(1), nextday(2), nextday(3), 0, svemis_b) + call reademission(nextday(1), nextday(2), nextday(3), 0, svemis(:,:,:,:,2)) else - call reademission( datex(1), datex(2), datex(3), datex(4)+1, svemis_b) + call reademission( datex(1), datex(2), datex(3), datex(4)+1, svemis(:,:,:,:,2)) endif endif @@ -184,7 +227,9 @@ subroutine exitemission implicit none - deallocate(svemis_a, svemis_b) + if (.not. (l_emission)) return + + deallocate(svemis) end subroutine exitemission