Skip to content

Commit

Permalink
#815 Add the possibility to specify in the assembling the side of which
Browse files Browse the repository at this point in the history
the SVC is regulating for hvdcs
closes #815

Signed-off-by: Florentine Rosiere <[email protected]>
  • Loading branch information
rosiereflo authored and gaouizer committed Dec 18, 2024
1 parent 901fea6 commit baed753
Show file tree
Hide file tree
Showing 28 changed files with 1,969 additions and 80 deletions.
8 changes: 8 additions & 0 deletions etc/xsd/assembling_dynaflow.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,16 @@ SPDX-License-Identifier: MPL-2.0 -->

<xs:complexType name="HVDC">
<xs:attribute name="name" use="required" type="xs:string"/>
<xs:attribute name="converterStation1" use="optional" type="converterStationSide"/>
</xs:complexType>

<xs:simpleType name="converterStationSide">
<xs:restriction base="xs:string">
<xs:enumeration value="SIDE1"/>
<xs:enumeration value="SIDE2"/>
</xs:restriction>
</xs:simpleType>

<xs:complexType name="MacroConnect">
<xs:attribute name="macroConnection" use="required" type="xs:string"/>
<xs:attribute name="id" use="required" type="xs:string"/>
Expand Down
41 changes: 33 additions & 8 deletions sources/Algo/include/HVDCDefinitionAlgorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,13 @@ class HVDCDefinition {
HvdcPVRpcl2Side1,
HvdcPVDiagramPQRpcl2Side1,
HvdcPVDanglingRpcl2Side1,
HvdcPVDanglingDiagramPQRpcl2Side1
HvdcPVDanglingDiagramPQRpcl2Side1,
HvdcPVEmulationSetRpcl2Side2,
HvdcPVDiagramPQEmulationSetRpcl2Side2,
HvdcPVRpcl2Side2,
HvdcPVDiagramPQRpcl2Side2,
HvdcPVDanglingRpcl2Side2,
HvdcPVDanglingDiagramPQRpcl2Side2
};

/**
Expand All @@ -135,7 +141,8 @@ class HVDCDefinition {
model == HVDCModel::HvdcPTanPhiDiagramPQ || model == HVDCModel::HvdcPQPropDiagramPQ || model == HVDCModel::HvdcPQPropDiagramPQEmulationSet ||
model == HVDCModel::HvdcPVDiagramPQ || model == HVDCModel::HvdcPVDiagramPQEmulationSet ||
model == HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side1 || model == HVDCModel::HvdcPVDiagramPQRpcl2Side1 ||
model == HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side1;
model == HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side1 || model == HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side2 ||
model == HVDCModel::HvdcPVDiagramPQRpcl2Side2 || model == HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side2;
}

/**
Expand All @@ -145,7 +152,8 @@ class HVDCDefinition {
bool hasEmulationModel() const {
return model == HVDCModel::HvdcPQPropEmulationSet || model == HVDCModel::HvdcPQPropDiagramPQEmulationSet || model == HVDCModel::HvdcPVEmulationSet ||
model == HVDCModel::HvdcPVDiagramPQEmulationSet || model == HVDCModel::HvdcPVEmulationSetRpcl2Side1 ||
model == HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side1;
model == HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side1 || model == HVDCModel::HvdcPVEmulationSetRpcl2Side2 ||
model == HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side2;
}

/**
Expand All @@ -164,7 +172,8 @@ class HVDCDefinition {
bool hasDanglingModel() const {
return model == HVDCModel::HvdcPTanPhiDangling || model == HVDCModel::HvdcPTanPhiDanglingDiagramPQ || model == HVDCModel::HvdcPQPropDangling ||
model == HVDCModel::HvdcPQPropDanglingDiagramPQ || model == HVDCModel::HvdcPVDangling || model == HVDCModel::HvdcPVDanglingDiagramPQ ||
model == HVDCModel::HvdcPVDanglingRpcl2Side1 || model == HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side1;
model == HVDCModel::HvdcPVDanglingRpcl2Side1 || model == HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side1 ||
model == HVDCModel::HvdcPVDanglingRpcl2Side2 || model == HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side2;
}
/**
* @brief test is the HVDC definition has a reactive power control loop 2 for connection to the secondary voltage control
Expand All @@ -174,7 +183,19 @@ class HVDCDefinition {
bool hasRpcl2() const {
return model == HVDCModel::HvdcPVEmulationSetRpcl2Side1 || model == HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side1 ||
model == HVDCModel::HvdcPVRpcl2Side1 || model == HVDCModel::HvdcPVDiagramPQRpcl2Side1 || model == HVDCModel::HvdcPVDanglingRpcl2Side1 ||
model == HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side1;
model == HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side1 || model == HVDCModel::HvdcPVEmulationSetRpcl2Side2 ||
model == HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side2 || model == HVDCModel::HvdcPVRpcl2Side2 || model == HVDCModel::HvdcPVDiagramPQRpcl2Side2 ||
model == HVDCModel::HvdcPVDanglingRpcl2Side2 || model == HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side2;
}
/**
* @brief test is the HVDC definition has a reactive power control loop 2 for connection to the secondary voltage control
*
* @return @b true if the HVDC definition has a reactive power control loop 2 for connection to the secondary voltage control, @b false otherwise
*/
bool converterStationOnSide2() const {
return model == HVDCModel::HvdcPVEmulationSetRpcl2Side2 || model == HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side2 ||
model == HVDCModel::HvdcPVRpcl2Side2 || model == HVDCModel::HvdcPVDiagramPQRpcl2Side2 || model == HVDCModel::HvdcPVDanglingRpcl2Side2 ||
model == HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side2;
}

