Skip to content

Measurement statistics module #896

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

Merged
merged 46 commits into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
5c8d7b3
add statistics module setup
mgovers Feb 4, 2025
e606f4c
minor refactor
mgovers Jan 29, 2025
698bc1f
add calculation parameter tests
mgovers Jan 29, 2025
dab85bc
add sym calculation params for symmetric current sensor
mgovers Feb 4, 2025
4f63f86
unit tests for statistics
mgovers Feb 4, 2025
d5234f1
extend statistics functionality
mgovers Feb 4, 2025
159dd45
Merge branch 'feature/statistics-module' into feature/current-sensor-…
mgovers Feb 4, 2025
deffcfd
change to rdv and add some tests
nitbharambe Feb 10, 2025
a2fe613
add decomposed rough
nitbharambe Feb 12, 2025
befc6c8
rename rdv 2
nitbharambe Feb 13, 2025
3e20a34
fix polar tests non conversion
nitbharambe Feb 13, 2025
72013ec
add remaining tests
nitbharambe Feb 13, 2025
2581a62
wip tests correction
nitbharambe Feb 14, 2025
f7cd9eb
fix remaining
nitbharambe Feb 14, 2025
279e3a9
cleanup
nitbharambe Feb 17, 2025
0012881
structured bindings ref
nitbharambe Feb 17, 2025
30f1787
remove irrelavant todos
nitbharambe Feb 17, 2025
b4edcaf
Merge branch 'feature/statistics-module' into feature/current-sensor-…
nitbharambe Feb 17, 2025
909ebcf
add implementation of current sensor
nitbharambe Feb 18, 2025
79db492
add decomposed sym asym conversions
nitbharambe Feb 18, 2025
101d0a3
move subcases
nitbharambe Feb 18, 2025
38d716f
Merge branch 'feature/statistics-module' into feature/current-sensor-…
nitbharambe Feb 18, 2025
9883966
add calc param
nitbharambe Feb 18, 2025
2cb1b9f
Merge branch 'main' into feature/statistics-module
nitbharambe Feb 18, 2025
004d2bf
Merge branch 'feature/statistics-module' into feature/current-sensor-…
nitbharambe Feb 18, 2025
ea4fcd8
wip current sensor
nitbharambe Feb 20, 2025
decc9e4
finish all tests
nitbharambe Feb 24, 2025
ae2b2c5
revert new conversions
nitbharambe Feb 24, 2025
a165f46
add correct new conversions
nitbharambe Feb 24, 2025
280729c
rename to randvar
nitbharambe Feb 24, 2025
f21f599
address comments
nitbharambe Feb 24, 2025
49caa85
Apply suggestions from code review
nitbharambe Feb 24, 2025
73045b9
use constants
nitbharambe Feb 24, 2025
6e31899
Merge branch 'feature/statistics-module' into feature/current-sensor-…
nitbharambe Feb 24, 2025
4d37735
Update power_grid_model_c/power_grid_model/include/power_grid_model/c…
nitbharambe Feb 25, 2025
5f9ab40
add tests and fixes
nitbharambe Feb 26, 2025
12eb949
shorten tests
nitbharambe Feb 26, 2025
5ee89e4
change shift to loop
nitbharambe Feb 26, 2025
981a65a
Merge branch 'feature/statistics-module' into feature/current-sensor-…
nitbharambe Feb 27, 2025
fb6da0f
add equation docs
nitbharambe Feb 27, 2025
2eba909
resolve docstring comments
nitbharambe Feb 27, 2025
273bbcd
change order of initialization
nitbharambe Feb 27, 2025
83838ec
remove todos
nitbharambe Feb 27, 2025
68c9fd3
Merge branch 'feature/statistics-module' into feature/current-sensor-…
Jerry-Jinfeng-Guo Feb 28, 2025
101936d
Merge pull request #903 from PowerGridModel/feature/current-sensor-impl
Jerry-Jinfeng-Guo Feb 28, 2025
0202694
Merge branch 'main' into feature/statistics-module
Jerry-Jinfeng-Guo Feb 28, 2025
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 @@ -7,6 +7,7 @@
#include "common/common.hpp"
#include "common/enum.hpp"
#include "common/grouped_index_vector.hpp"
#include "common/statistics.hpp"
#include "common/three_phase_tensor.hpp"

