Customize emissions with HEMCO

In this Guide, we will walk you through the process of adding your own emissions file (a new regional inventory, a replacement for an existing species, a locally-produced dataset, etc.) to the Base Emissions section of HEMCO_Config.rc.

Attention

If the emissions inventory that you wish to add depends on external meteorology, you will need to implement it as a new HEMCO Extension. This is a customized Fortran module that computes emissions using meteorology inputs supplied from HEMCO.

For the full, authoritative reference on every HEMCO_Config.rc attribute, see the HEMCO configuration file reference guide and the GEOS-Chem summary of it. This Guide does not replace that reference, but rather walks through the specific decisions and mistakes that come up most often when adding a new emissions field.

Anatomy of a Base Emissions entry

Every entry under the BASE EMISSIONS section of HEMCO_Config.rc (see Base emissions) has the same eleven columns:

# ExtNr Name sourceFile sourceVar sourceTime C/R/E SrcDim SrcUnit Species ScalIDs Cat Hier

0 CEDS_NO_ENE  $ROOT/CEDS/v2024-06/$YYYY/CEDS_NO_0.1x0.1_$YYYY.nc  NO_ene  1980-2019/1-12/1/0 C xyL* kg/m2/s NO  2401/706/315  1 5

Column

What it means

ExtNr

0 for a file-based (Base) entry. A nonzero value assigns the entry to a HEMCO extension instead (not covered here).

Name

A label you choose for this entry. Used in log/verbose output and in scale-factor bookkeeping—it does not need to match anything in the file.

sourceFile

Path to your netCDF file. May contain $ROOT, $YYYY, $MM, $DD, $HH tokens.

sourceVar

The exact netCDF variable name inside the file (case-sensitive – check with ncdump -h).

sourceTime

The time range/frequency covered by the file(s), plus a cycling mode letter – see Time cycle flags (C/R/E) – which to pick below.

C/R/E

The time cycle flag: what HEMCO should do when the simulation date falls outside what the file(s) provide. See Time cycle flags (C/R/E) – which to pick.

SrcDim

The spatial/vertical shape of the data in the file, and how to map it onto model levels. See Getting SrcDim right (2-D vs. 3-D data).

SrcUnit

The units HEMCO should assume the data is in. See Units: A source of silent errors.

Species

The GEOS-Chem species this data will be emitted as.

ScalIDs

Scale factor ID(s) (from the SCALE FACTORS section, Scale factors) to apply to this field, separated by /. Use - for none.

Cat / Hier

Emission category and hierarchy, used to combine/override this field against other inventories. Only meaningful for ExtNr = 0 entries. See Category and hierarchy (Cat / Hier).

Important

GCHP users: GCHP does not use HEMCO for file I/O, but instead relies upon the MAPL ExtData mechanism. Thus, GCHP will ignore entirely the following columns of HEMCO_Config.rc: sourceFile, sourceVar, sourceTime, C/R/E, SrcDim, and SrcUnit.

To tell GCHP to read a variable from disk, you must also add a corresponding entry to ExtData.rc specifying the file path, variable name, and read frequency. GCHP only uses the masking and scaling fields from HEMCO_Config.rc (ExtNr, Species ScalIDs, Cat, and Hier.).

Updating only HEMCO_Config.rc without making corresponding changes to ExtData.rc is a common source of error. Please see GCHP vs. GC-Classic usage differences for more information.

Getting SrcDim right (2-D vs. 3-D data)

Attention

If your emissions come out entirely at the surface level when you expected a vertical profile, this is almost always a SrcDim mistake, not a bug in HEMCO or GEOS-Chem.

SrcDim tells HEMCO both the shape of your input data and which model levels to put it into. The most common settings are:

SrcDim setting

Behavior

xy

2-D data (one horizontal field, no vertical dimension). This is what almost all surface emissions files use.

xyz

3-D data whose vertical dimension already matches (or can be vertically regridded to) the model’s vertical levels.

xyL*