/**
Expand All @@ -201,18 +222,20 @@ class HVDCDefinition {
* @param pSetPoint active power set-point of the hvdc line in MW
* @param rdc dc resistance of the hvdc line in Ohm
* @param lossFactors loss factors for converters 1 and 2
* @param ConverterStationSide1 whether the side1 of the hvdc should be connected to the side1 of the network
*/
explicit HVDCDefinition(const HvdcLineId &id, const inputs::HvdcLine::ConverterType converterType, const ConverterId &converter1Id,
const BusId &converter1BusId, const boost::optional<bool> &converter1VoltageRegulationOn, const ConverterId &converter2Id,
const BusId &converter2BusId, const boost::optional<bool> &converter2VoltageRegulationOn, const Position position,
const HVDCModel &model, const std::array<double, 2> &powerFactors, double pMax, const boost::optional<VSCDefinition> &vscDefinition1,
const boost::optional<VSCDefinition> &vscDefinition2, const boost::optional<double> &droop, const boost::optional<double> &p0,
bool isConverter1Rectifier, const double vdcNom, const double pSetPoint, const double rdc, const std::array<double, 2> &lossFactors)
bool isConverter1Rectifier, const double vdcNom, const double pSetPoint, const double rdc, const std::array<double, 2> &lossFactors,
bool ConverterStationSide1)
: id{id}, converterType{converterType}, converter1Id{converter1Id}, converter1BusId{converter1BusId},
converter1VoltageRegulationOn{converter1VoltageRegulationOn}, converter2Id{converter2Id}, converter2BusId{converter2BusId},
converter2VoltageRegulationOn{converter2VoltageRegulationOn}, position{position}, model{model}, powerFactors(powerFactors), pMax{pMax},
vscDefinition1(vscDefinition1), vscDefinition2(vscDefinition2), droop(droop), p0(p0), isConverter1Rectifier{isConverter1Rectifier}, vdcNom(vdcNom),
pSetPoint(pSetPoint), rdc(rdc), lossFactors(lossFactors) {}
pSetPoint(pSetPoint), rdc(rdc), lossFactors(lossFactors), ConverterStationSide1(ConverterStationSide1) {}

const HvdcLineId id; ///< HvdcLine id
const ConverterType converterType; ///< type of converter of the hvdc line
Expand All @@ -235,6 +258,7 @@ class HVDCDefinition {
const double pSetPoint; ///< active power set-point of the hvdc line in MW
const double rdc; ///< dc resistance of the hvdc line in Ohm
const std::array<double, 2> lossFactors; ///< loss factors for converters 1 and 2
const bool ConverterStationSide1; ///< whether the side1 of the hvdc should be connected to the side1 of the network
};

