Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ template <symmetry_tag sym_type> struct StateEstimationInput {
struct ShortCircuitInput {
DenseGroupedIdxVector fault_buses;
std::vector<FaultCalcParam> faults;
ComplexVector source; // Complex u_ref of each source
ComplexVector source; // Complex u_ref of each source
DoubleVector source_admittance_scaling; // Multiplier for source y_ref in short-circuit calculations

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe if we just do the cabs(input.source[source_number]) at short_circuit_solver directly, we wont need to add source_admittance_scaling right? Lets remove so if thats the case

};

template <typename T>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ prepare_short_circuit_input(main_model_state_c auto const& state, ComponentToMat
sc_input[i].faults.resize(state.components.template size<Fault>());

sc_input[i].source.resize(state.math_topology[i]->n_source());
sc_input[i].source_admittance_scaling.resize(state.math_topology[i]->n_source());
}

comp_coup = ComponentToMathCoupling{.fault = std::move(fault_coup)};
Expand All @@ -324,6 +325,13 @@ prepare_short_circuit_input(main_model_state_c auto const& state, ComponentToMat
return std::pair{state.components.template get_item<Node>(source.node()).u_rated(), voltage_scaling};
});

// Source::calc_param() returns c * exp(j * angle). sk is defined at rated voltage, so its source-equivalent
// impedance scales with c and the corresponding admittance scales with 1 / c.
for (auto& input : sc_input) {
std::ranges::transform(input.source, input.source_admittance_scaling.begin(),
[](DoubleComplex const& u_ref) { return 1.0 / cabs(u_ref); });
}

// only now do we know where the fault objects are placed => resize to used only
for (auto& input : sc_input) {
auto const is_unused = [](FaultCalcParam const& param) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,31 @@ template <symmetry_tag sym> class ShortCircuitSolver {
auto& diagonal_element = mat_data_[diagonal_position];
auto& u_bus = output.u_bus[bus_number];

detail::add_sources<sym>(sources, bus_number, y_bus, input.source, diagonal_element, u_bus);
add_sources(sources, y_bus, input, diagonal_element, u_bus);

add_faults(faults, bus_number, y_bus, input, diagonal_element, u_bus, infinite_admittance_fault_counter,
fault_type, phase_1, phase_2);
}
}

static ComplexTensor<sym> source_admittance(YBus<sym> const& y_bus, ShortCircuitInput const& input,
Idx source_number) {
assert(input.source_admittance_scaling.empty() ||
input.source_admittance_scaling.size() == input.source.size());
double const scaling =
input.source_admittance_scaling.empty() ? 1.0 : input.source_admittance_scaling[source_number];
return scaling * y_bus.math_model_param().source_param[source_number].template y_ref<sym>();
}
Comment on lines +102 to +109

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Could you please move the above comment of calculation_input_preparation regarding the reason to this place?

I would like a explaining docstring here along the lines:
"source admittance is calculated on sk for a specific u_ref for powerflow solvers within PGM.
However for generic short circuit calculation, sk is defined at rated voltage, so its source-equivalent impedance scales with c and the corresponding admittance scales with 1 / c = 1 / cabs(input.source[source_number])"


static void add_sources(IdxRange const& sources, YBus<sym> const& y_bus, ShortCircuitInput const& input,
ComplexTensor<sym>& diagonal_element, ComplexValue<sym>& u_bus) {
for (Idx const source_number : sources) {
ComplexTensor<sym> const y_source = source_admittance(y_bus, input, source_number);
diagonal_element += y_source;
u_bus += dot(y_source, ComplexValue<sym>{input.source[source_number]});
}
}

