@@ -122,6 +122,8 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
122
122
auto const & abs_u_psi_inv (Order ij_voltage_order) const {
123
123
return ij_voltage_order == Order::row_major ? abs_uj_inv : abs_ui_inv;
124
124
}
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; }
125
127
};
126
128
127
129
struct NRSEJacobian {
@@ -336,7 +338,10 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
336
338
measurement);
337
339
break ;
338
340
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 ;
340
345
default :
341
346
assert (measurement.angle_measurement_type == AngleMeasurementType::local_angle ||
342
347
measurement.angle_measurement_type == AngleMeasurementType::global_angle);
@@ -353,7 +358,10 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
353
358
measurement);
354
359
break ;
355
360
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 ;
357
365
default :
358
366
assert (measurement.angle_measurement_type == AngleMeasurementType::local_angle ||
359
367
measurement.angle_measurement_type == AngleMeasurementType::global_angle);
@@ -503,8 +511,8 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
503
511
}
504
512
}
505
513
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.
508
516
void process_branch_local_current_measurement (NRSEGainBlock<sym>& block, NRSEGainBlock<sym>& diag_block,
509
517
NRSERhs<sym>& rhs_block, auto const & y_xi_xi, auto const & y_xi_mu,
510
518
auto const & u_state, Order const order,
@@ -533,6 +541,29 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
533
541
}
534
542
}
535
543
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
+
536
567
void multiply_add_branch_blocks (NRSEGainBlock<sym>& block, NRSEGainBlock<sym>& diag_block, NRSERhs<sym>& rhs_block,
537
568
auto & left_block, auto const & right_block,
538
569
DecomposedComplexRandVar<sym> const & measured_flow, auto const & f_x_complex) {
@@ -709,6 +740,10 @@ template <symmetry_tag sym_type> class NewtonRaphsonSESolver {
709
740
// / @brief Construct the F_k(u1, u2, y12) block using helper function of hnml complex form
710
741
// / The 4 members are H, N, M, L in the order.
711
742
// /
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
+ // /
712
747
// / @param hm_complex hm_complex
713
748
// / @param nl_complex hm_complex / abs(u2)
714
749
// / @return F_k(u1, u2, y12)
0 commit comments