Skip to content

Capacity|Electricity is over-estimated when desired_regions is a subset of regions #79

Description

@jiheunha

When generate_report() is run with a subset of regions via desired_regions, the resulting Capacity|Electricity|* values for the selected regions are inflated by roughly 7x–60x compared to the same region in an all-regions run. Running with desired_regions = "All" gives correct, realistic capacities.

Observed behavior

Same single scenario, same region (South Korea), same GCAM_version = "v7.0", same database. The only difference is desired_regions. Values in GW, year 2020:

Variable desired_regions = "All" desired_regions = c("South Korea","Russia") ratio
Capacity|Electricity (total) 153.0 3091.3 20.2x
Capacity|Electricity|Coal 39.8 1139.7 28.6x
Capacity|Electricity|Gas 65.6 595.2 9.1x
Capacity|Electricity|Nuclear 22.9 162.7 7.1x
Capacity|Electricity|Solar 14.5 655.1 45.2x
Capacity|Electricity|Wind 3.4 199.3 58.2x

The "All" column matches real South Korea installed capacity well (≈150 GW total, ≈40 GW coal, ≈23 GW nuclear, ≈15 GW solar in 2020). The subset column is physically impossible. The inflation grows as fewer regions are selected.

Root cause

In get_cf_iea_tmp() (R/functions.R), the IEA-consistent capacity factor is

cf = EJ / (value * hr_per_yr * EJ_to_GWh)

where the numerator and denominator are computed at different region scopes:

  • Numerator EJ comes from secondary_energy_clean, summed by technology:

    tmp1 <- secondary_energy_clean %>%
      dplyr::filter(year == base_year_p, scenario == unique(secondary_energy_clean$scenario)[1]) %>%
      dplyr::group_by(var) %>%
      dplyr::summarise(EJ = sum(value, na.rm = T))

    secondary_energy_clean only contains the regions present in the project, so when desired_regions is a subset this sum is the generation of only those regions.

  • Denominator value comes from iea_capacity, which is provided only for region "World" (global installed capacity, region-independent and fixed):

    tmp2 <- iea_capacity %>%
      dplyr::filter(period == base_year_p, scenario == "Current Policies Scenario")

So selecting fewer regions shrinks the numerator (less generation) while the denominator stays at the global World capacity. cf_iea therefore comes out far too small, and since downstream capacity is generation / (cf * ...) (get_elec_capacity_tot()), the reported capacity explodes. The approximate inflation factor is (world generation) / (selected-region generation), which is consistent with the 7x–60x range above.

cf_iea is intended to be a single global (world-average) capacity factor, so the numerator must be world generation. With a region-filtered project, the world generation is simply not available, which is what breaks the calculation.

How to reproduce

# Correct
generate_report(db_path, db_name, scenarios = <scenario>,
                GCAM_version = "v7.0", desired_regions = "All",
                desired_variables = "Capacity*")

# Inflated — compare South Korea Capacity|Electricity between the two
generate_report(db_path, db_name, scenarios = <scenario>,
                GCAM_version = "v7.0", desired_regions = c("South Korea", "Russia"),
                desired_variables = "Capacity*")

Confirmed on v7.0. Because iea_capacity is World-only for every version, the
same scope mismatch should affect all GCAM versions.

Possible fixes

The proper fix is a design decision, so we would like your input before sending a PR:

  1. Compute the cf_iea numerator from global base-year generation regardless of desired_regions (e.g. always query/keep world secondary energy, or bundle a precomputed global base-year generation so cf_iea is region-independent by construction), or
  2. Restrict Capacity|Electricity to desired_regions = "All" and clearly document (and warn) that capacity is not valid for region subsets.

Happy to help with a PR if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions