@@ -332,8 +332,8 @@ template <symmetry_tag sym> class MeasuredValues {
332
332
333
333
// combine valid appliance_injection_measurement and direct_injection_measurement
334
334
// three scenarios; check if we have valid injection measurement
335
- auto const uncertain_direct_injection =
336
- is_inf (direct_injection_measurement. p_variance ) || is_inf (direct_injection_measurement.q_variance );
335
+ auto const uncertain_direct_injection = is_inf (direct_injection_measurement. real_component . variance ) ||
336
+ is_inf (direct_injection_measurement.imag_component . variance );
337
337
338
338
bus_injection_[bus].idx_bus_injection = static_cast <Idx>(power_main_value_.size ());
339
339
if (n_unmeasured > 0 ) {
@@ -343,8 +343,8 @@ template <symmetry_tag sym> class MeasuredValues {
343
343
// only direct injection
344
344
power_main_value_.push_back (direct_injection_measurement);
345
345
}
346
- } else if (uncertain_direct_injection || any_zero (appliance_injection_measurement.p_variance ) ||
347
- any_zero (appliance_injection_measurement.q_variance )) {
346
+ } else if (uncertain_direct_injection || any_zero (appliance_injection_measurement.real_component . variance ) ||
347
+ any_zero (appliance_injection_measurement.imag_component . variance )) {
348
348
// only appliance injection if
349
349
// there is no direct injection measurement,
350
350
// or we have zero injection
@@ -370,13 +370,15 @@ template <symmetry_tag sym> class MeasuredValues {
370
370
}
371
371
372
372
auto const & appliance_measurement = extra_value_[appliance_idx];
373
- if (is_inf (appliance_measurement.p_variance ) || is_inf (appliance_measurement.q_variance )) {
373
+ if (is_inf (appliance_measurement.real_component .variance ) ||
374
+ is_inf (appliance_measurement.imag_component .variance )) {
374
375
++n_unmeasured;
375
376
return ;
376
377
}
377
- measurements.value += appliance_measurement.value ;
378
- measurements.p_variance += appliance_measurement.p_variance ;
379
- measurements.q_variance += appliance_measurement.q_variance ;
378
+ measurements.real_component .value += appliance_measurement.real_component .value ;
379
+ measurements.imag_component .value += appliance_measurement.imag_component .value ;
380
+ measurements.real_component .variance += appliance_measurement.real_component .variance ;
381
+ measurements.imag_component .variance += appliance_measurement.imag_component .variance ;
380
382
}
381
383
382
384
void process_branch_measurements (StateEstimationInput<sym> const & input) {
@@ -463,22 +465,25 @@ template <symmetry_tag sym> class MeasuredValues {
463
465
for (auto pos : sensors) {
464
466
auto const & measurement = data[pos];
465
467
466
- accumulated_inverse_p_variance += RealValue<sym>{1.0 } / measurement.p_variance ;
467
- accumulated_inverse_q_variance += RealValue<sym>{1.0 } / measurement.q_variance ;
468
+ accumulated_inverse_p_variance += RealValue<sym>{1.0 } / measurement.real_component . variance ;
469
+ accumulated_inverse_q_variance += RealValue<sym>{1.0 } / measurement.imag_component . variance ;
468
470
469
- accumulated_p_value += real ( measurement.value ) / measurement.p_variance ;
470
- accumulated_q_value += imag ( measurement.value ) / measurement.q_variance ;
471
+ accumulated_p_value += measurement.real_component . value / measurement.real_component . variance ;
472
+ accumulated_q_value += measurement.imag_component . value / measurement.imag_component . variance ;
471
473
}
472
474
473
475
if (is_normal (accumulated_inverse_p_variance) && is_normal (accumulated_inverse_q_variance)) {
474
- return PowerSensorCalcParam<sym>{accumulated_p_value / accumulated_inverse_p_variance +
475
- 1 .0i * accumulated_q_value / accumulated_inverse_q_variance,
476
- RealValue<sym>{1.0 } / accumulated_inverse_p_variance,
477
- RealValue<sym>{1.0 } / accumulated_inverse_q_variance};
476
+ return PowerSensorCalcParam<sym>{
477
+ .real_component = {.value = accumulated_p_value / accumulated_inverse_p_variance,
478
+ .variance = RealValue<sym>{1.0 } / accumulated_inverse_p_variance},
479
+ .imag_component = {.value = accumulated_q_value / accumulated_inverse_q_variance,
480
+ .variance = RealValue<sym>{1.0 } / accumulated_inverse_q_variance}};
478
481
}
479
- return PowerSensorCalcParam<sym>{accumulated_p_value + 1 .0i * accumulated_q_value,
480
- RealValue<sym>{std::numeric_limits<double >::infinity ()},
481
- RealValue<sym>{std::numeric_limits<double >::infinity ()}};
482
+ return PowerSensorCalcParam<sym>{
483
+ .real_component = {.value = accumulated_p_value,
484
+ .variance = RealValue<sym>{std::numeric_limits<double >::infinity ()}},
485
+ .imag_component = {.value = accumulated_q_value,
486
+ .variance = RealValue<sym>{std::numeric_limits<double >::infinity ()}}};
482
487
}
483
488
484
489
template <sensor_calc_param_type CalcParam, bool only_magnitude = false >
@@ -538,7 +543,7 @@ template <symmetry_tag sym> class MeasuredValues {
538
543
unconstrained_min (x.variance );
539
544
}
540
545
for (auto const & x : power_main_value_) {
541
- auto const variance = x.p_variance + x.q_variance ;
546
+ auto const variance = x.real_component . variance + x.imag_component . variance ;
542
547
if constexpr (is_symmetric_v<sym>) {
543
548
unconstrained_min (variance);
544
549
} else {
@@ -552,8 +557,8 @@ template <symmetry_tag sym> class MeasuredValues {
552
557
auto const inv_norm_var = 1.0 / min_var;
553
558
std::ranges::for_each (voltage_main_value_, [inv_norm_var](auto & x) { x.variance *= inv_norm_var; });
554
559
std::ranges::for_each (power_main_value_, [inv_norm_var](auto & x) {
555
- x.p_variance *= inv_norm_var;
556
- x.q_variance *= inv_norm_var;
560
+ x.real_component . variance *= inv_norm_var;
561
+ x.imag_component . variance *= inv_norm_var;
557
562
});
558
563
}
559
564
@@ -563,17 +568,17 @@ template <symmetry_tag sym> class MeasuredValues {
563
568
FlowVector& source_flow) const {
564
569
// calculate residual, divide, and assign to unmeasured (but connected) appliances
565
570
ComplexValue<sym> const s_residual_per_appliance =
566
- (s - bus_appliance_injection.value ) / static_cast <double >(n_unmeasured);
571
+ (s - bus_appliance_injection.value () ) / static_cast <double >(n_unmeasured);
567
572
for (Idx const load_gen : load_gens) {
568
573
if (has_load_gen (load_gen)) {
569
- load_gen_flow[load_gen].s = load_gen_power (load_gen).value ;
574
+ load_gen_flow[load_gen].s = load_gen_power (load_gen).value () ;
570
575
} else if (idx_load_gen_power_[load_gen] == unmeasured) {
571
576
load_gen_flow[load_gen].s = s_residual_per_appliance;
572
577
}
573
578
}
574
579
for (Idx const source : sources) {
575
580
if (has_source (source)) {
576
- source_flow[source].s = source_power (source).value ;
581
+ source_flow[source].s = source_power (source).value () ;
577
582
} else if (idx_source_power_[source] == unmeasured) {
578
583
source_flow[source].s = s_residual_per_appliance;
579
584
}
@@ -586,13 +591,14 @@ template <symmetry_tag sym> class MeasuredValues {
586
591
FlowVector& source_flow) const {
587
592
// residual normalized by variance
588
593
// mu = (sum[S_i] - S_cal) / sum[variance]
589
- auto const delta = bus_appliance_injection.value - s;
590
- ComplexValue<sym> const mu =
591
- real (delta) / bus_appliance_injection. p_variance + 1 .0i * imag (delta) / bus_appliance_injection.q_variance ;
594
+ auto const delta = ComplexValue<sym>{ bus_appliance_injection.value () - s} ;
595
+ ComplexValue<sym> const mu = real (delta) / bus_appliance_injection. real_component . variance +
596
+ 1 .0i * imag (delta) / bus_appliance_injection.imag_component . variance ;
592
597
593
598
// S_i = S_i_mea - var_i * mu
594
599
auto const calculate_injection = [&mu](auto const & power) {
595
- return power.value - (power.p_variance * real (mu) + 1 .0i * power.q_variance * imag (mu));
600
+ return ComplexValue<sym>{power.value () - ((power.real_component .variance * real (mu)) +
601
+ (1 .0i * power.imag_component .variance * imag (mu)))};
596
602
};
597
603
598
604
for (Idx const load_gen : load_gens) {
0 commit comments