Skip to content

Commit

Permalink
changes from code review
Browse files Browse the repository at this point in the history
  • Loading branch information
samgdotson committed Jan 14, 2025
1 parent 4a9cf2e commit 0e59b00
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 23 deletions.
15 changes: 10 additions & 5 deletions osier/models/capacity_expansion.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

LARGE_NUMBER = 1e20

dispatch_models = {'lp': DispatchModel,
'hierarchical': LogicDispatchModel,
'logical': LogicDispatchModel,
'rule_based': LogicDispatchModel}
dispatch_models = {
'optimal':DispatchModel,
'logical': LogicDispatchModel
}


class CapacityExpansion(ElementwiseProblem):
Expand Down Expand Up @@ -77,6 +77,11 @@ class CapacityExpansion(ElementwiseProblem):
Indicates which solver to use. May require separate installation.
Accepts: ['cplex', 'cbc', 'glpk']. Other solvers will be added in the
future.
model_engine : str
Determines which dispatch algorithm to use.
Accepts: ['optimal', 'logical'] where 'optimal' will use a linear
program and 'logical' will use a myopic rule-based approach.
Default is 'optimal'.
Notes
-----
Expand All @@ -103,7 +108,7 @@ def __init__(self,
allow_blackout=False,
verbosity=50,
solver='cbc',
model_engine='lp',
model_engine='optimal',
**kwargs):
self.technology_list = deepcopy(technology_list)
self.demand = demand
Expand Down
1 change: 0 additions & 1 deletion osier/models/logic_dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ def _calculate_objective(self):
def solve(self):
"""
This function executes the model solve with a rule-based approach.
Net demand is copied, then the technology histories are reset.
"""
self.covered_demand = self.net_demand.copy()
self._reset_all()
Expand Down
4 changes: 2 additions & 2 deletions osier/tech_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pandas as pd
from osier.technology import *
from osier.technology import _dim_opts
from unyt import GW, MW, kW, hour, day, year, kg
from unyt import GW, MW, kW, hour, day, year, kg, MWh
import unyt as u

to_MDOLLARS = 1e-6
Expand Down Expand Up @@ -96,7 +96,7 @@
fuel_cost=0*to_MDOLLARS,
storage_duration=4,
efficiency=0.85,
initial_storage=0.0*MW*hr,
initial_storage=0.0*MWh,
capacity_credit=0.5,
lifecycle_co2_rate=3.3e-5*co2_eq_units,
land_intensity=0.0,
Expand Down
78 changes: 63 additions & 15 deletions osier/technology.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,38 +329,30 @@ def __ge__(self, tech) -> bool:
"""Tests greater or equal to."""
if (self.variable_cost == tech.variable_cost):
return self.efficiency >= tech.efficiency
elif self.variable_cost >= tech.variable_cost:
return True
else:
return False
return self.variable_cost >= tech.variable_cost

def __le__(self, tech) -> bool:
"""Tests greater or equal to."""
"""Tests less or equal to."""
if (self.variable_cost == tech.variable_cost):
return self.efficiency <= tech.efficiency
elif self.variable_cost <= tech.variable_cost:
return True
else:
return False
return self.variable_cost <= tech.variable_cost

def __lt__(self, tech) -> bool:
"""Tests greater or equal to."""
"""Tests less than."""
if (self.variable_cost == tech.variable_cost):
return self.efficiency < tech.efficiency
elif self.variable_cost < tech.variable_cost:
return True
else:
return False
return self.variable_cost < tech.variable_cost

def __gt__(self, tech) -> bool:
"""Tests greater or equal to."""
"""Tests greater than."""

if (self.variable_cost == tech.variable_cost):
return self.efficiency > tech.efficiency
elif self.variable_cost > tech.variable_cost:
return True
else:
return False
return self.variable_cost > tech.variable_cost

@property
def unit_power(self):
Expand Down Expand Up @@ -641,6 +633,11 @@ def power_output(self,
demand : :class:`unyt.unyt_quantity`
The demand at a particular timestep. Must be a :class:`unyt.unyt_quantity`
to avoid ambiguity.
Returns
-------
power_level : :class:`unyt.unyt_quantity`
The current power level of the technology.
"""
assert isinstance(demand, unyt_quantity)
self.power_level = max(0 * demand.units, min(demand, self.capacity))
Expand Down Expand Up @@ -721,6 +718,11 @@ def max_power(self, time_delta: unyt_quantity = 1 * hr):
----------
time_delta : :class:`unyt.unyt_quantity`
The difference between two timesteps. Default is one hour.
Returns
-------
max_power : :class:`unyt.unyt_quantity`
The maximum achievable power level.
"""

output = self.power_level + self.ramp_up * time_delta
Expand All @@ -735,6 +737,11 @@ def min_power(self, time_delta: unyt_quantity = 1 * hr):
----------
time_delta : :class:`unyt.unyt_quantity`
The difference between two timesteps. Default is one hour.
Returns
-------
max_power : :class:`unyt.unyt_quantity`
The maximum achievable power level.
"""

output = self.power_level - self.ramp_down * time_delta
Expand All @@ -756,6 +763,11 @@ def power_output(self,
to avoid ambiguity.
time_delta : :class:`unyt.unyt_quantity`
The difference between two timesteps. Default is one hour.
Returns
-------
power_level : :class:`unyt.unyt_quantity`
The current power level of the technology.
"""

assert isinstance(demand, unyt_quantity)
Expand Down Expand Up @@ -875,7 +887,21 @@ def reset_history(self):
self.charge_history = []

def discharge(self, demand: unyt_quantity, time_delta=1 * hr):
"""
Discharges the battery if there is a surplus of energy.
Parameters
----------
demand : :class:`unyt.unyt_quantity`
Amount of surplus.
time_delta : :class:`unyt.unyt_quantity`
The real time passed between modeled timesteps.
Returns
-------
power_level : :class:`unyt.unyt_quantity`
The current power level of the technology.
"""
# check that the battery has power to discharge fully.
power_out = max(0 * demand.units, min(demand, self.capacity))

Expand All @@ -891,7 +917,21 @@ def discharge(self, demand: unyt_quantity, time_delta=1 * hr):
return self.power_level.to(demand.units)

def charge(self, surplus, time_delta=1 * hr):
"""
Charges the battery if there is a surplus of energy.
Parameters
----------
surplus : :class:`unyt.unyt_quantity`
Amount of surplus.
time_delta : :class:`unyt.unyt_quantity`
The real time passed between modeled timesteps.
Returns
-------
power_level : :class:`unyt.unyt_quantity`
The current power level of the technology.
"""
# check that the battery has enough power to consume surplus.
power_in = min(np.abs(min(0 * surplus.units, surplus)), self.capacity)

Expand All @@ -908,6 +948,14 @@ def charge(self, surplus, time_delta=1 * hr):
return self.power_level.to(surplus.units)

def power_output(self, v, time_delta=1 * hr):
"""
Calculates the power output given a demand value.
Returns
-------
output : :class:`unyt.unyt_quantity`
The current power level of the technology.
"""
if v >= 0:
output = self.discharge(demand=v, time_delta=time_delta)
else:
Expand Down

0 comments on commit 0e59b00

Please sign in to comment.