def get_as_dense_by_bus_carrier(n, attr, comps=None, snapshots=None): snapshots = check_snapshots(snapshots, n) comps = check_one_port_comps(comps, n) buses_i = n.buses.index return xr.concat((reindex_by_bus_carrier( get_switchable_as_dense(n, c, attr, snapshots), c, n) for c in comps), dim='carrier').reindex(bus=buses_i, fill_value=0)
def assign_solution(network, snapshots, variables_sol, constraints_dual, extra_postprocessing): allocate_series_dataframes( network, { 'Generator': ['p'], 'Load': ['p'], 'StorageUnit': ['p', 'state_of_charge', 'spill'], 'Store': ['p', 'e'], 'Bus': ['p', 'v_ang', 'v_mag_pu', 'marginal_price'], 'Line': ['p0', 'p1', 'mu_lower', 'mu_upper'], 'Transformer': ['p0', 'p1', 'mu_lower', 'mu_upper'], 'Link': [ "p" + col[3:] for col in network.links.columns if col[:3] == "bus" ] + ['mu_lower', 'mu_upper'] }) def set_from_series(df, series): df.loc[snapshots] = series.unstack(0).reindex(columns=df.columns) if len(network.generators) > 0: start, finish = network.variable_positions.loc["Generator-p"] set_from_series( network.generators_t.p, pd.Series(data=variables_sol[start:finish].values, index=pd.MultiIndex.from_product( [network.generators.index, snapshots]))) if len(network.stores) > 0: start, finish = network.variable_positions.loc["Store-p"] set_from_series( network.stores_t.p, pd.Series(data=variables_sol[start:finish].values, index=pd.MultiIndex.from_product( [network.stores.index, snapshots]))) start, finish = network.variable_positions.loc["Store-e"] set_from_series( network.stores_t.e, pd.Series(data=variables_sol[start:finish].values, index=pd.MultiIndex.from_product( [network.stores.index, snapshots]))) if len(network.links) > 0: start, finish = network.variable_positions.loc["Link-p"] set_from_series( network.links_t.p0, pd.Series(data=variables_sol[start:finish].values, index=pd.MultiIndex.from_product( [network.links.index, snapshots]))) efficiency = get_switchable_as_dense(network, 'Link', 'efficiency', snapshots) network.links_t.p1.loc[ snapshots, network.links.index] = -network.links_t.p0.loc[ snapshots, network.links.index] * efficiency.loc[ snapshots, network.links.index] for i in [ int(col[3:]) for col in network.links.columns if col[:3] == "bus" and col not in ["bus0", "bus1"] ]: efficiency = get_switchable_as_dense(network, 'Link', 'efficiency{}'.format(i), snapshots) network.links_t["p" + str(i)].loc[ snapshots, network.links.index] = -network.links_t.p0.loc[ snapshots, network.links.index] * efficiency.loc[ snapshots, network.links.index] for c in network.iterate_components(network.passive_branch_components): start, finish = network.variable_positions.loc["{}-s".format(c.name)] set_from_series( c.pnl.p0, pd.Series(data=variables_sol[start:finish].values, index=pd.MultiIndex.from_product([c.df.index, snapshots]))) c.pnl.p1.loc[snapshots, c.df.index] = -c.pnl.p0.loc[snapshots, c.df.index] for component in ["Generator", "Link", "Store", "Line", "Transformer"]: df = getattr(network, network.components[component]["list_name"]) if component == "Store": attr = "e" elif component in ["Line", "Transformer"]: attr = "s" else: attr = "p" df[attr + "_nom_opt"] = df[attr + "_nom"] ext = df.index[df[attr + "_nom_extendable"]] if len(ext) > 0: start, finish = network.variable_positions.loc["{}-{}_nom".format( component, attr)] df.loc[ext, attr + "_nom_opt"] = variables_sol[start:finish].values #marginal prices if constraints_dual is not None: start, finish = network.constraint_positions.loc["nodal_balance"] set_from_series( network.buses_t.marginal_price, pd.Series(data=constraints_dual[start:finish].values, index=pd.MultiIndex.from_product( [network.buses.index, snapshots]))) #correct for snapshot weightings network.buses_t.marginal_price.loc[ snapshots] = network.buses_t.marginal_price.loc[snapshots].divide( network.snapshot_weightings.loc[snapshots], axis=0) if extra_postprocessing is not None: extra_postprocessing(network, snapshots, variables_sol)
def redo_passive_branch_constraints(network, snapshots): model_components_to_delete = [ "flow_upper", "flow_lower", "flow_upper_index", "flow_lower_index", "flow_upper_index_0", "flow_lower_index_0", "flow_upper_index_1", "flow_lower_index_1", ] for model_component in model_components_to_delete: network.model.del_component(model_component) passive_branches = network.passive_branches() extendable_branches = passive_branches[passive_branches.s_nom_extendable] fixed_branches = passive_branches[~passive_branches.s_nom_extendable] s_max_pu = pd.concat( { c: get_switchable_as_dense(network, c, "s_max_pu", snapshots) for c in network.passive_branch_components }, axis=1, sort=False, ) flow_upper = {(b[0], b[1], sn): [ [ (1, network.model.passive_branch_p[b[0], b[1], sn]), (1, network.model.loss[b[0], b[1], sn]), ], "<=", s_max_pu.at[sn, b] * fixed_branches.at[b, "s_nom"], ] for b in fixed_branches.index for sn in snapshots} flow_upper.update({(b[0], b[1], sn): [ [ (1, network.model.passive_branch_p[b[0], b[1], sn]), (1, network.model.loss[b[0], b[1], sn]), ( -s_max_pu.at[sn, b], network.model.passive_branch_s_nom[b[0], b[1]], ), ], "<=", 0, ] for b in extendable_branches.index for sn in snapshots}) l_constraint(network.model, "flow_upper", flow_upper, list(passive_branches.index), snapshots) flow_lower = {(b[0], b[1], sn): [ [ (1, network.model.passive_branch_p[b[0], b[1], sn]), (-1, network.model.loss[b[0], b[1], sn]), ], ">=", -s_max_pu.at[sn, b] * fixed_branches.at[b, "s_nom"], ] for b in fixed_branches.index for sn in snapshots} flow_lower.update({(b[0], b[1], sn): [ [ (1, network.model.passive_branch_p[b[0], b[1], sn]), (-1, network.model.loss[b[0], b[1], sn]), ( s_max_pu.at[sn, b], network.model.passive_branch_s_nom[b[0], b[1]], ), ], ">=", 0, ] for b in extendable_branches.index for sn in snapshots}) l_constraint(network.model, "flow_lower", flow_lower, list(passive_branches.index), snapshots)
def define_nodal_balance_constraints(network, snapshots): constraint_matrix = {} for i_bus, bus in enumerate(network.buses.index): i = i_bus * len(snapshots) for k in range(len(snapshots)): constraint_matrix[i + k] = {} for component in ["Generator", "Store"]: df = getattr(network, network.components[component]["list_name"]) for unit in df.index: bus = df.at[unit, "bus"] sign = df.at[unit, "sign"] i = network.buses.index.get_loc(bus) * len(snapshots) j = network.variable_positions.at[ "{}-p".format(component), "start"] + df.index.get_loc(unit) * len(snapshots) for k, sn in enumerate(snapshots): constraint_matrix[i + k][j + k] = sign efficiency = get_switchable_as_dense(network, 'Link', 'efficiency', snapshots) for link in network.links.index: bus0 = network.links.at[link, "bus0"] bus1 = network.links.at[link, "bus1"] i0 = network.buses.index.get_loc(bus0) * len(snapshots) i1 = network.buses.index.get_loc(bus1) * len(snapshots) j = network.variable_positions.at[ "Link-p", "start"] + network.links.index.get_loc(link) * len(snapshots) for k, sn in enumerate(snapshots): constraint_matrix[i0 + k][j + k] = -1. constraint_matrix[i1 + k][j + k] = efficiency.at[sn, link] #Add any other buses to which the links are attached for i in [ int(col[3:]) for col in network.links.columns if col[:3] == "bus" and col not in ["bus0", "bus1"] ]: efficiency = get_switchable_as_dense(network, 'Link', 'efficiency{}'.format(i), snapshots) for link in network.links.index[ network.links["bus{}".format(i)] != ""]: bus = network.links.at[link, "bus{}".format(i)] ii = network.buses.index.get_loc(bus) * len(snapshots) j = network.variable_positions.at[ "Link-p", "start"] + network.links.index.get_loc(link) * len(snapshots) for k, sn in enumerate(snapshots): constraint_matrix[ii + k][j + k] = efficiency.at[sn, link] for component in network.passive_branch_components: df = getattr(network, network.components[component]["list_name"]) for unit in df.index: bus0 = df.at[unit, "bus0"] bus1 = df.at[unit, "bus1"] i0 = network.buses.index.get_loc(bus0) * len(snapshots) i1 = network.buses.index.get_loc(bus1) * len(snapshots) j = network.variable_positions.at[ "{}-s".format(component), "start"] + df.index.get_loc(unit) * len(snapshots) for k, sn in enumerate(snapshots): constraint_matrix[i0 + k][j + k] = -1. constraint_matrix[i1 + k][j + k] = 1. group = "nodal_balance" add_group(network, "constraint", group, len(network.buses.index) * len(snapshots)) start = network.constraint_positions.at[group, "start"] rhs = -get_switchable_as_dense( network, 'Load', 'p_set', snapshots).multiply( network.loads.sign).groupby( network.loads.bus, axis=1).sum().reindex( columns=network.buses.index, fill_value=0.) for i_bus, bus in enumerate(network.buses.index): i = i_bus * len(snapshots) rhs_i = rhs[bus] for k in range(len(snapshots)): write_constraint(network, constraint_matrix[i + k], "==", rhs_i[k], start + i + k)
def define_loss_constraints(network, snapshots): tangents = network.tangents positions = range(1, tangents + 1) signs = [-1, 1] passive_branches = network.passive_branches() s_max_pus = get_switchable_as_dense(network, "Line", "s_max_pu") network.model.loss = Var(list(passive_branches.index), snapshots, domain=NonNegativeReals) redo_passive_branch_constraints(network, snapshots) loss_upper = {} loss_tangents = {} for branch in passive_branches.index: bus0 = passive_branches.at[branch, "bus0"] bus1 = passive_branches.at[branch, "bus1"] bt = branch[0] bn = branch[1] r_pu_eff = passive_branches.at[branch, "r_pu_eff"] if passive_branches.at[branch, "s_nom_extendable"]: attr = "s_nom_max" elif passive_branches.at[branch, "s_nom_opt"] != 0.0: attr = "s_nom_opt" else: attr = "s_nom" s_nom_max = passive_branches.at[branch, attr] assert np.isfinite(s_nom_max) and not np.isnan( s_nom_max ), f"Infinite or non-existent 's_nom_max' encountered at line {bn}" for sn in snapshots: s_max_pu = s_max_pus.loc[sn, bn] # adjust kcl # use of ._body because of pyomo bug for bus in [bus0, bus1]: network.model.power_balance[bus, sn]._body -= ( network.model.loss[bt, bn, sn] / 2) # upper loss limit lhs = LExpression( [(1, network.model.loss[bt, bn, sn])], -r_pu_eff * (s_max_pu * s_nom_max)**2, ) loss_upper[bt, bn, sn] = LConstraint(lhs, "<=", LExpression()) # loss tangents for k in positions: p_k = k / tangents * s_max_pu * s_nom_max loss_k = r_pu_eff * p_k**2 slope_k = 2 * r_pu_eff * p_k offset_k = loss_k - slope_k * p_k for sign in signs: lhs = LExpression([(1, network.model.loss[bt, bn, sn])]) rhs = LExpression( [(sign * slope_k, network.model.passive_branch_p[bt, bn, sn])], offset_k, ) loss_tangents[sign, k, bt, bn, sn] = LConstraint(lhs, ">=", rhs) l_constraint(network.model, "loss_upper", loss_upper, list(passive_branches.index), snapshots) l_constraint( network.model, "loss_tangents", loss_tangents, signs, list(positions), list(passive_branches.index), snapshots, )