import pypsa, os
import numpy as np

network = pypsa.examples.scigrid_de(from_master=True)

"""
Explanation: Security-Constrained Optimisation
In this example, the dispatch of generators is optimised using the security-constrained linear OPF, to guaranteed that no branches are overloaded by certain branch outages.
End of explanation
"""


for line_name in ["316", "527", "602"]:
    network.lines.loc[line_name, "s_nom"] = 1200

now = network.snapshots[0]

"""
Explanation: There are some infeasibilities without line extensions.
End of explanation
"""


branch_outages = network.lines.index[:15]
network.sclopf(now, branch_outages=branch_outages, solver_name="cbc")

"""
Explanation: Performing security-constrained linear OPF
End of explanation
"""


network.generators_t.p_set = network.generators_t.p_set.reindex(
    columns=network.generators.index
)
network.generators_t.p_set.loc[now] = network.generators_t.p.loc[now]

network.storage_units_t.p_set = network.storage_units_t.p_set.reindex(
    columns=network.storage_units.index
)
network.storage_units_t.p_set.loc[now] = network.storage_units_t.p.loc[now]

"""
Explanation: For the PF, set the P to the optimised P.
End of explanation
"""


p0_test = network.lpf_contingency(now, branch_outages=branch_outages)
p0_test

"""
Explanation: Check no lines are overloaded with the linear contingency analysis
End of explanation
"""


max_loading = (
    abs(p0_test.divide(network.passive_branches().s_nom, axis=0)).describe().loc["max"]
)
max_loading

np.allclose(max_loading, np.ones((len(max_loading))))

"""
Explanation: Check loading as per unit of s_nom in each contingency
End of explanation
"""