Copies a 2-D field into every model level uniformly. You then apply a scale factor (see below) to redistribute the total vertically – e.g. to spread stack/plume-rise emissions across several levels. This is how CEDS energy/industry/ship emissions are vertically allocated in the default configuration.

xyL=5

Puts a 2-D field entirely into model level 5.

xyL=1:PBL

Distributes a 2-D field from the surface up to the boundary layer top.

xy5 / xy-5

The input file itself has (at least) 5 levels; read the lowest (or, with the minus sign, the topmost) 5 of them into model levels 1-5.

If your file has one value per model column with no vertical structure, use xy. If it has real 3-D structure that should land on the model grid as-is, use xyz. Use xyL* (plus a scale factor) only when you want to take a 2-D total and spread it across levels according to some vertical profile.

See the full SrcDim reference table for every variant (fixed heights in meters, ensemble dimensions, etc.).

Worked example: vertically distributing a 2-D emission field

Suppose you have a file vert_profile.nc with a variable frac giving the fraction of your emissions to place in each model level. First define it as a scale factor:

###############################################################################
### BEGIN SECTION SCALE FACTORS
###############################################################################

# Vertical profile definition
400 MY_VERT_PROFILE vert_profile.nc frac 2020/1/1/0 C xyz 1 1

Then reference it from your Base Emissions entry, using xyL*. This will copy the 2-D field to every level, and then apply the scale factor that you just defined.

0 MY_INVENTORY_CO  $ROOT/MY_INVENTORY/v2024-01/co_$YYYY.nc  CO  2015-2024/1-12/1/0 C xyL* kg/m2/s CO 400 1 5

Time cycle flags (C/R/E) – which to pick

The C/R/E time cycle flag controls what HEMCO does when your simulation date and time does not does not line up exactly with the date and time in the netCDF file containing your emissions data.

C/R/E setting

Behavior

C

Cycling. If the simulation date lies outside the file’s date range, reuse the nearest available year (or day/hour, depending on frequency). Use this for most emission inventories that only cover a fixed set of years.

R

Range-restricted. Only use this data within its exact valid date range; HEMCO does not know what to do outside it. Use this for fields that should never be silently substituted).

E

Exact match required. HEMCO halts if the simulation date does not exactly match a time slice in the file.

EFYO / EY / CYS

Most often used with the GEOS-Chem Classic restart-file entry (aka SPC_).

If you should encounter an error such as:

  • “Cannot find field”

  • “Not enough time slices”

  • “Time stamps may be wrong”

this usually means that HEMCO believes that the netCDF variable timestamp for your emissions field lies lies outside of the time range defined by your choice of C/R/E and sourceTime. Our Understand what error messages mean supplemental guide contains detailed information on how to resolve these type of errors.

As a starting point when authoring a new entry:

  • If the file covers exactly the years/dates you’ll simulate, use E or R.

  • If the file covers a fixed historical period and you may run outside it (spin-up years, future scenarios, etc.), use C.

Units: A source of silent errors

Unlike a missing file or a bad date, a units mismatch does not always stop your run. By default HEMCO’s unit tolerance. setting only prints a warning. This makes it very easy to end up with incorrect emissions without generating any error or warning at all.

To check if your unit conversion is correct, set Verbose to true in the Settings section of (HEMCO_Config.rc) and run a short (~1 hour) simulation. The unit conversion factor that HEMCO applies will be written to the log file. If the unit conversion factor is not 1.0, and you didn’t expect units to be converted, then that indicates an error.

Other unit pitfalls to check:

  • Negative or implausible totals right after adding a new file. Check the netCDF file for a _FillValue or missing_value attribute that doesn’t match what’s actually used as the fill value in the data. HEMCO does not always catch a mismatched fill value, which can then be summed into your emissions as a huge negative or positive number.

  • Only unitless scale factors. Tightening the unit tolerance to 0 while testing a new inventory will cause HEMCO to halt on any units mismatch instead of generating warnings.

