! #define TRACEBACK write (gol,'("in ",a," (",a,", line",i5,")")') rname, __FILE__, __LINE__; call goErr #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if ! #include "tm5.inc" ! !----------------------------------------------------------------------------- ! TM5 ! !----------------------------------------------------------------------------- !BOP ! ! !MODULE: EMISSION_ISOP ! ! !DESCRIPTION: data and methods for Isoprene emissions. !\\ !\\ ! !INTERFACE: ! MODULE EMISSION_ISOP ! ! !USES: ! use GO, only : gol, goPr, goErr, goBug use tm5_distgrid, only : dgrid, get_distgrid, scatter, gather use partools, only : isRoot, par_broadcast use dims, only : nregions, idate, okdebug use global_types, only : emis_data, d3_data use global_types, only : isop_data use emission_read, only : used_providers_isop, has_isop_emis IMPLICIT NONE PRIVATE ! ! !PUBLIC MEMBER FUNCTIONS: ! public :: Emission_isop_Init public :: Emission_isop_Done public :: emission_isop_Declare public :: Emission_isop_Apply ! ! !PRIVATE DATA MEMBERS: ! character(len=*), parameter :: mname = 'emission_isop' !isoprene emission distribution function type(isop_data),dimension(nregions),target :: isop_dat !flags the daily calculation of isoprene distribution func. integer,dimension(nregions) :: day_isop type( emis_data ), dimension(:,:), allocatable :: isop_emis_2d type( d3_data ), dimension(:,:), allocatable :: isop_emis_3d integer :: j_start, j_end ! indices for tropics integer :: isop_3dsec, isop_2dsec logical, allocatable :: has_data_3d(:), has_data_2d(:) ! ! !REVISION HISTORY: ! 1 Oct 2010 - Achim Strunk - overhaul for AR5 ! 28 Jun 2012 - Ph. Le Sager - adapted for lon-lat MPI domain decomposition ! ! !REMARKS: ! !EOP !------------------------------------------------------------------------ contains !-------------------------------------------------------------------------- ! TM5 ! !-------------------------------------------------------------------------- !BOP ! ! !IROUTINE: EMISSION_ISOP_INIT ! ! !DESCRIPTION: Allocate memory !\\ !\\ ! !INTERFACE: ! SUBROUTINE EMISSION_ISOP_INIT( status ) ! ! !USES: ! use dims, only : ndyn_max, tref, im, jm, lm, idate, nlon360, nlat180 use dims, only : sec_month, dy, yref, ybeg use global_data, only : rcfile use emission_read, only : providers_def, numb_providers, sectors_def ! ! !OUTPUT PARAMETERS: ! integer, intent(out) :: status ! ! !REVISION HISTORY: ! 1 Oct 2010 - Achim Strunk - adapted for AR5 ! 28 Jun 2012 - Ph. Le Sager - adapted for lon-lat MPI domain decomposition ! ! !REMARKS: ! !EOP !------------------------------------------------------------------------ !BOC character(len=*), parameter :: rname = mname//'/emission_isop_init' integer :: region, i1, i2, j1, j2 integer :: lmr, lsec, ntim, lprov real :: dtime, dy1 ! --- begin ----------------------------------------- status = 0 if(.not. has_isop_emis) return isop_2dsec = 0 isop_3dsec = 0 do lprov = 1, numb_providers if (count(used_providers_isop == providers_def(lprov)%name)/=0) then ! limit AR5 to the 2D biomass burning sector if ( trim(providers_def(lprov)%name) == 'AR5' ) then isop_2dsec = isop_2dsec + count( sectors_def%prov == 'AR5 ' & .and. sectors_def%catname == 'biomassburning') else ! use all sectors isop_2dsec = isop_2dsec + providers_def(lprov)%nsect2d isop_3dsec = isop_3dsec + providers_def(lprov)%nsect3d end if endif enddo allocate( isop_emis_2d( nregions, isop_2dsec ) ) allocate( isop_emis_3d( nregions, isop_3dsec ) ) allocate( has_data_2d(isop_2dsec)) ; has_data_2d=.false. allocate( has_data_3d(isop_3dsec)) ; has_data_3d=.false. ! allocate information arrays (2d and 3d) do region=1,nregions CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 ) lmr = lm(region) do lsec=1,isop_2dsec allocate( isop_emis_2d(region,lsec)%surf(i1:i2, j1:j2) ) end do do lsec=1,isop_3dsec allocate( isop_emis_3d(region,lsec)%d3(i1:i2, j1:j2,lmr) ) end do dtime=float(ndyn_max)/(2*tref(region)) ! timestep emissions ntim=86400/nint(dtime) ! number of timesteps in 24 hours for this region allocate(isop_dat(region)%scalef_isop(ntim,j1:j2)) ! allocate enough memory! enddo ! find indices of tropics for splitting emissions dy1=dy/yref(1) j_start = floor((-20. - ybeg(1))/dy1) + 1 j_end = floor(( 20. - ybeg(1))/dy1) + 1 ! ok status = 0 end subroutine Emission_isop_Init !EOC !-------------------------------------------------------------------------- ! TM5 ! !-------------------------------------------------------------------------- !BOP ! ! !IROUTINE: EMISSION_ISOP_DONE ! ! !DESCRIPTION: Free memory !\\ !\\ ! !INTERFACE: ! subroutine Emission_isop_Done( status ) ! ! !OUTPUT PARAMETERS: ! integer, intent(out) :: status ! ! !REVISION HISTORY: ! 1 Oct 2010 - Achim Strunk - adapted to new structures ! 28 Jun 2012 - Ph. Le Sager - adapted for lon-lat MPI domain decomposition ! !EOP !------------------------------------------------------------------------ !BOC character(len=*), parameter :: rname = mname//'/Emission_isop_Done' integer :: region, lsec ! --- begin -------------------------------------- status = 0 if(.not. has_isop_emis) return do region = 1, nregions do lsec=1,isop_2dsec deallocate( isop_emis_2d(region,lsec)%surf ) end do do lsec=1,isop_3dsec deallocate( isop_emis_3d(region,lsec)%d3 ) end do deallocate(isop_dat(region)%scalef_isop ) end do deallocate( isop_emis_2d, isop_emis_3d ) deallocate( has_data_2d, has_data_3d ) status = 0 end subroutine Emission_isop_Done !EOC !-------------------------------------------------------------------------- ! TM5 ! !-------------------------------------------------------------------------- !BOP ! ! !IROUTINE: EMISSION_ISOP_DECLARE ! ! !DESCRIPTION: Opens, reads and evaluates input files (per month). ! Provides emissions on 2d/3d-arrays which are then added ! to mixing ratios in routine *apply. !\\ !\\ ! !INTERFACE: ! SUBROUTINE EMISSION_ISOP_DECLARE( status ) ! ! !USES: ! use toolbox, only : coarsen_emission use dims, only : im, jm, lm, idate, sec_month, nlon360, nlat180, iglbsfc use chem_param, only : xmisop use emission_data, only : msg_emis, LAR5BMB, LMEGAN ! ---------------- AR5 - MACC -------------------- use emission_data, only : emis_input_year use emission_data, only : emis_input_dir_mac use emission_data, only : emis_input_dir_megan use emission_data, only : emis_input_dir_retro use emission_data, only : emis_input_dir_gfed use emission_read, only : emission_ar5_regrid_aircraft use emission_read, only : emission_ar5_ReadSector use emission_read, only : emission_macc_ReadSector use emission_read, only : emission_megan_ReadSector use emission_read, only : emission_gfed_ReadSector use emission_read, only : emission_retro_ReadSector use emission_read, only : sectors_def, numb_sectors use emission_read, only : ar5_dim_3ddata ! ! !OUTPUT PARAMETERS: ! integer, intent(out) :: status ! ! !REVISION HISTORY: ! 1 Oct 2010 - Achim Strunk - adapted for AR5 ! !EOP !------------------------------------------------------------------------ !BOC character(len=*), parameter :: rname = mname//'/emission_isop_declare' integer :: region, hasData integer, parameter :: add_field=0 integer, parameter :: amonth=2 integer :: imr, jmr, lmr, lsec ! AR5 real,dimension(:,:,:),allocatable :: field3d, field3d2 type(d3_data) :: emis3d, work(nregions) type(emis_data) :: wrk2D(nregions) integer :: seccount2d, seccount3d ! --- begin ----------------------------------------- status = 0 if(.not. has_isop_emis) return write(gol,'(" EMISS-INFO ------------- read ISOPRENE emissions -------------")'); call goPr ! flag calculation of daily isoprene emission distribution day_isop(1:nregions) = -1 do region = 1, nregions do lsec=1,isop_2dsec isop_emis_2d(region,lsec)%surf = 0.0 end do do lsec=1,isop_3dsec isop_emis_3d(region,lsec)%d3 = 0.0 end do end do ! global arrays for coarsening do region = 1, nregions if (isRoot)then allocate(work(region)%d3(im(region),jm(region),lm(region))) else allocate(work(region)%d3(1,1,1)) end if enddo do region = 1, nregions wrk2D(region)%surf => work(region)%d3(:,:,1) end do ! -------------------------------- ! do a loop over available sectors ! -------------------------------- ! count 2d and 3d sectors seccount2d = 0 seccount3d = 0 ! always allocate here 3d data set (for 2d sectors it will be filled in first layer only) if (isRoot) then allocate( field3d( nlon360, nlat180, ar5_dim_3ddata ) ) ; field3d = 0.0 else allocate( field3d( 1, 1, 1 ) ) end if sec : do lsec = 1, numb_sectors ! screen out unused providers if (count(used_providers_isop.eq.sectors_def(lsec)%prov).eq.0) cycle ! screen out AR5 non-fires if ( sectors_def(lsec)%prov == 'AR5 ' .and. sectors_def(lsec)%catname /= 'biomassburning') cycle field3d = 0.0 if( sectors_def(lsec)%f3d ) then seccount3d = seccount3d + 1 else seccount2d = seccount2d + 1 end if if (isRoot) then ! READ select case( trim(sectors_def(lsec)%prov) ) case( 'AR5' ) ! here only if we select AR5, and if sector is BMB if (LAR5BMB) then call emission_ar5_ReadSector( 'isoprene', emis_input_year, idate(2), lsec, field3d, status ) IF_NOTOK_RETURN(status=1) endif case( 'MACC' ) ! skip if MEGAN is used, screen out sectors w/o isop else if( (trim(sectors_def(lsec)%name) .eq. 'emiss_bio') .and. (.not. LMEGAN) ) then call emission_macc_ReadSector( emis_input_dir_mac, 'ISOPRENE', emis_input_year, idate(2), & '0.5x0.5_kg.nc', sectors_def(lsec)%name, 'kg / s', field3d, status ) IF_NOTOK_RETURN(status=1) endif case('GFEDv3') call emission_gfed_ReadSector( emis_input_dir_gfed, 'isoprene', emis_input_year, idate(2), & sectors_def(lsec)%name, 'kg / s', field3d(:,:,1), status ) IF_NOTOK_RETURN(status=1) case('RETRO') call emission_retro_ReadSector( emis_input_dir_retro, 'ISOPRENE', emis_input_year, idate(2), & sectors_def(lsec)%name, 'kg / s', field3d(:,:,1), status ) IF_NOTOK_RETURN(status=1) case('MEGAN') call emission_megan_ReadSector( emis_input_dir_megan, 'isoprene', emis_input_year, idate(2), & sectors_def(lsec)%name, 'kg / s', field3d(:,:,1), status ) IF_NOTOK_RETURN(status=1) case('DUMMY') case default write(gol,*) "Error in buidling list of providers USED_PROVIDERS_ISOP" ; call goErr status=1; TRACEBACK; return end select ! nothing found??? if( sum(field3d) < 100.*TINY(1.0) ) then if (okdebug) then write(gol,'("EMISS-INFO - no ISOP emissions found for ",a," ",a," for month ",i2 )') & trim(sectors_def(lsec)%prov), trim(sectors_def(lsec)%name), idate(2) ; call goPr endif hasData=0 else if (okdebug) then write(gol,'("EMISS-INFO - found ISOP emissions for ",a," ",a," for month ",i2 )') & trim(sectors_def(lsec)%prov), trim(sectors_def(lsec)%name), idate(2) ; call goPr endif ! scale from kg/s to kg/month field3d = field3d * sec_month ! kg / month hasData=1 end if end if call Par_broadcast(hasData, status) IF_NOTOK_RETURN(status=1) if (hasData == 0) then cycle sec else if ( sectors_def(lsec)%f3d ) then has_data_3d(seccount3d)=.true. else has_data_2d(seccount2d)=.true. end if end if ! Distinguish 2d/3d sectors if( sectors_def(lsec)%f3d ) then write(gol,'("EMISS-ERROR - Unexpected 3D data: Uncomment code below ")'); call goErr status=1; TRACEBACK; return ! --------------------------- ! 3d data (AIRCRAFT) ! --------------------------- ! if (isRoot) then ! regrid ! ! helper array for regridding ! allocate( field3d2( nlon360,nlat180,lm(1) ) ) ; field3d2 = 0.0 ! ! aircraft data: regrid vertically to model layers ! call emission_ar5_regrid_aircraft( iglbsfc, field3d, nlon360, nlat180, ar5_dim_3ddata, lm(1), field3d2, status ) ! IF_NOTOK_RETURN(status=1;deallocate(field3d,field3d2)) ! ! write some numbers ! call msg_emis( amonth, 'aircraft. mass month', 'ISOP', xmisop, sum(field3d2) ) ! ! distribute to isop_emis in regions ! call Coarsen_Emission( 'ISOP '//trim(sectors_def(lsec)%name), nlon360, nlat180, lm(1), & ! field3d2, work, add_field, status ) ! IF_NOTOK_RETURN(status=1;deallocate(field3d,field3d2)) ! deallocate( field3d2 ) ! end if ! do region = 1, nregions ! call scatter(dgrid(region), isop_emis_3d(region,seccount3d)%d3, work(region)%d3, 0, status) ! IF_NOTOK_RETURN(status=1) ! end do else ! --------------------------- ! 2d data (Anthropogenic, Ships, Biomassburning) ! --------------------------- if (isRoot) then ! print total & regrid call msg_emis( amonth, trim(sectors_def(lsec)%prov), sectors_def(lsec)%name, 'ISOP', xmisop, sum(field3d(:,:,1)) ) call coarsen_emission( 'ISOP '//sectors_def(lsec)%name, nlon360, nlat180, field3d(:,:,1), wrk2D, add_field, status ) IF_NOTOK_RETURN(status=1) end if do region = 1, nregions call scatter(dgrid(region), isop_emis_2d(region,seccount2d)%surf, work(region)%d3(:,:,1), 0, status) IF_NOTOK_RETURN(status=1) end do end if end do sec ! sectors deallocate( field3d ) do region = 1, nregions if (associated(wrk2D(region)%surf)) nullify(wrk2D(region)%surf) deallocate( work(region)%d3 ) end do status = 0 END SUBROUTINE EMISSION_ISOP_DECLARE !EOC !-------------------------------------------------------------------------- ! TM5 ! !-------------------------------------------------------------------------- !BOP ! ! !IROUTINE: EMISSION_ISOP_APPLY ! ! !DESCRIPTION: Take monthly emissions, and ! - split them vertically ! - apply time splitting factors ! - add them up (add_isop) !\\ !\\ ! !INTERFACE: ! SUBROUTINE EMISSION_ISOP_APPLY( region, status ) ! ! !USES: ! use dims, only : itaur, nsrce, tref use dims, only : im, jm, lm, mlen, ndyn_max use dims, only : yref, dy, ybeg use datetime, only : tau2date, get_day use emission_data, only : emission_vdist_by_sector use chem_param, only : iisop, xmisop use emission_data, only : do_add_3d use emission_read, only : sectors_def, numb_sectors use tracer_data, only : tracer_print ! ! !INPUT PARAMETERS: ! integer, intent(in) :: region ! ! !OUTPUT PARAMETERS: ! integer, intent(out) :: status ! ! !REVISION HISTORY: ! 1 Oct 2010 - Achim Strunk - adapted for AR5 ! 27 Apr 2012 - Ph. Le Sager - adapted for lon-lat MPI domain decomposition ! ! !REMARKS: ! !EOP !------------------------------------------------------------------------ !BOC character(len=*), parameter :: rname = mname//'/emission_isop_apply' integer, dimension(6) :: idater real :: dtime, fraction integer :: imr, jmr, lmr, lsec integer :: seccount2d, seccount3d type(d3_data) :: emis3d real :: dlatr integer :: day, ntim, i1, i2, j1, j2, j01, j02 ! --- begin ----------------------------------------- status = 0 if(.not. has_isop_emis) return if( okdebug ) then write(gol,*) 'start of emission_apply_isop'; call goPr end if ! --- WHERE, WHEN CALL TAU2DATE( itaur(region), idater) CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 ) day = GET_DAY(idater(2),idater(3),mlen) dtime = float(nsrce)/(2*tref(region)) !emissions are added in two steps...XYZECCEZYX. if(okdebug) then write(gol,*)'emission_isop_apply in region ',region,' at date: ',idater, ' with time step:', dtime call goPr end if ! --- DIURNAL CYCLE if ( day /= day_isop(region) ) then dlatr = dy/yref(region) ! should be the same as lli%dlat_deg dtime=float(ndyn_max)/(2*tref(region)) ! timestep emissions ntim=86400/nint(dtime) ! number of timesteps in 24 hours. if ( okdebug ) then write (gol,*) 'day',day,'ntim',ntim,'jm',jm(region),'ybeg',& ybeg(region),'dlatr',dlatr,'sum(mlen)',sum(mlen),nsrce,dtime call goPr end if ! NOTE : latitude_start must be an integer. This is ok as long as ! the regions ybeg are integer. call scale_isop(day, ntim, j1, isop_dat(region)%scalef_isop, ybeg(region), dlatr, sum(mlen)) day_isop(region) = day !avoid recalculation during this day! endif ! --- ADD EMISSIONS ! get a working structure for 3d emissions allocate( emis3d%d3(i1:i2,j1:j2,lm(region)) ) ; emis3d%d3 = 0.0 ! count 2d and 3d sectors seccount2d = 0 seccount3d = 0 ! cycle over sectors do lsec = 1, numb_sectors ! screen out unused providers if (count(used_providers_isop.eq.sectors_def(lsec)%prov).eq.0) cycle ! screen out AR5 non-fires if ( sectors_def(lsec)%prov == 'AR5 ' .and. sectors_def(lsec)%catname /= 'biomassburning') cycle ! default: no additional splitting fraction = 1.0 ! ---------------------------------------------------------------------------------------- ! distinguish here between sectors and whether they should have additional splitting ! if( sectors_def(lsec)%catname == 'biomassburning' ) fraction = fraction * bb_frac etc... ! ---------------------------------------------------------------------------------------- ! distinguish between 2d/3d sectors if( sectors_def(lsec)%f3d ) then seccount3d = seccount3d + 1 if (.not.has_data_3d(seccount3d)) cycle emis3d%d3 = isop_emis_3d(region,seccount3d)%d3 else seccount2d = seccount2d + 1 if (.not.has_data_2d(seccount2d)) cycle emis3d%d3 = 0.0 ! vertically distribute according to sector call emission_vdist_by_sector( sectors_def(lsec)%vdisttype, 'ISOP', region, isop_emis_2d(region,seccount2d), & emis3d, status) IF_NOTOK_RETURN(status=1) ! is tile in tropics if ((j_end .lt. j1 ).or.(j_start .gt. j2) ) then continue else ! limit range j02=j_end j01=j_start if (j_end .gt. j2 ) j02 = j2 if (j_start .lt. j1 ) j01 = j1 emis3d%d3(:,j01:j02,1)=0.5*emis3d%d3(:,j01:j02,1) emis3d%d3(:,j01:j02,2)=emis3d%d3(:,j01:j02,1) end if end if ! add dataset according to sector and category if( trim(sectors_def(lsec)%catname) == "natural" ) then call do_add_isop( region, i1, j1, emis3d%d3, status, fraction ) ! special routine with additional emission scaling... IF_NOTOK_RETURN(status=1) else call do_add_3d( region, iisop, i1, j1, emis3d%d3, xmisop, xmisop, status, fraction ) IF_NOTOK_RETURN(status=1) end if end do deallocate( emis3d%d3 ) if(okdebug) then write(gol,*) 'end of emission_isop_apply' ; call goPr end if ! OK status = 0 END SUBROUTINE EMISSION_ISOP_APPLY !EOC !-------------------------------------------------------------------------- ! TM5 ! !-------------------------------------------------------------------------- !BOP ! ! !IROUTINE: SCALE_ISOP ! ! !DESCRIPTION: calculates factors to be multiplied with an emission field ! (e.g. isop) in order to simulate a diurnal cycle in ! emissions (caused by solar dependency), e.g. : ! ! rm(i,j,1,isop) = rm(i,j,1,isop) + e_isop(i,j)*scalef(ipos,j)*dt ! ! with ipos depending on time and longitude. ! ! The scalefactor is calculated for -180 longitude and the ! mean value for ntim timesteps during a day is scaled to 1. ! The routine should be called every day, since the position ! relative to the sun changes. The scaling is based on the ! cos(zenith) which is 1 for overhead sun and 0 at sunset. ! For the polar night, the values are set to 1.0 (even distribution) ! One thing is sure afterwards: we know that e_isop kg/s is added. !\\ !\\ ! !INTERFACE: ! SUBROUTINE SCALE_ISOP(day, ntim, j1, scalef, lat_start, dlat, idayy) ! ! !INPUT PARAMETERS: ! integer, intent(in) :: day ! day number based on 365 days a year integer, intent(in) :: ntim ! number of timesteps during one day integer, intent(in) :: j1 ! start index for latitudes integer, intent(in) :: lat_start ! southern edge of the domain (integer!) real, intent(in) :: dlat ! increment (real!) integer, intent(in) :: idayy ! # days this year ! ! !OUTPUT PARAMETERS: ! real, dimension(:,j1:), intent(out) :: scalef ! ! !REVISION HISTORY: ! 10 May 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition ! ! !REMARKS: ! !EOP !------------------------------------------------------------------------ !BOC real :: pi, piby, obliq, deday, delta, dt, lon, hr, lat, houra, smm integer :: i, j pi = acos(-1.0) piby = pi/180.0 obliq = 23.45 * piby deday = 4.88 + 2*pi/idayy * day delta = asin(sin(obliq)*sin(deday)) dt = 24./ntim ! timestep in hours lon = -180.0*piby ! calculate for dateline do j=j1,ubound(scalef,2) ! over latitudes hr = - 0.5*dt ! shift half a interval back lat = (lat_start + (j-0.5)*dlat)*piby smm = 0.0 do i=1,ntim hr = hr + dt houra = lon - pi + hr * (2.*pi/24.) scalef(i,j) = & max((sin(delta)*sin(lat) + cos(delta)*cos(lat)*cos(houra)),0.0) smm = smm+scalef(i,j)/ntim end do if ( smm > 1e-5 ) then scalef(1:ntim,j) = scalef(1:ntim,j)/smm else scalef(1:ntim,j) = 1.0 end if end do END SUBROUTINE SCALE_ISOP !EOC !-------------------------------------------------------------------------- ! TM5 ! !-------------------------------------------------------------------------- !BOP ! ! !IROUTINE: DO_ADD_ISOP ! ! !DESCRIPTION: Add local time splitted emissions to chemical array !\\ !\\ ! !INTERFACE: ! SUBROUTINE DO_ADD_ISOP(region, i1, j1, em_isop, status, fraction) ! ! !USES: ! use dims, only : tref, nsrce, itaur, ndyn_max use dims, only : sec_month, lm, dx, xref, xbeg use global_data, only : mass_dat use chem_param, only : iisop, xmisop #ifdef with_budgets use budget_global, only : budg_dat, nzon_vg use emission_data, only : sum_emission, budemi_dat #endif use datetime, only : tau2date ! ! !INPUT PARAMETERS: ! integer, intent(in) :: region, i1, j1 real, intent(in) :: em_isop(i1:,j1:,:) real, optional, intent(in) :: fraction ! ! !OUTPUT PARAMETERS: ! integer, intent(out) :: status ! ! !REVISION HISTORY: ! 1 Oct 2010 - Achim Strunk - added fraction input ! - switch from 2D to 3D input => remove tropics case ! 10 May 2012 - Ph. Le Sager - adapted for lon-lat MPI domain decomposition ! ! !REMARKS: ! (1) scalef_isop has been calculated w/ ndyn_max. !EOP !------------------------------------------------------------------------ !BOC character(len=*), parameter :: rname = mname//'/do_add_isop' real :: x, xlon, dtime, month2dt, dtime2 integer :: i, j, l, ipos, nzone, nzone_v integer :: sec_in_day, ntim, itim, i2, j2 integer, dimension(6) :: idater real, dimension(:,:,:,:), pointer :: rm ! --- begin ----------------------------------------- rm => mass_dat(region)%rm CALL GET_DISTGRID( dgrid(region), I_STOP=i2, J_STOP=j2 ) dtime = float(nsrce) / (2*tref(region)) ! timestep emissions dtime2 = float(ndyn_max) / (2*tref(region)) ! timestep emissions based on non-CFL interference (CMK 05/2006) month2dt = dtime/sec_month ! conversion to emission per timestep (CFl induced timestep CMK 05/2006) ntim = 86400/nint(dtime2) ! number of timesteps in 24 hours based on non-CFL interference (CMK 05/2006) call tau2date(itaur(region),idater) sec_in_day = idater(4)*3600 + idater(5)*60 + idater(6) ! elapsd seconds this day itim = sec_in_day/nint(dtime2)+1 ! # time interval CMK 05/2006 do l= 1,lm(region) do j=j1,j2 do i=i1,i2 xlon = xbeg(region) + (i-0.5)*dx/xref(region) ! itim = 1 and lon = -180 --->position 1 ! itim = ntim ant lon = -180 --->position ntim, etc. ! itim = 1 and lon = 0 ---->position ntim/2 ipos = 1 + mod(int((xlon+180.)*ntim/360.) + (itim-1),ntim) !position in array depending on time and lon. x=em_isop(i,j,l)*isop_dat(region)%scalef_isop(ipos,j)*month2dt rm(i,j,l,iisop)=rm(i,j,l,iisop)+x #ifdef with_budgets nzone=budg_dat(region)%nzong(i,j) !global budget nzone_v=nzon_vg(l) budemi_dat(region)%emi(i,j,nzone_v,iisop) = & budemi_dat(region)%emi(i,j,nzone_v,iisop) + x/xmisop*1e3 if(iisop ==1) sum_emission(region) = sum_emission(region) + x !in kg #endif !-- !AJS: strange statement: injection of emission decreases vertical slope ? !AJS: this gives negative slopes in case of large emissions ... !if(adv_scheme.eq.'slope') rzm(i,j,L,iisop)=rzm(i,j,L,iisop)-x !-- enddo !i enddo !j enddo !l nullify(rm) status=0 END SUBROUTINE DO_ADD_ISOP !EOC END MODULE EMISSION_ISOP