/// @brief HVDC line definitions
Expand Down Expand Up @@ -328,7 +352,8 @@ class HVDCDefinitionAlgorithm {
const inputs::NetworkManager::BusMapRegulating &busesToNumberOfRegulationMap_; ///< mapping of busId and the number of generators that regulates them
const bool infiniteReactiveLimits_; ///< whether we use infinite reactive limits
std::unordered_map<inputs::Converter::ConverterId, std::shared_ptr<inputs::Converter>> vscConverters_; ///< List of VSC converters to use
std::unordered_set<std::string> hvdcLinesInSVC; ///< If a hvdc line id is in this map then it belongs to a secondary voltage control area
std::unordered_map<std::string, inputs::AssemblingDataBase::HvdcLineConverterSide>
hvdcLinesInSVC_; ///< If a hvdc line id is in this map then it belongs to a secondary voltage control area
};

} // namespace algo
Expand Down
54 changes: 39 additions & 15 deletions sources/Algo/src/HVDCDefinitionAlgorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ HVDCDefinitionAlgorithm::HVDCDefinitionAlgorithm(HVDCLineDefinitions &hvdcLinesD
if (manager.assembling().isSingleAssociation(macroConn.id)) {
const auto &assoc = manager.assembling().getSingleAssociation(macroConn.id);
if (assoc.hvdcLine) {
hvdcLinesInSVC.insert(assoc.hvdcLine.get().name);
hvdcLinesInSVC_[assoc.hvdcLine.get().name] = assoc.hvdcLine.get().converterStation1;
}
}
}
Expand Down Expand Up @@ -80,27 +80,39 @@ auto HVDCDefinitionAlgorithm::computeModelVSC(const inputs::HvdcLine &hvdcline,

auto HVDCDefinitionAlgorithm::computeModel(const inputs::HvdcLine &hvdcline, HVDCDefinition::Position position, inputs::HvdcLine::ConverterType type) const
-> HVDCModelDefinition {
const bool isInSVC = hvdcLinesInSVC.find(hvdcline.id) != hvdcLinesInSVC.end();
const auto &itHvdc = hvdcLinesInSVC_.find(hvdcline.id);
const bool isInSVC = itHvdc != hvdcLinesInSVC_.end();
const bool converterSide1 = isInSVC && itHvdc->second == inputs::AssemblingDataBase::HvdcLineConverterSide::SIDE1;
if (position == HVDCDefinition::Position::BOTH_IN_MAIN_COMPONENT) {
if (type == inputs::HvdcLine::ConverterType::LCC) {
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPTanPhi : HVDCDefinition::HVDCModel::HvdcPTanPhiDiagramPQ};
} else {
const bool hvdcAngleDroopActivePowerControlIsEnabled = hvdcline.activePowerControl.has_value();
if (!hvdcAngleDroopActivePowerControlIsEnabled) {
if (isInSVC)
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPVRpcl2Side1
: HVDCDefinition::HVDCModel::HvdcPVDiagramPQRpcl2Side1};
else
if (isInSVC) {
if (converterSide1)
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPVRpcl2Side1
: HVDCDefinition::HVDCModel::HvdcPVDiagramPQRpcl2Side1};
else
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPVRpcl2Side2
: HVDCDefinition::HVDCModel::HvdcPVDiagramPQRpcl2Side2};
} else {
return computeModelVSC(hvdcline, position, HVDCDefinition::HVDCModel::HvdcPQProp, HVDCDefinition::HVDCModel::HvdcPQPropDiagramPQ,
HVDCDefinition::HVDCModel::HvdcPV, HVDCDefinition::HVDCModel::HvdcPVDiagramPQ);
}
} else {
if (isInSVC)
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPVEmulationSetRpcl2Side1
: HVDCDefinition::HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side1};
else
if (isInSVC) {
if (converterSide1)
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPVEmulationSetRpcl2Side1
: HVDCDefinition::HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side1};
else
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPVEmulationSetRpcl2Side2
: HVDCDefinition::HVDCModel::HvdcPVDiagramPQEmulationSetRpcl2Side2};
} else {
return computeModelVSC(hvdcline, position, HVDCDefinition::HVDCModel::HvdcPQPropEmulationSet,
HVDCDefinition::HVDCModel::HvdcPQPropDiagramPQEmulationSet, HVDCDefinition::HVDCModel::HvdcPVEmulationSet,
HVDCDefinition::HVDCModel::HvdcPVDiagramPQEmulationSet);
}
}
}
} else {
Expand All @@ -109,19 +121,25 @@ auto HVDCDefinitionAlgorithm::computeModel(const inputs::HvdcLine &hvdcline, HVD
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPTanPhiDangling
: HVDCDefinition::HVDCModel::HvdcPTanPhiDanglingDiagramPQ};
} else {
if (isInSVC)
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPVDanglingRpcl2Side1
: HVDCDefinition::HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side1};
else
if (isInSVC) {
if (converterSide1)
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPVDanglingRpcl2Side1
: HVDCDefinition::HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side1};
else
return HVDCModelDefinition{infiniteReactiveLimits_ ? HVDCDefinition::HVDCModel::HvdcPVDanglingRpcl2Side2
: HVDCDefinition::HVDCModel::HvdcPVDanglingDiagramPQRpcl2Side2};
} else {
return computeModelVSC(hvdcline, position, HVDCDefinition::HVDCModel::HvdcPQPropDangling, HVDCDefinition::HVDCModel::HvdcPQPropDanglingDiagramPQ,
HVDCDefinition::HVDCModel::HvdcPVDangling, HVDCDefinition::HVDCModel::HvdcPVDanglingDiagramPQ);
}
}
}
}