See the full HEMCO units reference for the complete list of recognized unit strings and for more unit conversion examples.

Category and hierarchy (Cat / Hier)

Cat and Hier only matter for Base Emissions (ExtNr = 0) entries, and only if you want to combine your new field with (or have it override) an existing inventory.

  • Category (Cat) groups independent emission sources that should be added together (e.g. anthropogenic, biofuel, biomass burning. etc. are typically different categories).

  • Hierarchy (Hier) ranks fields within the same category. A higher hierarchy value overrides a lower one, but only inside the new field’s own spatial mask. This is how a fine-resolution regional inventory (high hierarchy) can override a coarse global inventory (low hierarchy) only within the region it covers, while the global inventory still applies everywhere else.

If you’re not sure what category/hierarchy an existing inventory uses, then:

  • Set Verbose to true, and run a short (~1 hour) simulation. The category and hierarchy of each emissions entry read by HEMCO will be reflected in the logfile.

  • Search for the category/hierarchy values in each of the emission field entries in HEMCO_Config.rc that you wish to replace with your own emissions. Then use those same category/hierarchy values when you swap in your own emissions.

Worked example: replacing one species’ source

Here is how you can replace a default emissions for a species with an emissions field from your own inventory:

  1. Find the existing Base Emissions entries for the species that you wish to replace:

    (((XIAO_C3H8
    0 XIAO_C3H8  $ROOT/XIAO/v2014-09/C3H8_C2H6_ngas.geos.1x1.nc  C3H8  1985/1/1/0 C xy kgC/m2/s C3H8 6/7/26/22 1 5
    )))
    

    The brackets allow the emissions entry to be toggled on and off in the Extension Switches section of HEMCO_Config.rc.

  2. Add a new entry for your inventory. Edit sourceFile and sourceVar to point at your replacement data:

    (((MY_ANTHRO_C3H8
    0 MY_C3H8  $ROOT/MY_ANTHRO_C3H8/v2024-01/c3h8_$YYYY.nc  C3H8  2015-2026/1-12/1/0 C xy kg/m2/s C2H6 - 1 5
    )))
    
  3. (Optional) Add a scale factor under the Scale Factors section of HEMCO_Config.rc and reference its ID number in the ScalIDs column.

  4. Disable the old emissions inventory and enable your new inventory. This will prevent double-counting emissions.

    ###############################################################################
    ### BEGIN SECTION EXTENSION SWITCHES
    ###############################################################################
    # ExtNr ExtName                on/off  Species  Years avail.
    0       Base                   : on    *
    ...
        --> XIAO_C3H8              :       false    # 1985
        --> MY_ANTHRO_C3H8         :       true     # 2015-2026
    ...
    
  5. Update HEMCO_Diagn.rc so that the diagnostic output reflects the swap.

Wiring your new field into HEMCO_Diagn.rc

Adding a Base Emissions entry does not automatically create a diagnostic for it. You must separately update HEMCO_Diagn.rc with the combination of species/extension/category/hierarchy to sum into each diagnostic output variable.

Important

GCHP users: For each diagnostic entry in HEMCO_Diagn.rc, you must also make a corresponding entry in the Emissions collection of HISTORY.rc. This is because GCHP relies upon the MAPL HISTORY component to archive diagnostic data. If you forget to update HISTORY.rc, then your HEMCO diagnostic output will not be saved to disk. Please see GCHP vs. GC-Classic usage differences for more information.

For example, this HEMCO_Diagn.rc entry:

# Name            Spec ExtNr  Cat Hier Dim Unit     LongName
EmisC3H8_Total    C3H8 -1     -1  -1   2   kg/m2/s  C3H8_emission_flux_from_all_sectors

will result in this behavior:

Setting

Value

Behavior

ExtNr

-1

Sums C3H8 emissions over all extensions. This not only includes the Base Emissions (ExtNr = 0) but also any HEMCO extensions (e.g. MEGAN) that have been activated.

Cat

-1

