From 489f5b0bc3daf70fa0f05d40bdfdac2e5cdae5f7 Mon Sep 17 00:00:00 2001 From: Le Courtois Florent Date: Tue, 5 Oct 2021 13:03:30 +0200 Subject: [PATCH] #216 Add shunt connections to dyd --- sources/Algo/include/Algo.h | 3 +- sources/Context.cpp | 2 +- sources/Outputs/include/Constants.h | 5 ++ sources/Outputs/include/Dyd.h | 11 +++- sources/Outputs/src/Dyd.cpp | 58 ++++++++++++++++--- tests/outputs/TestDyd.cpp | 55 ++++++++++++++++-- .../reference/TestDydShunts/TestDydShunts.dyd | 46 +++++++++++++++ 7 files changed, 164 insertions(+), 16 deletions(-) create mode 100644 tests/outputs/reference/TestDydShunts/TestDydShunts.dyd diff --git a/sources/Algo/include/Algo.h b/sources/Algo/include/Algo.h index 26e4d8270..e09f717d0 100644 --- a/sources/Algo/include/Algo.h +++ b/sources/Algo/include/Algo.h @@ -867,8 +867,9 @@ struct VLShuntsDefinition { struct ShuntHash { size_t operator()(const inputs::Shunt& shunt) const noexcept; }; + using ShuntsSet = std::unordered_set; - std::unordered_set shunts; + ShuntsSet shunts; bool dynamicModelAssociated = false; }; diff --git a/sources/Context.cpp b/sources/Context.cpp index 8b0e277c4..46e3a7c37 100644 --- a/sources/Context.cpp +++ b/sources/Context.cpp @@ -159,7 +159,7 @@ Context::exportOutputs() { file::path dydOutput(config_.outputDir()); dydOutput.append(basename_ + ".dyd"); outputs::Dyd dydWriter(outputs::Dyd::DydDefinition(basename_, dydOutput.generic_string(), generators_, loads_, slackNode_, hvdcLineDefinitions_, - busesWithDynamicModel_, dynamicDataBaseManager_, dynamicModels_, svarcsDefinitions_)); + busesWithDynamicModel_, dynamicDataBaseManager_, dynamicModels_, svarcsDefinitions_, shunts_)); dydWriter.write(); // Par diff --git a/sources/Outputs/include/Constants.h b/sources/Outputs/include/Constants.h index f8cccaeb6..252c28775 100644 --- a/sources/Outputs/include/Constants.h +++ b/sources/Outputs/include/Constants.h @@ -59,6 +59,11 @@ computeQmax(double powerFactor, double pMax) { */ std::string diagramFilename(const std::string& id); +static inline std::string +computeShuntRegulationId(const std::string& busId) { + return "ShuntRegulation_" + busId; +} + const std::string loadParId{"GenericRestorativeLoad"}; ///< PAR id common to all loads const std::string diagramDirectorySuffix{"_Diagram"}; ///< Suffix for the diagram directory const std::string diagramMaxTableSuffix{"_tableqmax"}; ///< Suffix for the table name for qmax in diagram file diff --git a/sources/Outputs/include/Dyd.h b/sources/Outputs/include/Dyd.h index 9373d231b..c051bb815 100644 --- a/sources/Outputs/include/Dyd.h +++ b/sources/Outputs/include/Dyd.h @@ -109,7 +109,7 @@ class Dyd { const std::vector& loaddefs, const std::shared_ptr& slacknode, const algo::HVDCLineDefinitions& hvdcDefinitions, const algo::GeneratorDefinitionAlgorithm::BusGenMap& busesWithDynamicModel, const inputs::DynamicDataBaseManager& dynamicDataBaseManager, const algo::DynamicModelDefinitions& models, - const algo::StaticVarCompensatorDefinitions& svarcsDefinitions) : + const algo::StaticVarCompensatorDefinitions& svarcsDefinitions, const algo::ShuntDefinitions& shuntsDefinitions) : basename(base), filename(filepath), generators(gens), @@ -119,7 +119,8 @@ class Dyd { busesWithDynamicModel(busesWithDynamicModel), dynamicDataBaseManager(dynamicDataBaseManager), dynamicModelsDefinitions(models), - svarcsDefinitions(svarcsDefinitions) {} + svarcsDefinitions(svarcsDefinitions), + shuntsDefinitions(shuntsDefinitions) {} std::string basename; ///< basename for file std::string filename; ///< filepath for file to write @@ -131,6 +132,7 @@ class Dyd { const inputs::DynamicDataBaseManager& dynamicDataBaseManager; ///< dynamic database manager const algo::DynamicModelDefinitions& dynamicModelsDefinitions; ///< the list of dynamic models to export const algo::StaticVarCompensatorDefinitions& svarcsDefinitions; ///< the SVarC definitions to use + const algo::ShuntDefinitions& shuntsDefinitions; }; /** @@ -186,6 +188,8 @@ class Dyd { */ static boost::shared_ptr writeHvdcLine(const algo::HVDCDefinition& hvdcLine, const std::string& basename); + static boost::shared_ptr writeShuntRegulation(const inputs::Shunt::BusId& busId, const std::string& basename); + /** * @brief Create constant models * @@ -302,6 +306,9 @@ class Dyd { */ static boost::shared_ptr writeSVarCMacroConnect(const inputs::StaticVarCompensator& svarc); + static std::unordered_map>> + computeShuntsByIds(const algo::ShuntDefinitions& shuntDefinitions); + private: static const std::unordered_map correspondence_lib_; ///< Correspondance between generator model type and library name in dyd file diff --git a/sources/Outputs/src/Dyd.cpp b/sources/Outputs/src/Dyd.cpp index 93ce65383..c899597bc 100644 --- a/sources/Outputs/src/Dyd.cpp +++ b/sources/Outputs/src/Dyd.cpp @@ -151,7 +151,17 @@ Dyd::write() const { dynamicModelsToConnect->addMacroConnect(writeSVarCMacroConnect(svarc)); } - dynamicModelsToConnect->addConnect(signalNModelName_, "signalN_thetaRef", "NETWORK", def_.slackNode->id + "_phi"); + auto shuntsByBusId = computeShuntsByIds(def_.shuntsDefinitions); + for (const auto& shuntPair : shuntsByBusId) { + dynamicModelsToConnect->addModel(writeShuntRegulation(shuntPair.first, def_.basename)); + auto modelId = constants::computeShuntRegulationId(shuntPair.first); + dynamicModelsToConnect->addConnect(modelId, "UMonitoredPu_value", networkModelName_, shuntPair.first); + for (unsigned int i = 0; i < shuntPair.second.size(); i++) { + dynamicModelsToConnect->addConnect(modelId, "section_" + std::to_string(i) + "_value", networkModelName_, shuntPair.second.at(i).get().id); + } + } + + dynamicModelsToConnect->addConnect(signalNModelName_, "signalN_thetaRef", networkModelName_, def_.slackNode->id + "_phi"); for (auto it = def_.generators.cbegin(); it != def_.generators.cend(); ++it) { writeGenConnect(dynamicModelsToConnect, *it); @@ -268,6 +278,17 @@ Dyd::writeHvdcLine(const algo::HVDCDefinition& hvdcLine, const std::string& base return model; } +boost::shared_ptr +Dyd::writeShuntRegulation(const inputs::Shunt::BusId& busId, const std::string& basename) { + auto id = constants::computeShuntRegulationId(busId); + auto model = dynamicdata::BlackBoxModelFactory::newModel(id); + model->setLib("DYNModelCentralizedShuntsSectionControl"); + model->setParFile(basename + ".par"); + model->setParId(id); + + return model; +} + boost::shared_ptr Dyd::writeLoad(const algo::LoadDefinition& load, const std::string& basename) { auto model = dynamicdata::BlackBoxModelFactory::newModel(load.id); @@ -409,7 +430,7 @@ Dyd::writeSVarCMacroConnect(const inputs::StaticVarCompensator& svarc) { void Dyd::writeGenConnect(const boost::shared_ptr& dynamicModelsToConnect, const algo::GeneratorDefinition& def) { if (def.model == algo::GeneratorDefinition::ModelType::REMOTE_SIGNALN || def.model == algo::GeneratorDefinition::ModelType::REMOTE_DIAGRAM_PQ_SIGNALN) { - dynamicModelsToConnect->addConnect(def.id, "generator_URegulated", "NETWORK", def.regulatedBusId + "_U_value"); + dynamicModelsToConnect->addConnect(def.id, "generator_URegulated", networkModelName_, def.regulatedBusId + "_U_value"); } else if (def.model == algo::GeneratorDefinition::ModelType::PROP_SIGNALN || def.model == algo::GeneratorDefinition::ModelType::PROP_DIAGRAM_PQ_SIGNALN) { dynamicModelsToConnect->addConnect(def.id, "generator_NQ_value", modelSignalNQprefix_ + def.regulatedBusId, "vrremote_NQ"); } @@ -417,19 +438,19 @@ Dyd::writeGenConnect(const boost::shared_ptr& dynamicModelsToConnect, const std::string& busId) { - dynamicModelsToConnect->addConnect(modelSignalNQprefix_ + busId, "vrremote_URegulated", "NETWORK", busId + "_U_value"); + dynamicModelsToConnect->addConnect(modelSignalNQprefix_ + busId, "vrremote_URegulated", networkModelName_, busId + "_U_value"); } void Dyd::writeHvdcLineConnect(const boost::shared_ptr& dynamicModelsToConnect, const algo::HVDCDefinition& hvdcDefinition) { const std::string vrremoteNqValue("vrremote_NQ"); if (hvdcDefinition.position == algo::HVDCDefinition::Position::SECOND_IN_MAIN_COMPONENT) { - dynamicModelsToConnect->addConnect("NETWORK", hvdcDefinition.converter1BusId + "_ACPIN", hvdcDefinition.id, "hvdc_terminal2"); - dynamicModelsToConnect->addConnect("NETWORK", hvdcDefinition.converter2BusId + "_ACPIN", hvdcDefinition.id, "hvdc_terminal1"); + dynamicModelsToConnect->addConnect(networkModelName_, hvdcDefinition.converter1BusId + "_ACPIN", hvdcDefinition.id, "hvdc_terminal2"); + dynamicModelsToConnect->addConnect(networkModelName_, hvdcDefinition.converter2BusId + "_ACPIN", hvdcDefinition.id, "hvdc_terminal1"); } else { // case both : 1 <-> 1 and 2 <-> 2 - dynamicModelsToConnect->addConnect("NETWORK", hvdcDefinition.converter1BusId + "_ACPIN", hvdcDefinition.id, "hvdc_terminal1"); - dynamicModelsToConnect->addConnect("NETWORK", hvdcDefinition.converter2BusId + "_ACPIN", hvdcDefinition.id, "hvdc_terminal2"); + dynamicModelsToConnect->addConnect(networkModelName_, hvdcDefinition.converter1BusId + "_ACPIN", hvdcDefinition.id, "hvdc_terminal1"); + dynamicModelsToConnect->addConnect(networkModelName_, hvdcDefinition.converter2BusId + "_ACPIN", hvdcDefinition.id, "hvdc_terminal2"); } if (hvdcDefinition.hasPQPropModel()) { const auto& busId1 = @@ -439,6 +460,27 @@ Dyd::writeHvdcLineConnect(const boost::shared_ptraddConnect(hvdcDefinition.id, "hvdc_NQ2_value", modelSignalNQprefix_ + hvdcDefinition.converter2BusId, vrremoteNqValue); } } -} // namespace outputs +} + +std::unordered_map>> +Dyd::computeShuntsByIds(const algo::ShuntDefinitions& shuntDefinitions) { + std::unordered_map>> ret; + + for (const auto& shuntDefPair : shuntDefinitions.shunts) { + const auto& shuntDef = shuntDefPair.second; + if (shuntDef.dynamicModelAssociated) { + continue; + } + for (const auto& shunt : shuntDef.shunts) { + if (!shunt.voltageRegulationOn) { + continue; + } + ret[shunt.busId].push_back(std::ref(shunt)); + } + } + + return ret; +} + } // namespace outputs } // namespace dfl diff --git a/tests/outputs/TestDyd.cpp b/tests/outputs/TestDyd.cpp index d8b5ce6a0..84a675989 100644 --- a/tests/outputs/TestDyd.cpp +++ b/tests/outputs/TestDyd.cpp @@ -55,7 +55,8 @@ TEST(Dyd, write) { outputPath.append(filename); - dfl::outputs::Dyd dydWriter(dfl::outputs::Dyd::DydDefinition(basename, outputPath.generic_string(), generators, loads, node, {}, {}, manager, {}, svarcDefs)); + dfl::outputs::Dyd dydWriter( + dfl::outputs::Dyd::DydDefinition(basename, outputPath.generic_string(), generators, loads, node, {}, {}, manager, {}, svarcDefs, {})); dydWriter.write(); @@ -97,7 +98,7 @@ TEST(Dyd, writeRemote) { outputPath.append(filename); dfl::algo::GeneratorDefinitionAlgorithm::BusGenMap busesWithDynamicModel = {{bus1, "G1"}, {bus2, "G4"}}; dfl::outputs::Dyd dydWriter( - dfl::outputs::Dyd::DydDefinition(basename, outputPath.generic_string(), generators, {}, node, {}, busesWithDynamicModel, manager, {}, {})); + dfl::outputs::Dyd::DydDefinition(basename, outputPath.generic_string(), generators, {}, node, {}, busesWithDynamicModel, manager, {}, {}, {})); dydWriter.write(); @@ -140,7 +141,7 @@ TEST(Dyd, writeHvdc) { outputPath.append(filename); - dfl::outputs::Dyd dydWriter(dfl::outputs::Dyd::DydDefinition(basename, outputPath.generic_string(), {}, {}, node, hvdcDefs, {}, manager, {}, {})); + dfl::outputs::Dyd dydWriter(dfl::outputs::Dyd::DydDefinition(basename, outputPath.generic_string(), {}, {}, node, hvdcDefs, {}, manager, {}, {}, {})); dydWriter.write(); @@ -193,7 +194,53 @@ TEST(Dyd, writeDynamicModel) { outputPath.append(filename); - dfl::outputs::Dyd dydWriter(dfl::outputs::Dyd::DydDefinition(basename, outputPath.generic_string(), generators, loads, node, {}, {}, manager, models, {})); + dfl::outputs::Dyd dydWriter( + dfl::outputs::Dyd::DydDefinition(basename, outputPath.generic_string(), generators, loads, node, {}, {}, manager, models, {}, {})); + + dydWriter.write(); + + boost::filesystem::path reference("reference"); + reference.append(basename); + reference.append(filename); + + dfl::test::checkFilesEqual(outputPath.generic_string(), reference.generic_string()); +} + +TEST(Dyd, writeShunts) { + std::string basename = "TestDydShunts"; + std::string filename = basename + ".dyd"; + boost::filesystem::path outputPath("results"); + outputPath.append(basename); + + dfl::inputs::DynamicDataBaseManager manager("", ""); + + if (!boost::filesystem::exists(outputPath)) { + boost::filesystem::create_directories(outputPath); + } + + dfl::algo::ShuntDefinitions shuntDefs; + shuntDefs.shunts["VL"].dynamicModelAssociated = false; + shuntDefs.shunts["VL"].shunts = { + dfl::inputs::Shunt("1.1", "1", true, {}), + dfl::inputs::Shunt("1.2", "1", true, {}), + }; + shuntDefs.shunts["VL2"].dynamicModelAssociated = true; + shuntDefs.shunts["VL2"].shunts = { + dfl::inputs::Shunt("2.1", "2", true, {}), + dfl::inputs::Shunt("2.2", "2", true, {}), + }; + shuntDefs.shunts["VL3"].dynamicModelAssociated = false; + shuntDefs.shunts["VL3"].shunts = { + dfl::inputs::Shunt("3.1", "3", true, {}), + dfl::inputs::Shunt("3.2", "3", true, {}), + }; + + auto vl = std::make_shared("VL"); + auto node = dfl::inputs::Node::build("Slack", vl, 100., {}); + + outputPath.append(filename); + + dfl::outputs::Dyd dydWriter(dfl::outputs::Dyd::DydDefinition(basename, outputPath.generic_string(), {}, {}, node, {}, {}, manager, {}, {}, shuntDefs)); dydWriter.write(); diff --git a/tests/outputs/reference/TestDydShunts/TestDydShunts.dyd b/tests/outputs/reference/TestDydShunts/TestDydShunts.dyd new file mode 100644 index 000000000..720d37061 --- /dev/null +++ b/tests/outputs/reference/TestDydShunts/TestDydShunts.dyd @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +