Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable additional emissions types #16

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions hypatia/analysis/postprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,25 @@
"lines_decomisioning_cost": {"index": "years", "var": "results.cost_decom_line"},
}


import pandas as pd
import numpy as np
from hypatia.utility.utility import get_emission_types
import os

def get_result_map(glob_mapping):
result_map = RESULT_MAP.copy()
emission_types = get_emission_types(glob_mapping)
for emission_type in emission_types:
result_map["{}_emission_cost".format(emission_type)] = {
"index": "years",
"var": "results.emission_cost_by_type['{}']".format(emission_type)
}
result_map["{}_emission".format(emission_type)] = {
"index": "years",
"var": "results.emission_by_type['{}']".format(emission_type)
}
return result_map


def dict_to_csv(Dict, path):
"""Writes nested dicts to csv"""
Expand Down Expand Up @@ -80,7 +94,7 @@ def set_DataFrame(

vars_frames = {}

for item, info in RESULT_MAP.items():
for item, info in get_result_map(glob_mapping).items():
try:
var = eval(info["var"])
except (KeyError, AttributeError):
Expand Down
21 changes: 11 additions & 10 deletions hypatia/backend/Build.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
annual_activity,
get_regions_with_storage,
storage_max_flow,
get_emission_types,
)
from hypatia.backend.constraints.ConstraintList import CONSTRAINTS
import logging
Expand All @@ -38,8 +39,8 @@
"totalcapacity",
"cost_fix_tax",
"cost_fix_sub",
"emission_cost",
"CO2_equivalent",
"emission_cost_by_type",
"emission_by_type",
"demand",
]

Expand Down Expand Up @@ -186,10 +187,10 @@ def _set_regional_objective_planning(self):
self.inv_allregions += self.vars.cost_inv_fvalue[reg][ctgry]

if ctgry != "Transmission" and ctgry != "Storage":

totalcost_regional += cp.sum(
self.vars.emission_cost[reg][ctgry], axis=1
)
for emission_type in get_emission_types(self.model_data.settings.global_settings):
totalcost_regional += cp.sum(
self.vars.emission_cost_by_region[reg][emission_type][ctgry], axis=1
)

discount_factor = (
1 + self.model_data.regional_parameters[reg]["discount_rate"]["Annual Discount Rate"].values
Expand Down Expand Up @@ -222,10 +223,10 @@ def _set_regional_objective_operation(self):
)

if ctgry != "Transmission" and ctgry != "Storage":

totalcost_regional += cp.sum(
self.vars.emission_cost[reg][ctgry], axis=1
)
for emission_type in get_emission_types(self.model_data.settings.global_settings):
totalcost_regional += cp.sum(
self.vars.emission_cost_by_region[reg][emission_type][ctgry], axis=1
)

self.totalcost_allregions += totalcost_regional

Expand Down
25 changes: 20 additions & 5 deletions hypatia/backend/ModelSettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
check_carrier_type,
check_years_mode_consistency,
)
from hypatia.utility.utility import create_technology_columns
from hypatia.utility.utility import (
create_technology_columns,
get_emission_types,
)
from hypatia.backend.constraints.ConstraintList import CONSTRAINTS

class ModelSettings:
Expand Down Expand Up @@ -374,6 +377,18 @@ def regional_parameters_template(self) -> Optional[Dict]:
additional_level=("Taxes or Subsidies", ["Tax", "Sub"])
)

specific_emission_indexer = create_technology_columns(
self.technologies[reg],
ignored_tech_categories=["Demand"],
additional_level=("Emission Type", get_emission_types(self.global_settings))
)

carbon_tax_indexer = create_technology_columns(
self.technologies[reg],
ignored_tech_categories=["Demand", "Storage", "Transmission"],
additional_level=("Emission Type", get_emission_types(self.global_settings))
)

regional_parameters_template[reg] = {
"tech_fixed_cost": {
"sheet_name": "F_OM",
Expand Down Expand Up @@ -403,13 +418,13 @@ def regional_parameters_template(self) -> Optional[Dict]:
"sheet_name": "Specific_emission",
"value": 0,
"index": pd.Index(self.years, name="Years"),
"columns": indexer_reg_drop2,
"columns": specific_emission_indexer,
},
"carbon_tax": {
"sheet_name": "Carbon_tax",
"emission_tax": {
"sheet_name": "Emission_tax",
"value": 0,
"index": pd.Index(self.years, name="Years"),
"columns": indexer_reg_drop2,
"columns": carbon_tax_indexer,
},
"fix_taxsub": {
"sheet_name": "Fix_taxsub",
Expand Down
53 changes: 29 additions & 24 deletions hypatia/backend/ModelVariables.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import cvxpy as cp
import itertools as it
from hypatia.utility.utility import *
from collections import defaultdict

class ModelVariables():
def __init__(self, model_data: ModelData):
Expand Down Expand Up @@ -157,8 +158,6 @@ def _calc_variable_planning(self):
self.decommissioned_capacity = {}
self.cost_decom = {}
self.cost_variable = {}
self.CO2_equivalent = {}
self.emission_cost = {}
self.production_annual = {}

for reg in self.model_data.settings.regions:
Expand Down Expand Up @@ -597,31 +596,37 @@ def _balance_(self):


def _calc_emission_variables(self):
self.CO2_equivalent = {}
self.emission_cost = {}
self.regional_emission = {}
self.emission_by_region = {}
self.emission_cost_by_region = {}
self.emission_by_type = {}
self.emission_cost_by_type = {}

for reg in self.model_data.settings.regions:
CO2_equivalent_regional = {}
emission_cost_regional = {}
emission = np.zeros(
(len(self.model_data.settings.years) * len(self.model_data.settings.time_steps), 1)
)
emissions_regional = defaultdict(dict)
emission_cost_regional = defaultdict(dict)
for key in self.model_data.settings.technologies[reg].keys():
if key == "Demand" or key == "Transmission" or key == "Storage":
continue

CO2_equivalent_regional[key] = cp.multiply(
self.production_annual[reg][key],
self.model_data.regional_parameters[reg]["specific_emission"].loc[:, key],
)

emission_cost_regional[key] = cp.multiply(
CO2_equivalent_regional[key],
self.model_data.regional_parameters[reg]["carbon_tax"].loc[:, key],
)

emission += cp.sum(CO2_equivalent_regional[key], axis=1)
for emission_type in get_emission_types(self.model_data.settings.global_settings):
emissions_regional[emission_type][key] = cp.multiply(
self.production_annual[reg][key],
self.model_data.regional_parameters[reg]["specific_emission"][emission_type].loc[:, key],
)

self.CO2_equivalent[reg] = CO2_equivalent_regional
self.emission_cost[reg] = emission_cost_regional
self.regional_emission[reg] = emission
emission_cost_regional[emission_type][key] = cp.multiply(
emissions_regional[emission_type][key],
self.model_data.regional_parameters[reg]["emission_tax"][emission_type].loc[:, key],
)
self.emission_by_region[reg] = emissions_regional
self.emission_cost_by_region[reg] = emission_cost_regional

self.emission_by_type = self.flip_keys(self.emission_by_region)
self.emission_cost_by_type = self.flip_keys(self.emission_cost_by_region)

def flip_keys(self, d):
result = defaultdict(dict)
for key, value in d.items():
for k, v in value.items():
result[k][key] = v
return result
38 changes: 23 additions & 15 deletions hypatia/backend/constraints/EmissionCapGlobal.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
ModelMode,
TopologyType
)
import numpy as np
from hypatia.utility.utility import get_emission_types
import pandas as pd

import numpy as np
import cvxpy as cp

"""
Defines the CO2 emission cap across all regions
Expand All @@ -14,27 +15,34 @@ class EmissionCapGlobal(Constraint):
TOPOLOGY_TYPES = [TopologyType.MultiNode]

def _check(self):
assert hasattr(self.variables, "regional_emission"), "regional_emission must be defined"
assert hasattr(self.variables, "emission_by_region"), "emission_by_region must be defined"

def rules(self):
global_emission = np.zeros(
(len(self.model_data.settings.years) * len(self.model_data.settings.time_steps), 1)
)
for reg in self.model_data.settings.regions:
global_emission += self.variables.regional_emission[reg]

global_emission_cap = self.model_data.global_parameters[
"global_emission_cap_annual"
].values
global_emission_cap.shape = global_emission.shape
return [global_emission_cap - global_emission >= 0]
rules = []
for emission_type in get_emission_types(self.model_data.settings.global_settings):
global_emission = np.zeros(
(len(self.model_data.settings.years) * len(self.model_data.settings.time_steps), 1)
)
for reg in self.model_data.settings.regions:
for key, value in self.variables.emission_by_region[reg][emission_type].items():
global_emission += cp.sum(value, axis=1)
global_emission_cap = self.model_data.global_parameters[
"global_emission_cap_annual"
]["{} Global Emission Cap".format(emission_type)].values
global_emission_cap.shape = global_emission.shape
rules.append(global_emission_cap - global_emission >= 0)
return rules

def _required_global_parameters(settings):
return {
"global_emission_cap_annual": {
"sheet_name": "Glob_emission_cap_annual",
"value": 1e30,
"index": pd.Index(settings.years, name="Years"),
"columns": pd.Index(["Global Emission Cap"]),
"columns": pd.Index(
[emission_type + " Global Emission Cap" for emission_type in get_emission_types(
settings.global_settings
)]
),
},
}
31 changes: 21 additions & 10 deletions hypatia/backend/constraints/EmissionCapRegional.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,32 @@
ModelMode,
TopologyType
)
from hypatia.utility.utility import get_emission_types
import pandas as pd
import numpy as np
import cvxpy as cp

"""
Defines the CO2 emission cap within each region
"""
class EmissionCapRegional(Constraint):
def _check(self):
assert hasattr(self.variables, "regional_emission"), "regional_emission must be defined"
assert hasattr(self.variables, "CO2_equivalent"), "regional_emission must be defined"
assert hasattr(self.variables, "emission_by_region"), "emission_by_region must be defined"

def rules(self):
rules = []
for reg in self.model_data.settings.regions:
for key, value in self.variables.CO2_equivalent[reg].items():
emission_cap = self.model_data.regional_parameters[reg]["emission_cap_annual"].values
emission_cap.shape = self.variables.regional_emission[reg].shape

rules.append(emission_cap - self.variables.regional_emission[reg] >= 0)

for emission_type in get_emission_types(self.model_data.settings.global_settings):
for reg in self.model_data.settings.regions:
regional_emission = np.zeros(
(len(self.model_data.settings.years) * len(self.model_data.settings.time_steps), 1)
)
for key, value in self.variables.emission_by_region[reg][emission_type].items():
regional_emission += cp.sum(value, axis=1)
emission_cap = self.model_data.regional_parameters[reg]["emission_cap_annual"][
"{} Global Cap".format(emission_type)
].values
emission_cap.shape = regional_emission.shape
rules.append(emission_cap - regional_emission >= 0)
return rules

def _required_regional_parameters(settings):
Expand All @@ -32,7 +39,11 @@ def _required_regional_parameters(settings):
"sheet_name": "Emission_cap_annual",
"value": 1e10,
"index": pd.Index(settings.years, name="Years"),
"columns": pd.Index(["Emission Cap"]),
"columns": pd.Index(
[emission_type + " Global Cap" for emission_type in get_emission_types(
settings.global_settings
)]
),
},
}

Expand Down
Loading