Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -360,6 +360,7 @@ class Serializer {
static void json_convert_inf(nlohmann::json& json_document) {
switch (json_document.type()) {
case nlohmann::json::value_t::object:
[[fallthrough]];
case nlohmann::json::value_t::array:
for (auto& value : json_document) {
json_convert_inf(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ struct ComponentTopology {
IdxVector voltage_sensor_node_idx;
IdxVector power_sensor_object_idx; // the index is relative to branch, source, shunt, or load_gen
std::vector<MeasuredTerminalType> power_sensor_terminal_type;
IdxVector regulated_object_idx; // the index is relative to branch
std::vector<ComponentType> regulated_object_type;

inline Idx n_node_total() const { return n_node + static_cast<Idx>(branch3_node_idx.size()); }
};
Expand Down Expand Up @@ -369,7 +371,6 @@ struct Idx2DBranch3 {
// pos = -1 means not connected at that side, only applicable for branches
struct ComponentToMathCoupling {
std::vector<Idx2D> fault;
std::vector<Idx2D> transformer_tap_regulator; // TODO: should this be in TopologicalComponentToMathCoupling?
};

// couple component to math model
Expand All @@ -388,6 +389,7 @@ struct TopologicalComponentToMathCoupling {
std::vector<Idx2D> source;
std::vector<Idx2D> voltage_sensor;
std::vector<Idx2D> power_sensor; // can be coupled to branch-from/to, source, load_gen, or shunt sensor
std::vector<Idx2D> regulator;
};

// change of update cause topology and param change, or just param change
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class PowerGridError : public std::exception {

template <typename T> class MissingCaseForEnumError : public PowerGridError {
public:
MissingCaseForEnumError(const std::string& method, const T& value) {
MissingCaseForEnumError(std::string const& method, const T& value) {
append_msg(method + " is not implemented for " + typeid(T).name() + " #" + std::to_string(IntS(value)) + "!\n");
}
};
Expand Down Expand Up @@ -103,8 +103,18 @@ class IDNotFound : public PowerGridError {

class InvalidMeasuredObject : public PowerGridError {
public:
InvalidMeasuredObject(const std::string& object, const std::string& sensor) {
append_msg(sensor + " is not supported for " + object);
InvalidMeasuredObject(std::string const& object, std::string const& sensor) {
append_msg(sensor + " measurement is not supported for object of type " + object);
}
};

class InvalidRegulatedObject : public PowerGridError {
public:
InvalidRegulatedObject(std::string const& object, std::string const& regulator) {
append_msg(regulator + " regulator is not supported for object of type " + object);
}
InvalidRegulatedObject(ID id, std::string const& regulator) {
append_msg(regulator + " regulator is not supported for object with ID " + std::to_string(id));
}
};

Expand Down Expand Up @@ -172,7 +182,16 @@ class SerializationError : public PowerGridError {

class DatasetError : public PowerGridError {
public:
explicit DatasetError(std::string const& msg) { append_msg(msg); }
explicit DatasetError(std::string const& msg) { append_msg("Dataset error: " + msg); }
};

class UnreachableHit : public PowerGridError {
public:
UnreachableHit(std::string const& method, std::string const& reason_for_assumption) {
append_msg("Unreachable code hit when executing " + method +
".\n The following assumption for unreachability was not met: " + reason_for_assumption +
".\n This may be a bug in the library\n");
}
};

} // namespace power_grid_model
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,31 @@ class Branch : public Base {
}

// getter
ID from_node() const { return from_node_; }
ID to_node() const { return to_node_; }
bool from_status() const { return from_status_; }
bool to_status() const { return to_status_; }
bool branch_status() const { return from_status_ && to_status_; }
constexpr ID from_node() const { return from_node_; }
constexpr ID to_node() const { return to_node_; }
constexpr ID node(BranchSide side) const {
switch (side) {
case BranchSide::from:
return from_node();
case BranchSide::to:
return to_node();
default:
throw MissingCaseForEnumError{"node(BranchSide)", side};
}
}
constexpr bool from_status() const { return from_status_; }
constexpr bool to_status() const { return to_status_; }
constexpr bool branch_status() const { return from_status() && to_status(); }
constexpr bool status(BranchSide side) const {
switch (side) {
case BranchSide::from:
return from_status();
case BranchSide::to:
return to_status();
default:
throw MissingCaseForEnumError{"status(BranchSide)", side};
}
}
template <symmetry_tag sym> BranchCalcParam<sym> calc_param(bool is_connected_to_source = true) const {
if (!energized(is_connected_to_source)) {
return BranchCalcParam<sym>{};
Expand Down Expand Up @@ -175,9 +195,9 @@ class Branch : public Base {
double const tap = cabs(tap_ratio);
BranchCalcParam<symmetric_t> param{};
// not both connected
if (!(from_status_ && to_status_)) {
if (!branch_status()) {
// single connected
if (from_status_ || to_status_) {
if (from_status() || to_status()) {
DoubleComplex branch_shunt;
// shunt value
if (cabs(y_shunt) < numerical_tolerance) {
Expand All @@ -187,8 +207,8 @@ class Branch : public Base {
branch_shunt = 0.5 * y_shunt + 1.0 / (1.0 / y_series + 2.0 / y_shunt);
}
// from or to connected
param.yff() = from_status_ ? (1.0 / tap / tap) * branch_shunt : 0.0;
param.ytt() = to_status_ ? branch_shunt : 0.0;
param.yff() = from_status() ? (1.0 / tap / tap) * branch_shunt : 0.0;
param.ytt() = to_status() ? branch_shunt : 0.0;
}
}
// both connected
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,46 @@ class Branch3 : public Base {
}

// getter
ID node_1() const { return node_1_; }
ID node_2() const { return node_2_; }
ID node_3() const { return node_3_; }
bool status_1() const { return status_1_; }
bool status_2() const { return status_2_; }
bool status_3() const { return status_3_; }
bool branch3_status() const {
return status_1_ && status_2_ && status_3_; // TODO: check if this makes sense for branch3
constexpr ID node_1() const { return node_1_; }
constexpr ID node_2() const { return node_2_; }
constexpr ID node_3() const { return node_3_; }
constexpr ID node(Branch3Side side) const {
using enum Branch3Side;

switch (side) {
case side_1:
return node_1();
case side_2:
return node_2();
case side_3:
return node_3();
default:
throw MissingCaseForEnumError{"node(Branch3Side)", side};
}
}
constexpr bool status_1() const { return status_1_; }
constexpr bool status_2() const { return status_2_; }
constexpr bool status_3() const { return status_3_; }
constexpr bool branch3_status() const {
return status_1() && status_2() && status_3(); // TODO: check if this makes sense for branch3
}
constexpr bool status(Branch3Side side) const {
using enum Branch3Side;

switch (side) {
case side_1:
return status_1();
case side_2:
return status_2();
case side_3:
return status_3();
default:
throw MissingCaseForEnumError{"status(Branch3Side)", side};
}
}

// virtual getter
bool energized(bool is_connected_to_source = true) const final {
constexpr bool energized(bool is_connected_to_source = true) const final {
return is_connected_to_source && (status_1_ || status_2_ || status_3_);
}
virtual double base_i_1() const = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class Regulator : public Base {
static constexpr char const* name = "regulator";

ID regulated_object() const { return regulated_object_; };
ComponentType regulated_object_type() const { return regulated_object_type_; };

// regulator always energized
bool energized(bool /* is_connected_to_source */) const final { return true; }
Expand All @@ -35,9 +36,10 @@ class Regulator : public Base {

protected:
// constructor
explicit Regulator(RegulatorInput const& regulator_input)
explicit Regulator(RegulatorInput const& regulator_input, ComponentType regulated_object_type)
: Base{regulator_input},
regulated_object_{regulator_input.regulated_object},
regulated_object_type_{regulated_object_type},
status_{regulator_input.status != 0} {}

Regulator(Regulator const&) = default;
Expand All @@ -50,6 +52,7 @@ class Regulator : public Base {

private:
ID regulated_object_;
ComponentType regulated_object_type_;
bool status_;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,14 @@ class ThreeWindingTransformer : public Branch3 {
std::array<double, 3> phase_shift() const final { return {0.0, -clock_12_ * deg_30, -clock_13_ * deg_30}; }

// getters
IntS tap_pos() const { return tap_pos_; }
Branch3Side tap_side() const { return tap_side_; }
IntS tap_min() const { return tap_min_; }
IntS tap_max() const { return tap_max_; }
IntS tap_nom() const { return tap_nom_; }
constexpr IntS tap_pos() const { return tap_pos_; }
constexpr Branch3Side tap_side() const { return tap_side_; }
constexpr IntS tap_min() const { return tap_min_; }
constexpr IntS tap_max() const { return tap_max_; }
constexpr IntS tap_nom() const { return tap_nom_; }

// setter
bool set_tap(IntS new_tap) {
constexpr bool set_tap(IntS new_tap) {
if (new_tap == na_IntS || new_tap == tap_pos_) {
return false;
}
Expand Down Expand Up @@ -190,7 +190,7 @@ class ThreeWindingTransformer : public Branch3 {
DoubleComplex z_grounding_2_;
DoubleComplex z_grounding_3_;

IntS tap_limit(IntS new_tap) const {
constexpr IntS tap_limit(IntS new_tap) const {
new_tap = std::min(new_tap, std::max(tap_max_, tap_min_));
new_tap = std::max(new_tap, std::min(tap_max_, tap_min_));
return new_tap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ class Transformer : public Branch {
double phase_shift() const final { return clock_ * deg_30; }
bool is_param_mutable() const final { return true; }
// getters
IntS tap_pos() const { return tap_pos_; }
BranchSide tap_side() const { return tap_side_; }
IntS tap_min() const { return tap_min_; }
IntS tap_max() const { return tap_max_; }
IntS tap_nom() const { return tap_nom_; }
constexpr IntS tap_pos() const { return tap_pos_; }
constexpr BranchSide tap_side() const { return tap_side_; }
constexpr IntS tap_min() const { return tap_min_; }
constexpr IntS tap_max() const { return tap_max_; }
constexpr IntS tap_nom() const { return tap_nom_; }

// setter
bool set_tap(IntS new_tap) {
constexpr bool set_tap(IntS new_tap) {
if (new_tap == na_IntS || new_tap == tap_pos_) {
return false;
}
Expand Down Expand Up @@ -142,7 +142,7 @@ class Transformer : public Branch {
return {r / base_z, x / base_z};
}

IntS tap_limit(IntS new_tap) const {
constexpr IntS tap_limit(IntS new_tap) const {
new_tap = std::min(new_tap, std::max(tap_max_, tap_min_));
new_tap = std::max(new_tap, std::min(tap_max_, tap_min_));
return new_tap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class TransformerTapRegulator : public Regulator {
static constexpr char const* name = "transformer_tap_regulator";

explicit TransformerTapRegulator(TransformerTapRegulatorInput const& transformer_tap_regulator_input,
double u_rated)
: Regulator{transformer_tap_regulator_input},
ComponentType regulated_object_type, double u_rated)
: Regulator{transformer_tap_regulator_input, regulated_object_type},
control_side_{transformer_tap_regulator_input.control_side},
u_rated_{u_rated},
u_set_{transformer_tap_regulator_input.u_set},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class Container<RetrievableTypes<GettableTypes...>, StorageableTypes...> {
return cum_size[get_sub_cls_pos_v<StorageableSubType, StorageableTypes...>];
}

template <class Storageable> Idx get_type_idx() const {
template <class Storageable> static constexpr Idx get_type_idx() {
return static_cast<Idx>(get_type_index<Storageable, StorageableTypes...>());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ inline void add_component(MainModelState<ComponentContainer>& state, ForwardIter
using enum MeasuredTerminalType;

case branch_from:
[[fallthrough]];
case branch_to:
state.components.template get_item<Branch>(measured_object);
break;
Expand Down Expand Up @@ -91,6 +92,47 @@ inline void add_component(MainModelState<ComponentContainer>& state, ForwardIter
// check that fault object exists (currently, only faults at nodes are supported)
state.components.template get_item<Node>(input.fault_object);
state.components.template emplace<Component>(id, input);
} else if constexpr (std::derived_from<Component, TransformerTapRegulator>) {
Idx2D const regulated_object_idx = state.components.get_idx_by_id(input.regulated_object);

ID const regulated_terminal = [&input, &state, &regulated_object_idx] {
using enum ControlSide;

if (regulated_object_idx.group == state.components.template get_type_idx<Transformer>()) {
auto const& regulated_object =
state.components.template get_item<Transformer>(regulated_object_idx);
switch (input.control_side) {
case to:
[[fallthrough]];
case from:
return regulated_object.node(static_cast<BranchSide>(input.control_side));
default:
throw MissingCaseForEnumError{std::string{Component::name} + " item retrieval",
input.control_side};
}
} else if (regulated_object_idx.group ==
state.components.template get_type_idx<ThreeWindingTransformer>()) {
auto const& regulated_object =
state.components.template get_item<ThreeWindingTransformer>(regulated_object_idx);
switch (input.control_side) {
case side_1:
case side_2:
case side_3:
return regulated_object.node(static_cast<Branch3Side>(input.control_side));
default:
throw MissingCaseForEnumError{std::string{Component::name} + " item retrieval",
input.control_side};
}
} else {
throw InvalidRegulatedObject(input.regulated_object, Component::name);
}
}();

auto const regulated_object_type =
state.components.template get_item<Base>(regulated_object_idx).math_model_type();
double const u_rated = state.components.template get_item<Node>(regulated_terminal).u_rated();

state.components.template emplace<Component>(id, input, regulated_object_type, u_rated);
}
}
}
Expand Down
Loading