Sums C3H8 emissions over all categories. This will sum together anthropogenic, biomass, biogenic emissions. etc.

Hier

-1

Sums C3H8 emissions over all hierarchies.

Thus, if you wish to obtain the absolute total emissions of a given species, it is OK to use ExtNr = -1, Cat = -1 and Hier = -1. But if you wish to obtain a sectoral total, you should explicitly specify the ExtNr, Cat and Hier values.

For example, here is how you can add an entry to obtain anthropogenic emissions of C3H8 from the example inventory in the previous section:

# Name            Spec ExtNr  Cat Hier Dim Unit     LongName
EmisC3H8_Anthro   C3H8  0      1   5   2   kg/m2/s  C3H8_emission_flux_from_anthropogenic_sources

which will result in the following behavior:

Setting

Value

Behavior

ExtNr

0

Sums C3H8 emissions only from the Base Emissions (ExtNr = 0). This will only include the emissions that we have read from disk and not any extensions.

Cat

1

Sums C3H8 emissions only from Cat = 1, which specifies anthropogenic emissions. This matches the category in the example above.

Hier

5

Sums C3H8 emissions only from Hier = 5. This matches the hierarchy in the example above.

If you’re not sure what ExtNr, Cat, and Hier your HEMCO_Diagn.rc entry actually uses, set Verbose to true (under Settings in HEMCO_Config.rc and run a short (~1 hour) test simulation. The HEMCO log file will contain exactly what was read for each container, which you can then match against your diagnostic definition.

Validating your new emissions

Before trusting a new inventory in a full simulation:

  1. Check the raw file with ncdump -cts (or ncview) to confirm the variable name, units attribute, fill value, and number of vertical levels match what you put in HEMCO_Config.rc.

  2. Run a short test simulation (~1 hour) with Verbose: true and inspect the HEMCO log for the container name, unit conversion factor, and ExtNr/Cat/Hier that were actually assigned.

  3. Compare total mass between your input file and the corresponding HEMCO_diagnostics.*.nc output (e.g. with cdo fldsum or a quick GCPy/xarray script) for a single time step, to catch unit or regridding errors before running a full simulation.

  4. Watch for cross-resolution surprises: HEMCO regrids conservatively (preserving the weighted global average), so a coarse- or fine-resolution run’s total mass from the same file should match; if it doesn’t, suspect a masking or category/hierarchy overlap issue rather than regridding itself.

Quick-reference troubleshooting

Symptom

Likely cause

See

Emissions all show up at the surface level only

Wrong SrcDim (e.g. xy used for data that needed xyz or xyL* + a scale factor)

Getting SrcDim right (2-D vs. 3-D data)

“Cannot find field”, “Not enough time slices”, “Time stamps may be wrong”

C/R/E flag or date range doesn’t match the file

Time cycle flags (C/R/E) – which to pick

HEMCO Error: Cannot find field

Emissions are a suspicious multiple (e.g. ~2x) too high/low, or negative, with no error message

Species-mass vs. carbon-mass mismatch, or an unrecognized fill value

Units: A source of silent errors

New field runs fine but the diagnostic output is zero, mismatched, or double-counted

ExtNr/Cat/Hier in HEMCO_Diagn.rc don’t match (or are left at -1)

Wiring your new field into HEMCO_Diagn.rc

New regional inventory doesn’t override the global one where expected (or overrides it everywhere)

Hier too low, or mask boundaries not restricting the field as expected

Category and hierarchy (Cat / Hier)

New field has no effect at all under GCHP

Forgot to add the file to ExtData.rc – GCHP ignores HEMCO_Config.rc’s file-I/O columns

GCHP vs. GC-Classic usage differences

New field runs and diagnoses correctly, but never appears in output files under GCHP

Emissions diagnostics in GCHP must also be listed in HISTORY.rc, not just HEMCO_Diagn.rc

GCHP vs. GC-Classic usage differences

Wiring your new field into HEMCO_Diagn.rc