namespace power_grid_model {
Expand Down Expand Up @@ -78,21 +79,10 @@ template <symmetry_tag sym_type> struct ApplianceShortCircuitSolverOutput {
ComplexValue<sym> i{};
};

// Complex measured value of a sensor in p.u. with a uniform variance across all phases and axes of the complex plane
// (circularly symmetric)
template <symmetry_tag sym_type> struct UniformComplexRandomVariable {
using sym = sym_type;

static constexpr bool symmetric{is_symmetric_v<sym>};

ComplexValue<sym> value{};
double variance{}; // variance (sigma^2) of the error range, in p.u.
};

// voltage sensor calculation parameters for state estimation
// The value is the complex voltage
// If the imaginary part is NaN, it means the angle calculation is not correct
template <symmetry_tag sym> using VoltageSensorCalcParam = UniformComplexRandomVariable<sym>;
template <symmetry_tag sym> using VoltageSensorCalcParam = UniformComplexRDV<sym>;

// power sensor calculation parameters for state estimation
// The value is the complex power
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// SPDX-FileCopyrightText: Contributors to the Power Grid Model project <[email protected]>
//
// SPDX-License-Identifier: MPL-2.0

#pragma once

#include "common.hpp"
#include "three_phase_tensor.hpp"

/**
* @file statistics.hpp
* @brief This file contains various structures and functions for handling statistical representations of
* randomly distributed variables(RDV) used in the Power Grid Model, like in the State Estimation algorithms to
* handle measurements.
*
* The structures provided in this file are used to represent measured values of sensors
* with different types of variances. These structures support both symmetric and asymmetric representations and
* provide conversion operators to transform between these representations.
*
* A Randomly distributed variable in PGM can have following characteristics:
* - Uniform: Single Variance for all phases
* - Independent: Unique Variance for each phase
* - Real: The Real value without direction, eg. real axis: RealValue (* 1), imaginary axis: RealValue (* 1i).
* - Complex: A combined complex value in `a + bi` notation.
*
* Based on these, we use combine variables in Polar/Decomposed forms:
* - Decomposed: Treat RDV individually as in cartesian co-ordinates with a separate variance for both real and
* complex component.
* - Polar: RDV is in polar co-ordinates, with magnitude and angle.
*
*/

namespace power_grid_model {
template <symmetry_tag sym_type> struct UniformRealRDV {
using sym = sym_type;

static constexpr bool symmetric{is_symmetric_v<sym>};

RealValue<sym> value{};
double variance{}; // variance (sigma^2) of the error range, in p.u.

explicit operator UniformRealRDV<asymmetric_t>() const
requires(is_symmetric_v<sym>)
{
return {.value = RealValue<asymmetric_t>{std::piecewise_construct, value}, .variance = variance};
}
explicit operator UniformRealRDV<symmetric_t>() const
requires(is_asymmetric_v<sym>)
{
return {.value = mean_val(value), .variance = variance / 3.0};
}
};

template <symmetry_tag sym_type> struct IndependentRealRDV {
using sym = sym_type;

static constexpr bool symmetric{is_symmetric_v<sym>};

RealValue<sym> value{};
RealValue<sym> variance{}; // variance (sigma^2) of the error range, in p.u.

explicit operator UniformRealRDV<symmetric_t>() const {
constexpr auto scale = is_asymmetric_v<sym> ? 3.0 : 1.0;
return {.value = mean_val(value), .variance = mean_val(variance) / scale};
}
explicit operator UniformRealRDV<asymmetric_t>() const { return {.value = value, .variance = mean_val(variance)}; }
explicit operator IndependentRealRDV<asymmetric_t>() const
requires(is_symmetric_v<sym>)
{
return {.value = RealValue<asymmetric_t>{std::piecewise_construct, value},
.variance = RealValue<asymmetric_t>{std::piecewise_construct, variance}};
}
explicit operator IndependentRealRDV<symmetric_t>() const
requires(is_asymmetric_v<sym>)
{
return {.value = mean_val(value), .variance = mean_val(variance) / 3.0};
}
};

// Complex measured value of a sensor in p.u. with a uniform variance across all phases and axes of the complex plane
// (rotationally symmetric)
template <symmetry_tag sym_type> struct UniformComplexRDV {
using sym = sym_type;

static constexpr bool symmetric{is_symmetric_v<sym>};

ComplexValue<sym> value{};
double variance{}; // variance (sigma^2) of the error range, in p.u.
};

inline UniformComplexRDV<symmetric_t> pos_seq(UniformComplexRDV<asymmetric_t> const& var) {
return {.value = pos_seq(var.value), .variance = var.variance / 3.0};
}
inline UniformComplexRDV<asymmetric_t> three_phase(UniformComplexRDV<symmetric_t> const& var) {
return {.value = ComplexValue<asymmetric_t>{var.value}, .variance = var.variance};
}

// Complex measured value of a sensor in p.u. with separate variances per phase (but rotationally symmetric in the
// complex plane)
template <symmetry_tag sym_type> struct IndependentComplexRDV {
using sym = sym_type;

static constexpr bool symmetric{is_symmetric_v<sym>};

ComplexValue<sym> value{};
RealValue<sym> variance{}; // variance (sigma^2) of the error range, in p.u.

explicit operator UniformComplexRDV<sym>() const {
return UniformComplexRDV<sym>{.value = value, .variance = sum_val(variance)};
}
};

// Complex measured value of a sensor in p.u. modeled as separate real and imaginary components with independent
// variances (rotationally symmetric)
template <symmetry_tag sym_type> struct DecomposedComplexRDV {
using sym = sym_type;

static constexpr bool symmetric{is_symmetric_v<sym>};

IndependentRealRDV<sym> real_component;
IndependentRealRDV<sym> imag_component;

ComplexValue<sym> value() const { return {real_component.value, imag_component.value}; }

explicit operator UniformComplexRDV<sym>() const {
return static_cast<UniformComplexRDV<sym>>(static_cast<IndependentComplexRDV<sym>>(*this));
}
explicit operator IndependentComplexRDV<sym>() const {
return IndependentComplexRDV<sym>{.value = value(),
.variance = real_component.variance + imag_component.variance};
}
};

// Complex measured value of a sensor in p.u. in polar coordinates (magnitude and angle)
// (rotationally symmetric)
template <symmetry_tag sym_type> struct PolarComplexRDV {
using sym = sym_type;

static constexpr bool symmetric{is_symmetric_v<sym>};

UniformRealRDV<sym> magnitude;
UniformRealRDV<sym> angle;

ComplexValue<sym> value() const { return magnitude.value * exp(1.0i * angle.value); }

explicit operator UniformComplexRDV<sym>() const {
return static_cast<UniformComplexRDV<sym>>(static_cast<IndependentComplexRDV<sym>>(*this));
}
explicit operator IndependentComplexRDV<sym>() const {
return IndependentComplexRDV<sym>{
.value = value(), .variance = magnitude.variance + magnitude.value * magnitude.value * angle.variance};
}
explicit operator DecomposedComplexRDV<sym>() const {
auto const cos_theta = cos(angle.value);
auto const sin_theta = sin(angle.value);
auto const real_component = magnitude.value * cos_theta;
auto const imag_component = magnitude.value * sin_theta;
return DecomposedComplexRDV<sym>{
.real_component = {.value = real_component,
.variance = magnitude.variance * cos_theta * cos_theta +
imag_component * imag_component * angle.variance},
.imag_component = {.value = imag_component,
.variance = magnitude.variance * sin_theta * sin_theta +
real_component * real_component * angle.variance}};
}
};
} // namespace power_grid_model
1 change: 1 addition & 0 deletions tests/cpp_unit_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ set(PROJECT_SOURCES
"test_component_output.cpp"
"test_component_update.cpp"
"test_three_phase_tensor.cpp"
"test_statistics.cpp"
"test_node.cpp"
"test_line.cpp"
"test_generic_branch.cpp"
Expand Down
Loading
Loading