Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
"""
if tech in getattr(backend_model, 'techs_transmission_names', []):
all_loc_techs = [
i for i in backend_model.loc_techs_transmission
if i.split('::')[1].split(':')[0] == tech
]
multiplier = 2 # there are always two technologies associated with one link
else:
all_loc_techs = [
i for i in backend_model.loc_techs
if i.split('::')[1] == tech
]
multiplier = 1
max_systemwide = get_param(backend_model, 'units_max_systemwide', tech)
equals_systemwide = get_param(backend_model, 'units_equals_systemwide', tech)
if np.isinf(po.value(max_systemwide)) and not equals_systemwide:
return po.Constraint.NoConstraint
elif equals_systemwide and np.isinf(po.value(equals_systemwide)):
raise ValueError(
'Cannot use inf for energy_cap_equals_systemwide for tech `{}`'.format(tech)
)
sum_expr_units = sum(
backend_model.units[loc_tech] for loc_tech in all_loc_techs
if loc_tech_is_in(backend_model, loc_tech, 'loc_techs_milp')
)
sum_expr_purchase = sum(
backend_model.purchased[loc_tech] for loc_tech in all_loc_techs
if loc_tech_is_in(backend_model, loc_tech, 'loc_techs_purchase')
def get_capacity_constraint(backend_model, parameter, loc_tech,
_equals=None, _max=None, _min=None, scale=None):
decision_variable = getattr(backend_model, parameter)
if not _equals:
_equals = get_param(backend_model, parameter + '_equals', loc_tech)
if not _max:
_max = get_param(backend_model, parameter + '_max', loc_tech)
if not _min:
_min = get_param(backend_model, parameter + '_min', loc_tech)
if po.value(_equals) is not False and po.value(_equals) is not None:
if np.isinf(po.value(_equals)):
e = exceptions.ModelError
raise e('Cannot use inf for {}_equals for loc:tech `{}`'.format(parameter, loc_tech))
if scale:
_equals *= scale
return decision_variable[loc_tech] == _equals
else:
if po.value(_min) == 0 and np.isinf(po.value(_max)):
return po.Constraint.NoConstraint
else:
if scale:
.. math::
\\boldsymbol{storage_{inter\\_cluster}}(loc::tech, datestep) =
\\boldsymbol{storage_{inter\\_cluster}}(loc::tech, datestep_{previous})
\\times (1 - storage\\_loss(loc::tech, timestep))^{24}
+ \\boldsymbol{storage}(loc::tech, timestep_{final, cluster(datestep))})
\\quad \\forall loc::tech \\in loc::techs_{store}, \\forall datestep \\in datesteps
Where :math:`timestep_{final, cluster(datestep_{previous}))}` is the final timestep of the
cluster in the clustered timeseries corresponding to the previous day
"""
run_config = backend_model.__calliope_run_config
current_datestep = backend_model.datesteps.order_dict[datestep]
if current_datestep == 0 and not run_config['cyclic_storage']:
storage_previous_step = get_param(backend_model, 'storage_initial', loc_tech)
storage_intra = 0
else:
if current_datestep == 0 and run_config['cyclic_storage']:
previous_step = backend_model.datesteps[-1]
else:
previous_step = get_previous_timestep(backend_model.datesteps, datestep)
storage_loss = get_param(backend_model, 'storage_loss', loc_tech)
storage_previous_step = (
((1 - storage_loss) ** 24) *
backend_model.storage_inter_cluster[loc_tech, previous_step]
)
final_timestep = (
backend_model.__calliope_model_data
['data']['lookup_datestep_last_cluster_timestep'][previous_step]
)
storage_intra = backend_model.storage[loc_tech, final_timestep]
energy_eff = get_param(backend_model, 'energy_eff', (loc_tech, timestep))
carrier_prod = []
for loc_tech_carrier in loc_tech_carriers_out:
carrier_ratio = get_param(
backend_model, 'carrier_ratios', ('out', loc_tech_carrier, timestep)
)
if po.value(carrier_ratio) != 0:
carrier_prod.append(
backend_model.carrier_prod[loc_tech_carrier, timestep] / carrier_ratio
)
carrier_con = sum(
backend_model.carrier_con[loc_tech_carrier, timestep] *
get_param(backend_model, 'carrier_ratios', ('in', loc_tech_carrier, timestep))
for loc_tech_carrier in loc_tech_carriers_in
)
return sum(carrier_prod) == -1 * carrier_con * energy_eff
.. math::
\\boldsymbol{carrier_{export}}(loc::tech::carrier, timestep)
\\leq export_{cap}(loc::tech) \\times
\\boldsymbol{operating_{units}}(loc::tech, timestep)
"""
loc_tech = get_loc_tech(loc_tech_carrier)
if loc_tech_is_in(backend_model, loc_tech, 'loc_techs_milp'):
operating_units = backend_model.operating_units[loc_tech, timestep]
else:
operating_units = 1
export_cap = get_param(backend_model, 'export_cap', loc_tech)
return (backend_model.carrier_export[loc_tech_carrier, timestep] <=
export_cap * operating_units)
\\boldsymbol{cost_{var}}(cost, loc::tech, timestep) +=
cost_{export}(cost, loc::tech, timestep) \\times
\\boldsymbol{carrier_{export}}(loc::tech::carrier, timestep)
* timestep_{weight} \\quad \\forall cost \\in costs,
\\forall loc::tech \\in loc::techs_{cost_{var}, export},
\\forall timestep \\in timesteps
"""
model_data_dict = backend_model.__calliope_model_data['data']
loc_tech_carrier = model_data_dict['lookup_loc_techs_export'][(loc_tech)]
weight = backend_model.timestep_weights[timestep]
cost_export = (
get_param(backend_model, 'cost_export', (cost, loc_tech, timestep))
* backend_model.carrier_export[loc_tech_carrier, timestep]
* weight
)
backend_model.cost_var_rhs[cost, loc_tech, timestep].expr += cost_export
The sum constraint ensures that all decision shares add up to the share of
carrier demand specified in the constraint.
This constraint is only applied if the share of carrier demand has been
set to a not-None value.
.. container:: scrolling-wrapper
.. math::
share = \\sum_{loc::tech::carrier \\in given\\_group}
demand\\_share\\_per\\_timestep\\_decision(loc::tech::carrier)
"""
share_of_carrier_demand = get_param(backend_model, 'group_demand_share_per_timestep_decision', (carrier, group_name))
# If inf was given that means that we don't limit the total share
if share_of_carrier_demand is None or np.isinf(share_of_carrier_demand):
return return_noconstraint('demand_share_per_timestep_decision_sum', group_name)
else:
lhs_loc_tech_carriers, _ = get_demand_share_lhs_and_rhs_loc_tech_carriers(
backend_model, group_name, carrier
)
return share_of_carrier_demand == sum(
backend_model.demand_share_per_timestep_decision[loc_tech_carrier]
for loc_tech_carrier in lhs_loc_tech_carriers
)
.. container:: scrolling-wrapper
.. math::
available\\_resource(loc::tech, timestep) = resource(loc::tech, timestep)
\\times resource\\_scale(loc::tech) \\times \\boldsymbol{resource_{area}}(loc::tech)
"""
model_data_dict = backend_model.__calliope_model_data['data']
resource = get_param(backend_model, 'resource', (loc_tech, timestep))
energy_eff = get_param(backend_model, 'energy_eff', (loc_tech, timestep))
resource_scale = get_param(backend_model, 'resource_scale', loc_tech)
force_resource = get_param(backend_model, 'force_resource', loc_tech)
loc_tech_carrier = model_data_dict['lookup_loc_techs'][loc_tech]
min_use = get_param(backend_model, 'resource_min_use', (loc_tech, timestep))
resource_unit = get_param(backend_model, 'resource_unit', loc_tech)
if po.value(energy_eff) == 0:
return backend_model.carrier_prod[loc_tech_carrier, timestep] == 0
else:
carrier_prod = backend_model.carrier_prod[loc_tech_carrier, timestep] / energy_eff
if po.value(resource_unit) == 'energy_per_area':
available_resource = resource * resource_scale * backend_model.resource_area[loc_tech]
elif po.value(resource_unit) == 'energy_per_cap':
available_resource = resource * resource_scale * backend_model.energy_cap[loc_tech]
else:
available_resource = resource * resource_scale
if po.value(force_resource):
return carrier_prod == available_resource
def get_capacity_constraint(backend_model, parameter, loc_tech,
_equals=None, _max=None, _min=None, scale=None):
decision_variable = getattr(backend_model, parameter)
if not _equals:
_equals = get_param(backend_model, parameter + '_equals', loc_tech)
if not _max:
_max = get_param(backend_model, parameter + '_max', loc_tech)
if not _min:
_min = get_param(backend_model, parameter + '_min', loc_tech)
if po.value(_equals) is not False and po.value(_equals) is not None:
if np.isinf(po.value(_equals)):
e = exceptions.ModelError
raise e('Cannot use inf for {}_equals for loc:tech `{}`'.format(parameter, loc_tech))
if scale:
_equals *= scale
return decision_variable[loc_tech] == _equals
else:
if po.value(_min) == 0 and np.isinf(po.value(_max)):
return po.Constraint.NoConstraint
else:
if scale:
_max *= scale
_min *= scale
\\times resource_{scale}(loc::tech)
if :math:`loc::tech` is in :math:`loc::techs_{area}`:
.. container:: scrolling-wrapper
.. math::
available\\_resource(loc::tech, timestep) = resource(loc::tech, timestep)
\\times resource_{scale}(loc::tech)
\\times resource_{area}(loc::tech)
"""
resource = get_param(backend_model, 'resource', (loc_tech, timestep))
resource_scale = get_param(backend_model, 'resource_scale', loc_tech)
force_resource = get_param(backend_model, 'force_resource', loc_tech)
resource_unit = get_param(backend_model, 'resource_unit', loc_tech)
if po.value(resource_unit) == 'energy_per_area':
available_resource = resource * resource_scale * backend_model.resource_area[loc_tech]
elif po.value(resource_unit) == 'energy_per_cap':
available_resource = resource * resource_scale * backend_model.energy_cap[loc_tech]
else:
available_resource = resource * resource_scale
if po.value(force_resource):
return backend_model.resource_con[loc_tech, timestep] == available_resource
else:
return backend_model.resource_con[loc_tech, timestep] <= available_resource