std::pair<std::reference_wrapper<HVDCDefinition>, bool> HVDCDefinitionAlgorithm::getOrCreateHvdcLineDefinition(const inputs::HvdcLine &hvdcLine) {
auto &hvdcLines = hvdcLinesDefinitions_.hvdcLines;
auto it = hvdcLines.find(hvdcLine.id);
const auto &hvdcIt = hvdcLinesInSVC_.find(hvdcLine.id);
bool alreadyInserted = it != hvdcLines.end();
if (alreadyInserted) {
return {std::ref(it->second), alreadyInserted};
Expand All @@ -145,12 +163,18 @@ std::pair<std::reference_wrapper<HVDCDefinition>, bool> HVDCDefinitionAlgorithm:
voltageRegulation2 = converterVSC2->voltageRegulationOn;
}

inputs::AssemblingDataBase::HvdcLineConverterSide side = inputs::AssemblingDataBase::HvdcLineConverterSide::SIDE1; // by default
// side 1 of dynamic model is connected to the side 1 of the static model
if (hvdcIt != hvdcLinesInSVC_.end()) {
side = hvdcIt->second;
}
boost::optional<double> droop = (hvdcLine.activePowerControl) ? hvdcLine.activePowerControl->droop : boost::optional<double>();
boost::optional<double> p0 = (hvdcLine.activePowerControl) ? hvdcLine.activePowerControl->p0 : boost::optional<double>();
HVDCDefinition createdHvdcLine(hvdcLine.id, hvdcLine.converterType, hvdcLine.converter1->converterId, hvdcLine.converter1->busId, voltageRegulation1,
hvdcLine.converter2->converterId, hvdcLine.converter2->busId, voltageRegulation2,
HVDCDefinition::Position::BOTH_IN_MAIN_COMPONENT, HVDCDefinition::HVDCModel::HvdcPTanPhi, powerFactors, hvdcLine.pMax, def1,
def2, droop, p0, hvdcLine.isConverter1Rectifier, hvdcLine.vdcNom, hvdcLine.pSetPoint, hvdcLine.rdc, hvdcLine.lossFactors);
def2, droop, p0, hvdcLine.isConverter1Rectifier, hvdcLine.vdcNom, hvdcLine.pSetPoint, hvdcLine.rdc, hvdcLine.lossFactors,
side == inputs::AssemblingDataBase::HvdcLineConverterSide::SIDE1);
auto pair = hvdcLines.emplace(hvdcLine.id, createdHvdcLine);
return {std::ref(pair.first->second), alreadyInserted};
}
Expand Down
9 changes: 8 additions & 1 deletion sources/Inputs/include/AssemblingDataBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ namespace inputs {
*/
class AssemblingDataBase {
public:
/// @brief Different tables in the diagram, qmin or qmax
enum class HvdcLineConverterSide {
SIDE1 = 0, ///< Side 1
SIDE2 ///< Side 2
};

/**
* @brief Connection XML element
*/
Expand Down Expand Up @@ -93,7 +99,8 @@ class AssemblingDataBase {
* @brief Hvdc line XML element
*/
struct HvdcLine {
std::string name; ///< name of the Hvdc line
std::string name; ///< name of the Hvdc line
HvdcLineConverterSide converterStation1; ///< side of the network on which the side1 of the hvdc should be connected
};

/**
Expand Down
2 changes: 1 addition & 1 deletion sources/Inputs/include/HvdcLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@

#include "Behaviours.h"

#include <array>
#include <boost/optional.hpp>
#include <string>
#include <array>

namespace dfl {
namespace inputs {
Expand Down
10 changes: 9 additions & 1 deletion sources/Inputs/src/AssemblingDataBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,15 @@ AssemblingDataBase::AssemblingXmlDocument::TfoHandler::TfoHandler(const elementN
}

AssemblingDataBase::AssemblingXmlDocument::HvdcLineHandler::HvdcLineHandler(const elementName_type &root) {
onStartElement(root, [this](const parser::ElementName &, const attributes_type &attributes) { currentHvdcLine->name = attributes["name"].as_string(); });
onStartElement(root, [this](const parser::ElementName &, const attributes_type &attributes) {
currentHvdcLine->name = attributes["name"].as_string();
currentHvdcLine->converterStation1 = AssemblingDataBase::HvdcLineConverterSide::SIDE1;
if (attributes.has("converterStation1")) {
if (attributes["converterStation1"].as_string() == "SIDE2") {
currentHvdcLine->converterStation1 = AssemblingDataBase::HvdcLineConverterSide::SIDE2;
}
}
});
}

AssemblingDataBase::AssemblingXmlDocument::SingleShuntHandler::SingleShuntHandler(const elementName_type &root) {
Expand Down
Loading

0 comments on commit baed753

Please sign in to comment.