#ifdef GEOS5
#include "MAPL_Generic.h"
#endif
!-------------------------------------------------------------------------
! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
!-------------------------------------------------------------------------
!BOP
!
! !MODULE: CO2_GridCompMod --- CO2 Grid Component Class
!
! !INTERFACE:
!
module CO2_GridCompMod 1
! !USES:
#ifdef GEOS5
USE ESMF_Mod
USE MAPL_Mod
#endif
use Chem_Mod
! Chemistry Base Class
use Chem_StateMod
! Chemistry State
use Chem_ConstMod
, only: grav
use Chem_UtilMod
use m_inpak90
! Resource file management
#if defined(SPMD)
use mod_comm
, only: gid ! FvGCM communication library
#endif
implicit none
! !PUBLIC TYPES:
!
PRIVATE
PUBLIC CO2_GridComp ! The CO2 object
!
! !PUBLIIC MEMBER FUNCTIONS:
!
PUBLIC CO2_GridCompInitialize
PUBLIC CO2_GridCompRun
PUBLIC CO2_GridCompFinalize
!
! !DESCRIPTION:
!
! This module implements the (pre-ESMF) CO2 Grid Component.
!
! !REVISION HISTORY:
!
! 16Sep2003 da Silva First crack.
! 24OCT2005 Bian tag CO2 to 4 regions
! (total, north america, south america, africa)
! 19dec2005 da Silva Activated 3D diags for output
!
!EOP
!-------------------------------------------------------------------------
type CO2_GridComp
character(len=255) :: name
CHARACTER(LEN=255) :: eFilen_biomass ! biomass emissions
CHARACTER(LEN=255) :: eFilen ! Other emissions
CHARACTER(LEN=255) :: maskFileName
INTEGER :: nymd_eFilen
INTEGER :: BCnymd ! Date of last emissions/prodction read
REAL :: BBconFac ! conversion factor of BB emissions to CO2
REAL, POINTER :: eCO2_FF(:,:) ! kgC/m2/s, Earth surface
REAL, POINTER :: eCO2_NEP(:,:) ! kgC/m2/s, Earth surface
REAL, POINTER :: eCO2_OCN(:,:) ! kgC/m2/s, Earth surface
REAL, POINTER :: eCO2_BB(:,:) ! kgC/m2/s, PBL
REAL, POINTER :: regionMask(:,:) ! regional mask
INTEGER, POINTER :: regionIndex(:) ! desired regions from mask
end type CO2_GridComp
CONTAINS
!-------------------------------------------------------------------------
! NASA/GSFC, Global Modeling and Assimilation Office, Code 900.3 !
!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE: CO2_GridCompInitialize --- Initialize CO2_GridComp
!
! !INTERFACE:
!
subroutine CO2_GridCompInitialize ( gcCO2, w_c, impChem, expChem, & 1,54
nymd, nhms, cdt, rc )
! !USES:
implicit NONE
! !INPUT PARAMETERS:
type(Chem_Bundle), intent(in) :: w_c ! Chemical tracer fields
integer, intent(in) :: nymd, nhms ! time
real, intent(in) :: cdt ! chemical timestep (secs)
! !OUTPUT PARAMETERS:
type(CO2_GridComp), intent(inout) :: gcCO2 ! Grid Component
type(ESMF_State), intent(inout) :: impChem ! Import State
type(ESMF_State), intent(inout) :: expChem ! Export State
integer, intent(out) :: rc ! Error return code:
! 0 - all is well
! 1 -
! !DESCRIPTION: Initializes the CO2 Grid Component. It primarily sets
! the import state for each active constituent package.
!
! !REVISION HISTORY:
!
! 18Sep2003 da Silva First crack.
! 24OCT2005 Bian Mods for 5 tagged CO2
! (total, fossil fuel, ecosystem, oceanic, and biomass)
! 25OCT2005 Bian Mods for 5 regions
!
!EOP
!-------------------------------------------------------------------------
character(len=*), parameter :: myname = 'CO2_GridCompInitialize'
character(len=255) :: rcfilen = 'CO2_GridComp.rc'
integer :: ios, n
integer, allocatable :: ier(:)
integer :: i1, i2, im, j1, j2, jm, km, ijl
integer :: nbins, nbeg, nend, nbins_rc, nymd1, nhms1
integer :: nTimes, begTime, incSecs
real :: qmin, qmax
gcCO2%name = 'CO2 Constituent Package'
gcCO2%BCnymd = -1
! Initialize local variables
! --------------------------
rc = 0
i1 = w_c%grid%i1; i2 = w_c%grid%i2; im = w_c%grid%im
j1 = w_c%grid%j1; j2 = w_c%grid%j2; jm = w_c%grid%jm
km = w_c%grid%km
nbins = w_c%reg%n_CO2; nbeg = w_c%reg%i_CO2; nend = w_c%reg%j_CO2
ijl = ( i2 - i1 + 1 ) * ( j2 - j1 + 1 )
call init_
()
if ( rc /= 0 ) return
ier(:) =0
! -------------------
! Parse resource file
! -------------------
! Load resource file
! ------------------
call i90_loadf
( TRIM(rcfilen), ier(1) )
if ( ier(1) .ne. 0 ) then
call final_
(10)
return
end if
ier(:)=0
call i90_label
( 'number_CO2_bins:', ier(1) )
nbins_rc = i90_gint ( ier(2) )
if ( nbins_rc /= nbins ) then
call final_
(11)
return
end if
CALL I90_label
( 'CO2_biomass_emission_filename:', ier(3) )
CALL I90_gtoken
( gcCO2%eFilen_biomass, ier(4) )
CALL I90_label
( 'CO2_emissions_filename:', ier(5) )
CALL I90_gtoken
( gcCO2%eFilen, ier(6) )
CALL I90_label
( 'CO2_biomass_emission_factor:', ier(7) )
gcCO2%BBconFac = i90_gfloat ( ier(8) )
! Get the desired regions to run on
CALL I90_label
( 'CO2_regions:', ier(7) )
CALL I90_gtoken
( gcCO2%maskFileName, ier(8) )
call i90_label
( 'CO2_regions_indices:', ier(9) )
do n = 1, nbins
gcCO2%regionIndex(n) = i90_gint ( ier(9+n) )
end do
IF( ANY( ier(:) /= 0 ) ) THEN
CALL final_
(12)
RETURN
END IF
! Check initial date of inventory emission/oxidant files
! ------------------------------------------------------
! The intent here is that these files are valid for a particular
! YYYY or YYYYMMDD (if 1x year in file). We need to request
! the correct date
call Chem_UtilGetTimeInfo
( gcCO2%eFilen, gcCO2%nymd_eFilen, &
begTime, nTimes, incSecs )
ier(1) = gcCO2%nymd_eFilen
if( any(ier(1:1) < 0 ) ) then
call final_
(60)
return
endif
#ifndef GEOS5
!\/--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---\/
ier(:)=0
! Set which fvGCM fields are needed for the CO chemistry driver
! -------------------------------------------------------------
CALL Chem_StateSetNeeded
( impChem, iPBLH, .true., ier(1) )
CALL Chem_StateSetNeeded
( impChem, iT , .true., ier(2) )
CALL Chem_StateSetNeeded
( impChem, iAIRDENS, .true., ier(3) )
IF( ANY( ier(:) /= 0 ) ) THEN
CALL final_
(13)
RETURN
END IF
ier(:)=0
! Select fields to be produced in the export state.
! ----------------------------------------------------------------
! Emission Flux
n = nbins
if(n>0) call Chem_StateSetNeeded
( expChem, iCO2EM001, .true., ier(1) )
if(n>1) call Chem_StateSetNeeded
( expChem, iCO2EM002, .true., ier(2) )
if(n>2) call Chem_StateSetNeeded
( expChem, iCO2EM003, .true., ier(3) )
if(n>3) call Chem_StateSetNeeded
( expChem, iCO2EM004, .true., ier(4) )
if(n>4) call Chem_StateSetNeeded
( expChem, iCO2EM005, .true., ier(5) )
if(n>5) call Chem_StateSetNeeded
( expChem, iCO2EM006, .true., ier(6) )
if(n>6) call Chem_StateSetNeeded
( expChem, iCO2EM007, .true., ier(7) )
if(n>7) call Chem_StateSetNeeded
( expChem, iCO2EM008, .true., ier(8) )
if(n>8) ier(9) = 1 ! not enough bins - need to change mod_diag.F
! Column Burden
if(n>0) call Chem_StateSetNeeded
( expChem, iCO2CL001, .true., ier(1) )
if(n>1) call Chem_StateSetNeeded
( expChem, iCO2CL002, .true., ier(2) )
if(n>2) call Chem_StateSetNeeded
( expChem, iCO2CL003, .true., ier(3) )
if(n>3) call Chem_StateSetNeeded
( expChem, iCO2CL004, .true., ier(4) )
if(n>4) call Chem_StateSetNeeded
( expChem, iCO2CL005, .true., ier(5) )
if(n>5) call Chem_StateSetNeeded
( expChem, iCO2CL006, .true., ier(6) )
if(n>6) call Chem_StateSetNeeded
( expChem, iCO2CL007, .true., ier(7) )
if(n>7) call Chem_StateSetNeeded
( expChem, iCO2CL008, .true., ier(8) )
if(n>8) ier(9) = 1 ! not enough bins - need to change mod_diag.F
! Surface Mixing Ratio
ier(:)=0
if(n>0) call Chem_StateSetNeeded
( expChem, iCO2SC001, .true., ier(1) )
if(n>1) call Chem_StateSetNeeded
( expChem, iCO2SC002, .true., ier(2) )
if(n>2) call Chem_StateSetNeeded
( expChem, iCO2SC003, .true., ier(3) )
if(n>3) call Chem_StateSetNeeded
( expChem, iCO2SC004, .true., ier(4) )
if(n>4) call Chem_StateSetNeeded
( expChem, iCO2SC005, .true., ier(5) )
if(n>5) call Chem_StateSetNeeded
( expChem, iCO2SC006, .true., ier(6) )
if(n>6) call Chem_StateSetNeeded
( expChem, iCO2SC007, .true., ier(7) )
if(n>7) call Chem_StateSetNeeded
( expChem, iCO2SC008, .true., ier(8) )
if(n>8) ier(9) = 1 ! not enough bins - need to change mod_diag.F
IF( ANY( ier(:) /= 0 ) ) THEN
CALL final_
(14)
RETURN
END IF
! Select fields to be produced in the export state.
! ----------------------------------------------------------------
ier(:)=0
if(n>0) CALL Chem_StateSetNeeded
( expChem, iCO2 , .TRUE., ier(1) )
if(n>1) CALL Chem_StateSetNeeded
( expChem, iCO2NAMER , .TRUE., ier(2) )
if(n>2) CALL Chem_StateSetNeeded
( expChem, iCO2SAMER , .TRUE., ier(3) )
if(n>3) CALL Chem_StateSetNeeded
( expChem, iCO2AFRIC , .TRUE., ier(4) )
IF( ANY( ier(:) /= 0 ) ) THEN
CALL final_
(15)
RETURN
END IF
!/\--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---/\
#endif
ier(:)=0
! Obtain geographical region mask
! -------------------------------
call Chem_UtilGetTimeInfo
( gcCO2%maskFileName, nymd1, &
begTime, nTimes, incSecs )
if(nymd1 < 0) call final_
(15)
nhms1 = 120000
CALL Chem_UtilMPread
( gcCO2%maskFileName, 'COMASK', nymd1, nhms1, &
i1, i2, 0, im, j1, j2, 0, jm, 0, &
var2d=gcCO2%regionMask, grid=w_c%grid_esmf )
#ifdef DEBUG
CALL pmaxmin
('CO2: Mask', gcCO2%regionMask, qmin, qmax, &
ijl,1, 1. )
#endif
DEALLOCATE(ier)
return
CONTAINS
subroutine init_() 36,316
integer ios, nerr
nerr = max ( 32, nbins+1 )
allocate ( gcCO2%eCO2_FF(i1:i2,j1:j2), &
gcCO2%eCO2_NEP(i1:i2,j1:j2), &
gcCO2%eCO2_OCN(i1:i2,j1:j2), &
gcCO2%eCO2_BB(i1:i2,j1:j2), &
gcCO2%regionMask(i1:i2,j1:j2), &
gcCO2%regionIndex(nbins), &
ier(nerr), stat=ios )
if ( ios /= 0 ) rc = 100
end subroutine init_
subroutine final_(ierr) 174,11
integer :: ierr
integer ios
deallocate ( gcCO2%eCO2_FF, gcCO2%eCO2_NEP, gcCO2%eCO2_OCN, &
gcCO2%eCO2_BB, gcCO2%regionMask, gcCO2%regionIndex, &
ier, stat=ios )
call i90_release
()
rc = ierr
end subroutine final_
end subroutine CO2_GridCompInitialize
!-------------------------------------------------------------------------
! NASA/GSFC, Global Modeling and Assimilation Office, Code 900.3 !
!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE: CO2_GridCompRun --- The Chem Driver
!
! !INTERFACE:
!
subroutine CO2_GridCompRun ( gcCO2, w_c, impChem, expChem, & 1,25
nymd, nhms, cdt, rc )
! !USES:
implicit NONE
! !INPUT/OUTPUT PARAMETERS:
type(CO2_GridComp), intent(inout) :: gcCO2 ! Grid Component
type(Chem_Bundle), intent(inout) :: w_c ! Chemical tracer fields
! !INPUT PARAMETERS:
type(ESMF_State), intent(inout) :: impChem ! Import State
integer, intent(in) :: nymd, nhms ! time
real, intent(in) :: cdt ! chemical timestep (secs)
! !OUTPUT PARAMETERS:
type(ESMF_State), intent(inout) :: expChem ! Export State
integer, intent(out) :: rc ! Error return code:
! 0 - all is well
! 1 -
! !DESCRIPTION: This routine implements the so-called CO2 Driver. That
! is, adds chemical tendencies to each of the constituents,
! Note: water wapor, the first constituent is not considered a chemical
! constituents.
!
! !REVISION HISTORY:
!
! 18Sep2003 da Silva First crack.
! 24OCT2005 Bian Mods for 5 tagged CO2
! (total, fossil fuel, ecosystem, oceanic, and biomass)
! 25OCT2005 Bian Mods for 5 regions
! Mask Region
! ---- -------------
! 1 North America
! 2 Mexico
! 3 Europe
! 4 Asia
! 5 Africa
!
!EOP
!-------------------------------------------------------------------------
character(len=*), parameter :: myname = 'CO2_GridCompRun'
character(len=*), parameter :: Iam = myname
! Input fields from fvGCM
! -----------------------
REAL, POINTER, DIMENSION(:,:) :: PBLH
REAL, POINTER, DIMENSION(:,:,:) :: T
REAL, POINTER, DIMENSION(:,:,:) :: RHOA
integer :: i1, i2, im, j1, j2, jm, km, idiag, ios, ijl
integer :: i, j, k, n, nbins, nbeg, nend
INTEGER :: nymd1, nhms1, ier(7)
REAL :: qmin, qmax, BBconFac, c2co2
REAL, PARAMETER :: mwtAir=28.97
REAL, PARAMETER :: mwtCO2=44.00
#ifdef GEOS5
#define EXPORT expChem
#define ptrCO2EM CO2_emis
#define ptrCO2CL CO2_column
#define ptrCO2SC CO2_surface
integer :: STATUS
#include "CO2_GetPointer___.h"
#else
!\/--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---\/
! Quantities to be exported
! -------------------------
type(Chem_Array), pointer :: CO2_emis(:), CO2_column(:), CO2_surface(:), &
CO2,CO2NAMER,CO2SAMER,CO2AFRIC
!/\--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---/\
#endif
! Initialize local variables
! --------------------------
rc = 0
i1 = w_c%grid%i1; i2 = w_c%grid%i2; im = w_c%grid%im
j1 = w_c%grid%j1; j2 = w_c%grid%j2; jm = w_c%grid%jm
km = w_c%grid%km
ijl = ( i2 - i1 + 1 ) * ( j2 - j1 + 1 )
nbins = w_c%reg%n_CO2; nbeg = w_c%reg%i_CO2; nend = w_c%reg%j_CO2
c2co2=44.00/12.00
#ifdef GEOS5
if ( any((/NBIN_CO2CL,NBIN_CO2SC/)/=NBIN_CO2EM)) then
call die
(myname,'all emissions in registry must have same number of bins')
endif
if ( nbins > NBIN_CO2EM ) then
call die
(myname,'nbins in chem registry must be <= those in component registry')
end if
#endif
! Update emissions once each day.
! -----------------------------------------------------
IF ( gcCO2%BCnymd /= nymd ) THEN
! Selections based on biomass burning emission set chosen
! Currently, parse on:
! bian -> kg C m-2 s-1
! modisfire -> kg CO2 m-2 s-1
! else -> based on dry matter consumed
! Biomass Burning -- select on known inventories
! ----------------------------------------------
! Biomass burning climatology, is in kg C m^-2 s^-1
! -------------------------------------------------
IF ( index(gcCO2%eFilen_biomass,'bian') .GT. 0 ) then
nymd1 = 2000*10000 + MOD ( nymd, 10000 ) ! assumes 2000
nhms1 = 120000
BBconFac = c2co2
CALL Chem_UtilMPread
( gcCO2%eFilen_biomass, 'emco2bb', nymd1, nhms1, &
i1, i2, 0, im, j1, j2, 0, jm, 0, &
var2d=gcCO2%eCO2_BB, cyclic=.true., &
grid=w_c%grid_esmf )
ELSE ! time-varying biomass burning
! Biomass burning daily files, currently in kg m^-2 s^-1
! -------------------------------------------------------
! Daily files (e.g., MODIS) or GFED v.2 (1997 - 2005 valid)
BBconFac = gcCO2%BBconFac
if ( index(gcCO2%eFilen_biomass,'%') .gt. 0 .or. &
(index(gcCO2%eFilen_biomass,'gfed') .gt. 0 .and. &
index(gcCO2%eFilen_biomass,'v2') .gt. 0) ) then
nymd1 = nymd
nhms1 = 120000
! Assume GFED climatology or Martin (Duncan) climatology
else
nymd1 = 1971*10000 + mod ( nymd, 10000 ) ! assumes 1971
! nymd1 = nymd
nhms1 = 120000
end if
CALL Chem_UtilMPread
( gcCO2%eFilen_biomass, 'biomass', nymd1, nhms1, &
i1, i2, 0, im, j1, j2, 0, jm, 0, &
var2d=gcCO2%eCO2_BB, cyclic=.true., &
grid=w_c%grid_esmf )
ENDIF ! type of biomass burning
nymd1 = (gcCO2%nymd_eFilen/10000)*10000 + MOD ( nymd, 10000 )
nhms1 = 120000
CALL Chem_UtilMPread
( gcCO2%eFilen, 'emco2ff', nymd1, nhms1, &
i1, i2, 0, im, j1, j2, 0, jm, 0, &
var2d=gcCO2%eCO2_FF, cyclic=.true., &
grid=w_c%grid_esmf )
CALL Chem_UtilMPread
( gcCO2%eFilen, 'emco2nep', nymd1, nhms1, &
i1, i2, 0, im, j1, j2, 0, jm, 0, &
var2d=gcCO2%eCO2_NEP, cyclic=.true., &
grid=w_c%grid_esmf )
CALL Chem_UtilMPread
( gcCO2%eFilen, 'emco2ocn', nymd1, nhms1, &
i1, i2, 0, im, j1, j2, 0, jm, 0, &
var2d=gcCO2%eCO2_OCN, cyclic=.true., &
grid=w_c%grid_esmf )
#ifdef DEBUG
CALL pmaxmin
('CO2: e_ff', gcCO2%eCO2_FF, qmin, qmax, ijl, 1, 1. )
CALL pmaxmin
('CO2: e_nep', gcCO2%eCO2_NEP, qmin, qmax, ijl, 1, 1. )
CALL pmaxmin
('CO2: e_ocn', gcCO2%eCO2_OCN, qmin, qmax, ijl, 1, 1. )
CALL pmaxmin
('CO2: e_bb', gcCO2%eCO2_BB, qmin, qmax, ijl, 1, 1. )
#endif
gcCO2%BCnymd = nymd
! Units for surface flux must be kgCO2 m^-2 s^-1
! -------------------------------------------
gcCO2%eCO2_FF(i1:i2,j1:j2) = gcCO2%eCO2_FF(i1:i2,j1:j2)*c2co2
! Bian says that we need to adjust the uptake flux of CO2 in the
! ecosystem database to reflect the emissions from biomass burning.
! In principle this adds a factor which needs to be balanced on an
! interannual basis. For year 2000 TRMM (GFED v 1.2) emissions this
! factor is 1.2448
! ------------------------------------------------------------------
WHERE(gcCO2%eCO2_NEP(i1:i2,j1:j2) .gt. 0.0) &
gcCO2%eCO2_NEP(i1:i2,j1:j2) = gcCO2%eCO2_NEP(i1:i2,j1:j2)*c2co2
WHERE(gcCO2%eCO2_NEP(i1:i2,j1:j2) .le. 0.0) &
gcCO2%eCO2_NEP(i1:i2,j1:j2) = gcCO2%eCO2_NEP(i1:i2,j1:j2)*c2co2*1.2448
gcCO2%eCO2_OCN(i1:i2,j1:j2) = gcCO2%eCO2_OCN(i1:i2,j1:j2)*c2co2
gcCO2%eCO2_BB(i1:i2,j1:j2) = gcCO2%eCO2_BB(i1:i2,j1:j2)*BBconFac
END IF ! time to update biomass burning
#ifndef GEOS5
!\/--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---\/
! Work space for holding CO output
! ----------------------------------
allocate ( CO2_emis(nbins), CO2_column(nbins), CO2_surface(nbins), &
CO2, CO2NAMER, CO2SAMER, CO2AFRIC, &
stat = ios )
if ( ios /= 0 ) then
rc = 1
return
end if
!/\--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---/\
#endif
! Get imports
! -----------
#ifdef GEOS5
call MAPL_GetPointer ( impChem, pblh, 'ZPBL', rc=ier(1) )
call MAPL_GetPointer ( impChem, T, 'T', rc=ier(2) )
call MAPL_GetPointer ( impChem, rhoa, 'AIRDENS', rc=ier(3) )
#else
!\/--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---\/
CALL Chem_StateGetArray2D
( impChem, iPBLH, pblh, ier(1) )
CALL Chem_StateGetArray3D
( impChem, iT, T, ier(2) )
call Chem_StateGetArray3D
( impChem, iAIRDENS, rhoa, ier(3) )
!/\--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---/\
#endif
#ifdef DEBUG
CALL pmaxmin
('CO2: pblh', pblh, qmin, qmax, ijl, 1, 1. )
CALL pmaxmin
('CO2: T', T, qmin, qmax, ijl, 1, 1. )
CALL pmaxmin
('CO2: rhoa', rhoa, qmin, qmax, ijl, 1, 1. )
#endif
#ifndef GEOS5
!\/--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---\/
! Get pointers to export state
! ----------------------------
do n = 1, nbins
idiag = iCO2EM001 + n - 1
call Chem_StateGetArray2D
( expChem, idiag, CO2_emis(n)%data2d, ier(n) )
end do
if ( any(ier(1:nbins) /= 0) ) then
rc = 15
return
end if
do n = 1, nbins
idiag = iCO2CL001 + n - 1
call Chem_StateGetArray2D
( expChem, idiag, CO2_column(n)%data2d, ier(n) )
end do
if ( any(ier(1:nbins) /= 0) ) then
rc = 15
return
end if
do n = 1, nbins
idiag = iCO2SC001 + n - 1
call Chem_StateGetArray2D
( expChem, idiag, CO2_surface(n)%data2d, ier(n))
end do
if ( any(ier(1:nbins) /= 0) ) then
rc = 15
return
end if
n = nbins
ier = 0
if(n>0) CALL Chem_StateGetArray3D
( expChem, iCO2, CO2%data3d, ier(1) )
if(n>1) CALL Chem_StateGetArray3D
( expChem, iCO2NAMER, CO2NAMER%data3d, ier(2) )
if(n>2) CALL Chem_StateGetArray3D
( expChem, iCO2SAMER, CO2SAMER%data3d, ier(3) )
if(n>3) CALL Chem_StateGetArray3D
( expChem, iCO2AFRIC, CO2AFRIC%data3d, ier(4) )
IF( ANY( ier(1:4) /= 0 ) ) THEN
rc = 20
END IF
!/\--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---/\
#endif
! CO2 Emissions
! -------------
call CO2_Emission
( i1, i2, j1, j2, km, nbins, cdt, gcCO2, w_c, &
pblh, T, rhoa, CO2_emis, rc)
! Fill the export states
! ----------------------
! Surface concentration in PPMv
do n = 1, nbins
if(associated(CO2_surface(n)%data2d)) &
CO2_surface(n)%data2d(i1:i2,j1:j2) = w_c%qa(nbeg+n-1)%data3d(i1:i2,j1:j2,km)*1.e6
enddo
! Column burden in kg m-2
! -----------------------
do n = 1, nbins
if(associated(CO2_column(n)%data2d)) then
CO2_column(n)%data2d(i1:i2,j1:j2) = 0.
do k = 1, km
CO2_column(n)%data2d(i1:i2,j1:j2) &
= CO2_column(n)%data2d(i1:i2,j1:j2) &
+ w_c%qa(nbeg+n-1)%data3d(i1:i2,j1:j2,k)*mwtCO2/mwtAir &
* w_c%delp(i1:i2,j1:j2,k)/grav
enddo
endif
enddo
! Fill the export state with current mixing ratios
! ------------------------------------------------
if(associated(CO2%data3d)) &
CO2%data3d(i1:i2,j1:j2,1:km) = w_c%qa(nbeg)%data3d(i1:i2,j1:j2,1:km)
if(associated(CO2NAMER%data3d)) &
CO2NAMER%data3d(i1:i2,j1:j2,1:km) = w_c%qa(nbeg+1)%data3d(i1:i2,j1:j2,1:km)
if(associated(CO2SAMER%data3d)) &
CO2SAMER%data3d(i1:i2,j1:j2,1:km) = w_c%qa(nbeg+2)%data3d(i1:i2,j1:j2,1:km)
if(associated(CO2AFRIC%data3d)) &
CO2AFRIC%data3d(i1:i2,j1:j2,1:km) = w_c%qa(nbeg+3)%data3d(i1:i2,j1:j2,1:km)
#ifndef GEOS5
!\/--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---\/
deallocate( CO2_emis, CO2_column, CO2_surface, &
CO2, CO2NAMER, CO2SAMER, CO2AFRIC, stat=ios)
!/\--- cut --- --- cut --- --- cut --- --- cut --- --- cut --- --- cut ---/\
#endif
return
CONTAINS
!-------------------------------------------------------------------------
! NASA/GSFC, Global Modeling and Assimilation Office, Code 900.3 !
!-------------------------------------------------------------------------
!BOP
! !IROUTINE: CO2_Emission - Adds emissions for CO2 for one timestep
! We have emissions from 4 sources, which are distributed
! differently in the vertical
! 1) fossil fuel - emitted at surface
! 2) ecosystem - fluxes at surface
! 3) oceanic - fluxes at surface
! 4) biomass burning - uniformly mixed in PBL
!
! !INTERFACE:
!
subroutine CO2_Emission ( i1, i2, j1, j2, km, nbins, cdt, gcCO2, w_c, & 1
pblh, T, rhoa, CO2_emis, rc )
! !USES:
implicit NONE
! !INPUT PARAMETERS:
integer, intent(in) :: i1, i2, j1, j2, km, nbins
real, intent(in) :: cdt
type(CO2_GridComp), intent(in) :: gcCO2 ! CO2 Grid Component
real, pointer, dimension(:,:) :: pblh
real, pointer, dimension(:,:,:) :: T
real, pointer, dimension(:,:,:) :: rhoa
! !OUTPUT PARAMETERS:
type(Chem_Bundle), intent(inout) :: w_c ! Chemical tracer fields
type(Chem_Array), intent(inout) :: CO2_emis(nbins) ! CO2 emissions, kg/m2/s
integer, intent(out) :: rc ! Error return code:
! 0 - all is well
! 1 -
character(len=*), parameter :: myname = 'CO2_Emission'
! !DESCRIPTION: Updates the CO2 concentration with emissions every timestep
!
! !REVISION HISTORY:
!
! 24Oct2005, Bian
!
!EOP
!-------------------------------------------------------------------------
! !Local Variables
integer :: i, j, k, m, n, ios
integer :: nbeg, nend
real, dimension(i1:i2,j1:j2) :: pPblh ! pressure at PBLH
real, dimension(i1:i2,j1:j2) :: p0, z0, ps
real :: p1, z1, dz, delz, delp, fPblh, fs, fu
real :: zpbl
real :: srctot
integer :: iregWant
REAL, PARAMETER :: mwtAir=28.97
REAL, PARAMETER :: mwtCO2=44.00
! Initialize local variables
! --------------------------
nbeg = w_c%reg%i_CO2
nend = w_c%reg%j_CO2
! Zero out CO2 emissions
! ----------------------
do n = 1, nbins
if(associated(CO2_emis(n)%data2d)) CO2_emis(n)%data2d(i1:i2,j1:j2) = 0.
enddo
! Find the pressure of PBLH altitudes
ps = 0.0
do k = 1, km
ps(i1:i2,j1:j2) = ps(i1:i2,j1:j2) + w_c%delp(i1:i2,j1:j2,k)
end do
p0 = ps
z0(i1:i2,j1:j2) = 0.
do k = km, 1, -1
do j = j1, j2
do i = i1, i2
p1 = p0(i,j) - w_c%delp(i,j,k)
dz = w_c%delp(i,j,k)/rhoa(i,j,k)/grav
z1 = z0(i,j)+dz
zpbl = max ( 100., pblh(i,j) )
if(z0(i,j) .lt. zpbl .and. z1 .ge. zpbl) then
delz = z1-zpbl
delp = delz*rhoa(i,j,k)*grav
pPblh(i,j) = p1+delp
endif
p0(i,j) = p1
z0(i,j) = z1
end do
end do
end do
! Now update the tracer mixing ratios with the CO2 sources
p0 = ps
do k = km, 1, -1
if ( k .eq. km) fs = 1.00
if ( k .ne. km) fs = 0.00
do j = j1, j2
do i = i1, i2
p1 = p0(i,j) - w_c%delp(i,j,k)
fPblh = 0.
if(p1 .ge. pPblh(i,j)) fPblh = w_c%delp(i,j,k)/(ps(i,j)-pPblh(i,j))
if(p1 .lt. pPblh(i,j) .and. p0(i,j) .ge. pPblh(i,j)) &
fPblh = (p0(i,j)-pPblh(i,j))/(ps(i,j)-pPblh(i,j))
! Convert emission from Kg CO2/m2/s to mixing ratio/s (TVVMM/(delz*airden))
! --------------------------
fu = (mwtAir/mwtCO2)/(w_c%delp(i,j,k)/grav)
! Total source in kg m-2 s-1
srctot = (gcCO2%eCO2_FF(i,j) * fs &
+ gcCO2%eCO2_NEP(i,j) * fs &
+ gcCO2%eCO2_OCN(i,j) * fs &
+ gcCO2%eCO2_BB(i,j) * fPblh ) * fu
! Get tagged CO2 to regions
do n = 1, nbins
iregWant = gcCO2%regionIndex(n)
if(iregWant .eq. -1) then
w_c%qa(nbeg+n-1)%data3d(i,j,k) = w_c%qa(nbeg+n-1)%data3d(i,j,k) &
+ srctot*cdt
if(associated(CO2_emis(n)%data2d)) &
CO2_emis(n)%data2d(i,j) = CO2_emis(n)%data2d(i,j) + srctot/fu
else
if(int(gcCO2%regionMask(i,j)) .EQ. iregWant) then
w_c%qa(nbeg+n-1)%data3d(i,j,k) = w_c%qa(nbeg+n-1)%data3d(i,j,k) + srctot*cdt
if(associated(CO2_emis(n)%data2d)) &
CO2_emis(n)%data2d(i,j) = CO2_emis(n)%data2d(i,j) + srctot/fu
endif
endif
enddo
p0(i,j) = p1
end do
end do
end do
rc = 0
end subroutine CO2_Emission
end subroutine CO2_GridCompRun
!-------------------------------------------------------------------------
! NASA/GSFC, Global Modeling and Assimilation Office, Code 900.3 !
!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE: CO2_GridCompFinalize --- The Chem Driver
!
! !INTERFACE:
!
subroutine CO2_GridCompFinalize ( gcCO2, w_c, impChem, expChem, & 1
nymd, nhms, cdt, rc )
! !USES:
implicit NONE
! !INPUT/OUTPUT PARAMETERS:
type(CO2_GridComp), intent(inout) :: gcCO2 ! Grid Component
! !INPUT PARAMETERS:
type(Chem_Bundle), intent(in) :: w_c ! Chemical tracer fields
integer, intent(in) :: nymd, nhms ! time
real, intent(in) :: cdt ! chemical timestep (secs)
! !OUTPUT PARAMETERS:
type(ESMF_State), intent(inout) :: impChem ! Import State
type(ESMF_State), intent(inout) :: expChem ! Import State
integer, intent(out) :: rc ! Error return code:
! 0 - all is well
! 1 -
! !DESCRIPTION: This routine finalizes this Grid Component.
!
! !REVISION HISTORY:
!
! 18Sep2003 da Silva First crack.
!
!EOP
!-------------------------------------------------------------------------
character(len=*), parameter :: myname = 'CO2_GridCompFinalize'
INTEGER :: ios
DEALLOCATE ( gcCO2%eCO2_FF, gcCO2%eCO2_NEP, gcCO2%eCO2_OCN, &
gcCO2%eCO2_BB, gcCO2%regionMask, STAT=ios )
rc = 0
IF ( ios /= 0 ) rc = 1
return
end subroutine CO2_GridCompFinalize
end module CO2_GridCompMod