-
Notifications
You must be signed in to change notification settings - Fork 76
Fix short-circuit source impedance scaling #1547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: |
||
|
|
||
| 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, | ||
|
|
@@ -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]); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -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}; | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
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 |
|---|---|---|
|
|
@@ -29,11 +29,11 @@ | |
| "id": 5, | ||
| "energized": 1, | ||
| "i_f": [ | ||
| 63508.52961085883410, | ||
| 57735.026918962576, | ||
| 0.0, | ||
| 0.0 | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
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