Skip to content

Commit dd3bb19

Browse files
authored
Merge pull request #1030 from PowerGridModel/feature/nrse-global-current-sensor
NRSE current sensor: Global angle current sensor
2 parents 80a9c4d + 7ab943f commit dd3bb19

File tree

3 files changed

+156
-118
lines changed

3 files changed

+156
-118
lines changed

power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/newton_raphson_se_solver.hpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
122122
auto const& abs_u_psi_inv(Order ij_voltage_order) const {
123123
return ij_voltage_order == Order::row_major ? abs_uj_inv : abs_ui_inv;
124124
}
125+
auto const& u_chi(Order ij_voltage_order) const { return ij_voltage_order == Order::row_major ? ui : uj; }
126+
auto const& u_psi(Order ij_voltage_order) const { return ij_voltage_order == Order::row_major ? uj : ui; }
125127
};
126128

127129
struct NRSEJacobian {
@@ -336,7 +338,10 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
336338
measurement);
337339
break;
338340
case AngleMeasurementType::global_angle:
339-
throw SparseMatrixError{};
341+
process_branch_global_current_measurement(block, diag_block, rhs_block, y_branch.yff(),
342+
y_branch.yft(), u_state, ij_voltage_order,
343+
measurement);
344+
break;
340345
default:
341346
assert(measurement.angle_measurement_type == AngleMeasurementType::local_angle ||
342347
measurement.angle_measurement_type == AngleMeasurementType::global_angle);
@@ -353,7 +358,10 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
353358
measurement);
354359
break;
355360
case AngleMeasurementType::global_angle:
356-
throw SparseMatrixError{};
361+
process_branch_global_current_measurement(block, diag_block, rhs_block, y_branch.ytt(),
362+
y_branch.ytf(), u_state, ij_voltage_order,
363+
measurement);
364+
break;
357365
default:
358366
assert(measurement.angle_measurement_type == AngleMeasurementType::local_angle ||
359367
measurement.angle_measurement_type == AngleMeasurementType::global_angle);
@@ -503,8 +511,8 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
503511
}
504512
}
505513

506-
/// @brief Adds contribution of branch current measurements. Logic is similar to powermeasurements, but with an
507-
/// additional voltage division as per mathematical workout.
514+
/// @brief Adds contribution of local angle branch current measurements. Logic is similar to power measurements, but
515+
/// with an additional voltage division as per mathematical workout.
508516
void process_branch_local_current_measurement(NRSEGainBlock<sym>& block, NRSEGainBlock<sym>& diag_block,
509517
NRSERhs<sym>& rhs_block, auto const& y_xi_xi, auto const& y_xi_mu,
510518
auto const& u_state, Order const order,
@@ -533,6 +541,29 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
533541
}
534542
}
535543

544+
/// @brief Adds contribution of global angle branch current measurements.
545+
void process_branch_global_current_measurement(NRSEGainBlock<sym>& block, NRSEGainBlock<sym>& diag_block,
546+
NRSERhs<sym>& rhs_block, auto const& y_xi_xi, auto const& y_xi_mu,
547+
auto const& u_state, Order const order,
548+
CurrentSensorCalcParam<sym> const& current_sensor) {
549+
ComplexTensor<sym> const current_chi_chi = dot(y_xi_xi, ComplexDiagonalTensor<sym>{u_state.u_chi(order)});
550+
ComplexTensor<sym> const current_chi_psi = dot(y_xi_mu, ComplexDiagonalTensor<sym>{u_state.u_psi(order)});
551+
ComplexTensor<sym> const current_chi_chi_v_inv = dot(current_chi_chi, u_state.abs_u_chi_inv(order));
552+
ComplexTensor<sym> const current_chi_psi_v_inv = dot(current_chi_psi, u_state.abs_u_psi_inv(order));
553+
ComplexValue<sym> const f_x_complex = sum_row(current_chi_chi + current_chi_psi);
554+
555+
auto const block_rr_or_cc = calculate_jacobian(-current_chi_chi, current_chi_chi_v_inv);
556+
auto const block_rc_or_cr = calculate_jacobian(-current_chi_psi, current_chi_psi_v_inv);
557+
558+
if (order == Order::row_major) {
559+
multiply_add_branch_blocks(block, diag_block, rhs_block, block_rr_or_cc, block_rc_or_cr,
560+
current_sensor.measurement, f_x_complex);
561+
} else {
562+
multiply_add_branch_blocks(block, diag_block, rhs_block, block_rc_or_cr, block_rr_or_cc,
563+
current_sensor.measurement, f_x_complex);
564+
}
565+
}
566+
536567
void multiply_add_branch_blocks(NRSEGainBlock<sym>& block, NRSEGainBlock<sym>& diag_block, NRSERhs<sym>& rhs_block,
537568
auto& left_block, auto const& right_block,
538569
DecomposedComplexRandVar<sym> const& measured_flow, auto const& f_x_complex) {
@@ -709,6 +740,10 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
709740
/// @brief Construct the F_k(u1, u2, y12) block using helper function of hnml complex form
710741
/// The 4 members are H, N, M, L in the order.
711742
///
743+
/// Function is also reused for global current sensor.
744+
/// The notation in that case is as per current and current * V^-1 instead of HNML.
745+
///
746+
///
712747
/// @param hm_complex hm_complex
713748
/// @param nl_complex hm_complex / abs(u2)
714749
/// @return F_k(u1, u2, y12)

0 commit comments

Comments
 (0)