void add_faults(IdxRange const& faults, Idx bus_number, YBus<sym> const& y_bus, ShortCircuitInput const& input,
ComplexTensor<sym>& diagonal_element, ComplexValue<sym>& u_bus,
IdxVector& infinite_admittance_fault_counter, FaultType const& fault_type, IntS phase_1,
Expand Down Expand Up @@ -303,8 +321,7 @@ template <symmetry_tag sym> class ShortCircuitSolver {
ComplexValue<sym> i_source_bus{}; // total source current in to the bus
ComplexValue<sym> i_source_inject{}; // total raw source current as a Norton equivalent
for (Idx const source_number : sources) {
ComplexTensor<sym> const y_source =
y_bus.math_model_param().source_param[source_number].template y_ref<sym>();
ComplexTensor<sym> const y_source = source_admittance(y_bus, input, source_number);
ComplexValue<sym> const i_source_inject_single =
dot(y_source, ComplexValue<sym>{input.source[source_number]});
output.source[source_number].i = i_source_inject_single - dot(y_source, output.u_bus[bus_number]);
Expand Down
39 changes: 39 additions & 0 deletions tests/cpp_unit_tests/math_solver/test_math_solver_sc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,4 +462,43 @@ TEST_CASE("Short circuit solver") {
}
}

TEST_CASE("Short circuit source admittance follows the voltage factor") {
MathModelTopology topology;
topology.slack_bus = 0;
topology.phase_shift = {0.0};
topology.sources_per_bus = {from_sparse, {0, 1}};
topology.shunts_per_bus = {from_sparse, {0, 0}};
topology.load_gens_per_bus = {from_sparse, {0, 0}};

DoubleComplex const source_admittance{10.0 - 50.0i};
MathModelParam<symmetric_t> parameters;
parameters.source_param = {SourceCalcParam{.y1 = source_admittance, .y0 = source_admittance}};

YBus<symmetric_t> const y_bus{topology, std::move(parameters)};
ShortCircuitSolver<symmetric_t> solver{y_bus, topology};

DoubleComplex const solid_fault_admittance{std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::infinity()};
auto const run_with_voltage_factor = [&](double voltage_factor) {
ShortCircuitInput input;
input.source = {voltage_factor};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
input.source = {voltage_factor};
input.source = {{voltage_factor, 0.0}};

Good to be explicit

input.source_admittance_scaling = {1.0 / voltage_factor};
input.fault_buses = {from_sparse, {0, 1}};
input.faults = {
{.y_fault = solid_fault_admittance, .fault_type = FaultType::three_phase, .fault_phase = FaultPhase::abc}};
return solver.run_short_circuit(y_bus, input);
};

auto const low_voltage_minimum_output = run_with_voltage_factor(0.95);
auto const high_voltage_minimum_output = run_with_voltage_factor(1.0);
auto const maximum_output = run_with_voltage_factor(1.1);

CHECK(cabs(low_voltage_minimum_output.fault[0].i_fault - source_admittance) < numerical_tolerance);
CHECK(cabs(high_voltage_minimum_output.fault[0].i_fault - source_admittance) < numerical_tolerance);
CHECK(cabs(maximum_output.fault[0].i_fault - source_admittance) < numerical_tolerance);
CHECK(cabs(maximum_output.source[0].i - source_admittance) < numerical_tolerance);
CHECK(cabs(maximum_output.fault[0].i_fault - low_voltage_minimum_output.fault[0].i_fault) < numerical_tolerance);
CHECK(cabs(maximum_output.fault[0].i_fault - high_voltage_minimum_output.fault[0].i_fault) < numerical_tolerance);
}

} // namespace power_grid_model::math_solver
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
"id": 5,
"energized": 1,
"i_f": [
63508.52961085883410,
57735.026918962576,
0.0,
0.0
]
}
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"id": 5,
"energized": 1,
"i_f": [
63508.52961085883410,
57735.026918962576,
0.0,
0.0
]
Expand All @@ -43,7 +43,7 @@
"id": 1,
"energized": 1,
"u_pu": [
1.083914433075477,
1.0817685322751267,
1.1,
1.1
]
Expand All @@ -63,7 +63,7 @@
"id": 5,
"energized": 1,
"i_f": [
6257.9828971464731,
6245.59353309911,
0.0,
0.0
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@
"data": [
{
"node": [
{"id": 1, "energized": 1, "u_pu": [0, 1.1000077319762265, 1.1000098548415278], "u": [0, 6350.8976016714405, 6350.9098580399723], "u_angle": [0, -2.0944042236085978, 2.094402410425154]},
{"id": 2, "energized": 1, "u_pu": [0, 1.1003709155896784, 1.117158383518543], "u": [0, 6352.9944432413577, 6449.9169345187802], "u_angle": [0, -2.112990106753871, 2.0974639893699574]},
{"id": 3, "energized": 1, "u_pu": [0, 1.1003709152901693, 1.1171583831127465], "u": [0, 6352.9944415121408, 6449.9169321759127], "u_angle": [0, -2.1129901070564321, 2.0974639891599725]}
{"id": 1, "energized": 1, "u_pu": [0, 1.100008505188684, 1.1000108403504814], "u": [0, 6350.902065815646, 6350.915547878569], "u_angle": [0, -2.094405135749131, 2.094403141240517]},
{"id": 2, "energized": 1, "u_pu": [0, 1.10037169814409, 1.1171594117225554], "u": [0, 6352.99896132136, 6449.922870857413], "u_angle": [0, -2.112991042936463, 2.097464714857289]},
{"id": 3, "energized": 1, "u_pu": [0, 1.1003716978445806, 1.1171594113167584], "u": [0, 6352.998959592142, 6449.922868514544], "u_angle": [0, -2.112991043239024, 2.0974647146473044]}
],
"line": [
{"id": 4, "energized": 1, "i_from": [309.26652168666647, 728.9516101684294, 732.36548748962139], "i_from_angle": [-2.3422247532036535, -1.3419762083430138, -1.8295943660541507], "i_to": [436.49378866975974, 3.6564812397251591, 3.8271101981503142], "i_to_angle": [-1.0791563599686425, 2.6521928824986034, 0.26542148608168392]},
{"id": 4, "energized": 1, "i_from": [309.26720894741226, 728.95311410609, 732.3670692013686], "i_from_angle": [-2.342225010996923, -1.3419769001103916, -1.829594168056166], "i_to": [436.4947586585155, 3.65648296050423, 3.8271128254544378], "i_to_angle": [-1.0791566177619114, 2.652192140837011, 0.2654220381852178]},
{"id": 5, "energized": 0, "i_from": [0, 0, 0], "i_from_angle": [0, 0, 0], "i_to": [0, 0, 0], "i_to_angle": [0, 0, 0]},
{"id": 6, "energized": 0, "i_from": [0, 0, 0], "i_from_angle": [0, 0, 0], "i_to": [0, 0, 0], "i_to_angle": [0, 0, 0]}
],
"link": [
{"id": 9, "energized": 1, "i_from": [0, 3.6564798344471052, 3.827107363916523], "i_from_angle": [0, -0.48939955972358584, -2.8761707632835742], "i_to": [0, 3.6564798344471052, 3.827107363916523], "i_to_angle": [0, 2.6521930938662073, 0.2654218903062191]}
{"id": 9, "energized": 1, "i_from": [0, 3.656483779705358, 3.8271127964214253], "i_from_angle": [0, -0.4894005845110841, -2.8761706832415648], "i_to": [0, 3.656483779705358, 3.8271127964214253], "i_to_angle": [0, 2.6521920690787093, 0.2654219703482284]}
],
"shunt": [
{"id": 7, "energized": 1, "i": [0.66507454600033922, 3.6621221898722189, 3.7855668750333362], "i_angle": [1.570793748925259, -0.47527539810683334, -2.8784819041528089]},
{"id": 8, "energized": 1, "i": [0.68295207957823156, 3.6564810900168685, 3.8271100083522671], "i_angle": [1.5502437165727303, -0.4893997316430107, -2.8761711433811832]}
{"id": 7, "energized": 1, "i": [0.665076023947669, 3.662123914711542, 3.7855694022618493], "i_angle": [1.5707934911319938, -0.47527611928440006, -2.8784813531611757]},
{"id": 8, "energized": 1, "i": [0.6829535972535181, 3.6564828107883494, 3.8271126356552787], "i_angle": [1.5502434587794647, -0.48940047330335473, -2.8761705912777473]}
],
"source": [
{"id": 10, "energized": 1, "i": [63508529.610858843, 731.32759227924817, 734.26006094063086], "i_angle": [-1.4711276743037347, -1.3381594964606927, -1.8340636301254731]}
{"id": 10, "energized": 1, "i": [57735026.91896259, 731.3290974137417, 734.2616450593654], "i_angle": [-1.4711276743037347, -1.338160194402424, -1.8340634245549368]}
],
"sym_load": [
{"id": 11, "energized": 0, "i": [0, 0, 0], "i_angle": [0, 0, 0]}
Expand All @@ -32,31 +32,31 @@
{"id": 12, "energized": 0, "i": [0, 0, 0], "i_angle": [0, 0, 0]}
],
"fault": [
{"id": 13, "energized": 1, "i_f": [63508331.109258644, 0, 0], "i_f_angle": [-1.4711239498504336, 0, 0]},
{"id": 14, "energized": 1, "i_f": [436.49378866976025, 0, 0], "i_f_angle": [2.0624362936211509, 0, 0]},
{"id": 15, "energized": 1, "i_f": [0.68295207957823156, 0, 0], "i_f_angle": [-1.5913489370170628, 0, 0]}
{"id": 13, "energized": 1, "i_f": [57734828.41702631, 0, 0], "i_f_angle": [-1.4711235773938323, 0, 0]},
{"id": 14, "energized": 1, "i_f": [436.49475865851304, 0, 0], "i_f_angle": [2.0624360358278855, 0, 0]},
{"id": 15, "energized": 1, "i_f": [0.6829535972535181, 0, 0], "i_f_angle": [-1.5913491948103287, 0, 0]}
]
},
{
"node": [
{"id": 1, "energized": 1, "u_pu": [0, 1.1000077319762265, 1.1000098548415278], "u": [0, 6350.8976016714405, 6350.9098580399723], "u_angle": [0, -2.0944042236085978, 2.094402410425154]},
{"id": 2, "energized": 1, "u_pu": [0, 1.1003709155896784, 1.117158383518543], "u": [0, 6352.9944432413577, 6449.9169345187802], "u_angle": [0, -2.112990106753871, 2.0974639893699574]},
{"id": 3, "energized": 1, "u_pu": [0, 1.1003709152901693, 1.1171583831127465], "u": [0, 6352.9944415121408, 6449.9169321759127], "u_angle": [0, -2.1129901070564321, 2.0974639891599725]}
{"id": 1, "energized": 1, "u_pu": [0, 1.100008505188684, 1.1000108403504814], "u": [0, 6350.902065815646, 6350.915547878569], "u_angle": [0, -2.094405135749131, 2.094403141240517]},
{"id": 2, "energized": 1, "u_pu": [0, 1.10037169814409, 1.1171594117225554], "u": [0, 6352.99896132136, 6449.922870857413], "u_angle": [0, -2.112991042936463, 2.0974647148572894]},
{"id": 3, "energized": 1, "u_pu": [0, 1.1003716978445806, 1.1171594113167584], "u": [0, 6352.998959592142, 6449.922868514544], "u_angle": [0, -2.112991043239024, 2.0974647146473044]}
],
"line": [
{"id": 4, "energized": 1, "i_from": [309.26652168666647, 728.9516101684294, 732.36548748962139], "i_from_angle": [-2.3422247532036535, -1.3419762083430138, -1.8295943660541507], "i_to": [436.49378866975974, 3.6564812397251591, 3.8271101981503142], "i_to_angle": [-1.0791563599686425, 2.6521928824986034, 0.26542148608168392]},
{"id": 5, "energized": 1, "i_from": [0.33253727300016961, 1.8310610949361095, 1.8927834375166681], "i_from_angle": [1.570793748925259, -0.47527539810683334, -2.8784819041528089], "i_to": [0.33253727300016961, 1.8310610949361095, 1.8927834375166681], "i_to_angle": [1.570793748925259, -0.47527539810683334, -2.8784819041528089]},
{"id": 6, "energized": 1, "i_from": [0.34147603978911578, 1.8282405450084342, 1.9135550041761336], "i_from_angle": [1.5502437165727303, -0.4893997316430107, -2.8761711433811832], "i_to": [0.34147603978911578, 1.8282405450084342, 1.9135550041761336], "i_to_angle": [1.5502437165727303, -0.4893997316430107, -2.8761711433811832]}
{"id": 4, "energized": 1, "i_from": [309.2672089474149, 728.9531141060909, 732.3670692013725], "i_from_angle": [-2.342225010996926, -1.3419769001103965, -1.8295941680561507], "i_to": [436.49475865851554, 3.656482960502105, 3.827112825448242], "i_to_angle": [-1.079156617761905, 2.652192140836193, 0.2654220381874352]},
{"id": 5, "energized": 1, "i_from": [0.3325380119706501, 1.8310619573374212, 1.8927847011366388], "i_from_angle": [1.570793491129836, -0.4752761192891239, -2.878481353146739], "i_to": [0.3325380119706501, 1.8310619573374212, 1.8927847011366388], "i_to_angle": [1.570793491129836, -0.4752761192891239, -2.878481353146739]},
{"id": 6, "energized": 1, "i_from": [0.3414767986218242, 1.828241405387754, 1.913556317820028], "i_from_angle": [1.550243458778323, -0.4894004733039044, -2.876170591274497], "i_to": [0.3414767986218242, 1.828241405387754, 1.913556317820028], "i_to_angle": [1.550243458778323, -0.4894004733039044, -2.876170591274497]}
],
"link": [
{"id": 9, "energized": 1, "i_from": [0, 3.6564798344471052, 3.827107363916523], "i_from_angle": [0, -0.48939955972358584, -2.8761707632835742], "i_to": [0, 3.6564798344471052, 3.827107363916523], "i_to_angle": [0, 2.6521930938662073, 0.2654218903062191]}
{"id": 9, "energized": 1, "i_from": [0, 3.656483779705358, 3.8271127964214253], "i_from_angle": [0, -0.4894005845110841, -2.8761706832415648], "i_to": [0, 3.656483779705358, 3.8271127964214253], "i_to_angle": [0, 2.6521920690787093, 0.2654219703482284]}
],
"shunt": [
{"id": 7, "energized": 0, "i": [0, 0, 0], "i_angle": [0, 0, 0]},
{"id": 8, "energized": 0, "i": [0, 0, 0], "i_angle": [0, 0, 0]}
],
"source": [
{"id": 10, "energized": 1, "i": [63508529.610858843, 731.32759227924817, 734.26006094063086], "i_angle": [-1.4711276743037347, -1.3381594964606927, -1.8340636301254731]}
{"id": 10, "energized": 1, "i": [57735026.91896259, 731.3290974137417, 734.2616450593654], "i_angle": [-1.4711276743037347, -1.338160194402424, -1.8340634245549368]}
],
"sym_load": [
{"id": 11, "energized": 0, "i": [0, 0, 0], "i_angle": [0, 0, 0]}
Expand All @@ -65,9 +65,9 @@
{"id": 12, "energized": 0, "i": [0, 0, 0], "i_angle": [0, 0, 0]}
],
"fault": [
{"id": 13, "energized": 1, "i_f": [63508331.109258644, 0, 0], "i_f_angle": [-1.4711239498504336, 0, 0]},
{"id": 14, "energized": 1, "i_f": [436.49378866976025, 0, 0], "i_f_angle": [2.0624362936211509, 0, 0]},
{"id": 15, "energized": 1, "i_f": [0.68295207957823156, 0, 0], "i_f_angle": [-1.5913489370170628, 0, 0]}
{"id": 13, "energized": 1, "i_f": [57734828.41702631, 0, 0], "i_f_angle": [-1.4711235773938323, 0, 0]},
{"id": 14, "energized": 1, "i_f": [436.49475865851304, 0, 0], "i_f_angle": [2.062436035827888, 0, 0]},
{"id": 15, "energized": 1, "i_f": [0.6829535972495371, 0, 0], "i_f_angle": [-1.5913491948103282, 0, 0]}
]
}
]
Expand Down
Loading
Loading