From d14c2d7b11d7d89f207b21d429ea331069cde027 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 20 Oct 2022 17:20:51 -0500 Subject: [PATCH 01/52] Add bus factory. --- ComponentLib/Bus/BaseBus.hpp | 2 + ComponentLib/Bus/BusFactory.hpp | 97 +++++++++++++++++++++++++++++++++ ComponentLib/Bus/BusPQ.cpp | 10 ++++ ComponentLib/Bus/BusPQ.hpp | 8 +++ ComponentLib/Bus/BusPV.cpp | 10 ++++ ComponentLib/Bus/BusPV.hpp | 8 +++ ComponentLib/Bus/BusSlack.cpp | 9 +++ ComponentLib/Bus/BusSlack.hpp | 8 +++ 8 files changed, 152 insertions(+) create mode 100644 ComponentLib/Bus/BusFactory.hpp diff --git a/ComponentLib/Bus/BaseBus.hpp b/ComponentLib/Bus/BaseBus.hpp index 70b5eb2a0..bc3b31a0c 100644 --- a/ComponentLib/Bus/BaseBus.hpp +++ b/ComponentLib/Bus/BaseBus.hpp @@ -61,6 +61,7 @@ #define _BASE_BUS_HPP_ #include +// #include namespace ModelLib { @@ -138,6 +139,7 @@ namespace ModelLib virtual ScalarT& QB() = 0; virtual const ScalarT& QB() const = 0; + virtual const int BusType() const = 0; }; // class BaseBus } // namespace ModelLib diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp new file mode 100644 index 000000000..93bb1466c --- /dev/null +++ b/ComponentLib/Bus/BusFactory.hpp @@ -0,0 +1,97 @@ +/* + * + * Copyright (c) 2017, Lawrence Livermore National Security, LLC. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Slaven Peles . + * LLNL-CODE-718378. + * All rights reserved. + * + * This file is part of GridKit™. For details, see github.com/LLNL/GridKit + * Please also read the LICENSE file. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the disclaimer (as noted below) in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the LLNS/LLNL nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL + * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * Lawrence Livermore National Laboratory is operated by Lawrence Livermore + * National Security, LLC, for the U.S. Department of Energy, National + * Nuclear Security Administration under Contract DE-AC52-07NA27344. + * + * This document was prepared as an account of work sponsored by an agency + * of the United States government. Neither the United States government nor + * Lawrence Livermore National Security, LLC, nor any of their employees + * makes any warranty, expressed or implied, or assumes any legal liability + * or responsibility for the accuracy, completeness, or usefulness of any + * information, apparatus, product, or process disclosed, or represents that + * its use would not infringe privately owned rights. Reference herein to + * any specific commercial product, process, or service by trade name, + * trademark, manufacturer, or otherwise does not necessarily constitute or + * imply its endorsement, recommendation, or favoring by the United States + * government or Lawrence Livermore National Security, LLC. The views and + * opinions of authors expressed herein do not necessarily state or reflect + * those of the United States government or Lawrence Livermore National + * Security, LLC, and shall not be used for advertising or product + * endorsement purposes. + * + */ + +#pragma once + +#include +#include + +namespace ModelLib { + + template + class BusFactory + { + public: + using BusData = GridKit::MatPowerUtils::BusRow; + + BaseBus* create(BusData& data) + { + BaseBus* bus = nullptr; + switch(data.type) + { + case 1: + bus = new BusPQ(data); + break; + case 2: + bus = new BusPV(data); + break; + case 3: + bus = new BusSlack(data); + break; + default: + // Throw exception + std::cout << "Bus type " << data.type << " unrecognized.\n"; + } + return bus; + } + private: + BusFactory(){} + }; + +} \ No newline at end of file diff --git a/ComponentLib/Bus/BusPQ.cpp b/ComponentLib/Bus/BusPQ.cpp index 9f3838409..00247d8d7 100644 --- a/ComponentLib/Bus/BusPQ.cpp +++ b/ComponentLib/Bus/BusPQ.cpp @@ -103,6 +103,16 @@ BusPQ::BusPQ(ScalarT V, ScalarT theta) size_ = 2; } +template +BusPQ::BusPQ(BusData& data) + : V0_(data.Vm), theta0_(data.Va) +{ + //std::cout << "Create BusPQ..." << std::endl; + //std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 2; +} + template BusPQ::~BusPQ() { diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp index 37fb6e57b..9fff6f6c5 100644 --- a/ComponentLib/Bus/BusPQ.hpp +++ b/ComponentLib/Bus/BusPQ.hpp @@ -61,6 +61,7 @@ #define _BUS_PQ_HPP_ #include "BaseBus.hpp" +#include namespace ModelLib { @@ -86,9 +87,11 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; + using BusData = GridKit::MatPowerUtils::BusRow; BusPQ(); BusPQ(ScalarT V, ScalarT theta); + BusPQ(BusData& data); virtual ~BusPQ(); virtual int allocate(); @@ -178,6 +181,11 @@ namespace ModelLib return fB_[1]; } + virtual const int BusType() const + { + return 1; + } + private: // Default initial values for voltage and phase on PQ bus ScalarT V0_; diff --git a/ComponentLib/Bus/BusPV.cpp b/ComponentLib/Bus/BusPV.cpp index e4a82f546..0618f1284 100644 --- a/ComponentLib/Bus/BusPV.cpp +++ b/ComponentLib/Bus/BusPV.cpp @@ -103,6 +103,16 @@ BusPV::BusPV(ScalarT V, ScalarT theta0, ScalarT Pg) size_ = 1; } +template +BusPV::BusPV(BusData& data) + : V_(data.Vm), theta0_(data.Va) //, Pg_(Pg) +{ + //std::cout << "Create BusPV ..." << std::endl; + //std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 1; +} + template BusPV::~BusPV() { diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index 0089be5cb..dd2c41e99 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -62,6 +62,7 @@ #include #include "BaseBus.hpp" +#include namespace ModelLib { @@ -87,9 +88,11 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; + using BusData = GridKit::MatPowerUtils::BusRow; BusPV(); BusPV(ScalarT V, ScalarT theta0, ScalarT P); + BusPV(BusData& data); virtual ~BusPV(); virtual int allocate(); @@ -188,6 +191,11 @@ namespace ModelLib return QB_; } + virtual const int BusType() const + { + return 2; + } + private: ScalarT V_; ScalarT theta0_; ///< Default initial value for phase diff --git a/ComponentLib/Bus/BusSlack.cpp b/ComponentLib/Bus/BusSlack.cpp index d94937bd8..c108e5d22 100644 --- a/ComponentLib/Bus/BusSlack.cpp +++ b/ComponentLib/Bus/BusSlack.cpp @@ -100,6 +100,15 @@ BusSlack::BusSlack(ScalarT V, ScalarT theta) size_ = 0; } +template +BusSlack::BusSlack(BusData& data) + : V_(data.Vm), theta_(data.Va) //, P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) +{ + //std::cout << "Create BusSlack..." << std::endl; + //std::cout << "Number of equations is " << size_ << std::endl; + size_ = 0; +} + template BusSlack::~BusSlack() { diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index 4a1193186..969b28ae2 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -61,6 +61,7 @@ #define _BUS_SLACK_HPP_ #include "BaseBus.hpp" +#include namespace ModelLib { @@ -86,9 +87,11 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; + using BusData = GridKit::MatPowerUtils::BusRow; BusSlack(); BusSlack(ScalarT V, ScalarT theta); + BusSlack(BusData& data); virtual ~BusSlack(); virtual int evaluateResidual(); virtual int evaluateAdjointResidual(); @@ -177,6 +180,11 @@ namespace ModelLib return QB_; } + virtual const int BusType() const + { + return 3; + } + private: ScalarT V_; ScalarT theta_; From 99c1aecfc6ba60965cd280bfbc47cfcc2a64ff57 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 20 Oct 2022 17:22:31 -0500 Subject: [PATCH 02/52] Parse load data from the input file. --- .../MatPowerTesting/test_parse_bus_row.cpp | 26 ++- .../MatPowerTesting/test_parse_matpower.cpp | 2 +- Utilities/FileIO.hpp | 33 ++- Utilities/MatPowerUtils.hpp | 194 +++++++++++------- Utilities/Testing.hpp | 15 ++ 5 files changed, 184 insertions(+), 86 deletions(-) diff --git a/Examples/MatPowerTesting/test_parse_bus_row.cpp b/Examples/MatPowerTesting/test_parse_bus_row.cpp index b1190c289..26a65f757 100644 --- a/Examples/MatPowerTesting/test_parse_bus_row.cpp +++ b/Examples/MatPowerTesting/test_parse_bus_row.cpp @@ -29,21 +29,37 @@ mpc.bus = [ int main(int argc, char** argv) { int fail = 0; std::vector> bus_answer{ - {1, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {2, 1, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {3, 2, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {1, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {2, 1, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {3, 2, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {4, 3, 400, 131.47, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {5, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, + {5, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, + }; + + std::vector> load_answer{ + {1, 0, 0}, + {2, 300, 98.61}, + {3, 300, 98.61}, + {4, 400, 131.47}, + {5, 0, 0}, }; - MatPower mp; { + MatPower mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.bus, bus_answer)) fail++; std::cout << "After reading the bus component, fail == " << fail << "\n"; } + { + MatPower mp; + std::istringstream iss(matpower_data); + GridKit::readMatPower(mp, iss); + if (!isEqual(mp.load, load_answer)) fail++; + std::cout << "After reading the bus component, fail == " << fail << "\n"; + } + std::cout << "Tests " << (fail?"FAILED":"PASSED") << "\n"; return fail; diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index 855267e97..69b87ed47 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -137,7 +137,7 @@ int main(int argc, char **argv) { GridKit::readMatPower(mp, iss); if (!isEqual(mp, mp_answer)) fail++; - std::cout << "After reading the gencost component, fail == " << fail + std::cout << "\n\nAfter reading the gencost component, fail == " << fail << "\n"; } diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp index 080912187..1a5b366eb 100644 --- a/Utilities/FileIO.hpp +++ b/Utilities/FileIO.hpp @@ -130,9 +130,12 @@ std::string getMatPowerComponent(const std::string& line) std::regex pat("mpc.([a-zA-Z]+)\\s*=.+"); std::smatch matches; std::string component; - if (std::regex_match(line, matches, pat)) { + if (std::regex_match(line, matches, pat)) + { component = matches[1].str(); - } else { + } + else + { throw std::runtime_error(matlab_syntax_error + "\nGot line " + line); } ltrim(component); @@ -148,19 +151,27 @@ void checkEndOfMatrixRow(std::istream& is) is >> rest; ltrim(rest); rtrim(rest); - if (rest != ";") throw std::runtime_error(matlab_syntax_error); + if (rest != ";") + throw std::runtime_error(matlab_syntax_error); } template -BusRow readMatPowerBusRow(std::string& row) +// BusRow +void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow& lr) { logs() << "Parsing MATPOWER bus row\n"; std::stringstream is(row); - BusRow br; + // BusRow br; + // LoadRow lr; is >> br.bus_i >> br.type >> br.Pd >> br.Qd >> br.Gs >> br.Bs >> br.area - >> br.Vm >> br.Va >> br.baseKV >> br.zone >> br.Vmax >> br.Vmin; - logs() << "Read BusRow with the following values:\n" << br.str(); - return br; + >> br.Vm >> br.Va >> br.baseKV >> br.zone >> br.Vmax >> br.Vmin; + + lr.bus_i = br.bus_i; + lr.Pd = br.Pd; + lr.Qd = br.Qd; + // std::cout << br.str(); + // logs() << "Read BusRow with the following values:\n" << br.str(); + // return br; } template @@ -294,6 +305,7 @@ void readMatPower(MatPower& mp, std::istream& is) using GenRowT = GenRow; using BranchRowT = BranchRow; using GenCostRowT = GenCostRow; + using LoadRowT = LoadRow; for (std::string line; std::getline(is, line);) { // Trim whitespace and remove comments @@ -316,8 +328,11 @@ void readMatPower(MatPower& mp, std::istream& is) if (component == "bus") { while (std::getline(is, line)) { if (line.find("];") != std::string::npos) break; - BusRowT br = readMatPowerBusRow(line); + BusRowT br; + LoadRowT lr; + readMatPowerBusRow(line, br, lr); mp.bus.push_back(std::move(br)); + mp.load.push_back(std::move(lr)); } } else if (component == "gen") { while (std::getline(is, line)) { diff --git a/Utilities/MatPowerUtils.hpp b/Utilities/MatPowerUtils.hpp index 75566d65c..a9d52e537 100644 --- a/Utilities/MatPowerUtils.hpp +++ b/Utilities/MatPowerUtils.hpp @@ -21,106 +21,156 @@ namespace MatPowerUtils { template - struct BusRow { - IntT bus_i; - IntT type; - IntT Pd; - RealT Qd; - IntT Gs; - IntT Bs; - IntT area; - RealT Vm; - RealT Va; - IntT baseKV; - IntT zone; - RealT Vmax; - RealT Vmin; + struct BusRow + { + IntT bus_i; ///< Bus ID + IntT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + RealT Pd; ///< Active power demand [MW] + RealT Qd; ///< Reactive power demand [MVAr] + RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) + RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) + IntT area; ///< Area number (>0) + RealT Vm; ///< Voltage magnitude (p.u.) + RealT Va; ///< Voltage phase (deg) + RealT baseKV; ///< Base voltage [kV] + IntT zone; ///< Loss zone number (>0) + RealT Vmax; ///< Maximum voltage magnitude (p.u.) + RealT Vmin; ///< Minimum voltage magnitude (p.u.) inline std::string str() const { std::stringstream ss; - std::cerr << std::setw(10) << bus_i << std::setw(10) << type << std::setw(10) - << Pd << std::setw(10) << Qd << std::setw(10) << Gs << std::setw(10) - << Bs << std::setw(10) << area << std::setw(10) << Vm << std::setw(10) - << Va << std::setw(10) << baseKV << std::setw(10) << zone - << std::setw(10) << Vmax << std::setw(10) << Vmin; + std::cerr << std::setw(10) << bus_i + << std::setw(10) << type + << std::setw(10) << Pd + << std::setw(10) << Qd + << std::setw(10) << Gs + << std::setw(10) << Bs + << std::setw(10) << area + << std::setw(10) << Vm + << std::setw(10) << Va + << std::setw(10) << baseKV + << std::setw(10) << zone + << std::setw(10) << Vmax + << std::setw(10) << Vmin; ss << "\n"; return ss.str(); } }; template - struct GenRow { - IntT bus; - RealT Pg; - RealT Qg; - RealT Qmax; - RealT Qmin; - RealT Vg; - IntT mBase; - IntT status; - IntT Pmax; - IntT Pmin; - IntT Pc1; - IntT Pc2; - IntT Qc1min; - IntT Qc1max; - IntT Qc2min; - IntT Qc2max; - IntT ramp_agc; - IntT ramp_10; - IntT ramp_30; - IntT ramp_q; - IntT apf; + struct LoadRow + { + IntT bus_i; ///< Bus ID + RealT Pd; ///< Active power demand [MW] + RealT Qd; ///< Reactive power demand [MVAr] inline std::string str() const { std::stringstream ss; - ss << std::setw(10) << bus << std::setw(10) << Pg << std::setw(10) << Qg - << std::setw(10) << Qmax << std::setw(10) << Qmin << std::setw(10) - << Vg << std::setw(10) << mBase << std::setw(10) << status - << std::setw(10) << Pmax << std::setw(10) << Pmin << std::setw(10) - << Pc1 << std::setw(10) << Pc2 << std::setw(10) << Qc1min - << std::setw(10) << Qc1max << std::setw(10) << Qc2min << std::setw(10) - << Qc2max << std::setw(10) << ramp_agc << std::setw(10) << ramp_10 - << std::setw(10) << ramp_30 << std::setw(10) << ramp_q << std::setw(10) - << apf; + std::cerr << std::setw(10) << bus_i + << std::setw(10) << Pd + << std::setw(10) << Qd; ss << "\n"; return ss.str(); } }; template - struct BranchRow { - IntT fbus; - IntT tbus; - RealT r; - RealT x; - RealT b; - IntT rateA; - IntT rateB; - IntT rateC; - IntT ratio; - IntT angle; - IntT status; - IntT angmin; - IntT angmax; + struct GenRow + { + IntT bus; ///< Bus ID + RealT Pg; ///< Active power output [MW] + RealT Qg; ///< Reactive power output [MVAr] + RealT Qmax; ///< Maximum reactive power output [MVAr] + RealT Qmin; ///< Minimum reactive power output [MVAr] + RealT Vg; ///< + RealT mBase; ///< Total MVA base of machine + IntT status; ///< Service status (>0 in service, <=0 out of service) + RealT Pmax; ///< Maximum active power output [MVAr] + RealT Pmin; ///< Minimum active power output [MVAr] + RealT Pc1; ///< + RealT Pc2; ///< + RealT Qc1min; ///< + RealT Qc1max; ///< + RealT Qc2min; ///< + RealT Qc2max; ///< + RealT ramp_agc; ///< + RealT ramp_10; ///< + RealT ramp_30; ///< + RealT ramp_q; ///< + RealT apf; ///< inline std::string str() const { std::stringstream ss; - ss << std::setw(10) << fbus << std::setw(10) << tbus << std::setw(10) << r - << std::setw(10) << x << std::setw(10) << b << std::setw(10) << rateA - << std::setw(10) << rateB << std::setw(10) << rateC << std::setw(10) - << ratio << std::setw(10) << angle << std::setw(10) << status - << std::setw(10) << angmin << std::setw(10) << angmax; + ss << std::setw(10) << bus + << std::setw(10) << Pg + << std::setw(10) << Qg + << std::setw(10) << Qmax + << std::setw(10) << Qmin + << std::setw(10) << Vg + << std::setw(10) << mBase + << std::setw(10) << status + << std::setw(10) << Pmax + << std::setw(10) << Pmin + << std::setw(10) << Pc1 + << std::setw(10) << Pc2 + << std::setw(10) << Qc1min + << std::setw(10) << Qc1max + << std::setw(10) << Qc2min + << std::setw(10) << Qc2max + << std::setw(10) << ramp_agc + << std::setw(10) << ramp_10 + << std::setw(10) << ramp_30 + << std::setw(10) << ramp_q + << std::setw(10) << apf; ss << "\n"; return ss.str(); } }; template - struct GenCostRow { + struct BranchRow + { + IntT fbus; ///< "From" bus ID + IntT tbus; ///< "To" bus ID + RealT r; ///< Resistance (p.u.) + RealT x; ///< Reactance (p.u.) + RealT b; ///< Total line charging susceptance (p.u.) + RealT rateA; ///< MVA rating A (long term rating), 0=unlimited + RealT rateB; ///< MVA rating B (short term rating), 0=unlimited + RealT rateC; ///< MVA rating C (emergency rating), 0=unlimited + RealT ratio; ///< Transformer off nominal turns ratio + RealT angle; ///< Transformer phase shift angle [deg], positive ⇒ delay + IntT status; ///< Initial service status: 1=in-service, 0=out-of-service + RealT angmin; ///< Minimum anngle difference af - at [deg] + RealT angmax; ///< Maximum anngle difference af - at [deg] + + inline std::string str() const + { + std::stringstream ss; + ss << std::setw(10) << fbus + << std::setw(10) << tbus + << std::setw(10) << r + << std::setw(10) << x + << std::setw(10) << b + << std::setw(10) << rateA + << std::setw(10) << rateB + << std::setw(10) << rateC + << std::setw(10) << ratio + << std::setw(10) << angle + << std::setw(10) << status + << std::setw(10) << angmin + << std::setw(10) << angmax; + ss << "\n"; + return ss.str(); + } + }; + + template + struct GenCostRow + { IntT kind; IntT startup; IntT shutdown; @@ -145,6 +195,7 @@ namespace MatPowerUtils using GenRowT = GenRow; using BranchRowT = BranchRow; using GenCostRowT = GenCostRow; + using LoadRowT = LoadRow; std::string version; IntT baseMVA; @@ -152,6 +203,7 @@ namespace MatPowerUtils std::vector gen; std::vector branch; std::vector gencost; + std::vector load; // Not sure if these should be in this struct... Not all matpower files // I found contained them. @@ -167,7 +219,7 @@ namespace MatPowerUtils ss << "Bus:\n"; for (const auto& v : bus) - ss << bus.str(); + ss << bus.str() << "\n"; ss << "Gen:\n"; for (const auto& v : gen) diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index f81f8b3cf..f4cb5855d 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -169,6 +169,21 @@ inline bool isEqual(MatPowerUtils::BusRow a, return fail == 0; } +template +inline bool isEqual(MatPowerUtils::LoadRow a, + MatPowerUtils::LoadRow b, RealT tol = tol_) { + int fail = 0; + fail += a.bus_i != b.bus_i; + fail += !isEqual(a.Pd, b.Pd, tol); + fail += !isEqual(a.Qd, b.Qd, tol); + if (fail) { + errs() << "bus_i: a=" << a.bus_i << ", b=" << b.bus_i << "\n" + << "Pd: a=" << a.Pd << ", b=" << b.Pd << "\n" + << "Qd: a=" << a.Qd << ", b=" << b.Qd << "\n"; + } + return fail == 0; +} + template inline bool isEqual(MatPowerUtils::BranchRow a, MatPowerUtils::BranchRow b, RealT tol = tol_) { From dfb52127fba3276c42dab4e9cb9bfc252505953b Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 20 Oct 2022 17:44:05 -0500 Subject: [PATCH 03/52] Check load data when testing Matpower parser. --- .../MatPowerTesting/test_parse_matpower.cpp | 18 ++++++++++++++---- Utilities/Testing.hpp | 5 +++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index 69b87ed47..9f01a9a2c 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -90,6 +90,7 @@ int main(int argc, char **argv) { using BranchRowT = BranchRow; using GenCostRowT = GenCostRow; using MatPowerT = MatPower; + using LoadRowT = LoadRow; // Create the struct of expected values std::vector branch_answer{ @@ -101,11 +102,11 @@ int main(int argc, char **argv) { {4, 5, 0.00297, 0.0297, 0.00674, 240, 240, 240, 0, 0, 1, -360, 360}, }; std::vector bus_answer{ - {1, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {2, 1, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {3, 2, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {1, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {2, 1, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {3, 2, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {4, 3, 400, 131.47, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {5, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, + {5, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; std::vector gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -121,12 +122,21 @@ int main(int argc, char **argv) { {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; + std::vector> load_answer{ + {1, 0, 0}, + {2, 300, 98.61}, + {3, 300, 98.61}, + {4, 400, 131.47}, + {5, 0, 0}, + }; + MatPowerT mp_answer; mp_answer.gencost = gencost_answer; mp_answer.gen = gen_answer; mp_answer.bus = bus_answer; mp_answer.branch = branch_answer; + mp_answer.load = load_answer; mp_answer.version = "2"; mp_answer.baseMVA = 100; diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index f4cb5855d..093bdafd7 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -178,8 +178,8 @@ inline bool isEqual(MatPowerUtils::LoadRow a, fail += !isEqual(a.Qd, b.Qd, tol); if (fail) { errs() << "bus_i: a=" << a.bus_i << ", b=" << b.bus_i << "\n" - << "Pd: a=" << a.Pd << ", b=" << b.Pd << "\n" - << "Qd: a=" << a.Qd << ", b=" << b.Qd << "\n"; + << "Pd: a=" << a.Pd << ", b=" << b.Pd << "\n" + << "Qd: a=" << a.Qd << ", b=" << b.Qd << "\n"; } return fail == 0; } @@ -239,6 +239,7 @@ inline bool isEqual(MatPowerUtils::MatPower a, fail += !isEqual(a.gen, b.gen); fail += !isEqual(a.gencost, b.gencost); fail += !isEqual(a.branch, b.branch); + fail += !isEqual(a.load, b.load); return fail == 0; } From 8c237b06ed28b46e0be61824969b7257cd5856ea Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 20 Oct 2022 21:34:56 -0500 Subject: [PATCH 04/52] Do not store load data in bus data structure. --- .../MatPowerTesting/test_parse_bus_row.cpp | 10 ++--- .../MatPowerTesting/test_parse_matpower.cpp | 10 ++--- Utilities/FileIO.hpp | 39 +++++++++++-------- Utilities/MatPowerUtils.hpp | 10 ++--- Utilities/Testing.hpp | 4 -- 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/Examples/MatPowerTesting/test_parse_bus_row.cpp b/Examples/MatPowerTesting/test_parse_bus_row.cpp index 26a65f757..d84ff215d 100644 --- a/Examples/MatPowerTesting/test_parse_bus_row.cpp +++ b/Examples/MatPowerTesting/test_parse_bus_row.cpp @@ -29,11 +29,11 @@ mpc.bus = [ int main(int argc, char** argv) { int fail = 0; std::vector> bus_answer{ - {1, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {2, 1, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {3, 2, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {4, 3, 400, 131.47, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {5, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, + {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {4, 3, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; std::vector> load_answer{ diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index 9f01a9a2c..c9950d0c7 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -102,11 +102,11 @@ int main(int argc, char **argv) { {4, 5, 0.00297, 0.0297, 0.00674, 240, 240, 240, 0, 0, 1, -360, 360}, }; std::vector bus_answer{ - {1, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {2, 1, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {3, 2, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {4, 3, 400, 131.47, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {5, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, + {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {4, 3, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; std::vector gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp index 1a5b366eb..c759fb6e4 100644 --- a/Utilities/FileIO.hpp +++ b/Utilities/FileIO.hpp @@ -156,19 +156,26 @@ void checkEndOfMatrixRow(std::istream& is) } template -// BusRow void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow& lr) { logs() << "Parsing MATPOWER bus row\n"; std::stringstream is(row); - // BusRow br; - // LoadRow lr; - is >> br.bus_i >> br.type >> br.Pd >> br.Qd >> br.Gs >> br.Bs >> br.area - >> br.Vm >> br.Va >> br.baseKV >> br.zone >> br.Vmax >> br.Vmin; + is >> br.bus_i + >> br.type + >> lr.Pd + >> lr.Qd + >> br.Gs + >> br.Bs + >> br.area + >> br.Vm + >> br.Va + >> br.baseKV + >> br.zone + >> br.Vmax + >> br.Vmin; lr.bus_i = br.bus_i; - lr.Pd = br.Pd; - lr.Qd = br.Qd; + // std::cout << br.str(); // logs() << "Read BusRow with the following values:\n" << br.str(); // return br; @@ -180,9 +187,9 @@ void readMatPowerGenRow(GenRow& gr, std::string& row) logs() << "Parsing MATPOWER gen row\n"; std::stringstream is(row); is >> gr.bus >> gr.Pg >> gr.Qg >> gr.Qmax >> gr.Qmin >> gr.Vg >> gr.mBase - >> gr.status >> gr.Pmax >> gr.Pmin >> gr.Pc1 >> gr.Pc2 >> gr.Qc1min - >> gr.Qc1max >> gr.Qc2min >> gr.Qc2max >> gr.ramp_agc >> gr.ramp_10 - >> gr.ramp_30 >> gr.ramp_q >> gr.apf; + >> gr.status >> gr.Pmax >> gr.Pmin >> gr.Pc1 >> gr.Pc2 >> gr.Qc1min + >> gr.Qc1max >> gr.Qc2min >> gr.Qc2max >> gr.ramp_agc >> gr.ramp_10 + >> gr.ramp_30 >> gr.ramp_q >> gr.apf; checkEndOfMatrixRow(is); } @@ -192,8 +199,8 @@ void readMatPowerBranchRow(BranchRow& br, std::string& row) logs() << "Parsing MATPOWER branch row\n"; std::stringstream is(row); is >> br.fbus >> br.tbus >> br.r >> br.x >> br.b >> br.rateA >> br.rateB - >> br.rateC >> br.ratio >> br.angle >> br.status >> br.angmin - >> br.angmax; + >> br.rateC >> br.ratio >> br.angle >> br.status >> br.angmin + >> br.angmax; checkEndOfMatrixRow(is); } @@ -301,11 +308,11 @@ template void readMatPower(MatPower& mp, std::istream& is) { - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; using GenCostRowT = GenCostRow; - using LoadRowT = LoadRow; + using LoadRowT = LoadRow; for (std::string line; std::getline(is, line);) { // Trim whitespace and remove comments diff --git a/Utilities/MatPowerUtils.hpp b/Utilities/MatPowerUtils.hpp index a9d52e537..5dab48dcd 100644 --- a/Utilities/MatPowerUtils.hpp +++ b/Utilities/MatPowerUtils.hpp @@ -25,8 +25,6 @@ namespace MatPowerUtils { IntT bus_i; ///< Bus ID IntT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated - RealT Pd; ///< Active power demand [MW] - RealT Qd; ///< Reactive power demand [MVAr] RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) IntT area; ///< Area number (>0) @@ -42,8 +40,6 @@ namespace MatPowerUtils std::stringstream ss; std::cerr << std::setw(10) << bus_i << std::setw(10) << type - << std::setw(10) << Pd - << std::setw(10) << Qd << std::setw(10) << Gs << std::setw(10) << Bs << std::setw(10) << area @@ -180,8 +176,10 @@ namespace MatPowerUtils inline std::string str() const { std::stringstream ss; - ss << std::setw(10) << kind << std::setw(10) << startup << std::setw(10) - << shutdown << std::setw(10) << n; + ss << std::setw(10) << kind + << std::setw(10) << startup + << std::setw(10) << shutdown + << std::setw(10) << n; for (const auto& val : rest) ss << std::setw(10) << val; ss << "\n"; diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index 093bdafd7..990fb4ae9 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -140,8 +140,6 @@ inline bool isEqual(MatPowerUtils::BusRow a, int fail = 0; fail += a.bus_i != b.bus_i; fail += a.type != b.type; - fail += a.Pd != b.Pd; - fail += !isEqual(a.Qd, b.Qd, tol); fail += a.Gs != b.Gs; fail += a.Bs != b.Bs; fail += a.area != b.area; @@ -154,8 +152,6 @@ inline bool isEqual(MatPowerUtils::BusRow a, if (fail) { errs() << "bus_i: a=" << a.bus_i << ", b=" << b.bus_i << "\n" << "type: a=" << a.type << ", b=" << b.type << "\n" - << "Pd: a=" << a.Pd << ", b=" << b.Pd << "\n" - << "Qd: a=" << a.Qd << ", b=" << b.Qd << "\n" << "Gs: a=" << a.Gs << ", b=" << b.Gs << "\n" << "Bs: a=" << a.Bs << ", b=" << b.Bs << "\n" << "area: a=" << a.area << ", b=" << b.area << "\n" From 0a13036991e711fc25be5c192ea1b1bb905b7dbf Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Fri, 21 Oct 2022 08:52:58 -0500 Subject: [PATCH 05/52] Changed names and order of template parameters in power system data structures. --- ComponentLib/Bus/BusFactory.hpp | 10 ++-- ComponentLib/Bus/BusPQ.hpp | 2 +- ComponentLib/Bus/BusPV.hpp | 2 +- ComponentLib/Bus/BusSlack.hpp | 2 +- .../MatPowerTesting/test_parse_branch_row.cpp | 8 +-- .../MatPowerTesting/test_parse_bus_row.cpp | 12 ++--- .../MatPowerTesting/test_parse_gen_row.cpp | 8 +-- .../test_parse_gencost_row.cpp | 8 +-- .../MatPowerTesting/test_parse_matpower.cpp | 18 +++---- Utilities/FileIO.hpp | 44 +++++++-------- Utilities/MatPowerUtils.hpp | 54 +++++++++---------- Utilities/Testing.hpp | 36 ++++++------- 12 files changed, 102 insertions(+), 102 deletions(-) diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp index 93bb1466c..5fcb1cd55 100644 --- a/ComponentLib/Bus/BusFactory.hpp +++ b/ComponentLib/Bus/BusFactory.hpp @@ -68,9 +68,11 @@ namespace ModelLib { class BusFactory { public: - using BusData = GridKit::MatPowerUtils::BusRow; + using BusData = GridKit::PowerSystemData::BusRow; - BaseBus* create(BusData& data) + BusFactory() = delete; + + static BaseBus* create(BusData& data) { BaseBus* bus = nullptr; switch(data.type) @@ -90,8 +92,6 @@ namespace ModelLib { } return bus; } - private: - BusFactory(){} }; -} \ No newline at end of file +} // namespace ModelLib \ No newline at end of file diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp index 9fff6f6c5..d2f21f8ef 100644 --- a/ComponentLib/Bus/BusPQ.hpp +++ b/ComponentLib/Bus/BusPQ.hpp @@ -87,7 +87,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::MatPowerUtils::BusRow; + using BusData = GridKit::PowerSystemData::BusRow; BusPQ(); BusPQ(ScalarT V, ScalarT theta); diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index dd2c41e99..29af45ecb 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -88,7 +88,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::MatPowerUtils::BusRow; + using BusData = GridKit::PowerSystemData::BusRow; BusPV(); BusPV(ScalarT V, ScalarT theta0, ScalarT P); diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index 969b28ae2..1b5455a2e 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -87,7 +87,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::MatPowerUtils::BusRow; + using BusData = GridKit::PowerSystemData::BusRow; BusSlack(); BusSlack(ScalarT V, ScalarT theta); diff --git a/Examples/MatPowerTesting/test_parse_branch_row.cpp b/Examples/MatPowerTesting/test_parse_branch_row.cpp index a0ed8e20f..8b4659ed8 100644 --- a/Examples/MatPowerTesting/test_parse_branch_row.cpp +++ b/Examples/MatPowerTesting/test_parse_branch_row.cpp @@ -5,11 +5,11 @@ using namespace GridKit; using namespace GridKit::Testing; -using namespace GridKit::MatPowerUtils; +using namespace GridKit::PowerSystemData; namespace { -using IntT = int; +using IdxT = int; using RealT = double; static const std::string matpower_data{ @@ -33,7 +33,7 @@ mpc.branch = [ int main(int argc, char **argv) { int fail = 0; - std::vector> branch_answer{ + std::vector> branch_answer{ {1, 2, 0.00281, 0.0281, 0.00712, 400, 400, 400, 0, 0, 1, -360, 360}, {1, 4, 0.00304, 0.0304, 0.00658, 0, 0, 0, 0, 0, 1, -360, 360}, {1, 5, 0.00064, 0.0064, 0.03126, 0, 0, 0, 0, 0, 1, -360, 360}, @@ -41,7 +41,7 @@ int main(int argc, char **argv) { {3, 4, 0.00297, 0.0297, 0.00674, 0, 0, 0, 0, 0, 1, -360, 360}, {4, 5, 0.00297, 0.0297, 0.00674, 240, 240, 240, 0, 0, 1, -360, 360}, }; - MatPower mp; + MatPower mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_bus_row.cpp b/Examples/MatPowerTesting/test_parse_bus_row.cpp index d84ff215d..bd723c542 100644 --- a/Examples/MatPowerTesting/test_parse_bus_row.cpp +++ b/Examples/MatPowerTesting/test_parse_bus_row.cpp @@ -5,11 +5,11 @@ using namespace GridKit; using namespace GridKit::Testing; -using namespace GridKit::MatPowerUtils; +using namespace GridKit::PowerSystemData; namespace { -using IntT = int; +using IdxT = int; using RealT = double; static const std::string matpower_data{ @@ -28,7 +28,7 @@ mpc.bus = [ int main(int argc, char** argv) { int fail = 0; - std::vector> bus_answer{ + std::vector> bus_answer{ {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, @@ -36,7 +36,7 @@ int main(int argc, char** argv) { {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; - std::vector> load_answer{ + std::vector> load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, @@ -45,7 +45,7 @@ int main(int argc, char** argv) { }; { - MatPower mp; + MatPower mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.bus, bus_answer)) fail++; @@ -53,7 +53,7 @@ int main(int argc, char** argv) { } { - MatPower mp; + MatPower mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.load, load_answer)) fail++; diff --git a/Examples/MatPowerTesting/test_parse_gen_row.cpp b/Examples/MatPowerTesting/test_parse_gen_row.cpp index 7d6abfa13..b31d8b2b4 100644 --- a/Examples/MatPowerTesting/test_parse_gen_row.cpp +++ b/Examples/MatPowerTesting/test_parse_gen_row.cpp @@ -5,11 +5,11 @@ using namespace GridKit; using namespace GridKit::Testing; -using namespace GridKit::MatPowerUtils; +using namespace GridKit::PowerSystemData; namespace { -using IntT = int; +using IdxT = int; using RealT = double; static const std::string matpower_data{ @@ -30,7 +30,7 @@ mpc.gen = [ int main(int argc, char **argv) { int fail = 0; - std::vector> gen_answer{ + std::vector> gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 170, 0, 127.5, -127.5, 1, 100, 1, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -39,7 +39,7 @@ int main(int argc, char **argv) { {4, 0, 0, 150, -150, 1, 100, 1, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 466.51, 0, 450, -450, 1, 100, 1, 600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - MatPower mp; + MatPower mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_gencost_row.cpp b/Examples/MatPowerTesting/test_parse_gencost_row.cpp index 4675ebaaa..49e7ad714 100644 --- a/Examples/MatPowerTesting/test_parse_gencost_row.cpp +++ b/Examples/MatPowerTesting/test_parse_gencost_row.cpp @@ -5,11 +5,11 @@ using namespace GridKit; using namespace GridKit::Testing; -using namespace GridKit::MatPowerUtils; +using namespace GridKit::PowerSystemData; namespace { -using IntT = int; +using IdxT = int; using RealT = double; static const std::string matpower_data{ @@ -33,12 +33,12 @@ mpc.gencost = [ int main(int argc, char **argv) { int fail = 0; - std::vector> gencost_answer{ + std::vector> gencost_answer{ {2, 0, 0, 3, {0, 14, 0}}, {2, 0, 0, 3, {0, 15, 0}}, {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - MatPower mp; + MatPower mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index c9950d0c7..1fe25766d 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -5,11 +5,11 @@ using namespace GridKit; using namespace GridKit::Testing; -using namespace GridKit::MatPowerUtils; +using namespace GridKit::PowerSystemData; namespace { -using IntT = int; +using IdxT = int; using RealT = double; static const std::string matpower_data{ @@ -85,12 +85,12 @@ int main(int argc, char **argv) { int fail = 0; // All types will use the scalar types at the top of the file - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using MatPowerT = MatPower; - using LoadRowT = LoadRow; + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; + using GenCostRowT = GenCostRow; + using MatPowerT = MatPower; + using LoadRowT = LoadRow; // Create the struct of expected values std::vector branch_answer{ @@ -122,7 +122,7 @@ int main(int argc, char **argv) { {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - std::vector> load_answer{ + std::vector> load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp index c759fb6e4..a2dc6e015 100644 --- a/Utilities/FileIO.hpp +++ b/Utilities/FileIO.hpp @@ -80,7 +80,7 @@ namespace { using namespace GridKit; -using namespace GridKit::MatPowerUtils; +using namespace GridKit::PowerSystemData; static const std::string matlab_syntax_error{ "Only a subset of Matlab syntax is supported." @@ -155,8 +155,8 @@ void checkEndOfMatrixRow(std::istream& is) throw std::runtime_error(matlab_syntax_error); } -template -void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow& lr) +template +void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow& lr) { logs() << "Parsing MATPOWER bus row\n"; std::stringstream is(row); @@ -181,8 +181,8 @@ void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow // return br; } -template -void readMatPowerGenRow(GenRow& gr, std::string& row) +template +void readMatPowerGenRow(GenRow& gr, std::string& row) { logs() << "Parsing MATPOWER gen row\n"; std::stringstream is(row); @@ -193,8 +193,8 @@ void readMatPowerGenRow(GenRow& gr, std::string& row) checkEndOfMatrixRow(is); } -template -void readMatPowerBranchRow(BranchRow& br, std::string& row) +template +void readMatPowerBranchRow(BranchRow& br, std::string& row) { logs() << "Parsing MATPOWER branch row\n"; std::stringstream is(row); @@ -204,8 +204,8 @@ void readMatPowerBranchRow(BranchRow& br, std::string& row) checkEndOfMatrixRow(is); } -template -void readMatPowerGenCostRow(GenCostRow& gcr, std::string& row) +template +void readMatPowerGenCostRow(GenCostRow& gcr, std::string& row) { logs() << "Parsing MATPOWER gen cost row\n"; // Ensure last character is semicolon. @@ -221,8 +221,8 @@ void readMatPowerGenCostRow(GenCostRow& gcr, std::string& row) } } -template -void readMatPowerVersion(MatPower& mp, std::string& line) +template +void readMatPowerVersion(MatPower& mp, std::string& line) { logs() << "Parsing matpower version\n"; std::regex pat("mpc\\.version\\s*=\\s*'([0-9])';"); @@ -234,8 +234,8 @@ void readMatPowerVersion(MatPower& mp, std::string& line) } } -template -void readMatPowerBaseMVA(MatPower& mp, std::string& line) +template +void readMatPowerBaseMVA(MatPower& mp, std::string& line) { std::regex pat("mpc\\.baseMVA\\s*=\\s*([0-9]+);"); std::smatch matches; @@ -296,23 +296,23 @@ void printLookupTable(std::vector> const& table) } } -template -void readMatPowerFile(MatPower& mp, std::string& filename) +template +void readMatPowerFile(MatPower& mp, std::string& filename) { std::ifstream ifs{filename}; readMatPower(mp, ifs); } -template -void readMatPower(MatPower& mp, std::istream& is) +void readMatPower(MatPower& mp, std::istream& is) { - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using LoadRowT = LoadRow; + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; + using GenCostRowT = GenCostRow; + using LoadRowT = LoadRow; for (std::string line; std::getline(is, line);) { // Trim whitespace and remove comments diff --git a/Utilities/MatPowerUtils.hpp b/Utilities/MatPowerUtils.hpp index 5dab48dcd..618c0ca2e 100644 --- a/Utilities/MatPowerUtils.hpp +++ b/Utilities/MatPowerUtils.hpp @@ -17,21 +17,21 @@ namespace GridKit { -namespace MatPowerUtils +namespace PowerSystemData { - template + template struct BusRow { - IntT bus_i; ///< Bus ID - IntT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + IdxT bus_i; ///< Bus ID + IdxT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) - IntT area; ///< Area number (>0) + IdxT area; ///< Area number (>0) RealT Vm; ///< Voltage magnitude (p.u.) RealT Va; ///< Voltage phase (deg) RealT baseKV; ///< Base voltage [kV] - IntT zone; ///< Loss zone number (>0) + IdxT zone; ///< Loss zone number (>0) RealT Vmax; ///< Maximum voltage magnitude (p.u.) RealT Vmin; ///< Minimum voltage magnitude (p.u.) @@ -54,10 +54,10 @@ namespace MatPowerUtils } }; - template + template struct LoadRow { - IntT bus_i; ///< Bus ID + IdxT bus_i; ///< Bus ID RealT Pd; ///< Active power demand [MW] RealT Qd; ///< Reactive power demand [MVAr] @@ -72,17 +72,17 @@ namespace MatPowerUtils } }; - template + template struct GenRow { - IntT bus; ///< Bus ID + IdxT bus; ///< Bus ID RealT Pg; ///< Active power output [MW] RealT Qg; ///< Reactive power output [MVAr] RealT Qmax; ///< Maximum reactive power output [MVAr] RealT Qmin; ///< Minimum reactive power output [MVAr] RealT Vg; ///< RealT mBase; ///< Total MVA base of machine - IntT status; ///< Service status (>0 in service, <=0 out of service) + IdxT status; ///< Service status (>0 in service, <=0 out of service) RealT Pmax; ///< Maximum active power output [MVAr] RealT Pmin; ///< Minimum active power output [MVAr] RealT Pc1; ///< @@ -126,11 +126,11 @@ namespace MatPowerUtils } }; - template + template struct BranchRow { - IntT fbus; ///< "From" bus ID - IntT tbus; ///< "To" bus ID + IdxT fbus; ///< "From" bus ID + IdxT tbus; ///< "To" bus ID RealT r; ///< Resistance (p.u.) RealT x; ///< Reactance (p.u.) RealT b; ///< Total line charging susceptance (p.u.) @@ -139,7 +139,7 @@ namespace MatPowerUtils RealT rateC; ///< MVA rating C (emergency rating), 0=unlimited RealT ratio; ///< Transformer off nominal turns ratio RealT angle; ///< Transformer phase shift angle [deg], positive ⇒ delay - IntT status; ///< Initial service status: 1=in-service, 0=out-of-service + IdxT status; ///< Initial service status: 1=in-service, 0=out-of-service RealT angmin; ///< Minimum anngle difference af - at [deg] RealT angmax; ///< Maximum anngle difference af - at [deg] @@ -164,13 +164,13 @@ namespace MatPowerUtils } }; - template + template struct GenCostRow { - IntT kind; - IntT startup; - IntT shutdown; - IntT n; + IdxT kind; + IdxT startup; + IdxT shutdown; + IdxT n; std::vector rest; inline std::string str() const @@ -187,16 +187,16 @@ namespace MatPowerUtils } }; - template + template struct MatPower { - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using LoadRowT = LoadRow; + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; + using GenCostRowT = GenCostRow; + using LoadRowT = LoadRow; std::string version; - IntT baseMVA; + IdxT baseMVA; std::vector bus; std::vector gen; std::vector branch; diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index 990fb4ae9..c722de6e3 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -88,9 +88,9 @@ template bool isEqual(const T value, const T ref, const T tol) { return (std::abs(value - ref) / (1.0 + std::abs(ref)) < tol); } -template -inline bool isEqual(MatPowerUtils::GenCostRow a, - MatPowerUtils::GenCostRow b, +template +inline bool isEqual(PowerSystemData::GenCostRow a, + PowerSystemData::GenCostRow b, RealT tol = tol_) { int fail = 0; fail += a.kind != b.kind; @@ -103,9 +103,9 @@ inline bool isEqual(MatPowerUtils::GenCostRow a, return fail == 0; } -template -inline bool isEqual(MatPowerUtils::GenRow a, - MatPowerUtils::GenRow b, RealT tol = tol_) { +template +inline bool isEqual(PowerSystemData::GenRow a, + PowerSystemData::GenRow b, RealT tol = tol_) { int fail = 0; fail += a.bus != b.bus; fail += !isEqual(a.Pg, b.Pg, tol); @@ -134,9 +134,9 @@ inline bool isEqual(MatPowerUtils::GenRow a, return fail == 0; } -template -inline bool isEqual(MatPowerUtils::BusRow a, - MatPowerUtils::BusRow b, RealT tol = tol_) { +template +inline bool isEqual(PowerSystemData::BusRow a, + PowerSystemData::BusRow b, RealT tol = tol_) { int fail = 0; fail += a.bus_i != b.bus_i; fail += a.type != b.type; @@ -165,9 +165,9 @@ inline bool isEqual(MatPowerUtils::BusRow a, return fail == 0; } -template -inline bool isEqual(MatPowerUtils::LoadRow a, - MatPowerUtils::LoadRow b, RealT tol = tol_) { +template +inline bool isEqual(PowerSystemData::LoadRow a, + PowerSystemData::LoadRow b, RealT tol = tol_) { int fail = 0; fail += a.bus_i != b.bus_i; fail += !isEqual(a.Pd, b.Pd, tol); @@ -180,9 +180,9 @@ inline bool isEqual(MatPowerUtils::LoadRow a, return fail == 0; } -template -inline bool isEqual(MatPowerUtils::BranchRow a, - MatPowerUtils::BranchRow b, RealT tol = tol_) { +template +inline bool isEqual(PowerSystemData::BranchRow a, + PowerSystemData::BranchRow b, RealT tol = tol_) { int fail = 0; fail += a.fbus != b.fbus; fail += a.tbus != b.tbus; @@ -225,9 +225,9 @@ inline bool isEqual(std::vector a, std::vector b, double tol = tol_) { return fail == 0; } -template -inline bool isEqual(MatPowerUtils::MatPower a, - MatPowerUtils::MatPower b) { +template +inline bool isEqual(PowerSystemData::MatPower a, + PowerSystemData::MatPower b) { int fail = 0; fail += a.version != b.version; fail += a.baseMVA != b.baseMVA; From b0b8f7aa0b63c347aed992d6c990e0fe71eb574e Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Fri, 21 Oct 2022 17:37:24 -0400 Subject: [PATCH 06/52] More intuitieve data structures names Changed names of data structures to distinguish Matpower specific data and general power system description data. --- ComponentLib/Bus/BusFactory.hpp | 4 +- ComponentLib/Bus/BusPQ.hpp | 4 +- ComponentLib/Bus/BusPV.hpp | 4 +- ComponentLib/Bus/BusSlack.hpp | 4 +- .../MatPowerTesting/test_parse_branch_row.cpp | 6 +-- .../MatPowerTesting/test_parse_bus_row.cpp | 10 ++--- .../MatPowerTesting/test_parse_gen_row.cpp | 6 +-- .../test_parse_gencost_row.cpp | 6 +-- .../MatPowerTesting/test_parse_matpower.cpp | 28 ++++++------- .../MatPowerUtils.hpp => PowerSystemData.hpp | 41 ++++++++++--------- Utilities/FileIO.hpp | 40 +++++++++--------- Utilities/Testing.hpp | 26 ++++++------ 12 files changed, 90 insertions(+), 89 deletions(-) rename Utilities/MatPowerUtils.hpp => PowerSystemData.hpp (90%) diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp index 5fcb1cd55..f4212a658 100644 --- a/ComponentLib/Bus/BusFactory.hpp +++ b/ComponentLib/Bus/BusFactory.hpp @@ -59,7 +59,7 @@ #pragma once -#include +#include #include namespace ModelLib { @@ -68,7 +68,7 @@ namespace ModelLib { class BusFactory { public: - using BusData = GridKit::PowerSystemData::BusRow; + using BusData = GridKit::PowerSystemData::BusData; BusFactory() = delete; diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp index d2f21f8ef..56798b6e2 100644 --- a/ComponentLib/Bus/BusPQ.hpp +++ b/ComponentLib/Bus/BusPQ.hpp @@ -61,7 +61,7 @@ #define _BUS_PQ_HPP_ #include "BaseBus.hpp" -#include +#include namespace ModelLib { @@ -87,7 +87,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusRow; + using BusData = GridKit::PowerSystemData::BusData; BusPQ(); BusPQ(ScalarT V, ScalarT theta); diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index 29af45ecb..56eda8b4d 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -62,7 +62,7 @@ #include #include "BaseBus.hpp" -#include +#include namespace ModelLib { @@ -88,7 +88,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusRow; + using BusData = GridKit::PowerSystemData::BusData; BusPV(); BusPV(ScalarT V, ScalarT theta0, ScalarT P); diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index 1b5455a2e..24f138083 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -61,7 +61,7 @@ #define _BUS_SLACK_HPP_ #include "BaseBus.hpp" -#include +#include namespace ModelLib { @@ -87,7 +87,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusRow; + using BusData = GridKit::PowerSystemData::BusData; BusSlack(); BusSlack(ScalarT V, ScalarT theta); diff --git a/Examples/MatPowerTesting/test_parse_branch_row.cpp b/Examples/MatPowerTesting/test_parse_branch_row.cpp index 8b4659ed8..8d87d9e82 100644 --- a/Examples/MatPowerTesting/test_parse_branch_row.cpp +++ b/Examples/MatPowerTesting/test_parse_branch_row.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -33,7 +33,7 @@ mpc.branch = [ int main(int argc, char **argv) { int fail = 0; - std::vector> branch_answer{ + std::vector> branch_answer{ {1, 2, 0.00281, 0.0281, 0.00712, 400, 400, 400, 0, 0, 1, -360, 360}, {1, 4, 0.00304, 0.0304, 0.00658, 0, 0, 0, 0, 0, 1, -360, 360}, {1, 5, 0.00064, 0.0064, 0.03126, 0, 0, 0, 0, 0, 1, -360, 360}, @@ -41,7 +41,7 @@ int main(int argc, char **argv) { {3, 4, 0.00297, 0.0297, 0.00674, 0, 0, 0, 0, 0, 1, -360, 360}, {4, 5, 0.00297, 0.0297, 0.00674, 240, 240, 240, 0, 0, 1, -360, 360}, }; - MatPower mp; + SystemModelData mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_bus_row.cpp b/Examples/MatPowerTesting/test_parse_bus_row.cpp index bd723c542..38695c5fa 100644 --- a/Examples/MatPowerTesting/test_parse_bus_row.cpp +++ b/Examples/MatPowerTesting/test_parse_bus_row.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -28,7 +28,7 @@ mpc.bus = [ int main(int argc, char** argv) { int fail = 0; - std::vector> bus_answer{ + std::vector> bus_answer{ {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, @@ -36,7 +36,7 @@ int main(int argc, char** argv) { {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; - std::vector> load_answer{ + std::vector> load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, @@ -45,7 +45,7 @@ int main(int argc, char** argv) { }; { - MatPower mp; + SystemModelData mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.bus, bus_answer)) fail++; @@ -53,7 +53,7 @@ int main(int argc, char** argv) { } { - MatPower mp; + SystemModelData mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.load, load_answer)) fail++; diff --git a/Examples/MatPowerTesting/test_parse_gen_row.cpp b/Examples/MatPowerTesting/test_parse_gen_row.cpp index b31d8b2b4..b524ae899 100644 --- a/Examples/MatPowerTesting/test_parse_gen_row.cpp +++ b/Examples/MatPowerTesting/test_parse_gen_row.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -30,7 +30,7 @@ mpc.gen = [ int main(int argc, char **argv) { int fail = 0; - std::vector> gen_answer{ + std::vector> gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 170, 0, 127.5, -127.5, 1, 100, 1, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -39,7 +39,7 @@ int main(int argc, char **argv) { {4, 0, 0, 150, -150, 1, 100, 1, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 466.51, 0, 450, -450, 1, 100, 1, 600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - MatPower mp; + SystemModelData mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_gencost_row.cpp b/Examples/MatPowerTesting/test_parse_gencost_row.cpp index 49e7ad714..efc409d89 100644 --- a/Examples/MatPowerTesting/test_parse_gencost_row.cpp +++ b/Examples/MatPowerTesting/test_parse_gencost_row.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -33,12 +33,12 @@ mpc.gencost = [ int main(int argc, char **argv) { int fail = 0; - std::vector> gencost_answer{ + std::vector> gencost_answer{ {2, 0, 0, 3, {0, 14, 0}}, {2, 0, 0, 3, {0, 15, 0}}, {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - MatPower mp; + SystemModelData mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index 1fe25766d..e4cec26fa 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -85,15 +85,15 @@ int main(int argc, char **argv) { int fail = 0; // All types will use the scalar types at the top of the file - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using MatPowerT = MatPower; - using LoadRowT = LoadRow; + using BusDataT = BusData; + using GenDataT = GenData; + using BranchDataT = BranchData; + using GenCostDataT = GenCostData; + using SystemModelDataT = SystemModelData; + using LoadDataT = LoadData; // Create the struct of expected values - std::vector branch_answer{ + std::vector branch_answer{ {1, 2, 0.00281, 0.0281, 0.00712, 400, 400, 400, 0, 0, 1, -360, 360}, {1, 4, 0.00304, 0.0304, 0.00658, 0, 0, 0, 0, 0, 1, -360, 360}, {1, 5, 0.00064, 0.0064, 0.03126, 0, 0, 0, 0, 0, 1, -360, 360}, @@ -101,14 +101,14 @@ int main(int argc, char **argv) { {3, 4, 0.00297, 0.0297, 0.00674, 0, 0, 0, 0, 0, 1, -360, 360}, {4, 5, 0.00297, 0.0297, 0.00674, 240, 240, 240, 0, 0, 1, -360, 360}, }; - std::vector bus_answer{ + std::vector bus_answer{ {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {4, 3, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; - std::vector gen_answer{ + std::vector gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 170, 0, 127.5, -127.5, 1, 100, 1, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -117,12 +117,12 @@ int main(int argc, char **argv) { {4, 0, 0, 150, -150, 1, 100, 1, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 466.51, 0, 450, -450, 1, 100, 1, 600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - std::vector gencost_answer{ + std::vector gencost_answer{ {2, 0, 0, 3, {0, 14, 0}}, {2, 0, 0, 3, {0, 15, 0}}, {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - std::vector> load_answer{ + std::vector> load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, @@ -131,7 +131,7 @@ int main(int argc, char **argv) { }; - MatPowerT mp_answer; + SystemModelDataT mp_answer; mp_answer.gencost = gencost_answer; mp_answer.gen = gen_answer; mp_answer.bus = bus_answer; @@ -140,7 +140,7 @@ int main(int argc, char **argv) { mp_answer.version = "2"; mp_answer.baseMVA = 100; - MatPowerT mp; + SystemModelDataT mp; { std::istringstream iss(matpower_data); diff --git a/Utilities/MatPowerUtils.hpp b/PowerSystemData.hpp similarity index 90% rename from Utilities/MatPowerUtils.hpp rename to PowerSystemData.hpp index 618c0ca2e..5bba07992 100644 --- a/Utilities/MatPowerUtils.hpp +++ b/PowerSystemData.hpp @@ -6,11 +6,11 @@ /** * - * @file Utilities/MatPowerUtils.hpp + * @file PowerSystemData.hpp * @author Asher Mancinelli * * @remark `std::stringstream` is preferred over `operator+(std::string, ...)` - * due to stringstream's lack of reallocation on append. + * since stringstream does not reallocate on append. * */ @@ -21,7 +21,7 @@ namespace PowerSystemData { template - struct BusRow + struct BusData { IdxT bus_i; ///< Bus ID IdxT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated @@ -55,7 +55,7 @@ namespace PowerSystemData }; template - struct LoadRow + struct LoadData { IdxT bus_i; ///< Bus ID RealT Pd; ///< Active power demand [MW] @@ -73,7 +73,7 @@ namespace PowerSystemData }; template - struct GenRow + struct GenData { IdxT bus; ///< Bus ID RealT Pg; ///< Active power output [MW] @@ -127,7 +127,7 @@ namespace PowerSystemData }; template - struct BranchRow + struct BranchData { IdxT fbus; ///< "From" bus ID IdxT tbus; ///< "To" bus ID @@ -165,7 +165,7 @@ namespace PowerSystemData }; template - struct GenCostRow + struct GenCostData { IdxT kind; IdxT startup; @@ -188,20 +188,21 @@ namespace PowerSystemData }; template - struct MatPower { - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using LoadRowT = LoadRow; + struct SystemModelData + { + using BusDataT = BusData; + using GenDataT = GenData; + using BranchDataT = BranchData; + using GenCostDataT = GenCostData; + using LoadDataT = LoadData; std::string version; IdxT baseMVA; - std::vector bus; - std::vector gen; - std::vector branch; - std::vector gencost; - std::vector load; + std::vector bus; + std::vector gen; + std::vector branch; + std::vector gencost; + std::vector load; // Not sure if these should be in this struct... Not all matpower files // I found contained them. @@ -235,7 +236,7 @@ namespace PowerSystemData return ss.str(); } - }; + }; // struct SystemModelData -} // namespace MatPower +} // namespace PowerSystemData } // namespace GridKit diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp index a2dc6e015..c32f4c030 100644 --- a/Utilities/FileIO.hpp +++ b/Utilities/FileIO.hpp @@ -74,7 +74,7 @@ #include #include -#include "MatPowerUtils.hpp" +#include namespace { @@ -156,7 +156,7 @@ void checkEndOfMatrixRow(std::istream& is) } template -void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow& lr) +void readMatPowerBusRow(const std::string& row, BusData& br, LoadData& lr) { logs() << "Parsing MATPOWER bus row\n"; std::stringstream is(row); @@ -177,12 +177,12 @@ void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow lr.bus_i = br.bus_i; // std::cout << br.str(); - // logs() << "Read BusRow with the following values:\n" << br.str(); + // logs() << "Read BusData with the following values:\n" << br.str(); // return br; } template -void readMatPowerGenRow(GenRow& gr, std::string& row) +void readMatPowerGenRow(GenData& gr, std::string& row) { logs() << "Parsing MATPOWER gen row\n"; std::stringstream is(row); @@ -194,7 +194,7 @@ void readMatPowerGenRow(GenRow& gr, std::string& row) } template -void readMatPowerBranchRow(BranchRow& br, std::string& row) +void readMatPowerBranchRow(BranchData& br, std::string& row) { logs() << "Parsing MATPOWER branch row\n"; std::stringstream is(row); @@ -205,7 +205,7 @@ void readMatPowerBranchRow(BranchRow& br, std::string& row) } template -void readMatPowerGenCostRow(GenCostRow& gcr, std::string& row) +void readMatPowerGenCostRow(GenCostData& gcr, std::string& row) { logs() << "Parsing MATPOWER gen cost row\n"; // Ensure last character is semicolon. @@ -222,7 +222,7 @@ void readMatPowerGenCostRow(GenCostRow& gcr, std::string& row) } template -void readMatPowerVersion(MatPower& mp, std::string& line) +void readMatPowerVersion(SystemModelData& mp, std::string& line) { logs() << "Parsing matpower version\n"; std::regex pat("mpc\\.version\\s*=\\s*'([0-9])';"); @@ -235,7 +235,7 @@ void readMatPowerVersion(MatPower& mp, std::string& line) } template -void readMatPowerBaseMVA(MatPower& mp, std::string& line) +void readMatPowerBaseMVA(SystemModelData& mp, std::string& line) { std::regex pat("mpc\\.baseMVA\\s*=\\s*([0-9]+);"); std::smatch matches; @@ -297,7 +297,7 @@ void printLookupTable(std::vector> const& table) } template -void readMatPowerFile(MatPower& mp, std::string& filename) +void readMatPowerFile(SystemModelData& mp, std::string& filename) { std::ifstream ifs{filename}; readMatPower(mp, ifs); @@ -306,13 +306,13 @@ void readMatPowerFile(MatPower& mp, std::string& filename) template -void readMatPower(MatPower& mp, std::istream& is) +void readMatPower(SystemModelData& mp, std::istream& is) { - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using LoadRowT = LoadRow; + using BusDataT = BusData; + using GenDataT = GenData; + using BranchDataT = BranchData; + using GenCostDataT = GenCostData; + using LoadDataT = LoadData; for (std::string line; std::getline(is, line);) { // Trim whitespace and remove comments @@ -335,8 +335,8 @@ void readMatPower(MatPower& mp, std::istream& is) if (component == "bus") { while (std::getline(is, line)) { if (line.find("];") != std::string::npos) break; - BusRowT br; - LoadRowT lr; + BusDataT br; + LoadDataT lr; readMatPowerBusRow(line, br, lr); mp.bus.push_back(std::move(br)); mp.load.push_back(std::move(lr)); @@ -344,21 +344,21 @@ void readMatPower(MatPower& mp, std::istream& is) } else if (component == "gen") { while (std::getline(is, line)) { if (line.find("];") != std::string::npos) break; - GenRowT gr; + GenDataT gr; readMatPowerGenRow(gr, line); mp.gen.push_back(gr); } } else if (component == "branch") { while (std::getline(is, line)) { if (line.find("];") != std::string::npos) break; - BranchRowT br; + BranchDataT br; readMatPowerBranchRow(br, line); mp.branch.push_back(br); } } else if (component == "gencost") { while (std::getline(is, line)) { if (line.find("];") != std::string::npos) break; - GenCostRowT gcr; + GenCostDataT gcr; readMatPowerGenCostRow(gcr, line); mp.gencost.push_back(gcr); } diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index c722de6e3..ea608734e 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -66,7 +66,7 @@ */ #pragma once -#include "MatPowerUtils.hpp" +#include #include #include @@ -89,8 +89,8 @@ template bool isEqual(const T value, const T ref, const T tol) { } template -inline bool isEqual(PowerSystemData::GenCostRow a, - PowerSystemData::GenCostRow b, +inline bool isEqual(PowerSystemData::GenCostData a, + PowerSystemData::GenCostData b, RealT tol = tol_) { int fail = 0; fail += a.kind != b.kind; @@ -104,8 +104,8 @@ inline bool isEqual(PowerSystemData::GenCostRow a, } template -inline bool isEqual(PowerSystemData::GenRow a, - PowerSystemData::GenRow b, RealT tol = tol_) { +inline bool isEqual(PowerSystemData::GenData a, + PowerSystemData::GenData b, RealT tol = tol_) { int fail = 0; fail += a.bus != b.bus; fail += !isEqual(a.Pg, b.Pg, tol); @@ -135,8 +135,8 @@ inline bool isEqual(PowerSystemData::GenRow a, } template -inline bool isEqual(PowerSystemData::BusRow a, - PowerSystemData::BusRow b, RealT tol = tol_) { +inline bool isEqual(PowerSystemData::BusData a, + PowerSystemData::BusData b, RealT tol = tol_) { int fail = 0; fail += a.bus_i != b.bus_i; fail += a.type != b.type; @@ -166,8 +166,8 @@ inline bool isEqual(PowerSystemData::BusRow a, } template -inline bool isEqual(PowerSystemData::LoadRow a, - PowerSystemData::LoadRow b, RealT tol = tol_) { +inline bool isEqual(PowerSystemData::LoadData a, + PowerSystemData::LoadData b, RealT tol = tol_) { int fail = 0; fail += a.bus_i != b.bus_i; fail += !isEqual(a.Pd, b.Pd, tol); @@ -181,8 +181,8 @@ inline bool isEqual(PowerSystemData::LoadRow a, } template -inline bool isEqual(PowerSystemData::BranchRow a, - PowerSystemData::BranchRow b, RealT tol = tol_) { +inline bool isEqual(PowerSystemData::BranchData a, + PowerSystemData::BranchData b, RealT tol = tol_) { int fail = 0; fail += a.fbus != b.fbus; fail += a.tbus != b.tbus; @@ -226,8 +226,8 @@ inline bool isEqual(std::vector a, std::vector b, double tol = tol_) { } template -inline bool isEqual(PowerSystemData::MatPower a, - PowerSystemData::MatPower b) { +inline bool isEqual(PowerSystemData::SystemModelData a, + PowerSystemData::SystemModelData b) { int fail = 0; fail += a.version != b.version; fail += a.baseMVA != b.baseMVA; From 87153deb1cb6c182f81a38e24861e9dfe6a6a337 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Sun, 23 Oct 2022 22:18:40 -0400 Subject: [PATCH 07/52] Pass correct scalar and real types to derived bus classes. --- ComponentLib/Bus/BaseBus.hpp | 1 - ComponentLib/Bus/BusFactory.hpp | 15 ++++++++------- ComponentLib/Bus/BusPQ.hpp | 4 ++-- ComponentLib/Bus/BusPV.hpp | 4 ++-- ComponentLib/Bus/BusSlack.hpp | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ComponentLib/Bus/BaseBus.hpp b/ComponentLib/Bus/BaseBus.hpp index bc3b31a0c..331060b04 100644 --- a/ComponentLib/Bus/BaseBus.hpp +++ b/ComponentLib/Bus/BaseBus.hpp @@ -61,7 +61,6 @@ #define _BASE_BUS_HPP_ #include -// #include namespace ModelLib { diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp index f4212a658..f19c66ad1 100644 --- a/ComponentLib/Bus/BusFactory.hpp +++ b/ComponentLib/Bus/BusFactory.hpp @@ -64,27 +64,28 @@ namespace ModelLib { - template + template class BusFactory { public: - using BusData = GridKit::PowerSystemData::BusData; + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; BusFactory() = delete; - static BaseBus* create(BusData& data) + static BaseBus* create(BusData& data) { - BaseBus* bus = nullptr; + BaseBus* bus = nullptr; switch(data.type) { case 1: - bus = new BusPQ(data); + bus = new BusPQ(data); break; case 2: - bus = new BusPV(data); + bus = new BusPV(data); break; case 3: - bus = new BusSlack(data); + bus = new BusSlack(data); break; default: // Throw exception diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp index 56798b6e2..9131dc21e 100644 --- a/ComponentLib/Bus/BusPQ.hpp +++ b/ComponentLib/Bus/BusPQ.hpp @@ -86,8 +86,8 @@ namespace ModelLib using BaseBus::tag_; public: - typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusData; + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; BusPQ(); BusPQ(ScalarT V, ScalarT theta); diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index 56eda8b4d..ada1c570a 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -87,8 +87,8 @@ namespace ModelLib using BaseBus::tag_; public: - typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusData; + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; BusPV(); BusPV(ScalarT V, ScalarT theta0, ScalarT P); diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index 24f138083..c3b8490c7 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -86,8 +86,8 @@ namespace ModelLib using BaseBus::rtol_; public: - typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusData; + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; BusSlack(); BusSlack(ScalarT V, ScalarT theta); From 46c8d9d98e0f6c61caec64ad87ddd46b8278d917 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Tue, 29 Nov 2022 22:13:52 -0500 Subject: [PATCH 08/52] Add generator base and slack classes. Classes compile correctly, not tested yet. --- ComponentLib/CMakeLists.txt | 1 + ComponentLib/Generator/CMakeLists.txt | 68 +++++++++ ComponentLib/Generator/GeneratorBase.hpp | 126 ++++++++++++++++ ComponentLib/Generator/GeneratorSlack.cpp | 168 ++++++++++++++++++++++ ComponentLib/Generator/GeneratorSlack.hpp | 144 +++++++++++++++++++ 5 files changed, 507 insertions(+) create mode 100644 ComponentLib/Generator/CMakeLists.txt create mode 100644 ComponentLib/Generator/GeneratorBase.hpp create mode 100644 ComponentLib/Generator/GeneratorSlack.cpp create mode 100644 ComponentLib/Generator/GeneratorSlack.hpp diff --git a/ComponentLib/CMakeLists.txt b/ComponentLib/CMakeLists.txt index 67112e1b1..0c422d5b9 100644 --- a/ComponentLib/CMakeLists.txt +++ b/ComponentLib/CMakeLists.txt @@ -62,6 +62,7 @@ add_subdirectory(Branch) add_subdirectory(Bus) +add_subdirectory(Generator) add_subdirectory(Generator2) add_subdirectory(Generator4) add_subdirectory(Generator4Governor) diff --git a/ComponentLib/Generator/CMakeLists.txt b/ComponentLib/Generator/CMakeLists.txt new file mode 100644 index 000000000..68ef63cf7 --- /dev/null +++ b/ComponentLib/Generator/CMakeLists.txt @@ -0,0 +1,68 @@ +# +# Copyright (c) 2017, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# Written by Slaven Peles . +# LLNL-CODE-718378. +# All rights reserved. +# +# This file is part of GridKit™. For details, see github.com/LLNL/GridKit +# Please also read the LICENSE file. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright notice, +# this list of conditions and the disclaimer below. +# - Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the disclaimer (as noted below) in the +# documentation and/or other materials provided with the distribution. +# - Neither the name of the LLNS/LLNL nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL +# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY +# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +# Lawrence Livermore National Laboratory is operated by Lawrence Livermore +# National Security, LLC, for the U.S. Department of Energy, National +# Nuclear Security Administration under Contract DE-AC52-07NA27344. +# +# This document was prepared as an account of work sponsored by an agency +# of the United States government. Neither the United States government nor +# Lawrence Livermore National Security, LLC, nor any of their employees +# makes any warranty, expressed or implied, or assumes any legal liability +# or responsibility for the accuracy, completeness, or usefulness of any +# information, apparatus, product, or process disclosed, or represents that +# its use would not infringe privately owned rights. Reference herein to +# any specific commercial product, process, or service by trade name, +# trademark, manufacturer, or otherwise does not necessarily constitute or +# imply its endorsement, recommendation, or favoring by the United States +# government or Lawrence Livermore National Security, LLC. The views and +# opinions of authors expressed herein do not necessarily state or reflect +# those of the United States government or Lawrence Livermore National +# Security, LLC, and shall not be used for advertising or product +# endorsement purposes. +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(generator + SOURCES + GeneratorSlack.cpp + OUTPUT_NAME + gridkit_generator) + diff --git a/ComponentLib/Generator/GeneratorBase.hpp b/ComponentLib/Generator/GeneratorBase.hpp new file mode 100644 index 000000000..164e6eb2a --- /dev/null +++ b/ComponentLib/Generator/GeneratorBase.hpp @@ -0,0 +1,126 @@ +/* + * + * Copyright (c) 2017, Lawrence Livermore National Security, LLC. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Slaven Peles . + * LLNL-CODE-718378. + * All rights reserved. + * + * This file is part of GridKit™. For details, see github.com/LLNL/GridKit + * Please also read the LICENSE file. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the disclaimer (as noted below) in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the LLNS/LLNL nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL + * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * Lawrence Livermore National Laboratory is operated by Lawrence Livermore + * National Security, LLC, for the U.S. Department of Energy, National + * Nuclear Security Administration under Contract DE-AC52-07NA27344. + * + * This document was prepared as an account of work sponsored by an agency + * of the United States government. Neither the United States government nor + * Lawrence Livermore National Security, LLC, nor any of their employees + * makes any warranty, expressed or implied, or assumes any legal liability + * or responsibility for the accuracy, completeness, or usefulness of any + * information, apparatus, product, or process disclosed, or represents that + * its use would not infringe privately owned rights. Reference herein to + * any specific commercial product, process, or service by trade name, + * trademark, manufacturer, or otherwise does not necessarily constitute or + * imply its endorsement, recommendation, or favoring by the United States + * government or Lawrence Livermore National Security, LLC. The views and + * opinions of authors expressed herein do not necessarily state or reflect + * those of the United States government or Lawrence Livermore National + * Security, LLC, and shall not be used for advertising or product + * endorsement purposes. + * + */ + +#pragma once + +#include +#include + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Implementation of a power grid. + * + */ + template + class GeneratorBase : public ModelEvaluatorImpl + { + protected: + using ModelEvaluatorImpl::size_; + using ModelEvaluatorImpl::nnz_; + using ModelEvaluatorImpl::time_; + using ModelEvaluatorImpl::alpha_; + using ModelEvaluatorImpl::y_; + using ModelEvaluatorImpl::yp_; + using ModelEvaluatorImpl::tag_; + using ModelEvaluatorImpl::f_; + using ModelEvaluatorImpl::g_; + using ModelEvaluatorImpl::yB_; + using ModelEvaluatorImpl::ypB_; + using ModelEvaluatorImpl::fB_; + using ModelEvaluatorImpl::gB_; + using ModelEvaluatorImpl::param_; + + using bus_type = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + // using BusData = GridKit::PowerSystemData::BusData; + // typedef typename ModelEvaluatorImpl::real_type real_type; + // typedef BaseBus bus_type; + + public: + GeneratorBase(){} + virtual ~GeneratorBase(){} + + virtual int allocate() { return 0;} + virtual int initialize() { return 0;} + virtual int tagDifferentiable() { return 0;} + virtual int evaluateResidual() { return 0;} + virtual int evaluateJacobian() { return 0;} + virtual int evaluateIntegrand() { return 0;} + + virtual int initializeAdjoint() { return 0;} + virtual int evaluateAdjointResidual() { return 0;} + //virtual int evaluateAdjointJacobian(); + virtual int evaluateAdjointIntegrand() { return 0;} + + void updateTime(real_type, real_type) {} + + virtual ScalarT& P() = 0; + virtual const ScalarT& P() const = 0; + virtual ScalarT& Q() = 0; + virtual const ScalarT& Q() const = 0; + }; +} + diff --git a/ComponentLib/Generator/GeneratorSlack.cpp b/ComponentLib/Generator/GeneratorSlack.cpp new file mode 100644 index 000000000..de97c4752 --- /dev/null +++ b/ComponentLib/Generator/GeneratorSlack.cpp @@ -0,0 +1,168 @@ +/* + * + * Copyright (c) 2017, Lawrence Livermore National Security, LLC. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Slaven Peles . + * LLNL-CODE-718378. + * All rights reserved. + * + * This file is part of GridKit™. For details, see github.com/LLNL/GridKit + * Please also read the LICENSE file. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the disclaimer (as noted below) in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the LLNS/LLNL nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL + * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * Lawrence Livermore National Laboratory is operated by Lawrence Livermore + * National Security, LLC, for the U.S. Department of Energy, National + * Nuclear Security Administration under Contract DE-AC52-07NA27344. + * + * This document was prepared as an account of work sponsored by an agency + * of the United States government. Neither the United States government nor + * Lawrence Livermore National Security, LLC, nor any of their employees + * makes any warranty, expressed or implied, or assumes any legal liability + * or responsibility for the accuracy, completeness, or usefulness of any + * information, apparatus, product, or process disclosed, or represents that + * its use would not infringe privately owned rights. Reference herein to + * any specific commercial product, process, or service by trade name, + * trademark, manufacturer, or otherwise does not necessarily constitute or + * imply its endorsement, recommendation, or favoring by the United States + * government or Lawrence Livermore National Security, LLC. The views and + * opinions of authors expressed herein do not necessarily state or reflect + * those of the United States government or Lawrence Livermore National + * Security, LLC, and shall not be used for advertising or product + * endorsement purposes. + * + */ + + +#include +#include +#include +#include "GeneratorSlack.hpp" +#include + +namespace ModelLib { + +/*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +GeneratorSlack::GeneratorSlack(bus_type* bus, GenData& data) + : bus_(bus) +{ + //std::cout << "Create a load model with " << size_ << " variables ...\n"; + size_ = 0; +} + +template +GeneratorSlack::~GeneratorSlack() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int GeneratorSlack::allocate() +{ + return 0; +} + +/** + * Initialization of the grid model + */ +template +int GeneratorSlack::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int GeneratorSlack::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int GeneratorSlack::evaluateResidual() +{ + // std::cout << "Evaluating load residual ...\n"; + // bus_->P() += P_; + // bus_->Q() += Q_; + return 0; +} + +template +int GeneratorSlack::evaluateJacobian() +{ + return 0; +} + +template +int GeneratorSlack::evaluateIntegrand() +{ + return 0; +} + +template +int GeneratorSlack::initializeAdjoint() +{ + return 0; +} + +template +int GeneratorSlack::evaluateAdjointResidual() +{ + return 0; +} + +template +int GeneratorSlack::evaluateAdjointIntegrand() +{ + return 0; +} + + + + +// Available template instantiations +template class GeneratorSlack; +template class GeneratorSlack; + + +} //namespace ModelLib + diff --git a/ComponentLib/Generator/GeneratorSlack.hpp b/ComponentLib/Generator/GeneratorSlack.hpp new file mode 100644 index 000000000..e821f8a6b --- /dev/null +++ b/ComponentLib/Generator/GeneratorSlack.hpp @@ -0,0 +1,144 @@ +/* + * + * Copyright (c) 2017, Lawrence Livermore National Security, LLC. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Slaven Peles . + * LLNL-CODE-718378. + * All rights reserved. + * + * This file is part of GridKit™. For details, see github.com/LLNL/GridKit + * Please also read the LICENSE file. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the disclaimer (as noted below) in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the LLNS/LLNL nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL + * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * Lawrence Livermore National Laboratory is operated by Lawrence Livermore + * National Security, LLC, for the U.S. Department of Energy, National + * Nuclear Security Administration under Contract DE-AC52-07NA27344. + * + * This document was prepared as an account of work sponsored by an agency + * of the United States government. Neither the United States government nor + * Lawrence Livermore National Security, LLC, nor any of their employees + * makes any warranty, expressed or implied, or assumes any legal liability + * or responsibility for the accuracy, completeness, or usefulness of any + * information, apparatus, product, or process disclosed, or represents that + * its use would not infringe privately owned rights. Reference herein to + * any specific commercial product, process, or service by trade name, + * trademark, manufacturer, or otherwise does not necessarily constitute or + * imply its endorsement, recommendation, or favoring by the United States + * government or Lawrence Livermore National Security, LLC. The views and + * opinions of authors expressed herein do not necessarily state or reflect + * those of the United States government or Lawrence Livermore National + * Security, LLC, and shall not be used for advertising or product + * endorsement purposes. + * + */ + +#pragma once + +// #include +#include "GeneratorBase.hpp" +#include +#include + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Implementation of a power grid. + * + */ + template + class GeneratorSlack : public GeneratorBase + { + using GeneratorBase::size_; + using GeneratorBase::nnz_; + using GeneratorBase::time_; + using GeneratorBase::alpha_; + using GeneratorBase::y_; + using GeneratorBase::yp_; + using GeneratorBase::tag_; + using GeneratorBase::f_; + using GeneratorBase::g_; + using GeneratorBase::yB_; + using GeneratorBase::ypB_; + using GeneratorBase::fB_; + using GeneratorBase::gB_; + using GeneratorBase::param_; + + using bus_type = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + using GenData = GridKit::PowerSystemData::GenData; + // typedef typename ModelEvaluatorImpl::real_type real_type; + // typedef BaseBus bus_type; + + public: + GeneratorSlack(bus_type* bus, GenData& data); + virtual ~GeneratorSlack(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + virtual ScalarT& P() + { + return bus_->P(); + } + + virtual const ScalarT& P() const + { + return bus_->P(); + } + + virtual ScalarT& Q() + { + return bus_->Q(); + } + + virtual const ScalarT& Q() const + { + return bus_->Q(); + } + + + private: + bus_type* bus_; + }; +} + From f1e52711297bf9d5c10155eb0000e81f07580619 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Wed, 14 Dec 2022 13:59:31 -0500 Subject: [PATCH 09/52] Infrastructure for adding buses and generators to power flow models Add steady-state generator models and factory. Constructors now read directly from GenData and BusData structures. Updated Bus classes accordingly. Usage example provided in Grid3BusSys app. --- ComponentLib/Bus/BaseBus.hpp | 2 + ComponentLib/Bus/BusFactory.hpp | 4 +- ComponentLib/Bus/BusPQ.hpp | 2 +- ComponentLib/Bus/BusPV.hpp | 2 +- ComponentLib/Bus/BusSlack.hpp | 2 +- ComponentLib/Generator/CMakeLists.txt | 2 + ComponentLib/Generator/GeneratorBase.hpp | 11 +- ComponentLib/Generator/GeneratorFactory.hpp | 102 +++++++++++ ComponentLib/Generator/GeneratorPQ.cpp | 168 ++++++++++++++++++ ComponentLib/Generator/GeneratorPQ.hpp | 143 +++++++++++++++ ComponentLib/Generator/GeneratorPV.cpp | 168 ++++++++++++++++++ ComponentLib/Generator/GeneratorPV.hpp | 142 +++++++++++++++ Examples/Grid3Bus/CMakeLists.txt | 7 +- Examples/Grid3Bus/Grid3BusSys.cpp | 37 +++- .../MatPowerTesting/test_parse_matpower.cpp | 2 +- PowerSystemData.hpp | 2 +- Utilities/FileIO.hpp | 26 +-- 17 files changed, 787 insertions(+), 35 deletions(-) create mode 100644 ComponentLib/Generator/GeneratorFactory.hpp create mode 100644 ComponentLib/Generator/GeneratorPQ.cpp create mode 100644 ComponentLib/Generator/GeneratorPQ.hpp create mode 100644 ComponentLib/Generator/GeneratorPV.cpp create mode 100644 ComponentLib/Generator/GeneratorPV.hpp diff --git a/ComponentLib/Bus/BaseBus.hpp b/ComponentLib/Bus/BaseBus.hpp index 331060b04..1d19d963f 100644 --- a/ComponentLib/Bus/BaseBus.hpp +++ b/ComponentLib/Bus/BaseBus.hpp @@ -102,6 +102,8 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; + enum BusType{PQ=1, PV, Slack, Isolated}; + BaseBus(){} virtual ~BaseBus(){} diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp index f19c66ad1..68fc5578e 100644 --- a/ComponentLib/Bus/BusFactory.hpp +++ b/ComponentLib/Bus/BusFactory.hpp @@ -60,7 +60,9 @@ #pragma once #include -#include +#include +#include +#include namespace ModelLib { diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp index 9131dc21e..45ed81a65 100644 --- a/ComponentLib/Bus/BusPQ.hpp +++ b/ComponentLib/Bus/BusPQ.hpp @@ -183,7 +183,7 @@ namespace ModelLib virtual const int BusType() const { - return 1; + return BaseBus::BusType::PQ; } private: diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index ada1c570a..fd0291b69 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -193,7 +193,7 @@ namespace ModelLib virtual const int BusType() const { - return 2; + return BaseBus::BusType::PV; } private: diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index c3b8490c7..19c27d96a 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -182,7 +182,7 @@ namespace ModelLib virtual const int BusType() const { - return 3; + return BaseBus::BusType::Slack; } private: diff --git a/ComponentLib/Generator/CMakeLists.txt b/ComponentLib/Generator/CMakeLists.txt index 68ef63cf7..a09c5aed1 100644 --- a/ComponentLib/Generator/CMakeLists.txt +++ b/ComponentLib/Generator/CMakeLists.txt @@ -63,6 +63,8 @@ gridkit_add_library(generator SOURCES GeneratorSlack.cpp + GeneratorPV.cpp + GeneratorPQ.cpp OUTPUT_NAME gridkit_generator) diff --git a/ComponentLib/Generator/GeneratorBase.hpp b/ComponentLib/Generator/GeneratorBase.hpp index 164e6eb2a..e1efa22bd 100644 --- a/ComponentLib/Generator/GeneratorBase.hpp +++ b/ComponentLib/Generator/GeneratorBase.hpp @@ -70,9 +70,11 @@ namespace ModelLib namespace ModelLib { - /*! - * @brief Implementation of a power grid. - * + /** + * @brief Generator base class template + * + * @tparam ScalarT - Scalar type + * @tparam IdxT - Matrix and vector index type */ template class GeneratorBase : public ModelEvaluatorImpl @@ -95,9 +97,6 @@ namespace ModelLib using bus_type = BaseBus; using real_type = typename ModelEvaluatorImpl::real_type; - // using BusData = GridKit::PowerSystemData::BusData; - // typedef typename ModelEvaluatorImpl::real_type real_type; - // typedef BaseBus bus_type; public: GeneratorBase(){} diff --git a/ComponentLib/Generator/GeneratorFactory.hpp b/ComponentLib/Generator/GeneratorFactory.hpp new file mode 100644 index 000000000..ccb2c07e1 --- /dev/null +++ b/ComponentLib/Generator/GeneratorFactory.hpp @@ -0,0 +1,102 @@ +/* + * + * Copyright (c) 2017, Lawrence Livermore National Security, LLC. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Slaven Peles . + * LLNL-CODE-718378. + * All rights reserved. + * + * This file is part of GridKit™. For details, see github.com/LLNL/GridKit + * Please also read the LICENSE file. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the disclaimer (as noted below) in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the LLNS/LLNL nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL + * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * Lawrence Livermore National Laboratory is operated by Lawrence Livermore + * National Security, LLC, for the U.S. Department of Energy, National + * Nuclear Security Administration under Contract DE-AC52-07NA27344. + * + * This document was prepared as an account of work sponsored by an agency + * of the United States government. Neither the United States government nor + * Lawrence Livermore National Security, LLC, nor any of their employees + * makes any warranty, expressed or implied, or assumes any legal liability + * or responsibility for the accuracy, completeness, or usefulness of any + * information, apparatus, product, or process disclosed, or represents that + * its use would not infringe privately owned rights. Reference herein to + * any specific commercial product, process, or service by trade name, + * trademark, manufacturer, or otherwise does not necessarily constitute or + * imply its endorsement, recommendation, or favoring by the United States + * government or Lawrence Livermore National Security, LLC. The views and + * opinions of authors expressed herein do not necessarily state or reflect + * those of the United States government or Lawrence Livermore National + * Security, LLC, and shall not be used for advertising or product + * endorsement purposes. + * + */ + +#pragma once + +#include +#include +#include +#include +#include + + +namespace ModelLib { + + template + class GeneratorFactory + { + public: + using real_type = typename ModelEvaluatorImpl::real_type; + using GenData = GridKit::PowerSystemData::GenData; + + GeneratorFactory() = delete; + + static GeneratorBase* create(BaseBus* bus, GenData& data) + { + GeneratorBase* gen = nullptr; + switch(bus->BusType()) + { + case 1: + gen = new GeneratorPQ(bus, data); + break; + case 2: + gen = new GeneratorPV(bus, data); + break; + case 3: + gen = new GeneratorSlack(bus, data); + break; + default: + // Throw exception + std::cout << "Generator type " << bus->BusType() << " unrecognized.\n"; + } + return gen; + } + }; + +} // namespace ModelLib \ No newline at end of file diff --git a/ComponentLib/Generator/GeneratorPQ.cpp b/ComponentLib/Generator/GeneratorPQ.cpp new file mode 100644 index 000000000..981ec786b --- /dev/null +++ b/ComponentLib/Generator/GeneratorPQ.cpp @@ -0,0 +1,168 @@ +/* + * + * Copyright (c) 2017, Lawrence Livermore National Security, LLC. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Slaven Peles . + * LLNL-CODE-718378. + * All rights reserved. + * + * This file is part of GridKit™. For details, see github.com/LLNL/GridKit + * Please also read the LICENSE file. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the disclaimer (as noted below) in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the LLNS/LLNL nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL + * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * Lawrence Livermore National Laboratory is operated by Lawrence Livermore + * National Security, LLC, for the U.S. Department of Energy, National + * Nuclear Security Administration under Contract DE-AC52-07NA27344. + * + * This document was prepared as an account of work sponsored by an agency + * of the United States government. Neither the United States government nor + * Lawrence Livermore National Security, LLC, nor any of their employees + * makes any warranty, expressed or implied, or assumes any legal liability + * or responsibility for the accuracy, completeness, or usefulness of any + * information, apparatus, product, or process disclosed, or represents that + * its use would not infringe privately owned rights. Reference herein to + * any specific commercial product, process, or service by trade name, + * trademark, manufacturer, or otherwise does not necessarily constitute or + * imply its endorsement, recommendation, or favoring by the United States + * government or Lawrence Livermore National Security, LLC. The views and + * opinions of authors expressed herein do not necessarily state or reflect + * those of the United States government or Lawrence Livermore National + * Security, LLC, and shall not be used for advertising or product + * endorsement purposes. + * + */ + + +#include +#include +#include +#include "GeneratorPQ.hpp" +#include + +namespace ModelLib { + +/*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +GeneratorPQ::GeneratorPQ(bus_type* bus, GenData& data) + : P_(data.Pg), + Q_(data.Qg), + bus_(bus) +{ + //std::cout << "Create a load model with " << size_ << " variables ...\n"; + size_ = 0; +} + +template +GeneratorPQ::~GeneratorPQ() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int GeneratorPQ::allocate() +{ + return 0; +} + +/** + * Initialization of the grid model + */ +template +int GeneratorPQ::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int GeneratorPQ::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int GeneratorPQ::evaluateResidual() +{ + // std::cout << "Evaluating load residual ...\n"; + bus_->P() += P_; + bus_->Q() += Q_; + return 0; +} + +template +int GeneratorPQ::evaluateJacobian() +{ + return 0; +} + +template +int GeneratorPQ::evaluateIntegrand() +{ + return 0; +} + +template +int GeneratorPQ::initializeAdjoint() +{ + return 0; +} + +template +int GeneratorPQ::evaluateAdjointResidual() +{ + return 0; +} + +template +int GeneratorPQ::evaluateAdjointIntegrand() +{ + return 0; +} + + +// Available template instantiations +template class GeneratorPQ; +template class GeneratorPQ; + + +} //namespace ModelLib + diff --git a/ComponentLib/Generator/GeneratorPQ.hpp b/ComponentLib/Generator/GeneratorPQ.hpp new file mode 100644 index 000000000..ba72d022a --- /dev/null +++ b/ComponentLib/Generator/GeneratorPQ.hpp @@ -0,0 +1,143 @@ +/* + * + * Copyright (c) 2017, Lawrence Livermore National Security, LLC. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Slaven Peles . + * LLNL-CODE-718378. + * All rights reserved. + * + * This file is part of GridKit™. For details, see github.com/LLNL/GridKit + * Please also read the LICENSE file. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the disclaimer (as noted below) in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the LLNS/LLNL nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL + * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * Lawrence Livermore National Laboratory is operated by Lawrence Livermore + * National Security, LLC, for the U.S. Department of Energy, National + * Nuclear Security Administration under Contract DE-AC52-07NA27344. + * + * This document was prepared as an account of work sponsored by an agency + * of the United States government. Neither the United States government nor + * Lawrence Livermore National Security, LLC, nor any of their employees + * makes any warranty, expressed or implied, or assumes any legal liability + * or responsibility for the accuracy, completeness, or usefulness of any + * information, apparatus, product, or process disclosed, or represents that + * its use would not infringe privately owned rights. Reference herein to + * any specific commercial product, process, or service by trade name, + * trademark, manufacturer, or otherwise does not necessarily constitute or + * imply its endorsement, recommendation, or favoring by the United States + * government or Lawrence Livermore National Security, LLC. The views and + * opinions of authors expressed herein do not necessarily state or reflect + * those of the United States government or Lawrence Livermore National + * Security, LLC, and shall not be used for advertising or product + * endorsement purposes. + * + */ + +#pragma once + +#include +#include +#include +#include "GeneratorBase.hpp" + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Implementation of a PV generator. + * + */ + template + class GeneratorPQ : public GeneratorBase + { + using GeneratorBase::size_; + using GeneratorBase::nnz_; + using GeneratorBase::time_; + using GeneratorBase::alpha_; + using GeneratorBase::y_; + using GeneratorBase::yp_; + using GeneratorBase::tag_; + using GeneratorBase::f_; + using GeneratorBase::g_; + using GeneratorBase::yB_; + using GeneratorBase::ypB_; + using GeneratorBase::fB_; + using GeneratorBase::gB_; + using GeneratorBase::param_; + + using bus_type = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + using GenData = GridKit::PowerSystemData::GenData; + + public: + GeneratorPQ(bus_type* bus, GenData& data); + virtual ~GeneratorPQ(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + virtual ScalarT& P() + { + return P_; + } + + virtual const ScalarT& P() const + { + return P_; + } + + virtual ScalarT& Q() + { + return Q_; + } + + virtual const ScalarT& Q() const + { + return Q_; + } + + private: + ScalarT P_; + ScalarT Q_; + bus_type* bus_; + }; +} + diff --git a/ComponentLib/Generator/GeneratorPV.cpp b/ComponentLib/Generator/GeneratorPV.cpp new file mode 100644 index 000000000..f6e4bd447 --- /dev/null +++ b/ComponentLib/Generator/GeneratorPV.cpp @@ -0,0 +1,168 @@ +/* + * + * Copyright (c) 2017, Lawrence Livermore National Security, LLC. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Slaven Peles . + * LLNL-CODE-718378. + * All rights reserved. + * + * This file is part of GridKit™. For details, see github.com/LLNL/GridKit + * Please also read the LICENSE file. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the disclaimer (as noted below) in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the LLNS/LLNL nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL + * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * Lawrence Livermore National Laboratory is operated by Lawrence Livermore + * National Security, LLC, for the U.S. Department of Energy, National + * Nuclear Security Administration under Contract DE-AC52-07NA27344. + * + * This document was prepared as an account of work sponsored by an agency + * of the United States government. Neither the United States government nor + * Lawrence Livermore National Security, LLC, nor any of their employees + * makes any warranty, expressed or implied, or assumes any legal liability + * or responsibility for the accuracy, completeness, or usefulness of any + * information, apparatus, product, or process disclosed, or represents that + * its use would not infringe privately owned rights. Reference herein to + * any specific commercial product, process, or service by trade name, + * trademark, manufacturer, or otherwise does not necessarily constitute or + * imply its endorsement, recommendation, or favoring by the United States + * government or Lawrence Livermore National Security, LLC. The views and + * opinions of authors expressed herein do not necessarily state or reflect + * those of the United States government or Lawrence Livermore National + * Security, LLC, and shall not be used for advertising or product + * endorsement purposes. + * + */ + + +#include +#include +#include +#include "GeneratorPV.hpp" +#include + +namespace ModelLib { + +/*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +GeneratorPV::GeneratorPV(bus_type* bus, GenData& data) + : P_(data.Pg), + // Q_(data.Qg), + bus_(bus) +{ + //std::cout << "Create a load model with " << size_ << " variables ...\n"; + size_ = 0; +} + +template +GeneratorPV::~GeneratorPV() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int GeneratorPV::allocate() +{ + return 0; +} + +/** + * Initialization of the grid model + */ +template +int GeneratorPV::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int GeneratorPV::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int GeneratorPV::evaluateResidual() +{ + // std::cout << "Evaluating load residual ...\n"; + bus_->P() += P_; + // bus_->Q() += Q_; + return 0; +} + +template +int GeneratorPV::evaluateJacobian() +{ + return 0; +} + +template +int GeneratorPV::evaluateIntegrand() +{ + return 0; +} + +template +int GeneratorPV::initializeAdjoint() +{ + return 0; +} + +template +int GeneratorPV::evaluateAdjointResidual() +{ + return 0; +} + +template +int GeneratorPV::evaluateAdjointIntegrand() +{ + return 0; +} + + +// Available template instantiations +template class GeneratorPV; +template class GeneratorPV; + + +} //namespace ModelLib + diff --git a/ComponentLib/Generator/GeneratorPV.hpp b/ComponentLib/Generator/GeneratorPV.hpp new file mode 100644 index 000000000..5e3be2041 --- /dev/null +++ b/ComponentLib/Generator/GeneratorPV.hpp @@ -0,0 +1,142 @@ +/* + * + * Copyright (c) 2017, Lawrence Livermore National Security, LLC. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Slaven Peles . + * LLNL-CODE-718378. + * All rights reserved. + * + * This file is part of GridKit™. For details, see github.com/LLNL/GridKit + * Please also read the LICENSE file. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the disclaimer (as noted below) in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the LLNS/LLNL nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL + * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * Lawrence Livermore National Laboratory is operated by Lawrence Livermore + * National Security, LLC, for the U.S. Department of Energy, National + * Nuclear Security Administration under Contract DE-AC52-07NA27344. + * + * This document was prepared as an account of work sponsored by an agency + * of the United States government. Neither the United States government nor + * Lawrence Livermore National Security, LLC, nor any of their employees + * makes any warranty, expressed or implied, or assumes any legal liability + * or responsibility for the accuracy, completeness, or usefulness of any + * information, apparatus, product, or process disclosed, or represents that + * its use would not infringe privately owned rights. Reference herein to + * any specific commercial product, process, or service by trade name, + * trademark, manufacturer, or otherwise does not necessarily constitute or + * imply its endorsement, recommendation, or favoring by the United States + * government or Lawrence Livermore National Security, LLC. The views and + * opinions of authors expressed herein do not necessarily state or reflect + * those of the United States government or Lawrence Livermore National + * Security, LLC, and shall not be used for advertising or product + * endorsement purposes. + * + */ + +#pragma once + +#include +#include +#include +#include "GeneratorBase.hpp" + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Implementation of a PV generator. + * + */ + template + class GeneratorPV : public GeneratorBase + { + using GeneratorBase::size_; + using GeneratorBase::nnz_; + using GeneratorBase::time_; + using GeneratorBase::alpha_; + using GeneratorBase::y_; + using GeneratorBase::yp_; + using GeneratorBase::tag_; + using GeneratorBase::f_; + using GeneratorBase::g_; + using GeneratorBase::yB_; + using GeneratorBase::ypB_; + using GeneratorBase::fB_; + using GeneratorBase::gB_; + using GeneratorBase::param_; + + using bus_type = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + using GenData = GridKit::PowerSystemData::GenData; + + public: + GeneratorPV(bus_type* bus, GenData& data); + virtual ~GeneratorPV(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + virtual ScalarT& P() + { + return P_; + } + + virtual const ScalarT& P() const + { + return P_; + } + + virtual ScalarT& Q() + { + return bus_->Q(); + } + + virtual const ScalarT& Q() const + { + return bus_->Q(); + } + + private: + ScalarT P_; + bus_type* bus_; + }; +} + diff --git a/Examples/Grid3Bus/CMakeLists.txt b/Examples/Grid3Bus/CMakeLists.txt index 253371f64..5aededa5e 100644 --- a/Examples/Grid3Bus/CMakeLists.txt +++ b/Examples/Grid3Bus/CMakeLists.txt @@ -65,7 +65,12 @@ # install(TARGETS grid3bus RUNTIME DESTINATION bin) add_executable(grid3bus Grid3BusSys.cpp) -target_link_libraries(grid3bus GRIDKIT::minigrid GRIDKIT::bus GRIDKIT::branch GRIDKIT::load GRIDKIT::solvers_steady) +target_link_libraries(grid3bus GRIDKIT::minigrid + GRIDKIT::bus + GRIDKIT::generator + GRIDKIT::branch + GRIDKIT::load + GRIDKIT::solvers_steady) install(TARGETS grid3bus RUNTIME DESTINATION bin) add_test(NAME Grid3Bus COMMAND $) diff --git a/Examples/Grid3Bus/Grid3BusSys.cpp b/Examples/Grid3Bus/Grid3BusSys.cpp index 17362feac..bb61902bb 100644 --- a/Examples/Grid3Bus/Grid3BusSys.cpp +++ b/Examples/Grid3Bus/Grid3BusSys.cpp @@ -71,13 +71,13 @@ #include #include -#include -#include -#include +#include +#include #include #include #include #include +#include #include @@ -88,6 +88,7 @@ int main() using namespace AnalysisManager::Sundials; using namespace AnalysisManager; using namespace GridKit::Testing; + using namespace GridKit::PowerSystemData; std::cout << "\nSolving power flow for a 3-bus monolithic model ...\n\n"; // Create a 3-bus model @@ -137,16 +138,34 @@ int main() SystemSteadyStateModel* sysmodel = new SystemSteadyStateModel(); // Next create and add buses ... - // Create a slack bus, fix V=1, theta=0 - BaseBus* bus1 = new BusSlack(1.0, 0.0); + // Create a slack bus, fix V=1, theta=0, bus ID = 1" << std::endl; + BusData bd1; + bd1.bus_i = 1; bd1.type = 3; bd1.Vm = 1.0; bd1.Va = 0.0; + auto* bus1 = BusFactory::create(bd1); + // BaseBus* bus1 = new BusSlack(bd1); sysmodel->addBus(bus1); - // Create a PQ bus, initialize V=1, theta=0 - BaseBus* bus2 = new BusPQ(1.0, 0.0); + + // Create a PQ bus, initialize V=1, theta=0, bus ID = 2" << std::endl; + BusData bd2; + bd2.bus_i = 2; bd2.type = 1; bd2.Vm = 1.0; bd2.Va = 0.0; + auto* bus2 = BusFactory::create(bd2); + // BaseBus* bus2 = new BusPQ(bd2); sysmodel->addBus(bus2); - // Create a PV bus, fix V=1.1, initialize theta=0, and set power injection Pg=2 - BaseBus* bus3 = new BusPV(1.1, 0.0, 2.0); + + std::cout << "// Create a PV bus, fix V=1.1, initialize theta=0, and set power injection Pg=2" << std::endl; + BusData bd3; + bd3.bus_i = 3; bd3.type = 2; bd3.Vm = 1.1; bd3.Va = 0.0; + auto* bus3 = BusFactory::create(bd3); + // BaseBus* bus3 = new BusPV(1.1, 0.0, 2.0); sysmodel->addBus(bus3); + // Create and add generators ... + std::cout << "// Set power injection to 2.0 for bus3" << std::endl; + GenData gd3; + gd3.Pg = 2.0; gd3.bus = 3; + auto* gen3 = GeneratorFactory::create(bus3, gd3); + sysmodel->addComponent(gen3); + // Create and add branches ... Branch* branch12 = new Branch(bus1, bus2); branch12->setX(1.0/10.0); diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index e4cec26fa..fa926cad2 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -122,7 +122,7 @@ int main(int argc, char **argv) { {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - std::vector> load_answer{ + std::vector load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, diff --git a/PowerSystemData.hpp b/PowerSystemData.hpp index 5bba07992..67294db4f 100644 --- a/PowerSystemData.hpp +++ b/PowerSystemData.hpp @@ -24,7 +24,7 @@ namespace PowerSystemData struct BusData { IdxT bus_i; ///< Bus ID - IdxT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + IdxT type; ///< Bus type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) IdxT area; ///< Area number (>0) diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp index c32f4c030..825123c97 100644 --- a/Utilities/FileIO.hpp +++ b/Utilities/FileIO.hpp @@ -160,19 +160,19 @@ void readMatPowerBusRow(const std::string& row, BusData& br, LoadDa { logs() << "Parsing MATPOWER bus row\n"; std::stringstream is(row); - is >> br.bus_i - >> br.type - >> lr.Pd - >> lr.Qd - >> br.Gs - >> br.Bs - >> br.area - >> br.Vm - >> br.Va - >> br.baseKV - >> br.zone - >> br.Vmax - >> br.Vmin; + is >> br.bus_i // Bus ID + >> br.type // Bus type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + >> lr.Pd // Active power demand [MW] + >> lr.Qd // Reactive power demand [MVAr] + >> br.Gs // Shunt conductance (MW demanded at V = 1.0 p.u.) + >> br.Bs // Shunt susceptance (MVAr injected at V = 1.0 p.u.) + >> br.area // Area number (>0) + >> br.Vm // Voltage magnitude (p.u.) + >> br.Va // Voltage phase (deg) + >> br.baseKV // Base voltage [kV] + >> br.zone // Loss zone number (>0) + >> br.Vmax // Maximum voltage magnitude (p.u.) + >> br.Vmin; // Minimum voltage magnitude (p.u.) lr.bus_i = br.bus_i; From e25b06c3a95ce33e60b5e957298c2c176f72876b Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 15 Dec 2022 00:22:26 -0500 Subject: [PATCH 10/52] Supporting infrastructure for Loads and Branches Expanded methods for adding components to the power system grid. Includes new constructors for loads and branches, as well as methods for accessing buses through their IDs. --- ComponentLib/Branch/Branch.cpp | 19 ++++++++++ ComponentLib/Branch/Branch.hpp | 8 +++-- ComponentLib/Bus/BaseBus.hpp | 10 +++++- ComponentLib/Bus/BusPQ.cpp | 6 ++-- ComponentLib/Bus/BusPV.cpp | 6 ++-- ComponentLib/Bus/BusSlack.cpp | 6 ++-- ComponentLib/Load/Load.cpp | 12 +++++++ ComponentLib/Load/Load.hpp | 15 +++++--- Examples/Grid3Bus/Grid3BusSys.cpp | 58 ++++++++++++++++++++----------- SystemSteadyStateModel.hpp | 7 ++++ Utilities/Testing.hpp | 31 ++++++++++++----- 11 files changed, 132 insertions(+), 46 deletions(-) diff --git a/ComponentLib/Branch/Branch.cpp b/ComponentLib/Branch/Branch.cpp index b819724ec..5adf0268a 100644 --- a/ComponentLib/Branch/Branch.cpp +++ b/ComponentLib/Branch/Branch.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include "Branch.hpp" @@ -81,6 +82,8 @@ Branch::Branch(bus_type* bus1, bus_type* bus2) X_(0.01), G_(0.0), B_(0.0), + fbusID_(0), + tbusID_(0), bus1_(bus1), bus2_(bus2) { @@ -93,11 +96,27 @@ Branch::Branch(real_type R, real_type X, real_type G, real_type B X_(X), G_(G), B_(B), + fbusID_(0), + tbusID_(0), bus1_(bus1), bus2_(bus2) { } +template +Branch::Branch(bus_type* bus1, bus_type* bus2, BranchData& data) + : R_(data.r), + X_(data.x), + G_(0.0), + B_(data.b), + fbusID_(data.fbus), + tbusID_(data.tbus), + bus1_(bus1), + bus2_(bus2) +{ + size_ = 0; +} + template Branch::~Branch() diff --git a/ComponentLib/Branch/Branch.hpp b/ComponentLib/Branch/Branch.hpp index 3504ed8e2..4637784cd 100644 --- a/ComponentLib/Branch/Branch.hpp +++ b/ComponentLib/Branch/Branch.hpp @@ -91,12 +91,14 @@ namespace ModelLib using ModelEvaluatorImpl::gB_; using ModelEvaluatorImpl::param_; - typedef typename ModelEvaluatorImpl::real_type real_type; - typedef BaseBus bus_type; + using bus_type = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + using BranchData = GridKit::PowerSystemData::BranchData; public: Branch(bus_type* bus1, bus_type* bus2); Branch(real_type R, real_type X, real_type G, real_type B, bus_type* bus1, bus_type* bus2); + Branch(bus_type* bus1, bus_type* bus2, BranchData& data); virtual ~Branch(); int allocate(); @@ -183,6 +185,8 @@ namespace ModelLib real_type X_; real_type G_; real_type B_; + const IdxT fbusID_; + const IdxT tbusID_; bus_type* bus1_; bus_type* bus2_; }; diff --git a/ComponentLib/Bus/BaseBus.hpp b/ComponentLib/Bus/BaseBus.hpp index 1d19d963f..4e8cbd5f1 100644 --- a/ComponentLib/Bus/BaseBus.hpp +++ b/ComponentLib/Bus/BaseBus.hpp @@ -104,7 +104,7 @@ namespace ModelLib enum BusType{PQ=1, PV, Slack, Isolated}; - BaseBus(){} + BaseBus(IdxT id) : busID_(id) {} virtual ~BaseBus(){} // Set defaults for ModelEvaluator methods @@ -141,6 +141,14 @@ namespace ModelLib virtual const ScalarT& QB() const = 0; virtual const int BusType() const = 0; + + virtual const IdxT BusID() const + { + return busID_; + } + + protected: + const IdxT busID_; }; // class BaseBus } // namespace ModelLib diff --git a/ComponentLib/Bus/BusPQ.cpp b/ComponentLib/Bus/BusPQ.cpp index 00247d8d7..18c6ec22c 100644 --- a/ComponentLib/Bus/BusPQ.cpp +++ b/ComponentLib/Bus/BusPQ.cpp @@ -74,7 +74,7 @@ namespace ModelLib { */ template BusPQ::BusPQ() - : V0_(0.0), theta0_(0.0) + : BaseBus(0), V0_(0.0), theta0_(0.0) { //std::cout << "Create BusPQ..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; @@ -95,7 +95,7 @@ BusPQ::BusPQ() */ template BusPQ::BusPQ(ScalarT V, ScalarT theta) - : V0_(V), theta0_(theta) + : BaseBus(0), V0_(V), theta0_(theta) { //std::cout << "Create BusPQ..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; @@ -105,7 +105,7 @@ BusPQ::BusPQ(ScalarT V, ScalarT theta) template BusPQ::BusPQ(BusData& data) - : V0_(data.Vm), theta0_(data.Va) + : BaseBus(data.bus_i), V0_(data.Vm), theta0_(data.Va) { //std::cout << "Create BusPQ..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; diff --git a/ComponentLib/Bus/BusPV.cpp b/ComponentLib/Bus/BusPV.cpp index 0618f1284..5daafa102 100644 --- a/ComponentLib/Bus/BusPV.cpp +++ b/ComponentLib/Bus/BusPV.cpp @@ -74,7 +74,7 @@ namespace ModelLib { */ template BusPV::BusPV() - : V_(0.0), theta0_(0.0), Pg_(0.0) + : BaseBus(0), V_(0.0), theta0_(0.0), Pg_(0.0) { //std::cout << "Create BusPV..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; @@ -95,7 +95,7 @@ BusPV::BusPV() */ template BusPV::BusPV(ScalarT V, ScalarT theta0, ScalarT Pg) - : V_(V), theta0_(theta0), Pg_(Pg) + : BaseBus(0), V_(V), theta0_(theta0), Pg_(Pg) { //std::cout << "Create BusPV ..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; @@ -105,7 +105,7 @@ BusPV::BusPV(ScalarT V, ScalarT theta0, ScalarT Pg) template BusPV::BusPV(BusData& data) - : V_(data.Vm), theta0_(data.Va) //, Pg_(Pg) + : BaseBus(data.bus_i), V_(data.Vm), theta0_(data.Va) { //std::cout << "Create BusPV ..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; diff --git a/ComponentLib/Bus/BusSlack.cpp b/ComponentLib/Bus/BusSlack.cpp index c108e5d22..80a5ae091 100644 --- a/ComponentLib/Bus/BusSlack.cpp +++ b/ComponentLib/Bus/BusSlack.cpp @@ -74,7 +74,7 @@ namespace ModelLib { */ template BusSlack::BusSlack() - : V_(0.0), theta_(0.0), P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) + : BaseBus(0), V_(0.0), theta_(0.0), P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) { //std::cout << "Create BusSlack..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; @@ -93,7 +93,7 @@ BusSlack::BusSlack() */ template BusSlack::BusSlack(ScalarT V, ScalarT theta) - : V_(V), theta_(theta), P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) + : BaseBus(0), V_(V), theta_(theta), P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) { //std::cout << "Create BusSlack..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; @@ -102,7 +102,7 @@ BusSlack::BusSlack(ScalarT V, ScalarT theta) template BusSlack::BusSlack(BusData& data) - : V_(data.Vm), theta_(data.Va) //, P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) + : BaseBus(data.bus_i), V_(data.Vm), theta_(data.Va) { //std::cout << "Create BusSlack..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; diff --git a/ComponentLib/Load/Load.cpp b/ComponentLib/Load/Load.cpp index 1dc798d80..65d44cfc5 100644 --- a/ComponentLib/Load/Load.cpp +++ b/ComponentLib/Load/Load.cpp @@ -76,6 +76,18 @@ template Load::Load(bus_type* bus, ScalarT P, ScalarT Q) : P_(P), Q_(Q), + busID_(0), + bus_(bus) +{ + //std::cout << "Create a load model with " << size_ << " variables ...\n"; + size_ = 0; +} + +template +Load::Load(bus_type* bus, LoadData& data) + : P_(data.Pd), + Q_(data.Qd), + busID_(data.bus_i), bus_(bus) { //std::cout << "Create a load model with " << size_ << " variables ...\n"; diff --git a/ComponentLib/Load/Load.hpp b/ComponentLib/Load/Load.hpp index e555e7002..c6d3d55a2 100644 --- a/ComponentLib/Load/Load.hpp +++ b/ComponentLib/Load/Load.hpp @@ -61,7 +61,7 @@ #define _LOAD_HPP_ #include -#include +#include namespace ModelLib { @@ -71,8 +71,8 @@ namespace ModelLib namespace ModelLib { - /*! - * @brief Implementation of a power grid. + /*! + * @brief Declaration of a passive load class. * */ template @@ -93,11 +93,15 @@ namespace ModelLib using ModelEvaluatorImpl::gB_; using ModelEvaluatorImpl::param_; - typedef typename ModelEvaluatorImpl::real_type real_type; - typedef BaseBus bus_type; + // typedef typename ModelEvaluatorImpl::real_type real_type; + // typedef BaseBus bus_type; + using bus_type = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + using LoadData = GridKit::PowerSystemData::LoadData; public: Load(bus_type* bus, ScalarT P, ScalarT Q); + Load(bus_type* bus, LoadData& data); virtual ~Load(); int allocate(); @@ -121,6 +125,7 @@ namespace ModelLib private: ScalarT P_; ScalarT Q_; + const IdxT busID_; bus_type* bus_; }; } diff --git a/Examples/Grid3Bus/Grid3BusSys.cpp b/Examples/Grid3Bus/Grid3BusSys.cpp index bb61902bb..e9a7182a7 100644 --- a/Examples/Grid3Bus/Grid3BusSys.cpp +++ b/Examples/Grid3Bus/Grid3BusSys.cpp @@ -121,12 +121,14 @@ int main() kinsol->printFinalStats(); int retval1 = 0; - retval1 += isEqual(th2, -4.878, 1e-4); - retval1 += isEqual(V2, 1.096, 1e-4); - retval1 += isEqual(th3, 1.491, 1e-4); + retval1 += !isEqual(th2, -4.87979, 1e-4); + retval1 += !isEqual(V2, 1.08281, 1e-4); + retval1 += !isEqual(th3, 1.46241, 1e-4); if(retval1 == 0) std::cout << "\nSucess!\n\n\n"; + else + std::cout << "\nFailed!\n\n\n"; // Delete solver and model delete kinsol; kinsol = nullptr; @@ -142,45 +144,59 @@ int main() BusData bd1; bd1.bus_i = 1; bd1.type = 3; bd1.Vm = 1.0; bd1.Va = 0.0; auto* bus1 = BusFactory::create(bd1); - // BaseBus* bus1 = new BusSlack(bd1); sysmodel->addBus(bus1); // Create a PQ bus, initialize V=1, theta=0, bus ID = 2" << std::endl; BusData bd2; bd2.bus_i = 2; bd2.type = 1; bd2.Vm = 1.0; bd2.Va = 0.0; auto* bus2 = BusFactory::create(bd2); - // BaseBus* bus2 = new BusPQ(bd2); sysmodel->addBus(bus2); - std::cout << "// Create a PV bus, fix V=1.1, initialize theta=0, and set power injection Pg=2" << std::endl; + // Create a PV bus, fix V=1.1, initialize theta=0, and set power injection Pg=2" << std::endl; BusData bd3; bd3.bus_i = 3; bd3.type = 2; bd3.Vm = 1.1; bd3.Va = 0.0; auto* bus3 = BusFactory::create(bd3); - // BaseBus* bus3 = new BusPV(1.1, 0.0, 2.0); sysmodel->addBus(bus3); // Create and add generators ... - std::cout << "// Set power injection to 2.0 for bus3" << std::endl; + // Create and add slack generator connected to bus1 + GenData gd1; + gd1.bus = 1; + auto* gen1 = GeneratorFactory::create(sysmodel->getBus(gd1.bus), gd1); + sysmodel->addComponent(gen1); + // Create and add PV generator connected to bus3 GenData gd3; gd3.Pg = 2.0; gd3.bus = 3; - auto* gen3 = GeneratorFactory::create(bus3, gd3); + auto* gen3 = GeneratorFactory::create(sysmodel->getBus(gd3.bus), gd3); sysmodel->addComponent(gen3); // Create and add branches ... - Branch* branch12 = new Branch(bus1, bus2); - branch12->setX(1.0/10.0); + // Branch 1-2 + BranchData brd12; + brd12.fbus = 1; brd12.tbus = 2; brd12.x = 1.0/10.0; brd12.r = 0.0; brd12.b = 0.0; + Branch* branch12 = new Branch(sysmodel->getBus(brd12.fbus), sysmodel->getBus(brd12.tbus), brd12); sysmodel->addComponent(branch12); - Branch* branch13 = new Branch(bus1, bus3); - branch13->setX(1.0/15.0); + // Branch 1-3 + BranchData brd13; + brd13.fbus = 1; brd13.tbus = 3; brd13.x = 1.0/15.0; brd13.r = 0.0; brd13.b = 0.0; + Branch* branch13 = new Branch(sysmodel->getBus(brd13.fbus), sysmodel->getBus(brd13.tbus), brd13); sysmodel->addComponent(branch13); - Branch* branch23 = new Branch(bus2, bus3); - branch23->setX(1.0/12.0); + // Branch 2-3 + BranchData brd23; + brd23.fbus = 2; brd23.tbus = 3; brd23.x = 1.0/12.0; brd23.r = 0.0; brd23.b = 0.0; + Branch* branch23 = new Branch(sysmodel->getBus(brd23.fbus), sysmodel->getBus(brd23.tbus), brd23); sysmodel->addComponent(branch23); // Create and add loads ... - Load* load1 = new Load(bus1, 2.0, 0.0); + // Load on bus1 + LoadData ld1; + ld1.bus_i = 1; ld1.Pd = 2.0; ld1.Qd = 0.0; + Load* load1 = new Load(sysmodel->getBus(ld1.bus_i), ld1); sysmodel->addComponent(load1); - Load* load2 = new Load(bus2, 2.5, -0.8); + // Load on bus2 + LoadData ld2; + ld2.bus_i = 2; ld2.Pd = 2.5; ld2.Qd = -0.8; + Load* load2 = new Load(sysmodel->getBus(ld2.bus_i), ld2); sysmodel->addComponent(load2); // allocate model @@ -210,12 +226,14 @@ int main() kinsol->printFinalStats(); int retval2 = 0; - retval2 += isEqual(th2, -4.878, 1e-4); - retval2 += isEqual(V2, 1.096, 1e-4); - retval2 += isEqual(th3, 1.491, 1e-4); + retval2 += !isEqual(th2, -4.87979, 1e-4); + retval2 += !isEqual(V2, 1.08281, 1e-4); + retval2 += !isEqual(th3, 1.46241, 1e-4); if(retval2 == 0) std::cout << "\nSucess!\n\n\n"; + else + std::cout << "\nFailed!\n\n\n"; // Delete solver and model diff --git a/SystemSteadyStateModel.hpp b/SystemSteadyStateModel.hpp index 6eaa34c66..9328ad2e4 100644 --- a/SystemSteadyStateModel.hpp +++ b/SystemSteadyStateModel.hpp @@ -369,6 +369,13 @@ class SystemSteadyStateModel : public ModelEvaluatorImpl components_.push_back(component); } + bus_type* getBus(IdxT busid) + { + // Need to implement mapping of bus IDs to buses in the system model + assert( (buses_[busid - 1])->BusID() == busid ); + return buses_[busid - 1]; + } + private: std::vector buses_; std::vector components_; diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index ea608734e..f061cdbd1 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -84,14 +84,17 @@ inline std::ostream &errs() { namespace GridKit { namespace Testing { -template bool isEqual(const T value, const T ref, const T tol) { - return (std::abs(value - ref) / (1.0 + std::abs(ref)) < tol); +template bool isEqual(const T value, const T ref, const T tol) +{ + T error = std::abs(value - ref) / (1.0 + std::abs(ref)); + return (error < tol); } template inline bool isEqual(PowerSystemData::GenCostData a, PowerSystemData::GenCostData b, - RealT tol = tol_) { + RealT tol = tol_) +{ int fail = 0; fail += a.kind != b.kind; fail += a.startup != b.startup; @@ -105,7 +108,9 @@ inline bool isEqual(PowerSystemData::GenCostData a, template inline bool isEqual(PowerSystemData::GenData a, - PowerSystemData::GenData b, RealT tol = tol_) { + PowerSystemData::GenData b, + RealT tol = tol_) +{ int fail = 0; fail += a.bus != b.bus; fail += !isEqual(a.Pg, b.Pg, tol); @@ -136,7 +141,9 @@ inline bool isEqual(PowerSystemData::GenData a, template inline bool isEqual(PowerSystemData::BusData a, - PowerSystemData::BusData b, RealT tol = tol_) { + PowerSystemData::BusData b, + RealT tol = tol_) +{ int fail = 0; fail += a.bus_i != b.bus_i; fail += a.type != b.type; @@ -167,7 +174,9 @@ inline bool isEqual(PowerSystemData::BusData a, template inline bool isEqual(PowerSystemData::LoadData a, - PowerSystemData::LoadData b, RealT tol = tol_) { + PowerSystemData::LoadData b, + RealT tol = tol_) +{ int fail = 0; fail += a.bus_i != b.bus_i; fail += !isEqual(a.Pd, b.Pd, tol); @@ -182,7 +191,9 @@ inline bool isEqual(PowerSystemData::LoadData a, template inline bool isEqual(PowerSystemData::BranchData a, - PowerSystemData::BranchData b, RealT tol = tol_) { + PowerSystemData::BranchData b, + RealT tol = tol_) +{ int fail = 0; fail += a.fbus != b.fbus; fail += a.tbus != b.tbus; @@ -204,7 +215,8 @@ inline bool isEqual(PowerSystemData::BranchData a, } template -inline bool isEqual(std::vector a, std::vector b, double tol = tol_) { +inline bool isEqual(std::vector a, std::vector b, double tol = tol_) +{ if (a.size() != b.size()) throw std::runtime_error([&] { std::stringstream errs; @@ -227,7 +239,8 @@ inline bool isEqual(std::vector a, std::vector b, double tol = tol_) { template inline bool isEqual(PowerSystemData::SystemModelData a, - PowerSystemData::SystemModelData b) { + PowerSystemData::SystemModelData b) +{ int fail = 0; fail += a.version != b.version; fail += a.baseMVA != b.baseMVA; From 57ca0f131ae3ed8924b88b2c10f3380c608fde30 Mon Sep 17 00:00:00 2001 From: "Gomillion, Reid" Date: Tue, 20 Jun 2023 18:17:21 +0000 Subject: [PATCH 11/52] Updated Parsing Example --- .gitignore | 2 + Examples/Grid3Bus/3bus.mat | 47 ++++++++ Examples/Grid3Bus/Grid3BusSys.cpp | 187 +++++++++++++++++++++++++++--- SystemSteadyStateModel.hpp | 37 ++++++ 4 files changed, 256 insertions(+), 17 deletions(-) create mode 100644 Examples/Grid3Bus/3bus.mat diff --git a/.gitignore b/.gitignore index 139e99d61..304aea9a5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .directory *.orig .vscode/ + +build/ diff --git a/Examples/Grid3Bus/3bus.mat b/Examples/Grid3Bus/3bus.mat new file mode 100644 index 000000000..4663eb33c --- /dev/null +++ b/Examples/Grid3Bus/3bus.mat @@ -0,0 +1,47 @@ +( +function mpc = case5 +% Created by Reid Gomillion + +% MATPOWER + +%% MATPOWER Case Format : Version 2 +mpc.version = '2'; + +%%----- Power Flow Data -----%% +%% system MVA base +mpc.baseMVA = 100; + +%% bus data +% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin +mpc.bus = [ + 1 3 2.0 0.0 0 0 0 1 0.0 0 0 0 0.0; + 2 1 2.5 -0.8 0 0 0 1 0.0 0 0 0 0.0; + 3 2 0 0 0 0 0 1.1 0.0 0 0 0 0.0; +]; + +%% generator data +% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf +mpc.gen = [ + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 3 2.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; +]; + +%% branch data +% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax +mpc.branch = [ + 1 2 0 0.1 0 0 0 0 0 0 0 0 0; + 1 3 0 0.0666666 0 0 0 0 0 0 0 0 0; + 2 3 0 0.0833333 0 0 0 0 0 0 0 0 0; +]; + +%%----- OPF Data -----%% +%% generator cost data +% 1 startup shutdown n x1 y1 ... xn yn +% 2 startup shutdown n c(n-1) ... c0 +mpc.gencost = [ + 2 0 0 3 0 14 0; + 2 0 0 3 0 15 0; + 2 0 0 3 0 30 0; +]; + +) \ No newline at end of file diff --git a/Examples/Grid3Bus/Grid3BusSys.cpp b/Examples/Grid3Bus/Grid3BusSys.cpp index e9a7182a7..bf70c655a 100644 --- a/Examples/Grid3Bus/Grid3BusSys.cpp +++ b/Examples/Grid3Bus/Grid3BusSys.cpp @@ -69,6 +69,8 @@ #include #include #include +#include +#include #include #include @@ -79,18 +81,74 @@ #include #include +#include #include -int main() -{ - using namespace ModelLib; - using namespace AnalysisManager::Sundials; - using namespace AnalysisManager; - using namespace GridKit::Testing; - using namespace GridKit::PowerSystemData; +//Note: This was traced from the subsequent calls +static const std::string BUS3_DATA_STRING = R"( +function mpc = case5 +% Created by Reid Gomillion + +% MATPOWER + +%% MATPOWER Case Format : Version 2 +mpc.version = '2'; + +%%----- Power Flow Data -----%% +%% system MVA base +mpc.baseMVA = 100; + +%% bus data +% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin +mpc.bus = [ + 1 3 2.0 0.0 0 0 0 1 0.0 0 0 0 0.0; + 2 1 2.5 -0.8 0 0 0 1 0.0 0 0 0 0.0; + 3 2 0 0 0 0 0 1.1 0.0 0 0 0 0.0; +]; + +%% generator data +% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf +mpc.gen = [ + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 3 2.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; +]; + +%% branch data +% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax +mpc.branch = [ + 1 2 0 0.1 0 0 0 0 0 0 0 0 0; + 1 3 0 0.0666666 0 0 0 0 0 0 0 0 0; + 2 3 0 0.0833333 0 0 0 0 0 0 0 0 0; +]; + +%%----- OPF Data -----%% +%% generator cost data +% 1 startup shutdown n x1 y1 ... xn yn +% 2 startup shutdown n c(n-1) ... c0 +mpc.gencost = [ + 2 0 0 3 0 14 0; + 2 0 0 3 0 15 0; + 2 0 0 3 0 30 0; +]; + +)"; - std::cout << "\nSolving power flow for a 3-bus monolithic model ...\n\n"; + +using namespace ModelLib; +using namespace AnalysisManager::Sundials; +using namespace AnalysisManager; +using namespace GridKit::Testing; +using namespace GridKit::PowerSystemData; + + +/** + * Testing the monlithic case via the class MiniGrid + * @return returns 0 if pass o.w. fails +*/ +int monolithic_case() +{ + std::cout << "\nSolving power flow for a 3-bus monolithic model ...\n\n"; // Create a 3-bus model MiniGrid* model = new MiniGrid(); @@ -133,8 +191,81 @@ int main() // Delete solver and model delete kinsol; kinsol = nullptr; delete model; model = nullptr; + return retval1; +} + +/** + * Run the Testing case for parser setup + * @return returns 0 if pass o.w. fail +*/ +int parser_case() +{ + std::cout << "Solving same problem, but assembled from components via a parser ...\n\n"; + + //Data File Reading + GridKit::PowerSystemData::SystemModelData mp; - std::cout << "Solving same problem, but assembled from components ...\n\n"; + std::istringstream iss(BUS3_DATA_STRING); + GridKit::readMatPower(mp, iss); + + + // Create an empty system model and pass the system model data to it + SystemSteadyStateModel* sysmodel = new SystemSteadyStateModel(mp); + + // allocate model + sysmodel->allocate(); + std::cout << "Model size: " << sysmodel->size() << "\n\n"; + + // Create numerical solver and attach the model to it. + // Here we use Kinsol solver from SUNDIALS library + Kinsol* kinsol = new Kinsol(sysmodel); + + // setup simulation + kinsol->configureSimulation(); + // initialize simulation with default initial guess + kinsol->getDefaultInitialCondition(); + // Compute solution + kinsol->runSimulation(); + // Print solution + double th2 = sysmodel->getBus(2)->theta() * 180.0/M_PI; + double V2 = sysmodel->getBus(2)->V(); + double th3 = sysmodel->getBus(3)->theta() * 180.0/M_PI; + + + std::cout << "Solution:\n"; + std::cout << " theta2 = " << th2 << " deg, expected = " << " -4.87979 deg\n"; + std::cout << " V2 = " << V2 << " p.u., expected = " << " 1.08281 p.u.\n"; + std::cout << " theta3 = " << th3 << " deg, expected = " << " 1.46241 deg\n\n"; + + // Print solver performance statistics + kinsol->printFinalStats(); + + int retval2 = 0; + retval2 += !isEqual(th2, -4.87979, 1e-4); + retval2 += !isEqual(V2, 1.08281, 1e-4); + retval2 += !isEqual(th3, 1.46241, 1e-4); + + if(retval2 == 0) + std::cout << "\nSucess!\n\n\n"; + else + std::cout << "\nFailed!\n\n\n"; + + + // Delete solver and model + + delete kinsol; kinsol = nullptr; + delete sysmodel; sysmodel = nullptr; + + return retval2; +} + +/** + * Hardwired Test Case + * @return 0 if pass otherwise fails +*/ +int hardwired_case() +{ + std::cout << "Solving same problem, but assembled from components manually ...\n\n"; // First, create an empty system model SystemSteadyStateModel* sysmodel = new SystemSteadyStateModel(); @@ -146,7 +277,7 @@ int main() auto* bus1 = BusFactory::create(bd1); sysmodel->addBus(bus1); - // Create a PQ bus, initialize V=1, theta=0, bus ID = 2" << std::endl; + //Create a PQ bus, initialize V=1, theta=0, bus ID = 2" << std::endl; BusData bd2; bd2.bus_i = 2; bd2.type = 1; bd2.Vm = 1.0; bd2.Va = 0.0; auto* bus2 = BusFactory::create(bd2); @@ -164,6 +295,7 @@ int main() gd1.bus = 1; auto* gen1 = GeneratorFactory::create(sysmodel->getBus(gd1.bus), gd1); sysmodel->addComponent(gen1); + // Create and add PV generator connected to bus3 GenData gd3; gd3.Pg = 2.0; gd3.bus = 3; @@ -176,16 +308,19 @@ int main() brd12.fbus = 1; brd12.tbus = 2; brd12.x = 1.0/10.0; brd12.r = 0.0; brd12.b = 0.0; Branch* branch12 = new Branch(sysmodel->getBus(brd12.fbus), sysmodel->getBus(brd12.tbus), brd12); sysmodel->addComponent(branch12); + // Branch 1-3 BranchData brd13; brd13.fbus = 1; brd13.tbus = 3; brd13.x = 1.0/15.0; brd13.r = 0.0; brd13.b = 0.0; Branch* branch13 = new Branch(sysmodel->getBus(brd13.fbus), sysmodel->getBus(brd13.tbus), brd13); sysmodel->addComponent(branch13); + // Branch 2-3 BranchData brd23; brd23.fbus = 2; brd23.tbus = 3; brd23.x = 1.0/12.0; brd23.r = 0.0; brd23.b = 0.0; Branch* branch23 = new Branch(sysmodel->getBus(brd23.fbus), sysmodel->getBus(brd23.tbus), brd23); sysmodel->addComponent(branch23); + // Create and add loads ... // Load on bus1 @@ -193,6 +328,7 @@ int main() ld1.bus_i = 1; ld1.Pd = 2.0; ld1.Qd = 0.0; Load* load1 = new Load(sysmodel->getBus(ld1.bus_i), ld1); sysmodel->addComponent(load1); + // Load on bus2 LoadData ld2; ld2.bus_i = 2; ld2.Pd = 2.5; ld2.Qd = -0.8; @@ -205,7 +341,7 @@ int main() // Create numerical solver and attach the model to it. // Here we use Kinsol solver from SUNDIALS library - kinsol = new Kinsol(sysmodel); + Kinsol* kinsol = new Kinsol(sysmodel); // setup simulation kinsol->configureSimulation(); @@ -214,9 +350,11 @@ int main() // Compute solution kinsol->runSimulation(); // Print solution - th2 = bus2->theta() * 180.0/M_PI; - V2 = bus2->V(); - th3 = bus3->theta() * 180.0/M_PI; + double th2 = bus2->theta() * 180.0/M_PI; + double V2 = bus2->V(); + double th3 = bus3->theta() * 180.0/M_PI; + + std::cout << "Solution:\n"; std::cout << " theta2 = " << th2 << " deg, expected = " << " -4.87979 deg\n"; std::cout << " V2 = " << V2 << " p.u., expected = " << " 1.08281 p.u.\n"; @@ -237,7 +375,22 @@ int main() // Delete solver and model - delete kinsol; - delete sysmodel; - return retval1 + retval2; + delete kinsol; kinsol = nullptr; + delete sysmodel; sysmodel = nullptr; + return retval2; +} + + +int main() +{ + //return the results of each case + //swapping orders of test causes memory error, specifically hardware <-> parser + int resolve = 0; + std::cout << std::string(32,'-') << std::endl; + resolve += monolithic_case(); + std::cout << std::string(32,'-') << std::endl; + resolve += hardwired_case(); + std::cout << std::string(32,'-') << std::endl; + resolve += parser_case(); + return resolve; } diff --git a/SystemSteadyStateModel.hpp b/SystemSteadyStateModel.hpp index 9328ad2e4..e483a92af 100644 --- a/SystemSteadyStateModel.hpp +++ b/SystemSteadyStateModel.hpp @@ -127,6 +127,43 @@ class SystemSteadyStateModel : public ModelEvaluatorImpl atol_ = 1e-5; } + SystemSteadyStateModel(GridKit::PowerSystemData::SystemModelData mp) : ModelEvaluatorImpl(0,0,0) + { + rtol_ = 1e-5; + atol_ = 1e-5; + + //buses + for(auto busdata : mp.bus) + { + auto* bus = BusFactory::create(busdata); + this->addBus(bus); + } + + //generators + for (auto gendata : mp.gen) + { + auto* gen = GeneratorFactory::create(this->getBus(gendata.bus),gendata); + this->addComponent(gen); + } + + //branches + for (auto branchdata : mp.branch) + { + auto* branch = new Branch(this->getBus(branchdata.fbus),this->getBus(branchdata.tbus),branchdata); + this->addComponent(branch); + } + + //loads + for (auto loaddata : mp.load) + { + auto* loadm = new Load(this->getBus(loaddata.bus_i),loaddata); + this->addComponent(loadm); + } + + //There appears to not be a Generator Cost Object + //TODO: Implment for GenCost + } + /** * @brief Destructor for the system model */ From a4efa0ff8036877737f4b28f3c86d8539f41868a Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 26 Jun 2023 11:53:13 -0400 Subject: [PATCH 12/52] Fixed Memory Errors in KinSol and SystemSteadyStateModel +Clean valgrind output --- Solver/SteadyState/Kinsol.cpp | 10 ++++++++++ SystemSteadyStateModel.hpp | 2 ++ 2 files changed, 12 insertions(+) diff --git a/Solver/SteadyState/Kinsol.cpp b/Solver/SteadyState/Kinsol.cpp index 3165230bf..9c00c2afc 100644 --- a/Solver/SteadyState/Kinsol.cpp +++ b/Solver/SteadyState/Kinsol.cpp @@ -102,6 +102,16 @@ namespace Sundials Kinsol::~Kinsol() { SUNContext_Free(&context_); + KINFree(&solver_); + + N_VDestroy_Serial(this->yy_); + N_VDestroy_Serial(this->yy0_); + N_VDestroy_Serial(this->scale_); + + SUNMatDestroy(this->JacobianMat_); + SUNLinSolFree_Dense(this->linearSolver_); + + solver_ = 0; } template diff --git a/SystemSteadyStateModel.hpp b/SystemSteadyStateModel.hpp index e483a92af..38b16389a 100644 --- a/SystemSteadyStateModel.hpp +++ b/SystemSteadyStateModel.hpp @@ -169,6 +169,8 @@ class SystemSteadyStateModel : public ModelEvaluatorImpl */ virtual ~SystemSteadyStateModel() { + for (auto comp : this->components_) delete comp; + for (auto bus : this->buses_) delete bus; } /** From 791b0e63c5dbfba57c52c26d71d54fca1c7c45f9 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Fri, 30 Jun 2023 15:42:21 -0400 Subject: [PATCH 13/52] Prototype Example of Creating a RL Circuit +Add hypergraph representation +Added Model form with appropiate indexing +Added Resistors, Capacitor, Inductor, and VoltageSource Component Models --- CircuitGraph.hpp | 119 ++++++++++ ComponentLib/CMakeLists.txt | 2 + .../PowerElectronicsComponents/CMakeLists.txt | 6 + .../Capacitor/CMakeLists.txt | 8 + .../Capacitor/Capacitor.cpp | 117 ++++++++++ .../Capacitor/Capacitor.hpp | 64 ++++++ .../CircuitComponent.hpp | 68 ++++++ .../Inductor/CMakeLists.txt | 8 + .../Inductor/Inductor.cpp | 117 ++++++++++ .../Inductor/Inductor.hpp | 66 ++++++ .../Resistor/CMakeLists.txt | 8 + .../Resistor/Resistor.cpp | 117 ++++++++++ .../Resistor/Resistor.hpp | 65 ++++++ .../VoltageSource/CMakeLists.txt | 8 + .../VoltageSource/VoltageSource.cpp | 119 ++++++++++ .../VoltageSource/VoltageSource.hpp | 63 +++++ Examples/CMakeLists.txt | 1 + Examples/RLCircuit/CMakeLists.txt | 12 + Examples/RLCircuit/RLCircuit.cpp | 114 +++++++++ ModelEvaluatorImpl.hpp | 8 + PowerElectronicsModel.hpp | 217 ++++++++++++++++++ 21 files changed, 1307 insertions(+) create mode 100644 CircuitGraph.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/Capacitor/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/Inductor/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/Resistor/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/VoltageSource/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp create mode 100644 Examples/RLCircuit/CMakeLists.txt create mode 100644 Examples/RLCircuit/RLCircuit.cpp create mode 100644 PowerElectronicsModel.hpp diff --git a/CircuitGraph.hpp b/CircuitGraph.hpp new file mode 100644 index 000000000..e54f5a150 --- /dev/null +++ b/CircuitGraph.hpp @@ -0,0 +1,119 @@ + + +#include +#include +#include +#include +#include + +/** + * @brief A very basic hypergraph setup for circuit representation. This forms the hypergraph as a bipartite graph. Doesn't allow removing. Can only grab sets of connections to nodes + * + * @todo should replace with something better and more efficent. Should replace with a libraries setup instead. This would allow fast and easy partitioning of circuits + * + * @todo should replace N and E with Node and Component classes respectively + * + * @tparam IdxT + * @tparam Label + */ +template +class CircuitGraph +{ +private: + std::set hypernodes; + std::set hyperedges; + std::map> edgestonodes; +public: + CircuitGraph(); + ~CircuitGraph(); + bool addHyperEdge(E he); + bool addHyperNode(N hn); + bool addConnection(N hn, E he); + std::set getHyperEdgeConnections(E he); + size_t amountHyperNodes(); + size_t amountHyperEdges(); + void printBiPartiteGraph(bool verbose = false); +}; + +template +CircuitGraph::CircuitGraph() +{ +} + +template +CircuitGraph::~CircuitGraph() +{ +} + +template +bool CircuitGraph::addHyperNode(N hn) +{ + return this->hypernodes.insert(hn).second; +} + +template +bool CircuitGraph::addHyperEdge(E he) +{ + return this->hyperedges.insert(he).second; +} + + +template +bool CircuitGraph::addConnection(N hn, E he) +{ + if(this->hyperedges.count(he) == 0 || this->hypernodes.count(hn) == 0) + { + return false; + } + return this->edgestonodes[he].insert(hn).second; +} + + +template +std::set CircuitGraph::getHyperEdgeConnections(E he) +{ + return this->edgestonodes[he]; +} + + +template +size_t CircuitGraph::amountHyperNodes() +{ + return this->hypernodes.size(); +} + + +template +size_t CircuitGraph::amountHyperEdges() +{ + return this->hyperedges.size(); +} + +/** + * @brief Printing + * + * @todo need to add verbose printing for connections display + * + * @tparam IdxT + * @param verbose + */ + +template +void CircuitGraph::printBiPartiteGraph(bool verbose) +{ + + std::cout << "Amount of HyperNodes: " << this->amountHyperNodes() << std::endl; + std::cout << "Amount of HyperEdges: " << this->amountHyperEdges() << std::endl; + std::cout << "Connections per Edge:" << std::endl; + for (auto i : this->edgestonodes) + { + std::cout << i.first << " : {"; + for (auto j : i.second){ + std::cout << j << ", "; + } + std::cout << "}\n"; + + } + + +} diff --git a/ComponentLib/CMakeLists.txt b/ComponentLib/CMakeLists.txt index 0c422d5b9..29a5a7988 100644 --- a/ComponentLib/CMakeLists.txt +++ b/ComponentLib/CMakeLists.txt @@ -69,3 +69,5 @@ add_subdirectory(Generator4Governor) add_subdirectory(Generator4Param) add_subdirectory(Load) add_subdirectory(MiniGrid) +add_subdirectory(PowerElectronicsComponents) + diff --git a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt new file mode 100644 index 000000000..c3e958300 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt @@ -0,0 +1,6 @@ + + +add_subdirectory(Capacitor) +add_subdirectory(Resistor) +add_subdirectory(VoltageSource) +add_subdirectory(Inductor) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/Capacitor/CMakeLists.txt new file mode 100644 index 000000000..62efc1795 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_capacitor + SOURCES + Capacitor.cpp + OUTPUT_NAME + gridkit_powerelec_capacitor) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp new file mode 100644 index 000000000..4fcda9d9f --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp @@ -0,0 +1,117 @@ + + + +#include +#include +#include +#include "Capacitor.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +Capacitor::Capacitor(IdxT id, ScalarT C) + : C_(C) +{ + this->size_ = 3; + this->n_intern = 1; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +Capacitor::~Capacitor() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int Capacitor::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int Capacitor::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int Capacitor::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int Capacitor::evaluateResidual() +{ + this->f_[0] = this->yp_[2]; + this->f_[1] = -this->yp_[2]; + this->f_[2] = this->y_[0] - this->y_[1] - this->y_[2] - this->C_ * this->yp_[2]; + return 0; +} + +template +int Capacitor::evaluateJacobian() +{ + + return 0; +} + +template +int Capacitor::evaluateIntegrand() +{ + return 0; +} + +template +int Capacitor::initializeAdjoint() +{ + return 0; +} + +template +int Capacitor::evaluateAdjointResidual() +{ + return 0; +} + +template +int Capacitor::evaluateAdjointIntegrand() +{ + return 0; +} + + + + +// Available template instantiations +template class Capacitor; +template class Capacitor; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp new file mode 100644 index 000000000..76cf94614 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp @@ -0,0 +1,64 @@ + + +#ifndef _CAP_HPP_ +#define _CAP_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive Capacitor class. + * + */ + template + class Capacitor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + Capacitor(IdxT id, ScalarT C); + virtual ~Capacitor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT C_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp new file mode 100644 index 000000000..7cfb5521a --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp @@ -0,0 +1,68 @@ + + +#ifndef _CIRCCOMP_HPP_ +#define _CIRCCOMP_HPP_ + +#include +#include +#include +#include + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive CircuitComponent class. + * + */ + template + class CircuitComponent : public ModelEvaluatorImpl + { + + public: + + + void updateTime(ScalarT t, ScalarT a) + { + this->time_ = t; + this->alpha_ = a; + } + + size_t getExternSize() + { + return this->n_extern; + } + + size_t getInternalSize() + { + return this->n_intern; + } + + std::set getExternIndices() + { + return this->extern_indices; + } + + bool setExternalConnectionNodes(size_t index, IdxT id) + { + this->connection_nodes[index] = id; + return true; + } + + IdxT getNodeConnection(size_t index) + { + return this->connection_nodes.at(index); + } + + protected: + size_t n_extern; + size_t n_intern; + std::set extern_indices; + std::map connection_nodes; + + }; + + +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/Inductor/CMakeLists.txt new file mode 100644 index 000000000..4c620030f --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Inductor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_inductor + SOURCES + Inductor.cpp + OUTPUT_NAME + gridkit_powerelec_inductor) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp new file mode 100644 index 000000000..278b0eebc --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -0,0 +1,117 @@ + + + +#include +#include +#include +#include "Inductor.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +Inductor::Inductor(IdxT id, ScalarT L) + : L_(L) +{ + this->size_ = 3; + this->n_intern = 1; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +Inductor::~Inductor() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int Inductor::allocate() +{ + + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int Inductor::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int Inductor::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int Inductor::evaluateResidual() +{ + this->f_[0] = this->y_[2]; + this->f_[1] = -this->y_[2]; + this->f_[2] = this->y_[0] - this->y_[1] - this->L_ * this->yp_[2]; + return 0; +} + +template +int Inductor::evaluateJacobian() +{ + return 0; +} + +template +int Inductor::evaluateIntegrand() +{ + return 0; +} + +template +int Inductor::initializeAdjoint() +{ + return 0; +} + +template +int Inductor::evaluateAdjointResidual() +{ + return 0; +} + +template +int Inductor::evaluateAdjointIntegrand() +{ + return 0; +} + + + + +// Available template instantiations +template class Inductor; +template class Inductor; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp new file mode 100644 index 000000000..e959aabf1 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp @@ -0,0 +1,66 @@ + + +#ifndef _IND_HPP_ +#define _IND_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive Inductor class. + * + */ + template + class Inductor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + + public: + Inductor(IdxT id, ScalarT L); + virtual ~Inductor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT L_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/Resistor/CMakeLists.txt new file mode 100644 index 000000000..9386bda83 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Resistor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_resistor + SOURCES + Resistor.cpp + OUTPUT_NAME + gridkit_powerelec_resistor) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp new file mode 100644 index 000000000..1aa06427a --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp @@ -0,0 +1,117 @@ + + + +#include +#include +#include +#include "Resistor.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant resistor model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +Resistor::Resistor(IdxT id, ScalarT R) + : R_(R) +{ + this->size_ = 2; + this->n_intern = 0; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +Resistor::~Resistor() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int Resistor::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int Resistor::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int Resistor::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int Resistor::evaluateResidual() +{ + + this->f_[0] = (this->y_[1] - this->y_[0])/this->R_ ; + this->f_[1] = (this->y_[0] - this->y_[1])/this->R_ ; + return 0; +} + +template +int Resistor::evaluateJacobian() +{ + return 0; +} + +template +int Resistor::evaluateIntegrand() +{ + return 0; +} + +template +int Resistor::initializeAdjoint() +{ + return 0; +} + +template +int Resistor::evaluateAdjointResidual() +{ + return 0; +} + +template +int Resistor::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class Resistor; +template class Resistor; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp new file mode 100644 index 000000000..0373e2c5c --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp @@ -0,0 +1,65 @@ + + +#ifndef _RES_HPP_ +#define _RES_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive Resistor class. + * + */ + template + class Resistor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + Resistor(IdxT id, ScalarT R); + virtual ~Resistor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT R_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/VoltageSource/CMakeLists.txt new file mode 100644 index 000000000..7196f4d43 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_voltagesource + SOURCES + VoltageSource.cpp + OUTPUT_NAME + gridkit_powerelec_voltagesource) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp new file mode 100644 index 000000000..c27c04bd2 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp @@ -0,0 +1,119 @@ + + + +#include +#include +#include +#include "VoltageSource.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant VoltageSource model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +VoltageSource::VoltageSource(IdxT id, ScalarT V) + : V_(V) +{ + this->size_ = 3; + this->n_intern = 1; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +VoltageSource::~VoltageSource() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int VoltageSource::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int VoltageSource::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int VoltageSource::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int VoltageSource::evaluateResidual() +{ + //Note this leaves induction lumped into y. Perhaps would be better to seperate volatge and induction into seperate vectors + // for easier development + this->f_[0] = this->y_[2]; + this->f_[1] = -this->y_[2]; + this->f_[2] = this->y_[0] - this->y_[1] - this->V_; + return 0; +} + +template +int VoltageSource::evaluateJacobian() +{ + return 0; +} + +template +int VoltageSource::evaluateIntegrand() +{ + return 0; +} + +template +int VoltageSource::initializeAdjoint() +{ + return 0; +} + +template +int VoltageSource::evaluateAdjointResidual() +{ + return 0; +} + +template +int VoltageSource::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class VoltageSource; +template class VoltageSource; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp new file mode 100644 index 000000000..dcbacf2f7 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp @@ -0,0 +1,63 @@ + + +#ifndef _VOSO_HPP_ +#define _VOSO_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive VoltageSource class. + * + */ + template + class VoltageSource : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + public: + VoltageSource(IdxT id, ScalarT V); + virtual ~VoltageSource(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT V_; + }; +} + +#endif diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index feec6623a..b42907fd3 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -56,6 +56,7 @@ # add_subdirectory(MatPowerTesting) +add_subdirectory(RLCircuit) if(TARGET SUNDIALS::kinsol) add_subdirectory(Grid3Bus) diff --git a/Examples/RLCircuit/CMakeLists.txt b/Examples/RLCircuit/CMakeLists.txt new file mode 100644 index 000000000..5069566bf --- /dev/null +++ b/Examples/RLCircuit/CMakeLists.txt @@ -0,0 +1,12 @@ + + + + +add_executable(rlcircuit RLCircuit.cpp) +target_link_libraries(rlcircuit GRIDKIT::powerelec_capacitor + GRIDKIT::powerelec_inductor + GRIDKIT::powerelec_resistor + GRIDKIT::powerelec_voltagesource) + +add_test(NAME RLCircuit COMMAND $) +install(TARGETS rlcircuit RUNTIME DESTINATION bin) diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp new file mode 100644 index 000000000..ba9333f40 --- /dev/null +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -0,0 +1,114 @@ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + + +int main(int argc, char const *argv[]) +{ + //Basic Circuit Setup + //@todo will want to eventually put components in the hyper graph instead of indicies + + std::unique_ptr> cirg(new CircuitGraph()); + for (size_t i = 0; i < 3; i++) + { + cirg->addHyperEdge(i); + } + for (size_t i = 0; i < 5; i++) + { + cirg->addHyperNode(i); + } + + //Create Connections of Nodes to edges sets + //External nodes + cirg->addConnection(0, 0); + cirg->addConnection(0, 2); + cirg->addConnection(2, 0); + cirg->addConnection(2, 1); + cirg->addConnection(3, 1); + cirg->addConnection(3, 2); + + //Internal nodes + cirg->addConnection(1,0); + cirg->addConnection(4,2); + + + cirg->printBiPartiteGraph(); + + + //Create circuit model + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(); + + size_t idoff = 0; + + //inductor + ModelLib::Inductor* induct = new ModelLib::Inductor(idoff,0.1); + //Form index to node uid realations + induct->setExternalConnectionNodes(0,2); + induct->setExternalConnectionNodes(2,1); + induct->setExternalConnectionNodes(1,0); + sysmodel->addComponent(induct); + + + //resistor + idoff++; + ModelLib::Resistor* resis = new ModelLib::Resistor(idoff, 1.0); + //Form index to node uid realations + resis->setExternalConnectionNodes(0,3); + resis->setExternalConnectionNodes(1,2); + sysmodel->addComponent(resis); + + //voltage source + idoff++; + ModelLib::VoltageSource* vsource = new ModelLib::VoltageSource(idoff, 0.1); + //Form index to node uid realations + vsource->setExternalConnectionNodes(0,0); + vsource->setExternalConnectionNodes(2,4); + vsource->setExternalConnectionNodes(1,3); + sysmodel->addComponent(vsource); + + + //Allocate with graph + sysmodel->allocate(*cirg); + + std::cout << sysmodel->y().size() << std::endl; + + //Create Intial points + sysmodel->y()[0] = 1.0; + sysmodel->y()[1] = 1.0; + sysmodel->y()[2] = 1.0; + sysmodel->y()[3] = 1.0; + sysmodel->y()[4] = 1.0; + + sysmodel->yp()[0] = 1.0; + sysmodel->yp()[1] = 1.0; + sysmodel->yp()[2] = 1.0; + sysmodel->yp()[3] = 1.0; + sysmodel->yp()[4] = 1.0; + + + sysmodel->initialize(); + + sysmodel->evaluateResidual(); + + std::cout << "Output: {"; + for (double i : sysmodel->getResidual()) + { + std::cout << i << ", "; + } + std::cout << "}\n"; + + + return 0; +} diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp index a4ef43a00..94cbeb5d3 100644 --- a/ModelEvaluatorImpl.hpp +++ b/ModelEvaluatorImpl.hpp @@ -252,6 +252,12 @@ namespace ModelLib return gB_; } + //@todo Fix ID naming + IdxT getIDcomponent() + { + return idc_; + } + protected: @@ -281,6 +287,8 @@ namespace ModelLib real_type rtol_; real_type atol_; + IdxT idc_; + }; diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp new file mode 100644 index 000000000..78350ee2f --- /dev/null +++ b/PowerElectronicsModel.hpp @@ -0,0 +1,217 @@ + + +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +namespace ModelLib +{ + +template +class PowerElectronicsModel : public ModelEvaluatorImpl +{ + typedef CircuitComponent component_type; + + using ModelEvaluatorImpl::size_; + // using ModelEvaluatorImpl::size_quad_; + // using ModelEvaluatorImpl::size_opt_; + using ModelEvaluatorImpl::nnz_; + // using ModelEvaluatorImpl::time_; + // using ModelEvaluatorImpl::alpha_; + using ModelEvaluatorImpl::y_; + using ModelEvaluatorImpl::yp_; + // using ModelEvaluatorImpl::yB_; + // using ModelEvaluatorImpl::ypB_; + // using ModelEvaluatorImpl::tag_; + using ModelEvaluatorImpl::f_; + // using ModelEvaluatorImpl::fB_; + // using ModelEvaluatorImpl::g_; + // using ModelEvaluatorImpl::gB_; + using ModelEvaluatorImpl::rtol_; + using ModelEvaluatorImpl::atol_; + // using ModelEvaluatorImpl::param_; + // using ModelEvaluatorImpl::param_up_; + // using ModelEvaluatorImpl::param_lo_; + +public: + /** + * @brief Constructor for the system model + */ + PowerElectronicsModel() : ModelEvaluatorImpl(0, 0, 0) + { + // Set system model tolerances + rtol_ = 1e-5; + atol_ = 1e-5; + } + + /** + * @brief Destructor for the system model + */ + virtual ~PowerElectronicsModel() + { + for (auto comp : this->components_) delete comp; + } + + /** + * @brief allocator default + * + * @todo this should throw an exception as no allocation without a graph is allowed. Or needs to be removed from the base class + * + * @return int + */ + int allocate() + { + + return 1; + } + + int allocate(CircuitGraph cir) + { + this->graph = cir; + + // Allocate all components + this->size_ = cir.amountHyperNodes(); + for(const auto& component : components_) + { + component->allocate(); + } + + // Allocate global vectors + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + int initialize() + { + + // Initialize components + for(const auto& component : components_) + { + component->initialize(); + } + + for(const auto& component : components_) + { + for(IdxT j=0; jsize(); ++j) + { + component->y()[j] = y_[component->getNodeConnection(j)]; + component->yp()[j] = yp_[component->getNodeConnection(j)]; + } + } + return 0; + } + + int tagDifferentiable() + { + return 0; + } + + int evaluateResidual() + { + for (IdxT i = 0; i < this->f_.size(); i++) + { + f_[i] = 0; + } + + // Update variables + for(const auto& component : components_) + { + for(IdxT j=0; jsize(); ++j) + { + component->y()[j] = y_[component->getNodeConnection(j)]; + component->yp()[j] = yp_[component->getNodeConnection(j)]; + } + component->evaluateResidual(); + } + + // Update system residual vector + + for(const auto& component : components_) + { + for(IdxT j=0; jsize(); ++j) + { + f_[component->getNodeConnection(j)] += component->getResidual()[j]; + } + } + + return 0; + } + + int evaluateJacobian() + { + return 0; + } + + /** + * @brief Evaluate integrands for the system quadratures. + */ + int evaluateIntegrand() + { + + return 0; + } + + /** + * @brief Initialize system adjoint. + * + * Updates variables and optimization parameters, then initializes + * adjoints locally and copies them to the system adjoint vector. + */ + int initializeAdjoint() + { + return 0; + } + + /** + * @brief Compute adjoint residual for the system model. + * + * + */ + int evaluateAdjointResidual() + { + return 0; + } + + + /** + * @brief Evaluate adjoint integrand for the system model. + * + * + */ + int evaluateAdjointIntegrand() + { + return 0; + } + + void updateTime(ScalarT t, ScalarT a) + { + } + + void addComponent(component_type* component) + { + this->components_.push_back(component); + } + + CircuitGraph getGraph() + { + return this->graph; + } + +private: + std::vector components_; + + CircuitGraph graph; + +}; // class PowerElectronicsModel + +} // namespace ModelLib From 416dfebbca3a186013ca51112fe044618edd11e1 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 13 Jul 2023 17:31:34 -0400 Subject: [PATCH 14/52] Release 0.0.7 updates --- CHANGELOG.md | 43 +++++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 4 ++-- README.md | 4 ++-- 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..12ba29457 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,43 @@ +# Release Changelog + +## v0.0.7 + +- Added parser for Matpower files. +- Added system composer, which assembles power flow models from components based on input from Matpower file. +- Updated bus and created generator factory. +- GridKit now depends on Sundials >= 6.0. +- GridKit now requires C++17 compliant compiler. +- Bug fixes. + +## v0.0.6 + +- Refactored CMake to use and export targets +- Bug fixes + +## 0.0.5 + +- Parameter estimation example +- Power flow model composer with test example +- Improved CMake build +- Updated documentation + +## 0.0.4 + +- Add branch component model. +- Add generator with governor component model. +- Add generator connected to infinite bus example. + +## 0.0.3 + +- Add basic system composer. +- Make GridKit forward compatible with Sundials >= 4.0 + +## 0.0.2 + +- Add dynamic constraint Ipopt interface and usage example. +- Add Generator 4 component model to the library. +- Require CMake >= 3.0 to build GridKit + +## 0.0.1 + +- Initial release. Skeleton of the library to be developed. diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b02706ff..19048d375 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,12 +65,12 @@ cmake_minimum_required(VERSION 3.12) project(gridkit) set(PACKAGE_NAME "GRIDKIT") -set(PACKAGE_STRING "GRIDKIT 0.0.6") +set(PACKAGE_STRING "GRIDKIT 0.0.7") set(PACKAGE_TARNAME "gridkit") set(PACKAGE_VERSION_MAJOR "0") set(PACKAGE_VERSION_MINOR "0") -set(PACKAGE_VERSION_PATCH "6") +set(PACKAGE_VERSION_PATCH "7") set(PACKAGE_VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}") diff --git a/README.md b/README.md index 2caa7e294..600516ea6 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ You should have all of the following installed before installing GridKit™ - [Suitesparse](https://github.com/DrTimothyAldenDavis/SuiteSparse) >= 5.x (optional) - [Ipopt](https://github.com/coin-or/Ipopt) >= 3.x (optional) - [CMake](https://cmake.org/) >= 3.12 -- C++ 11 compiler +- C++ 17 compliant compiler ### Installing @@ -45,4 +45,4 @@ as functionality test and executed by running `ctest` in the build directory. ## Contributors GridKit™ is written by Slaven Peles (peless@ornl.gov) and has received contributions -from Tamara Becejac, R. Cameron Rutherford and Asher J. Mancinelli, all from Pacific Northwest National Laboratory. +from Tamara Becejac (Avangrid), R. Cameron Rutherford (PNNL), Asher J. Mancinelli (NVIDIA), and Reid Gomillion (Virginia Tech). From 19abae6d65102851a925b5f30328532a44962968 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Thu, 27 Jul 2023 16:44:39 -0400 Subject: [PATCH 15/52] Add New Components and Changes to Composition +Added InductionMotor, Linear Transformer, and SynchronousMachine +Changes to PowerElectronicsModel --- .../PowerElectronicsComponents/CMakeLists.txt | 5 +- .../Capacitor/Capacitor.cpp | 2 + .../CircuitComponent.hpp | 69 ++++++++ .../InductionMotor/CMakeLists.txt | 8 + .../InductionMotor/InductionMotor.cpp | 135 ++++++++++++++++ .../InductionMotor/InductionMotor.hpp | 69 ++++++++ .../Inductor/Inductor.cpp | 2 + .../LinearTransformer/CMakeLists.txt | 8 + .../LinearTransformer/LinearTransformer.cpp | 124 ++++++++++++++ .../LinearTransformer/LinearTransformer.hpp | 67 ++++++++ .../Resistor/Resistor.cpp | 2 + .../SynchronousMachine/CMakeLists.txt | 8 + .../SynchronousMachine/SynchronousMachine.cpp | 151 ++++++++++++++++++ .../SynchronousMachine/SynchronousMachine.hpp | 76 +++++++++ .../VoltageSource/VoltageSource.cpp | 4 +- Examples/RLCircuit/RLCircuit.cpp | 31 +--- ModelEvaluatorImpl.hpp | 5 + PowerElectronicsModel.hpp | 19 ++- 18 files changed, 743 insertions(+), 42 deletions(-) create mode 100644 ComponentLib/PowerElectronicsComponents/InductionMotor/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/LinearTransformer/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/SynchronousMachine/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.hpp diff --git a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt index c3e958300..10f2c6fdc 100644 --- a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt +++ b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt @@ -3,4 +3,7 @@ add_subdirectory(Capacitor) add_subdirectory(Resistor) add_subdirectory(VoltageSource) -add_subdirectory(Inductor) \ No newline at end of file +add_subdirectory(Inductor) +add_subdirectory(LinearTransformer) +add_subdirectory(InductionMotor) +add_subdirectory(SynchronousMachine) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp index 4fcda9d9f..d905dda05 100644 --- a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp @@ -39,6 +39,8 @@ int Capacitor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); + this->J_.resize(this->size_^2); + this->M_.resize(this->size_^2); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp index 7cfb5521a..9e1052e43 100644 --- a/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp +++ b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp @@ -54,10 +54,79 @@ namespace ModelLib return this->connection_nodes.at(index); } + inline std::vector parkTransformMatrix(ScalarT angle) + { + std::vector result(9); + ScalarT anpim = angle - (2.0/3.0)*M_PI; + ScalarT anpip = angle + (2.0/3.0)*M_PI; + result[0] = (2.0/3.0)*cos(angle); + result[1] = (2.0/3.0)*cos(anpim); + result[2] = (2.0/3.0)*cos(anpip); + result[3] = (2.0/3.0)*sin(angle); + result[4] = (2.0/3.0)*sin(anpim); + result[5] = (2.0/3.0)*sin(anpip); + result[6] = 1.0/3.0; + result[7] = 1.0/3.0; + result[8] = 1.0/3.0; + return result; + } + + inline std::vector parkTransformMatrixDerivative(ScalarT angle) + { + std::vector result(9); + ScalarT anpim = angle - (2.0/3.0)*M_PI; + ScalarT anpip = angle + (2.0/3.0)*M_PI; + result[0] = (2.0/3.0)*sin(angle); + result[1] = (2.0/3.0)*sin(anpim); + result[2] = (2.0/3.0)*sin(anpip); + result[3] = (2.0/3.0)*-cos(angle); + result[4] = (2.0/3.0)*-cos(anpim); + result[5] = (2.0/3.0)*-cos(anpip); + result[6] = 0; + result[7] = 0; + result[8] = 0; + return result; + } + + inline std::vector inverseParkTransformMatrix(ScalarT angle) + { + std::vector result(9); + ScalarT anpim = angle - (2.0/3.0)*M_PI; + ScalarT anpip = angle + (2.0/3.0)*M_PI; + result[0] = cos(angle); + result[1] = sin(angle); + result[2] = 1.0; + result[3] = cos(anpim); + result[4] = sin(anpim); + result[5] = 1.0; + result[6] = cos(anpip); + result[7] = sin(anpip); + result[8] = 1.0; + return result; + } + + inline std::vector inverseParkTransformMatrixDerivative(ScalarT angle) + { + std::vector result(9); + ScalarT anpim = angle - (2.0/3.0)*M_PI; + ScalarT anpip = angle + (2.0/3.0)*M_PI; + result[0] = sin(angle); + result[1] = -cos(angle); + result[2] = 0.0; + result[3] = sin(anpim); + result[4] = -cos(anpim); + result[5] = 0.0; + result[6] = sin(anpip); + result[7] = -cos(anpip); + result[8] = 0.0; + return result; + } + protected: size_t n_extern; size_t n_intern; std::set extern_indices; + //@todo may want to replace the mapping of connection_nodes to Node objects instead of IdxT. Allows for container free setup std::map connection_nodes; }; diff --git a/ComponentLib/PowerElectronicsComponents/InductionMotor/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/InductionMotor/CMakeLists.txt new file mode 100644 index 000000000..95ef42436 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/InductionMotor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_inductionmotor + SOURCES + InductionMotor.cpp + OUTPUT_NAME + gridkit_powerelec_inductionmotor) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.cpp b/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.cpp new file mode 100644 index 000000000..75782b435 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.cpp @@ -0,0 +1,135 @@ + + + +#include +#include +#include +#include "InductionMotor.hpp" + + +namespace ModelLib { + + + +/*! + * @brief Constructor for a constant InductionMotor model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +InductionMotor::InductionMotor(IdxT id, ScalarT Lls, ScalarT Rs, ScalarT Llr, ScalarT Rr, ScalarT Lms, ScalarT J, ScalarT P) + : Lls_(Lls), + Rs_(Rs), + Llr_(Llr), + Rr_(Rr), + Lms_(Lms), + J_(J), + P_(P) +{ + this->size_ = 10; + this->n_intern = 5; + this->n_extern = 5; + this->extern_indices = {0,1,2,3,4}; + this->idc_ = id; +} + +template +InductionMotor::~InductionMotor() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int InductionMotor::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int InductionMotor::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int InductionMotor::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int InductionMotor::evaluateResidual() +{ + //Note this leaves induction lumped into y. Perhaps would be better to seperate volatge and induction into seperate vectors + // for easier development + this->f_[0] = y_[5] + y_[7]; + this->f_[1] = (-1.0/2.0) * y_[5] - (sqrt(3.0)/2.0)*y_[6] + y_[7]; + this->f_[2] = (-1.0/2.0) * y_[5] + (sqrt(3.0)/2.0)*y_[6] + y_[7]; + this->f_[3] = J_ * yp_[3] - (3.0/4.0)*P_*Lms_ * (y_[5]*y_[9] - y_[6]*y_[8]); + this->f_[4] = yp_[4] - y_[3]; + this->f_[5] = (1.0/3.0)*(2.0* y_[0] - y_[1] - y_[2]) - Rs_*y_[5] - (Lls_ + Lms_) * yp_[5] - Lms_ * yp_[6]; + this->f_[6] = (1.0/sqrt(3.0))*(-y_[1] + y_[2]) - Rs_*y_[6] - (Lls_ + Lms_) * yp_[6] - Lms_ * yp_[5]; + this->f_[7] = (y_[0] + y_[1] + y_[2])/3.0 - Rs_*y_[7] - Lls_ * yp_[7]; + this->f_[8] = Rr_*y_[8] + (Llr_ + Lms_)*yp_[8] + Lms_ * yp_[5] - (P_/2)*y_[3]*((Llr_+Lms_)*y_[9] + Lms_*y_[6]); + this->f_[9] = Rr_*y_[9] + (Llr_ + Lms_)*yp_[9] + Lms_ * yp_[6] + (P_/2)*y_[3]*((Llr_+Lms_)*y_[8] + Lms_*y_[5]); + return 0; +} + +template +int InductionMotor::evaluateJacobian() +{ + return 0; +} + +template +int InductionMotor::evaluateIntegrand() +{ + return 0; +} + +template +int InductionMotor::initializeAdjoint() +{ + return 0; +} + +template +int InductionMotor::evaluateAdjointResidual() +{ + return 0; +} + +template +int InductionMotor::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class InductionMotor; +template class InductionMotor; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.hpp b/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.hpp new file mode 100644 index 000000000..2547754e2 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.hpp @@ -0,0 +1,69 @@ + + +#ifndef _IMOTOR_HPP_ +#define _IMOTOR_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive InductionMotor class. + * + */ + template + class InductionMotor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + public: + InductionMotor(IdxT id, ScalarT Lls, ScalarT Rs, ScalarT Llr, ScalarT Rr, ScalarT Lms, ScalarT J, ScalarT P); + virtual ~InductionMotor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT Lls_; + ScalarT Rs_; + ScalarT Llr_; + ScalarT Rr_; + ScalarT Lms_; + ScalarT J_; + ScalarT P_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp index 278b0eebc..952a992d0 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -40,6 +40,8 @@ int Inductor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); + this->J_.resize(this->size_^2); + this->M_.resize(this->size_^2); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/LinearTransformer/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/LinearTransformer/CMakeLists.txt new file mode 100644 index 000000000..eaf95c043 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/LinearTransformer/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_lineartrasnformer + SOURCES + LinearTransformer.cpp + OUTPUT_NAME + gridkit_powerelec_lineartrasnformer) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.cpp b/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.cpp new file mode 100644 index 000000000..4caaeae66 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.cpp @@ -0,0 +1,124 @@ + + + +#include +#include +#include +#include "LinearTransformer.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant LinearTransformer model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +LinearTransformer::LinearTransformer(IdxT id, ScalarT L1, ScalarT L2, ScalarT R1, ScalarT R2, ScalarT M) + : L1_(L1), + L2_(L2), + R1_(R1), + R2_(R2), + M_(M) +{ + this->size_ = 4; + this->n_intern = 2; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +LinearTransformer::~LinearTransformer() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int LinearTransformer::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int LinearTransformer::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int LinearTransformer::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int LinearTransformer::evaluateResidual() +{ + //Note this leaves induction lumped into y. Perhaps would be better to seperate volatge and induction into seperate vectors + // for easier development + this->f_[0] = this->y_[2]; + this->f_[1] = this->y_[3]; + this->f_[2] = this->y_[0] - this->R1_ * this->y_[2] - this->L1_ * this->yp_[2] - this->M_ * this->yp_[3]; + this->f_[2] = this->y_[1] - this->R2_ * this->y_[3] - this->M_ * this->yp_[2] - this->L2_ * this->yp_[3]; + return 0; +} + +template +int LinearTransformer::evaluateJacobian() +{ + return 0; +} + +template +int LinearTransformer::evaluateIntegrand() +{ + return 0; +} + +template +int LinearTransformer::initializeAdjoint() +{ + return 0; +} + +template +int LinearTransformer::evaluateAdjointResidual() +{ + return 0; +} + +template +int LinearTransformer::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class LinearTransformer; +template class LinearTransformer; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.hpp b/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.hpp new file mode 100644 index 000000000..cf56adfa2 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.hpp @@ -0,0 +1,67 @@ + + +#ifndef _LTRANS_HPP_ +#define _LTRANS_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive LinearTransformer class. + * + */ + template + class LinearTransformer : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + public: + LinearTransformer(IdxT id, ScalarT L1, ScalarT L2, ScalarT R1, ScalarT R2, ScalarT M); + virtual ~LinearTransformer(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT L1_; + ScalarT L2_; + ScalarT R1_; + ScalarT R2_; + ScalarT M_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp index 1aa06427a..5faad23b4 100644 --- a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp @@ -39,6 +39,8 @@ int Resistor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); + this->J_.resize(this->size_^2); + this->M_.resize(this->size_^2); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/SynchronousMachine/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/CMakeLists.txt new file mode 100644 index 000000000..bfaeace4b --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_synmachine + SOURCES + SynchronousMachine.cpp + OUTPUT_NAME + gridkit_powerelec_synmachine) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.cpp b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.cpp new file mode 100644 index 000000000..05b1e59ac --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.cpp @@ -0,0 +1,151 @@ + + + +#include +#include +#include +#include "SynchronousMachine.hpp" + + +namespace ModelLib { + + + +/*! + * @brief Constructor for a constant SynchronousMachine model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +SynchronousMachine::SynchronousMachine(IdxT id, ScalarT Lls, std::tuple Llkq, ScalarT Llfd, ScalarT Llkd, ScalarT Lmq, ScalarT Lmd, ScalarT Rs, std::tuple Rkq, ScalarT Rfd, ScalarT Rkd, ScalarT J, ScalarT P, ScalarT mub) + : Lls_(Lls), + Llkq_(Llkq), + Llfd_(Llfd), + Llkd_(Llkd), + Lmq_(Lmq), + Lmd_(Lmd), + Rs_(Rs), + Rkq_(Rkq), + Rfd_(Rfd), + Rkd_(Rkd), + J_(J), + P_(P), + mub_(mub) +{ + this->size_ = 13; + this->n_intern = 6; + this->n_extern = 7; + this->extern_indices = {0,1,2,3,4}; + this->idc_ = id; +} + +template +SynchronousMachine::~SynchronousMachine() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int SynchronousMachine::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int SynchronousMachine::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int SynchronousMachine::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int SynchronousMachine::evaluateResidual() +{ + ScalarT rkq1 = std::get<0>(Rkq_); + ScalarT rkq2 = std::get<1>(Rkq_); + ScalarT llkq1 = std::get<0>(Llkq_); + ScalarT llkq2 = std::get<1>(Llkq_); + + ScalarT cos1 = cos((P_/2.0)*y_[5]); + ScalarT sin1 = sin((P_/2.0)*y_[5]); + ScalarT cos23m = cos((P_/2.0)*y_[5] - (2.0/3.0)*M_PI); + ScalarT sin23m = sin((P_/2.0)*y_[5] - (2.0/3.0)*M_PI); + ScalarT cos23p = cos((P_/2.0)*y_[5] + (2.0/3.0)*M_PI); + ScalarT sin23p = sin((P_/2.0)*y_[5] + (2.0/3.0)*M_PI); + + this->f_[0] = y_[6]*cos1 + y_[7]*sin1 + y_[8]; + this->f_[1] = y_[6]*cos23m + y_[7]*sin23m + y_[8]; + this->f_[2] = y_[6]*cos23p + y_[7]*sin23p + y_[8]; + this->f_[3] = J_ * yp_[4] - (3.0/4.0)*P_*(Lmd_ *y_[6]* (y_[7] + y_[11] + y_[12]) - Lmq_*y_[7]*(y_[6] + y_[9] + y_[0])); + this->f_[4] = yp_[5] - y_[4]; + this->f_[5] = (-2.0/3.0)*(y_[0]*cos1 +y_[1]*cos23m + y_[2]*cos23p) + Rs_*y_[6] + (Lls_ + Lmq_)*yp_[6] + Lmq_*yp_[9] + Lmq_*yp_[10] + y_[4]*(P_/2.0)*((Lls_ + Lmd_)*y_[7] + Lmd_*y_[11] + Lmd_*y_[12]); + this->f_[6] = (-2.0/3.0)*(y_[0]*sin1 -y_[1]*sin23m - y_[2]*sin23p) + Rs_*y_[7] + (Lls_ + Lmd_)*yp_[7] + Lmd_*yp_[11] + Lmd_*yp_[12] - y_[4]*(P_/2.0)*((Lls_ + Lmq_)*y_[6] + Lmq_*y_[9] + Lmq_*y_[10]); + this->f_[7] = (-1.0/3.0)*(y_[0] + y_[1] + y_[2]) + Rs_*y_[8] + Lls_*yp_[8]; + this->f_[8] = rkq1*y_[9] + (llkq1 + Lmq_)*yp_[9] + Lmq_*yp_[6] + Lmq_*yp_[10]; + this->f_[9] = rkq1*y_[9] + (llkq1 + Lmq_)*yp_[9] + Lmq_*yp_[6] + Lmq_*yp_[10]; + return 0; +} + +template +int SynchronousMachine::evaluateJacobian() +{ + return 0; +} + +template +int SynchronousMachine::evaluateIntegrand() +{ + return 0; +} + +template +int SynchronousMachine::initializeAdjoint() +{ + return 0; +} + +template +int SynchronousMachine::evaluateAdjointResidual() +{ + return 0; +} + +template +int SynchronousMachine::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class SynchronousMachine; +template class SynchronousMachine; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.hpp b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.hpp new file mode 100644 index 000000000..a18eca9c9 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.hpp @@ -0,0 +1,76 @@ + + +#ifndef _SYNMACH_HPP_ +#define _SYNMACH_HPP_ + +#include +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive SynchronousMachine class. + * + */ + template + class SynchronousMachine : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + public: + SynchronousMachine(IdxT id, ScalarT Lls, std::tuple Llkq, ScalarT Llfd, ScalarT Llkd, ScalarT Lmq, ScalarT Lmd, ScalarT Rs, std::tuple Rkq, ScalarT Rfd, ScalarT Rkd, ScalarT J, ScalarT P, ScalarT mub); + virtual ~SynchronousMachine(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT Lls_; + std::tuple Llkq_; + ScalarT Llfd_; + ScalarT Llkd_; + ScalarT Lmq_; + ScalarT Lmd_; + ScalarT Rs_; + std::tuple Rkq_; + ScalarT Rfd_; + ScalarT Rkd_; + ScalarT J_; + ScalarT P_; + ScalarT mub_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp index c27c04bd2..e26841a6c 100644 --- a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp @@ -39,6 +39,8 @@ int VoltageSource::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); + this->J_.resize(this->size_^2); + this->M_.resize(this->size_^2); return 0; } @@ -72,7 +74,7 @@ int VoltageSource::evaluateResidual() // for easier development this->f_[0] = this->y_[2]; this->f_[1] = -this->y_[2]; - this->f_[2] = this->y_[0] - this->y_[1] - this->V_; + this->f_[2] = this->y_[1] - this->y_[0] - this->V_; return 0; } diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index ba9333f40..6d44d6b4f 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -12,39 +12,10 @@ #include #include -#include int main(int argc, char const *argv[]) { - //Basic Circuit Setup - //@todo will want to eventually put components in the hyper graph instead of indicies - - std::unique_ptr> cirg(new CircuitGraph()); - for (size_t i = 0; i < 3; i++) - { - cirg->addHyperEdge(i); - } - for (size_t i = 0; i < 5; i++) - { - cirg->addHyperNode(i); - } - - //Create Connections of Nodes to edges sets - //External nodes - cirg->addConnection(0, 0); - cirg->addConnection(0, 2); - cirg->addConnection(2, 0); - cirg->addConnection(2, 1); - cirg->addConnection(3, 1); - cirg->addConnection(3, 2); - - //Internal nodes - cirg->addConnection(1,0); - cirg->addConnection(4,2); - - - cirg->printBiPartiteGraph(); //Create circuit model @@ -80,7 +51,7 @@ int main(int argc, char const *argv[]) //Allocate with graph - sysmodel->allocate(*cirg); + sysmodel->allocate(5); std::cout << sysmodel->y().size() << std::endl; diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp index 94cbeb5d3..72abb858b 100644 --- a/ModelEvaluatorImpl.hpp +++ b/ModelEvaluatorImpl.hpp @@ -90,6 +90,8 @@ namespace ModelLib yp_(size_), f_(size_), g_(size_quad_), + J_(size_quad^2), + M_(size_quad^2), yB_(size_), ypB_(size_), fB_(size_), @@ -277,6 +279,9 @@ namespace ModelLib std::vector fB_; std::vector gB_; + std::vector J_; + std::vector M_; + std::vector param_; std::vector param_up_; std::vector param_lo_; diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp index 78350ee2f..7a9304716 100644 --- a/PowerElectronicsModel.hpp +++ b/PowerElectronicsModel.hpp @@ -72,12 +72,18 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 1; } - int allocate(CircuitGraph cir) + /** + * @brief Allocate the vector data with size amount + * @todo Add capability to go through component model connection to get the size of the actual vector + * + * @param s + * @return int + */ + int allocate(IdxT s) { - this->graph = cir; // Allocate all components - this->size_ = cir.amountHyperNodes(); + this->size_ = s; for(const auto& component : components_) { component->allocate(); @@ -202,16 +208,9 @@ class PowerElectronicsModel : public ModelEvaluatorImpl this->components_.push_back(component); } - CircuitGraph getGraph() - { - return this->graph; - } - private: std::vector components_; - CircuitGraph graph; - }; // class PowerElectronicsModel } // namespace ModelLib From 78ca85c43a38436307d9d6b1b5ae34617491f03e Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Wed, 15 Nov 2023 20:47:04 -0500 Subject: [PATCH 16/52] Added COO Sparse Matrices, Component Jacobians, and Discrete Generator + Basic COO Sparse Matrix Implmentation + Discrete Generator Component + Resistor Jacobian + Capacitor Jacobian + Voltage Source Jacobian + Inductor Jacobian + Testing for Sparse Jacobian and Discrete Generator --- CMakeLists.txt | 3 + .../PowerElectronicsComponents/CMakeLists.txt | 3 +- .../Capacitor/Capacitor.cpp | 19 +- .../Capacitor/Capacitor.hpp | 1 + .../DiscreteGenerator/CMakeLists.txt | 8 + .../DiscreteGenerator/DiscreteGenerator.cpp | 278 ++++++++++ .../DiscreteGenerator/DiscreteGenerator.hpp | 100 ++++ .../Inductor/Inductor.cpp | 21 +- .../Inductor/Inductor.hpp | 1 + .../Resistor/Resistor.cpp | 11 +- .../Resistor/Resistor.hpp | 1 + .../VoltageSource/VoltageSource.cpp | 10 +- .../VoltageSource/VoltageSource.hpp | 1 + Examples/CMakeLists.txt | 2 + Examples/DiscreteGeneratorTest/CMakeLists.txt | 9 + Examples/DiscreteGeneratorTest/DGTest.cpp | 56 ++ Examples/RLCircuit/RLCircuit.cpp | 4 + Examples/SparseTest/CMakeLists.txt | 7 + Examples/SparseTest/SparseTest.cpp | 55 ++ ModelEvaluatorImpl.hpp | 20 +- PowerElectronicsModel.hpp | 6 + SparseMatrix/CMakeLists.txt | 7 + SparseMatrix/COO_Matrix.hpp | 515 ++++++++++++++++++ 23 files changed, 1122 insertions(+), 16 deletions(-) create mode 100644 ComponentLib/PowerElectronicsComponents/DiscreteGenerator/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp create mode 100644 Examples/DiscreteGeneratorTest/CMakeLists.txt create mode 100644 Examples/DiscreteGeneratorTest/DGTest.cpp create mode 100644 Examples/SparseTest/CMakeLists.txt create mode 100644 Examples/SparseTest/SparseTest.cpp create mode 100644 SparseMatrix/CMakeLists.txt create mode 100644 SparseMatrix/COO_Matrix.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 19048d375..ef6cbcf57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,9 @@ add_subdirectory(ComponentLib) # General Utilities and File IO add_subdirectory(Utilities) +#Local Sparse matrix operations +add_subdirectory(SparseMatrix) + # Create solvers add_subdirectory(Solver) diff --git a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt index 10f2c6fdc..9d6ad8be1 100644 --- a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt +++ b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt @@ -6,4 +6,5 @@ add_subdirectory(VoltageSource) add_subdirectory(Inductor) add_subdirectory(LinearTransformer) add_subdirectory(InductionMotor) -add_subdirectory(SynchronousMachine) \ No newline at end of file +add_subdirectory(SynchronousMachine) +add_subdirectory(DiscreteGenerator) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp index d905dda05..ecbe9d51f 100644 --- a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp @@ -39,8 +39,7 @@ int Capacitor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); - this->J_.resize(this->size_^2); - this->M_.resize(this->size_^2); + return 0; } @@ -72,13 +71,27 @@ int Capacitor::evaluateResidual() { this->f_[0] = this->yp_[2]; this->f_[1] = -this->yp_[2]; - this->f_[2] = this->y_[0] - this->y_[1] - this->y_[2] - this->C_ * this->yp_[2]; + this->f_[2] = -this->C_ * this->yp_[2] + this->y_[0] - this->y_[1] - this->y_[2]; return 0; } template int Capacitor::evaluateJacobian() { + //Create dF/dy + std::vector rcord{2,2,2}; + std::vector ccord{0,1,2}; + std::vector vals{1.0, -1.0, -1.0}; + this->J_.setValues(rcord, ccord, vals); + + //Create -dF/dy' + std::vector rcordder{0,1,2}; + std::vector ccordder{2,2,2}; + std::vector valsder{1.0, -1.0, -this->C_}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); + + //Perform dF/dy + \alpha dF/dy' + this->J_.AXPY(this->alpha_, &Jacder); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp index 76cf94614..e1a9974c3 100644 --- a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp @@ -36,6 +36,7 @@ namespace ModelLib using CircuitComponent::ypB_; using CircuitComponent::fB_; using CircuitComponent::gB_; + using CircuitComponent::J_; using CircuitComponent::param_; using CircuitComponent::idc_; diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/CMakeLists.txt new file mode 100644 index 000000000..c0ed2c7a9 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_disgen + SOURCES + DiscreteGenerator.cpp + OUTPUT_NAME + gridkit_powerelec_disgen) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp new file mode 100644 index 000000000..7770281d1 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp @@ -0,0 +1,278 @@ + + + +#include +#include +#include +#include "DiscreteGenerator.hpp" + +namespace ModelLib { + + +/*! + * @brief Constructor for a Discrete Generator + * @todo Maybe have parameters be templated in. Variables cannot be changed and are unlikely to. Allows for compile time optimizations + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +DiscreteGenerator::DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm) + : wb_(parm.wb), wc_(parm.wc), mp_(parm.mp), refmp_(parm.refmp), Vn_(parm.Vn), nq_(parm.nq), F_(parm.F), Kiv_(parm.Kiv), Kpv_(parm.Kpv), Kic_(parm.Kic), Kpc_(parm.Kpc), Cf_(parm.Cf), rLf_(parm.rLf), Lf_(parm.Lf), rLc_(parm.rLc), Lc_(parm.Lc) +{ + // internals [delta_i, Pi, Qi, phi_di, phi_qi, gamma_di, gamma_qi, il_di, il_qi, vo_di, vo_qi, io_di, io_qi] + // externals [Pref, Pbus, QBus] + this->size_ = 16; + this->n_intern = 13; + this->n_extern = 3; + this->extern_indices = {0,1,2}; + this->idc_ = id; +} + +template +DiscreteGenerator::~DiscreteGenerator() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int DiscreteGenerator::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + + return 0; +} + +/** + * Initialization of the grid model + */ +template +int DiscreteGenerator::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int DiscreteGenerator::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int DiscreteGenerator::evaluateResidual() +{ + // ### Externals Componenets ### + //Reference P + ScalarT wcom = this->wb_ - this->refmp_ * this->y_[0]; + + this->f_[0] = 0; + this->f_[1] = 0; + this->f_[2] = 0; + + // ### Internal Componenets ## + f_[3] = -yp_[3] + wb_ - mp_ * y_[4] - wcom; + + f_[4] = -yp_[4] + wc_ * (y_[12] * y_[14] + y_[13] * y_[15] - y_[4]); + f_[5] = -yp_[4] + wc_ * (-y_[12] * y_[15] + y_[13] * y_[14] - y_[5]); + + ScalarT vod_star = Vn_ - nq_ * y_[5]; + ScalarT voq_star = 0; + + f_[6] = -yp_[6] + vod_star - y_[12]; + f_[7] = -yp_[7] + voq_star - y_[13]; + + ScalarT ild_star = F_ * y_[14] - wb_ * Cf_ * y_[13] + Kpv_ * (vod_star - y_[12]) + Kiv_ * y_[6] ; + ScalarT ilq_star = F_ * y_[15] + wb_ * Cf_ * y_[12] + Kpv_ * (voq_star - y_[13]) + Kiv_ * y_[7]; + + f_[8] = -yp_[8] + ild_star - y_[10]; + f_[9] = -yp_[9] + ilq_star - y_[11]; + + ScalarT vid_star = -wb_ * Lf_ * y_[11] + Kpc_ * (ild_star - y_[10]) + Kic_ * y_[8]; + ScalarT viq_star = wb_ * Lf_ * y_[10] + Kpc_ * (ilq_star - y_[11]) + Kic_ * y_[9]; + + f_[10] = -yp_[10] - (rLf_ / Lf_) * y_[10] + wcom * y_[11] + (1/Lf_) * (vid_star - y_[12]); + f_[11] = -yp_[11] - (rLf_ / Lf_) * y_[11] - wcom * y_[10] + (1/Lf_) * (viq_star - y_[13]); + + f_[12] = -yp_[12] + wcom * y_[13] + (1/Cf_) * (y_[10] - y_[14]); + f_[13] = -yp_[13] - wcom * y_[12] + (1/Cf_) * (y_[11] - y_[15]); + + f_[14] = -yp_[14] - (rLc_ / Lc_) * y_[14] + wcom * y_[15] + (1/Lc_)*(y_[12] - y_[1]); + f_[15] = -yp_[15] - (rLc_ / Lc_) * y_[15] - wcom * y_[14] + (1/Lc_)*(y_[13] - y_[2]); + return 0; +} + +/** + * @brief Compute the jacobian of the DiscreteGenerator for iteration. dF/dy - \alpha dF/dy' + * + * The matrix dF/dy should be + * [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ mpref, 0, 0, 0, -mp, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, 0, wc*x15, wc*x16, wc*x13, wc*x14] +[ 0, 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, -wc*x16, wc*x15, wc*x14, -wc*x13] +[ 0, 0, 0, 0, 0, -nq, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0] +[ 0, 0, 0, 0, 0, -Kpv*nq, Kiv, 0, 0, 0, -1, 0, -Kpv, -Cf*wb, F, 0] +[ 0, 0, 0, 0, 0, 0, 0, Kiv, 0, 0, 0, -1, Cf*wb, -Kpv, 0, F] +[-mpref*x12, 0, 0, 0, 0, -(Kpc*Kpv*nq)/Lf, (Kiv*Kpc)/Lf, 0, Kic/Lf, 0, - Kpc/Lf - rLf/Lf, -mpref*x1, -(Kpc*Kpv + 1)/Lf, -(Cf*Kpc*wb)/Lf, (F*Kpc)/Lf, 0] +[ mpref*x11, 0, 0, 0, 0, 0, 0, (Kiv*Kpc)/Lf, 0, Kic/Lf, mpref*x1, - Kpc/Lf - rLf/Lf, (Cf*Kpc*wb)/Lf, -(Kpc*Kpv + 1)/Lf, 0, (F*Kpc)/Lf] +[-mpref*x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Cf, 0, 0, wb - mpref*x1, -1/Cf, 0] +[ mpref*x13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Cf, mpref*x1 - wb, 0, 0, -1/Cf] +[-mpref*x16, -1/Lc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, 0, -rLc/Lc, wb - mpref*x1] +[ mpref*x15, 0, -1/Lc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, mpref*x1 - wb, -rLc/Lc] + * 'Generated from MATLAB symbolic' + * Jacobian is mostly constant besides reference and rows 4 & 5 + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ +template +int DiscreteGenerator::evaluateJacobian() +{ + //Create dF/dy' + std::vector rcordder(13); + std::vector valsder(13,1.0); + for (int i = 0; i < 13; i++) + { + rcordder[i] = i + 3; + } + COO_Matrix Jacder = COO_Matrix(rcordder, rcordder, valsder,16,16); + + //Create dF/dy + //r = 3 + std::vector ctemp{0, 4}; + std::vector rtemp(ctemp.size(),3); + std::vector valtemp{this->refmp_, -this->mp_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 4 + ctemp = {4, 12, 13, 14, 15}; + std::fill(rtemp.begin(), rtemp.end(), 4); + valtemp = {-this->wc_, this->wc_*y_[14], this->wc_*y_[15], this->wc_*y_[12], this->wc_*y_[13]}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 5 + ctemp = {5, 12, 13, 14, 15}; + std::fill(rtemp.begin(), rtemp.end(), 5); + valtemp = {-this->wc_, -this->wc_*y_[15], this->wc_*y_[14], this->wc_*y_[13], -this->wc_*y_[12]}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 6 + ctemp = {5, 12}; + std::fill(rtemp.begin(), rtemp.end(), 6); + valtemp = {-this->nq_, -1.0}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 7 + ctemp = {13}; + std::fill(rtemp.begin(), rtemp.end(), 7); + valtemp = {-1.0}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 8 + ctemp = {5,6,10,12,13,14}; + std::fill(rtemp.begin(), rtemp.end(), 8); + valtemp = {-this->Kpv_*this->nq_, this->Kiv_, -1.0, -this->Kpv_, -this->Cf_*this->wb_, this->F_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 9 + ctemp = {7, 11, 12, 13, 15}; + std::fill(rtemp.begin(), rtemp.end(), 9); + valtemp = {this->Kiv_, -1.0, this->Cf_*this->wb_,-this->Kpv_,this->F_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 10 + ctemp = {0, 5, 6, 8, 10, 11, 12, 13, 14}; + std::fill(rtemp.begin(), rtemp.end(), 10); + valtemp = {-this->refmp_ * y_[11], -(this->Kpc_ * this->Kpv_ * this->nq_) / this->Lf_, (this->Kpc_ * this->Kiv_) / this->Lf_, this->Kic_ / this->Lf_, -(this->Kpc_ + this->rLf_) / this->Lf_, -this->refmp_ * y_[0], -(this->Kpc_ * this->Kpv_ + 1.0) / this->Lf_, -(this->Cf_ * this->Kpc_ * this->wb_) / this->Lf_, (this->F_ * this->Kpc_) / this->Lf_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 11 + ctemp = {0, 7, 9, 10, 11, 12, 13, 15}; + std::fill(rtemp.begin(), rtemp.end(), 11); + valtemp = {this->refmp_ * y_[10], (this->Kiv_ * this->Kpc_) / this->Lf_, this->Kic_ / this->Lf_, this->refmp_ * y_[0], -(this->Kpc_ + this->rLf_) / this->Lf_, (this->Cf_ * this->Kpc_ * this->wb_) / this->Lf_, -(this->Kpc_ * this->Kpv_ + 1.0) / this->Lf_, (this->F_ * this->Kpc_) / this->Lf_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 12 + ctemp = {0, 10, 13, 14}; + std::fill(rtemp.begin(), rtemp.end(), 12); + valtemp = {-this->refmp_ * y_[13], 1.0 / this->Cf_, this->wb_ - this->refmp_ * y_[0], -1.0 / this->Cf_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + + //r = 13 + ctemp = {0, 11, 12, 15}; + std::fill(rtemp.begin(), rtemp.end(), 13); + valtemp = {this->refmp_ * y_[12], 1.0 / this->Cf_, -this->wb_ + this->refmp_ * y_[0], -1.0 / this->Cf_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + + //r = 14 + ctemp = {0, 1, 12, 14, 15}; + std::fill(rtemp.begin(), rtemp.end(), 14); + valtemp = {-this->refmp_ * y_[15], -1.0 / this->Lc_, 1.0 / this->Lc_, -this->rLc_ / this->Lc_, this->wb_ - this->refmp_ * y_[0]}; + this->J_.setValues(rtemp, ctemp, valtemp); + + + //r = 15 + ctemp = {0, 2, 13, 14, 15}; + std::fill(rtemp.begin(), rtemp.end(), 15); + valtemp = {-this->refmp_ * y_[14], -1.0 / this->Lc_, 1.0 / this->Lc_, -this->wb_ + this->refmp_ * y_[0], -this->rLc_ / this->Lc_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + + //Perform dF/dy + \alpha dF/dy' + + this->J_.AXPY(-this->alpha_, &Jacder); + + return 0; +} + +template +int DiscreteGenerator::evaluateIntegrand() +{ + return 0; +} + +template +int DiscreteGenerator::initializeAdjoint() +{ + return 0; +} + +template +int DiscreteGenerator::evaluateAdjointResidual() +{ + return 0; +} + +template +int DiscreteGenerator::evaluateAdjointIntegrand() +{ + return 0; +} + + + + +// Available template instantiations +template class DiscreteGenerator; +template class DiscreteGenerator; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp new file mode 100644 index 000000000..f5ce86899 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp @@ -0,0 +1,100 @@ + + +#ifndef _CAP_HPP_ +#define _CAP_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; + + template + struct DiscreteGeneratorParameters + { + ScalarT wb; + ScalarT wc; + ScalarT mp; + ScalarT refmp; + ScalarT Vn; + ScalarT nq; + ScalarT F; + ScalarT Kiv; + ScalarT Kpv; + ScalarT Kic; + ScalarT Kpc; + ScalarT Cf; + ScalarT rLf; + ScalarT Lf; + ScalarT rLc; + ScalarT Lc; + }; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive DiscreteGenerator class. + * + */ + template + class DiscreteGenerator : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::J_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm); + virtual ~DiscreteGenerator(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT wb_; + ScalarT wc_; + ScalarT mp_; + ScalarT refmp_; + ScalarT Vn_; + ScalarT nq_; + ScalarT F_; + ScalarT Kiv_; + ScalarT Kpv_; + ScalarT Kic_; + ScalarT Kpc_; + ScalarT Cf_; + ScalarT rLf_; + ScalarT Lf_; + ScalarT rLc_; + ScalarT Lc_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp index 952a992d0..89f903436 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -40,8 +40,7 @@ int Inductor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); - this->J_.resize(this->size_^2); - this->M_.resize(this->size_^2); + return 0; } @@ -73,13 +72,29 @@ int Inductor::evaluateResidual() { this->f_[0] = this->y_[2]; this->f_[1] = -this->y_[2]; - this->f_[2] = this->y_[0] - this->y_[1] - this->L_ * this->yp_[2]; + this->f_[2] = - this->L_ * this->yp_[2] + this->y_[0] - this->y_[1] ; return 0; } template int Inductor::evaluateJacobian() { + + //Create dF/dy + std::vector rcord{0,1,2,2}; + std::vector ccord{2,2,0,1}; + std::vector vals{1.0, -1.0, 1.0, -1.0}; + this->J_.setValues(rcord, ccord, vals); + + //Create -dF/dy' + std::vector rcordder{2}; + std::vector ccordder{2}; + std::vector valsder{-this->L_}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); + + //Perform dF/dy + \alpha dF/dy' + this->J_.AXPY(this->alpha_, &Jacder); + return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp index e959aabf1..2f2c1085b 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp @@ -36,6 +36,7 @@ namespace ModelLib using CircuitComponent::ypB_; using CircuitComponent::fB_; using CircuitComponent::gB_; + using CircuitComponent::J_; using CircuitComponent::param_; using CircuitComponent::idc_; diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp index 5faad23b4..7536f2274 100644 --- a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp @@ -39,8 +39,7 @@ int Resistor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); - this->J_.resize(this->size_^2); - this->M_.resize(this->size_^2); + return 0; } @@ -79,6 +78,14 @@ int Resistor::evaluateResidual() template int Resistor::evaluateJacobian() { + + //Create dF/dy + //does compiler make constant??? + std::vector rcord{0,0,1,1}; + std::vector ccord{0,1,0,1}; + std::vector vals{-1.0 / this->R_, 1.0 / this->R_, 1.0 / this->R_, -1.0 / this->R_}; + this->J_.setValues(rcord, ccord, vals); + return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp index 0373e2c5c..984d8304b 100644 --- a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp @@ -36,6 +36,7 @@ namespace ModelLib using CircuitComponent::ypB_; using CircuitComponent::fB_; using CircuitComponent::gB_; + using CircuitComponent::J_; using CircuitComponent::param_; using CircuitComponent::idc_; diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp index e26841a6c..b7c18bd6f 100644 --- a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp @@ -39,8 +39,7 @@ int VoltageSource::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); - this->J_.resize(this->size_^2); - this->M_.resize(this->size_^2); + return 0; } @@ -81,6 +80,13 @@ int VoltageSource::evaluateResidual() template int VoltageSource::evaluateJacobian() { + + //Create dF/dy + std::vector rcord{0,1,2,2}; + std::vector ccord{2,2,0,1}; + std::vector vals{1.0, -1.0, -1.0, 1.0}; + this->J_.setValues(rcord, ccord, vals); + return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp index dcbacf2f7..3ac1c8699 100644 --- a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp @@ -36,6 +36,7 @@ namespace ModelLib using CircuitComponent::ypB_; using CircuitComponent::fB_; using CircuitComponent::gB_; + using CircuitComponent::J_; using CircuitComponent::param_; using CircuitComponent::idc_; diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index b42907fd3..e15774642 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -57,6 +57,8 @@ add_subdirectory(MatPowerTesting) add_subdirectory(RLCircuit) +add_subdirectory(SparseTest) +add_subdirectory(DiscreteGeneratorTest) if(TARGET SUNDIALS::kinsol) add_subdirectory(Grid3Bus) diff --git a/Examples/DiscreteGeneratorTest/CMakeLists.txt b/Examples/DiscreteGeneratorTest/CMakeLists.txt new file mode 100644 index 000000000..b1100b91a --- /dev/null +++ b/Examples/DiscreteGeneratorTest/CMakeLists.txt @@ -0,0 +1,9 @@ + + + + +add_executable(dgtest DGTest.cpp) +target_link_libraries(dgtest GRIDKIT::powerelec_disgen) + +add_test(NAME DiscreteGeneratorTest COMMAND $) +install(TARGETS dgtest RUNTIME DESTINATION bin) diff --git a/Examples/DiscreteGeneratorTest/DGTest.cpp b/Examples/DiscreteGeneratorTest/DGTest.cpp new file mode 100644 index 000000000..7d4aeda6f --- /dev/null +++ b/Examples/DiscreteGeneratorTest/DGTest.cpp @@ -0,0 +1,56 @@ + + +#include +#include +#include +#include +#include +#include + +#include + + +int main(int argc, char const *argv[]) +{ + + ModelLib::DiscreteGeneratorParameters parms; + //Parameters from MATLAB Microgrid code for first DG + //refmp is need for reference input + parms.wb = 2.0*M_PI*50.0; + parms.wc = 31.41; + parms.mp = 9.4e-5; + parms.refmp = 9.4e-5; + parms.Vn = 380; + parms.nq = 1.3e-3; + parms.F = 0.75; + parms.Kiv = 420.0; + parms.Kpv = 0.1; + parms.Kic = 20.0 * 1.0e3; + parms.Kpc = 15.0; + parms.Cf = 50.0e-6; + parms.rLf = 0.1; + parms.Lf = 1.35e-3; + parms.rLc = 0.03; + parms.Lc = 0.35e-3; + + ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(0, parms); + + std::vector t1(16,0.0); + std::vector t2{0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.1,1.2,1.3,1.4,1.5}; + + dg->allocate(); + + dg->y() = t2; + dg->yp() = t1; + + dg->evaluateResidual(); + + std::cout << "Output: {"; + for (double i : dg->getResidual()) + { + std::cout << i << ", "; + } + std::cout << "}\n"; + + return 0; +} diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index 6d44d6b4f..4669d564e 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -80,6 +80,10 @@ int main(int argc, char const *argv[]) } std::cout << "}\n"; + induct->updateTime(0.0, 1.0); + induct->evaluateJacobian(); + induct->getJacobian().printMatrix(true); + return 0; } diff --git a/Examples/SparseTest/CMakeLists.txt b/Examples/SparseTest/CMakeLists.txt new file mode 100644 index 000000000..d0b6f5e05 --- /dev/null +++ b/Examples/SparseTest/CMakeLists.txt @@ -0,0 +1,7 @@ + + +add_executable(spmattest SparseTest.cpp) +target_link_libraries(spmattest GRIDKIT::SparseMatrix) + +add_test(NAME SparseMatrixTest COMMAND $) +install(TARGETS spmattest RUNTIME DESTINATION bin) diff --git a/Examples/SparseTest/SparseTest.cpp b/Examples/SparseTest/SparseTest.cpp new file mode 100644 index 000000000..976759533 --- /dev/null +++ b/Examples/SparseTest/SparseTest.cpp @@ -0,0 +1,55 @@ + + +#include +#include +#include +#include +#include +#include +#include + +#include + + + + +int main(int argc, char const *argv[]) +{ + std::vector val{0.1, 0.2, 0.3, 0.4}; + std::vector x{2,1,3,1}; + std::vector y{1,3,2,2}; + size_t n = 4; + size_t m = 4; + + COO_Matrix A = COO_Matrix(x,y,val,m,n); + + std::vector valn(4); + std::vector xn(4); + std::vector yn(4); + + std::tie(xn, yn, valn) = A.getEntries(); + + for (size_t i = 0; i < valn.size(); i++) + { + std::cout << valn[i] << "\n"; + } + + std::cout << "A:\n"; + A.printMatrix(true); + + std::vector val2{0.5, 0.6, 0.7, 0.8, 1.0}; + std::vector x2{0,2,0,2,1}; + std::vector y2{3,3,2,2,3}; + COO_Matrix B = COO_Matrix(x2,y2,val2,m,n); + + std::cout << "B:\n"; + B.printMatrix(true); + + A.AXPY(2.0, &B); + + std::cout << "A + 2B:\n"; + A.printMatrix(true); + + + return 0; +} diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp index 72abb858b..ade61feff 100644 --- a/ModelEvaluatorImpl.hpp +++ b/ModelEvaluatorImpl.hpp @@ -62,6 +62,7 @@ #include #include +#include namespace ModelLib { @@ -90,16 +91,16 @@ namespace ModelLib yp_(size_), f_(size_), g_(size_quad_), - J_(size_quad^2), - M_(size_quad^2), yB_(size_), ypB_(size_), fB_(size_), gB_(size_opt_), + J_(COO_Matrix()), param_(size_opt_), param_up_(size_opt_), param_lo_(size_opt_) - {} + { + } virtual IdxT size() { @@ -224,6 +225,16 @@ namespace ModelLib return f_; } + COO_Matrix& getJacobian() + { + return J_; + } + + const COO_Matrix& getJacobian() const + { + return J_; + } + std::vector& getIntegrand() { return g_; @@ -279,8 +290,7 @@ namespace ModelLib std::vector fB_; std::vector gB_; - std::vector J_; - std::vector M_; + COO_Matrix J_; std::vector param_; std::vector param_up_; diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp index 7a9304716..018ceaeaf 100644 --- a/PowerElectronicsModel.hpp +++ b/PowerElectronicsModel.hpp @@ -34,6 +34,7 @@ class PowerElectronicsModel : public ModelEvaluatorImpl // using ModelEvaluatorImpl::fB_; // using ModelEvaluatorImpl::g_; // using ModelEvaluatorImpl::gB_; + using ModelEvaluatorImpl::J_; using ModelEvaluatorImpl::rtol_; using ModelEvaluatorImpl::atol_; // using ModelEvaluatorImpl::param_; @@ -153,6 +154,11 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 0; } + /** + * @brief Creates the Sparse COO Jacobian representing \alpha dF/dy' + dF/dy + * + * @return int + */ int evaluateJacobian() { return 0; diff --git a/SparseMatrix/CMakeLists.txt b/SparseMatrix/CMakeLists.txt new file mode 100644 index 000000000..b51d669ec --- /dev/null +++ b/SparseMatrix/CMakeLists.txt @@ -0,0 +1,7 @@ + +add_library(SparseMatrix INTERFACE) +include_directories(SparseMatrix INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +add_library(GRIDKIT::SparseMatrix ALIAS SparseMatrix) + + diff --git a/SparseMatrix/COO_Matrix.hpp b/SparseMatrix/COO_Matrix.hpp new file mode 100644 index 000000000..e4b087386 --- /dev/null +++ b/SparseMatrix/COO_Matrix.hpp @@ -0,0 +1,515 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief Quick class to provide sparse matrices of COO type. Simplifies data movement + * @todo Add base class of sparse matrix for conversion to CSR + * @todo Switch Push back with buffer allocation for resizing + * @todo NonZero Values for preallocation + * @todo Fix warnings, mostly type casting of indexes. Should try to move to iterator somehow + * + * m x n sparse matrix + */ +template +class COO_Matrix +{ +private: + std::vector values; + std::vector row_indexes; + std::vector column_indexes; + Intdx rows_size; + Intdx columns_size; + bool sorted; +public: + COO_Matrix(std::vector r, std::vector c, std::vector v, Intdx m, Intdx n); + COO_Matrix(Intdx m, Intdx n); + COO_Matrix(); + ~COO_Matrix(); + + //could replace with binary operation for both + // --- Functions which donot sort --- + void setValues(std::vector r, std::vector c, std::vector val); + void addValues(std::vector r, std::vector c, std::vector val); + + // --- Functions which call sort --- + std::tuple, std::vector> getRowCopy(Intdx r); + std::tuple, std::vector, std::vector> getEntries(); + + // BLAS. Will sort before running + void AXPY(ScalarT alpha, COO_Matrix* a); + + // --- Permutation Operations --- + //No sorting is actually done. Only done when nesscary + void permutation(std::vector row_perm, std::vector col_perm); + void permutationSizeMap(std::vector row_perm, std::vector col_perm, Intdx m, Intdx n); + + //Resort values + void sortSparse(); + bool isSorted(); + + std::tuple getDimensions(); + + void printMatrix(bool sort); + +private: + std::vector indexEntries(std::vector r, std::vector c); + Intdx indexStartRow(Intdx r); +}; + +/** + * @brief Set values of sparse matrix. Increases size if outside bounds + * + * @todo should error return if outside bounds instead? + * + * @tparam ScalarT + * @tparam Intdx + * @param r + * @param c + * @param val + */ +template +inline void COO_Matrix::setValues(std::vector r, std::vector c, std::vector val) +{ + std::vector indexes = this->indexEntries(r,c); + + for (int i = 0; i < indexes.size(); i++) + { + if (indexes[i] == -1) + { + if (r[i] >= this->rows_size) + { + this->rows_size = r[i]; + } + if (c[i] >= this->columns_size) + { + this->columns_size = c[i]; + } + + this->row_indexes.push_back(r[i]); + this->column_indexes.push_back(c[i]); + this->values.push_back(val[i]); + this->sorted = false; + } + else + { + this->values[indexes[i]] = val[i]; + } + } + +} + +/** + * @brief Add new values to sparse matrix. Will increase size if outside bounds + * + * @todo should error return if outside bounds instead? + * + * @tparam ScalarT + * @tparam Intdx + * @param r + * @param c + * @param val + */ +template +inline void COO_Matrix::addValues(std::vector r, std::vector c, std::vector val) +{ + std::vector indexes = this->indexEntries(r,c); + + for (int i = 0; i < indexes.size(); i++) + { + if (indexes[i] == -1) + { + if (r[i] >= this->rows_size) + { + this->rows_size = r[i]; + } + if (c[i] >= this->columns_size) + { + this->columns_size = c[i]; + } + + this->row_indexes.push_back(r[i]); + this->column_indexes.push_back(c[i]); + this->values.push_back(val[i]); + this->sorted = false; + } + else + { + this->values[indexes[i]] += val[i]; + } + } + +} + +/** + * @brief Get copy of row values + * + * @tparam ScalarT + * @tparam Intdx + * @param r + * @return std::tuple, std::vector> + */ +template +inline std::tuple, std::vector> COO_Matrix::getRowCopy(Intdx r) +{ + if (!this->sorted) + { + this->sortSparse(); + } + Intdx rowindex = this->indexStartRow(r); + + + if (rowindex == -1) + { + return {std::vector(),std::vector()}; + } + + Intdx rsize = rowindex; + do + { + rsize++; + } while (rsize < this->values.size() && this->row_indexes[rsize] == r); + + return {{this->column_indexes.begin() + rowindex, this->column_indexes.begin() + rsize},{this->values.begin() + rowindex, this->values.begin() + rsize}}; +} + +/** + * @brief Get all Entries + * + * @tparam ScalarT + * @tparam Intdx + * @return std::tuple, std::vector, std::vector> + */ +template +inline std::tuple, std::vector, std::vector> COO_Matrix::getEntries() +{ + if (!this->sorted) + { + this->sortSparse(); + } + return {this->row_indexes, this->column_indexes, this->values}; +} + +template +inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrix *a) +{ + if (alpha == 0) return; + + if (!this->sorted) + { + this->sortSparse(); + } + if (!a->isSorted()) + { + a->sortSparse(); + } + std::vector val; + std::vector r; + std::vector c; + Intdx m = 0; + Intdx n = 0; + std::tie(r,c,val) = a->getEntries(); + std::tie(m,n) = a->getDimensions(); + + this->rows_size = this->rows_size > m ? this->rows_size : m; + this->columns_size = this->columns_size > n ? this->columns_size : n; + + Intdx aiter = 0; + //iterate for all current values in matrix + for (Intdx i = 0; i < static_cast(this->row_indexes.size()); i++) + { + //pushback values when they are not in current matrix + while(aiter < static_cast(r.size()) && (r[aiter] < this->row_indexes[i] || (r[aiter] == this->row_indexes[i] && c[aiter] < this->column_indexes[i]))) + { + this->row_indexes.push_back(r[aiter]); + this->column_indexes.push_back(c[aiter]); + this->values.push_back(alpha * val[aiter]); + aiter++; + } + if (aiter >= r.size()) break; + + + if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) + { + this->values[i] += alpha * val[aiter]; + aiter++; + } + } + //push back rest that was not found sorted + for (Intdx i = aiter; i < static_cast(r.size()); i++) + { + this->row_indexes.push_back(r[i]); + this->column_indexes.push_back(c[i]); + this->values.push_back(alpha * val[i]); + } + + this->sorted = false; +} + +/** + * @brief Permutate the matrix to a different one. Only changes the coordinates + * + * @tparam ScalarT + * @tparam Intdx + * @param row_perm + * @param col_perm + */ +template +inline void COO_Matrix::permutation(std::vector row_perm, std::vector col_perm) +{ + assert(row_perm.size() = this->rows_size); + assert(col_perm.size() = this->columns_size); + + for (int i = 0; i < this->values.size(); i++) + { + this->row_indexes[i] = row_perm[this->row_indexes[i]]; + this->column_indexes[i] = col_perm[this->column_indexes[i]]; + } + this->sorted = false; +} + +/** + * @brief Permutates the matrix and can change its size efficently + * if size is shrinking and value is to be removed the negative one + * + * @tparam ScalarT + * @tparam Intdx + * @param row_perm size of m + * @param col_perm size of n + * @param m + * @param n + */ +template +inline void COO_Matrix::permutationSizeMap(std::vector row_perm, std::vector col_perm, Intdx m, Intdx n) +{ + assert(row_perm.size() == this->rows_size); + assert(col_perm.size() == this->columns_size); + + this->rows_size = m; + this->columns_size = n; + + for (int i = 0; i < this->values.size(); i++) + { + if (row_perm[this->row_indexes[i]] == -1 || col_perm[this->column_indexes[i]] == -1) + { + this->values[i] = 0; + } + else + { + this->row_indexes[i] = row_perm[this->row_indexes[i]]; + this->column_indexes[i] = col_perm[this->column_indexes[i]]; + } + } + this->sorted = false; +} + +/** + * @brief Restructure the sparse matrix for faster accesses and modifications + * + * @tparam ScalarT + * @tparam Intdx + */ +template +inline void COO_Matrix::sortSparse() +{ + //index based sort code + // https://stackoverflow.com/questions/25921706/creating-a-vector-of-indices-of-a-sorted-vector + + + //cannot call sort since two arrays are used instead + std::vector ordervec(this->row_indexes.size()); + std::size_t n(0); + std::generate(std::begin(ordervec), std::end(ordervec), [&]{ return n++; }); + + std::sort( std::begin(ordervec), + std::end(ordervec), + [&](int i1, int i2) { return this->row_indexes[i1] < this->row_indexes[i2] || + (this->row_indexes[i1] == this->row_indexes[i2] && this->column_indexes[i1] < this->column_indexes[i2]); } ); + + + //reorder based of index-sorting. Only swap no extra memory + // https://stackoverflow.com/a/22183350 + for (size_t i = 0; i < ordervec.size(); i++) + { + //permutation swap + while (ordervec[i] != ordervec[ordervec[i]]) + { + std::swap(this->row_indexes[ordervec[i]], this->row_indexes[ordervec[ordervec[i]]]); + std::swap(this->column_indexes[ordervec[i]], this->column_indexes[ordervec[ordervec[i]]]); + std::swap(this->values[ordervec[i]], this->values[ordervec[ordervec[i]]]); + + //swap orderings + std::swap(ordervec[i], ordervec[ordervec[i]]); + } + + } + this->sorted = true; +} + +template +inline bool COO_Matrix::isSorted() +{ + return this->sorted; +} + +template +inline std::tuple COO_Matrix::getDimensions() +{ + return std::tuple(this->rows_size, this->columns_size); +} + +template +inline void COO_Matrix::printMatrix(bool sort) +{ + if (sort == true && this->sorted == false) + { + this->sortSparse(); + } + + std::cout << "Sparse COO Matrix\n"; + std::cout << "(x , y, value)\n"; + for (size_t i = 0; i < this->values.size(); i++) + { + std::cout << "(" << this->row_indexes[i] + << ", " << this->column_indexes[i] + << ", " << this->values[i] << ")\n"; + } +} + +/** + * @brief Given vector indexes return the entries + * + * @tparam ScalarT + * @tparam Intdx + * @param r + * @param c + * @return std::vector + */ +template +inline std::vector COO_Matrix::indexEntries(std::vector r, std::vector c) +{ + assert(r.size() == c.size()); + std::vector valsnew(r.size(), -1); + + //cannot assume input is sorted so linear + Intdx aiter = 0; + //should fix this + for (Intdx i = 0; i < this->row_indexes.size(); i++) + { + while(r[aiter] < this->row_indexes[i] || (r[aiter] == this->row_indexes[i] && c[aiter] < this->column_indexes[i])) + { + valsnew.push_back(-1); + aiter++; + } + + if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) + { + valsnew.push_back(i); + aiter++; + } + + } + return valsnew; + +} + +/** + * @brief Given row index get start. If no start returns -1 + * + * @tparam ScalarT + * @tparam Intdx + * @param r + * @return Intdx + */ +template +inline Intdx COO_Matrix::indexStartRow(Intdx r) +{ + if (this->sorted) + { + //basic binary search + Intdx i1 = 0; + Intdx i2 = this->row_indexes.size()-1; + Intdx m = 0; + while (i1 <= i2) + { + m = (i2 + i1) / 2; + //rows + if (this->row_indexes[m] < r) + { + i1 = m + 1; + } + else if (r < this->row_indexes[m]) + { + i2 = m - 1; + } + else + { + break; + } + } + //drop to first index + while (this->row_indexes[m] == r) + { + m--; + } + return m; + + } + else + { + for (int i = 0; i < this->row_indexes.size(); i++) + { + if (this->row_indexes[i] == r) + { + return i; + } + } + } + return -1; +} + +template +inline COO_Matrix::COO_Matrix(std::vector r, std::vector c, std::vector v, Intdx m, Intdx n) +{ + this->values = v; + this->row_indexes = r; + this->column_indexes = c; + this->rows_size = m; + this->columns_size = n; + this->sorted = false; +} + +template +inline COO_Matrix::COO_Matrix(Intdx m, Intdx n) +{ + this->rows_size = m; + this->columns_size = n; + this->values = std::vector(); + this->row_indexes = std::vector(); + this->column_indexes = std::vector(); + this->sorted = false; +} + +template +inline COO_Matrix::COO_Matrix() +{ + this->rows_size = 0; + this->columns_size = 0; + this->values = std::vector(); + this->row_indexes = std::vector(); + this->column_indexes = std::vector(); + this->sorted = false; +} + +template +COO_Matrix::~COO_Matrix() +{ + +} From f4b209ad4c53a86778de30de4dd7674d0e19bd19 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 20 Nov 2023 17:21:22 -0500 Subject: [PATCH 17/52] Added Jacobian Assembly. Fixed and Added New Functionality to COO Matrices +Matrix Assembly +Refactored COO Matrix +COO can return CSR Data format --- .../Capacitor/Capacitor.cpp | 2 +- .../DiscreteGenerator/DiscreteGenerator.cpp | 2 +- .../Inductor/Inductor.cpp | 2 +- Examples/RLCircuit/RLCircuit.cpp | 9 +- Examples/SparseTest/SparseTest.cpp | 49 +- PowerElectronicsModel.hpp | 65 ++- SparseMatrix/COO_Matrix.hpp | 521 +++++++++++------- 7 files changed, 436 insertions(+), 214 deletions(-) diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp index ecbe9d51f..79faefe89 100644 --- a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp @@ -91,7 +91,7 @@ int Capacitor::evaluateJacobian() COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); //Perform dF/dy + \alpha dF/dy' - this->J_.AXPY(this->alpha_, &Jacder); + this->J_.AXPY(this->alpha_, Jacder); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp index 7770281d1..c66c5b0f9 100644 --- a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp @@ -237,7 +237,7 @@ int DiscreteGenerator::evaluateJacobian() //Perform dF/dy + \alpha dF/dy' - this->J_.AXPY(-this->alpha_, &Jacder); + this->J_.AXPY(-this->alpha_, Jacder); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp index 89f903436..b0b19e63b 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -93,7 +93,7 @@ int Inductor::evaluateJacobian() COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); //Perform dF/dy + \alpha dF/dy' - this->J_.AXPY(this->alpha_, &Jacder); + this->J_.AXPY(this->alpha_, Jacder); return 0; } diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index 4669d564e..124b50bc0 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -80,9 +80,12 @@ int main(int argc, char const *argv[]) } std::cout << "}\n"; - induct->updateTime(0.0, 1.0); - induct->evaluateJacobian(); - induct->getJacobian().printMatrix(true); + + sysmodel->updateTime(0.0, 1.0); + sysmodel->evaluateJacobian(); + sysmodel->getJacobian().printMatrix(); + + return 0; diff --git a/Examples/SparseTest/SparseTest.cpp b/Examples/SparseTest/SparseTest.cpp index 976759533..81e5ac7dd 100644 --- a/Examples/SparseTest/SparseTest.cpp +++ b/Examples/SparseTest/SparseTest.cpp @@ -10,9 +10,6 @@ #include - - - int main(int argc, char const *argv[]) { std::vector val{0.1, 0.2, 0.3, 0.4}; @@ -35,7 +32,7 @@ int main(int argc, char const *argv[]) } std::cout << "A:\n"; - A.printMatrix(true); + A.printMatrix(); std::vector val2{0.5, 0.6, 0.7, 0.8, 1.0}; std::vector x2{0,2,0,2,1}; @@ -43,13 +40,47 @@ int main(int argc, char const *argv[]) COO_Matrix B = COO_Matrix(x2,y2,val2,m,n); std::cout << "B:\n"; - B.printMatrix(true); + B.printMatrix(); - A.AXPY(2.0, &B); + A.AXPY(2.0, B); std::cout << "A + 2B:\n"; - A.printMatrix(true); - + A.printMatrix(); + + std::vector r; + std::vector c; + std::vector v; + std::tie(r,c,v) = A.getDataToCSR(); + + for (size_t i = 0; i < r.size() - 1; i++) + { + std::cout << r[i] << std::endl; + size_t rdiff = r[i+1] - r[i]; + for (size_t j = 0; j < rdiff; j++) + { + std::cout << c[j + r[i]] << ", " << v[j + r[i]] << std::endl; + } + } + std::cout << r[r.size()-1] << std::endl; + + //Basic Verification test + std::vector rtest = {0, 2, 4, 7, 8}; + std::vector ctest = {2,3,2,3,1,2,3,2}; + std::vector valtest = {1.4, 1.0, 0.4, 2.2, 0.1, 1.6, 1.2, 0.3}; + + assert(rtest.size() == r.size()); + assert(ctest.size() == c.size()); + assert(valtest.size() == v.size()); + + int failval = 0; + for (size_t i = 0; i < rtest.size(); i++) if (r[i] != rtest[i]) failval--; + for (size_t i = 0; i < ctest.size(); i++) + { + double vdiff = v[i] - valtest[i]; + if (c[i] != ctest[i] || -1e-14 > vdiff || vdiff > 1e-14) failval--; + } - return 0; + std::cout << failval << std::endl; + + return failval; } diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp index 018ceaeaf..bad48ecf0 100644 --- a/PowerElectronicsModel.hpp +++ b/PowerElectronicsModel.hpp @@ -23,8 +23,8 @@ class PowerElectronicsModel : public ModelEvaluatorImpl // using ModelEvaluatorImpl::size_quad_; // using ModelEvaluatorImpl::size_opt_; using ModelEvaluatorImpl::nnz_; - // using ModelEvaluatorImpl::time_; - // using ModelEvaluatorImpl::alpha_; + using ModelEvaluatorImpl::time_; + using ModelEvaluatorImpl::alpha_; using ModelEvaluatorImpl::y_; using ModelEvaluatorImpl::yp_; // using ModelEvaluatorImpl::yB_; @@ -98,6 +98,11 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 0; } + /** + * @brief Set intial y and y' of each component + * + * @return int + */ int initialize() { @@ -106,7 +111,18 @@ class PowerElectronicsModel : public ModelEvaluatorImpl { component->initialize(); } + this->distributeVectors(); + + return 0; + } + /** + * @brief Distribute y and y' to each component based of node connection graph + * + * @return int + */ + int distributeVectors() + { for(const auto& component : components_) { for(IdxT j=0; jsize(); ++j) @@ -123,6 +139,11 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 0; } + /** + * @brief Evaluate Residuals at each component then collect them + * + * @return int + */ int evaluateResidual() { for (IdxT i = 0; i < this->f_.size(); i++) @@ -130,16 +151,7 @@ class PowerElectronicsModel : public ModelEvaluatorImpl f_[i] = 0; } - // Update variables - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - component->y()[j] = y_[component->getNodeConnection(j)]; - component->yp()[j] = yp_[component->getNodeConnection(j)]; - } - component->evaluateResidual(); - } + this->distributeVectors(); // Update system residual vector @@ -161,6 +173,25 @@ class PowerElectronicsModel : public ModelEvaluatorImpl */ int evaluateJacobian() { + this->J_.zeroMatrix(); + this->distributeVectors(); + + //Evaluate component jacs + for(const auto& component : components_) + { + component->evaluateJacobian(); + std::vector r; + std::vector c; + std::vector v; + std::tie(r, c, v) = component->getJacobian().getEntrieCopies(); + for (IdxT i = 0; i < static_cast(r.size()); i++) + { + r[i] = component->getNodeConnection(r[i]); + c[i] = component->getNodeConnection(c[i]); + } + this->J_.AXPY(1.0, r, c, v); + } + return 0; } @@ -205,8 +236,18 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 0; } + /** + * @brief Distribute time and time scaling for each component + * + * @param t + * @param a + */ void updateTime(ScalarT t, ScalarT a) { + for(const auto& component : components_) + { + component->updateTime(t, a); + } } void addComponent(component_type* component) diff --git a/SparseMatrix/COO_Matrix.hpp b/SparseMatrix/COO_Matrix.hpp index e4b087386..5b0ece80c 100644 --- a/SparseMatrix/COO_Matrix.hpp +++ b/SparseMatrix/COO_Matrix.hpp @@ -11,10 +11,8 @@ /** * @brief Quick class to provide sparse matrices of COO type. Simplifies data movement - * @todo Add base class of sparse matrix for conversion to CSR - * @todo Switch Push back with buffer allocation for resizing - * @todo NonZero Values for preallocation - * @todo Fix warnings, mostly type casting of indexes. Should try to move to iterator somehow + * + * @todo add functionality to keep track of multiple sorted list. Faster adding of new entries and will have a threshold to sort completely. * * m x n sparse matrix */ @@ -29,176 +27,203 @@ class COO_Matrix Intdx columns_size; bool sorted; public: + //Constructors COO_Matrix(std::vector r, std::vector c, std::vector v, Intdx m, Intdx n); COO_Matrix(Intdx m, Intdx n); COO_Matrix(); ~COO_Matrix(); - //could replace with binary operation for both - // --- Functions which donot sort --- - void setValues(std::vector r, std::vector c, std::vector val); - void addValues(std::vector r, std::vector c, std::vector val); + + //Operations // --- Functions which call sort --- std::tuple, std::vector> getRowCopy(Intdx r); - std::tuple, std::vector, std::vector> getEntries(); + std::tuple&, std::vector&, std::vector&> getEntries(); + std::tuple, std::vector, std::vector> getEntrieCopies(); + + std::tuple, std::vector, std::vector> getDataToCSR(); // BLAS. Will sort before running - void AXPY(ScalarT alpha, COO_Matrix* a); + void setValues(std::vector r, std::vector c, std::vector v); + void AXPY(ScalarT alpha, COO_Matrix& a); + void AXPY(ScalarT alpha, std::vector r, std::vector c, std::vector v); + void SCAL(ScalarT alpha); // --- Permutation Operations --- //No sorting is actually done. Only done when nesscary void permutation(std::vector row_perm, std::vector col_perm); void permutationSizeMap(std::vector row_perm, std::vector col_perm, Intdx m, Intdx n); + void zeroMatrix(); + + void identityMatrix(Intdx n); + //Resort values void sortSparse(); bool isSorted(); std::tuple getDimensions(); - void printMatrix(bool sort); + void printMatrix(); private: - std::vector indexEntries(std::vector r, std::vector c); - Intdx indexStartRow(Intdx r); + Intdx indexStartRow(const std::vector &rows, Intdx r); + Intdx sparseCordBinarySearch(const std::vector &rows, const std::vector &columns, Intdx ri, Intdx ci); + void sortSparseCOO(std::vector &rows, std::vector &columns, std::vector &values); + }; /** - * @brief Set values of sparse matrix. Increases size if outside bounds - * - * @todo should error return if outside bounds instead? + * @brief Get copy of row values * * @tparam ScalarT * @tparam Intdx * @param r - * @param c - * @param val + * @return std::tuple, std::vector> */ template -inline void COO_Matrix::setValues(std::vector r, std::vector c, std::vector val) +inline std::tuple, std::vector> COO_Matrix::getRowCopy(Intdx r) { - std::vector indexes = this->indexEntries(r,c); + if (!this->sorted) + { + this->sortSparse(); + } + Intdx rowindex = this->indexStartRow(r); + - for (int i = 0; i < indexes.size(); i++) + if (rowindex == -1) { - if (indexes[i] == -1) - { - if (r[i] >= this->rows_size) - { - this->rows_size = r[i]; - } - if (c[i] >= this->columns_size) - { - this->columns_size = c[i]; - } - - this->row_indexes.push_back(r[i]); - this->column_indexes.push_back(c[i]); - this->values.push_back(val[i]); - this->sorted = false; - } - else - { - this->values[indexes[i]] = val[i]; - } + return {std::vector(),std::vector()}; } + + Intdx rsize = rowindex; + do + { + rsize++; + } while (rsize < this->values.size() && this->row_indexes[rsize] == r); + return {{this->column_indexes.begin() + rowindex, this->column_indexes.begin() + rsize},{this->values.begin() + rowindex, this->values.begin() + rsize}}; } /** - * @brief Add new values to sparse matrix. Will increase size if outside bounds - * - * @todo should error return if outside bounds instead? + * @brief Get all Entries pointers. Will sort before returnings * * @tparam ScalarT * @tparam Intdx - * @param r - * @param c - * @param val + * @return std::tuple, std::vector, std::vector> */ template -inline void COO_Matrix::addValues(std::vector r, std::vector c, std::vector val) +inline std::tuple&, std::vector&, std::vector&> COO_Matrix::getEntries() { - std::vector indexes = this->indexEntries(r,c); - - for (int i = 0; i < indexes.size(); i++) + if (!this->sorted) { - if (indexes[i] == -1) - { - if (r[i] >= this->rows_size) - { - this->rows_size = r[i]; - } - if (c[i] >= this->columns_size) - { - this->columns_size = c[i]; - } - - this->row_indexes.push_back(r[i]); - this->column_indexes.push_back(c[i]); - this->values.push_back(val[i]); - this->sorted = false; - } - else - { - this->values[indexes[i]] += val[i]; - } + this->sortSparse(); } - + return {this->row_indexes, this->column_indexes, this->values}; } /** - * @brief Get copy of row values + * @brief Get copies of the data. Sorted before returning * * @tparam ScalarT * @tparam Intdx - * @param r - * @return std::tuple, std::vector> + * @return std::tuple, std::vector, std::vector> */ template -inline std::tuple, std::vector> COO_Matrix::getRowCopy(Intdx r) +inline std::tuple, std::vector, std::vector> COO_Matrix::getEntrieCopies() { if (!this->sorted) { this->sortSparse(); } - Intdx rowindex = this->indexStartRow(r); - + return {this->row_indexes, this->column_indexes, this->values}; +} - if (rowindex == -1) +/** + * @brief Returns the data into CSR Format + * + * @tparam ScalarT + * @tparam Intdx + * @return std::tuple, std::vector, std::vector> + */ +template +inline std::tuple, std::vector, std::vector> COO_Matrix::getDataToCSR() +{ + if (!this->isSorted()) this->sortSparse(); + std::vector rowsizevec(this->rows_size + 1, 0); + Intdx counter = 0; + for (Intdx i = 0; i < static_cast(rowsizevec.size() - 1); i++) { - return {std::vector(),std::vector()}; + rowsizevec[i + 1] = rowsizevec[i]; + while (counter < static_cast(this->row_indexes.size()) && i == this->row_indexes[counter]) + { + rowsizevec[i+1]++; + counter++; + } } - - Intdx rsize = rowindex; - do - { - rsize++; - } while (rsize < this->values.size() && this->row_indexes[rsize] == r); - - return {{this->column_indexes.begin() + rowindex, this->column_indexes.begin() + rsize},{this->values.begin() + rowindex, this->values.begin() + rsize}}; + return {rowsizevec, this->column_indexes, this->values}; } /** - * @brief Get all Entries + * @brief Given set of vector data it will set the values into the matrix * * @tparam ScalarT * @tparam Intdx - * @return std::tuple, std::vector, std::vector> + * @param r + * @param c + * @param v */ template -inline std::tuple, std::vector, std::vector> COO_Matrix::getEntries() +inline void COO_Matrix::setValues(std::vector r, std::vector c, std::vector v) { - if (!this->sorted) + //sort input + this->sortSparseCOO(r, c, v); + + + //Duplicated with AXPY. Could replace with function depdent on lambda expression + Intdx aiter = 0; + //iterate for all current values in matrix + for (Intdx i = 0; i < static_cast(this->row_indexes.size()); i++) { - this->sortSparse(); + //pushback values when they are not in current matrix + while(aiter < static_cast(r.size()) && (r[aiter] < this->row_indexes[i] || (r[aiter] == this->row_indexes[i] && c[aiter] < this->column_indexes[i]))) + { + this->row_indexes.push_back(r[aiter]); + this->column_indexes.push_back(c[aiter]); + this->values.push_back(v[aiter]); + aiter++; + } + if (aiter >= static_cast(r.size())) break; + + + if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) + { + this->values[i] = v[aiter]; + aiter++; + } } - return {this->row_indexes, this->column_indexes, this->values}; + //push back rest that was not found sorted + for (Intdx i = aiter; i < static_cast(r.size()); i++) + { + this->row_indexes.push_back(r[i]); + this->column_indexes.push_back(c[i]); + this->values.push_back(v[i]); + } + + this->sorted = false; + } +/** + * @brief BLAS AXPY operation on another COO matrix. Will sort both matrices before acting + * + * @tparam ScalarT + * @tparam Intdx + * @param alpha + * @param a + */ template -inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrix *a) +inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrix& a) { if (alpha == 0) return; @@ -206,18 +231,17 @@ inline void COO_Matrix::AXPY(ScalarT alpha, COO_MatrixsortSparse(); } - if (!a->isSorted()) + if (!a.isSorted()) { - a->sortSparse(); + a.sortSparse(); } - std::vector val; - std::vector r; - std::vector c; Intdx m = 0; Intdx n = 0; - std::tie(r,c,val) = a->getEntries(); - std::tie(m,n) = a->getDimensions(); + std::tuple&, std::vector&, std::vector&> tpm = a.getEntries(); + const auto& [r, c, val] = tpm; + std::tie(m,n) = a.getDimensions(); + //Increase size as nesscary this->rows_size = this->rows_size > m ? this->rows_size : m; this->columns_size = this->columns_size > n ? this->columns_size : n; @@ -233,7 +257,7 @@ inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrixvalues.push_back(alpha * val[aiter]); aiter++; } - if (aiter >= r.size()) break; + if (aiter >= static_cast(r.size())) break; if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) @@ -253,6 +277,74 @@ inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrixsorted = false; } +/** + * @brief AXPY on 3list. + * + * @tparam ScalarT + * @tparam Intdx + * @param alpha + * @param r + * @param c + * @param v + */ +template +inline void COO_Matrix::AXPY(ScalarT alpha, std::vector r, std::vector c, std::vector v) +{ + if (alpha == 0) return; + + if (!this->sorted) + { + this->sortSparse(); + } + + //sort input + this->sortSparseCOO(r, c, v); + + Intdx aiter = 0; + //iterate for all current values in matrix + for (Intdx i = 0; i < static_cast(this->row_indexes.size()); i++) + { + //pushback values when they are not in current matrix + while(aiter < static_cast(r.size()) && (r[aiter] < this->row_indexes[i] || (r[aiter] == this->row_indexes[i] && c[aiter] < this->column_indexes[i]))) + { + this->row_indexes.push_back(r[aiter]); + this->column_indexes.push_back(c[aiter]); + this->values.push_back(alpha * v[aiter]); + aiter++; + } + if (aiter >= static_cast(r.size())) break; + + + if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) + { + this->values[i] += alpha * v[aiter]; + aiter++; + } + } + //push back rest that was not found sorted + for (Intdx i = aiter; i < static_cast(r.size()); i++) + { + this->row_indexes.push_back(r[i]); + this->column_indexes.push_back(c[i]); + this->values.push_back(alpha * v[i]); + } + + this->sorted = false; +} + +/** + * @brief Scale all values + * + * @tparam ScalarT + * @tparam Intdx + * @param alpha + */ +template +inline void COO_Matrix::SCAL(ScalarT alpha) +{ + for (auto i = this->values.begin(); i < this->values.end(); i++) *i *= alpha; +} + /** * @brief Permutate the matrix to a different one. Only changes the coordinates * @@ -273,6 +365,7 @@ inline void COO_Matrix::permutation(std::vector row_perm, this->column_indexes[i] = col_perm[this->column_indexes[i]]; } this->sorted = false; + //cycle sorting maybe useful since permutations are already known } /** @@ -311,48 +404,48 @@ inline void COO_Matrix::permutationSizeMap(std::vector ro } /** - * @brief Restructure the sparse matrix for faster accesses and modifications + * @brief Turn matrix into the zero matrix. Does not actual delete memory * * @tparam ScalarT * @tparam Intdx */ template -inline void COO_Matrix::sortSparse() +inline void COO_Matrix::zeroMatrix() { - //index based sort code - // https://stackoverflow.com/questions/25921706/creating-a-vector-of-indices-of-a-sorted-vector - - - //cannot call sort since two arrays are used instead - std::vector ordervec(this->row_indexes.size()); - std::size_t n(0); - std::generate(std::begin(ordervec), std::end(ordervec), [&]{ return n++; }); - - std::sort( std::begin(ordervec), - std::end(ordervec), - [&](int i1, int i2) { return this->row_indexes[i1] < this->row_indexes[i2] || - (this->row_indexes[i1] == this->row_indexes[i2] && this->column_indexes[i1] < this->column_indexes[i2]); } ); - + //resize doesn't effect capacity if smaller + this->column_indexes.resize(0); + this->row_indexes.resize(0); + this->values.resize(0); + this->sorted = true; +} - //reorder based of index-sorting. Only swap no extra memory - // https://stackoverflow.com/a/22183350 - for (size_t i = 0; i < ordervec.size(); i++) +template +inline void COO_Matrix::identityMatrix(Intdx n) +{ + //Reset Matrix + this->zeroMatrix(); + for (Intdx i = 0; i < n; i++) { - //permutation swap - while (ordervec[i] != ordervec[ordervec[i]]) - { - std::swap(this->row_indexes[ordervec[i]], this->row_indexes[ordervec[ordervec[i]]]); - std::swap(this->column_indexes[ordervec[i]], this->column_indexes[ordervec[ordervec[i]]]); - std::swap(this->values[ordervec[i]], this->values[ordervec[ordervec[i]]]); - - //swap orderings - std::swap(ordervec[i], ordervec[ordervec[i]]); - } - + this->column_indexes[i] = i; + this->row_indexes[i] = i; + this->values[i] = 1.0; } this->sorted = true; } +/** + * @brief Restructure the sparse matrix for faster accesses and modifications + * + * @tparam ScalarT + * @tparam Intdx + */ +template +inline void COO_Matrix::sortSparse() +{ + this->sortSparseCOO(this->row_indexes, this->column_indexes, this->values); + this->sorted = true; +} + template inline bool COO_Matrix::isSorted() { @@ -365,10 +458,16 @@ inline std::tuple COO_Matrix::getDimensions() return std::tuple(this->rows_size, this->columns_size); } +/** + * @brief Print matrix that is sorted + * + * @tparam ScalarT + * @tparam Intdx + */ template -inline void COO_Matrix::printMatrix(bool sort) +inline void COO_Matrix::printMatrix() { - if (sort == true && this->sorted == false) + if (this->sorted == false) { this->sortSparse(); } @@ -384,95 +483,143 @@ inline void COO_Matrix::printMatrix(bool sort) } /** - * @brief Given vector indexes return the entries + * @brief Find the lowest row cordinate from set of provided cordinates * + * Assumes rows and columns are sorted * @tparam ScalarT * @tparam Intdx * @param r - * @param c - * @return std::vector + * @return Intdx */ template -inline std::vector COO_Matrix::indexEntries(std::vector r, std::vector c) +inline Intdx COO_Matrix::indexStartRow(const std::vector &rows, Intdx r) { - assert(r.size() == c.size()); - std::vector valsnew(r.size(), -1); - - //cannot assume input is sorted so linear - Intdx aiter = 0; - //should fix this - for (Intdx i = 0; i < this->row_indexes.size(); i++) + //Specialized Binary Search for Lowest Row + Intdx i1 = 0; + Intdx i2 = rows->size()-1; + Intdx m_smallest = -1; + Intdx m = -1; + while (i1 <= i2) { - while(r[aiter] < this->row_indexes[i] || (r[aiter] == this->row_indexes[i] && c[aiter] < this->column_indexes[i])) + m = (i2 + i1) / 2; + //rows + if (rows[m] < r) { - valsnew.push_back(-1); - aiter++; + i1 = m + 1; } - - if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) + else if (r < rows[m]) { - valsnew.push_back(i); - aiter++; + i2 = m - 1; + } + else + { + if (i1 == i2) + { + return m_smallest; + } + + //Keep track of smallest cordinate + m_smallest = m; + i2 = m - 1; } - } - return valsnew; - + return m_smallest; } /** - * @brief Given row index get start. If no start returns -1 + * @brief Basic binary search * * @tparam ScalarT * @tparam Intdx - * @param r + * @param rows + * @param columns + * @param ri + * @param ci * @return Intdx */ template -inline Intdx COO_Matrix::indexStartRow(Intdx r) +inline Intdx COO_Matrix::sparseCordBinarySearch(const std::vector &rows, const std::vector &columns, Intdx ri, Intdx ci) { - if (this->sorted) + assert(rows.size() == columns.size()); + //basic binary search + Intdx i1 = 0; + Intdx i2 = rows.size()-1; + Intdx m = 0; + while (i1 <= i2) { - //basic binary search - Intdx i1 = 0; - Intdx i2 = this->row_indexes.size()-1; - Intdx m = 0; - while (i1 <= i2) + m = (i2 + i1) / 2; + //rows + if (rows[m] < ri) + { + i1 = m + 1; + } + else if (ri < rows[m]) + { + i2 = m - 1; + } + else { - m = (i2 + i1) / 2; - //rows - if (this->row_indexes[m] < r) + if (columns[m] < ci) { i1 = m + 1; } - else if (r < this->row_indexes[m]) + else if (ci < columns[m]) { i2 = m - 1; } - else - { - break; - } + break; } - //drop to first index - while (this->row_indexes[m] == r) - { - m--; - } - return m; - } - else + + return m; +} + +/** + * @brief Sort a disoreded set of values. Assume nothing on order. + * + * @todo simple setup. Should add better sorting since list are pre-sorted + * + * @tparam ScalarT + * @tparam Intdx + * @param rows + * @param columns + * @param values + */ +template +inline void COO_Matrix::sortSparseCOO(std::vector &rows, std::vector &columns, std::vector &values) +{ + + //index based sort code + // https://stackoverflow.com/questions/25921706/creating-a-vector-of-indices-of-a-sorted-vector + //cannot call sort since two arrays are used instead + std::vector ordervec(rows.size()); + std::size_t n(0); + std::generate(std::begin(ordervec), std::end(ordervec), [&]{ return n++; }); + + //Sort by row first then column. + std::sort( std::begin(ordervec), + std::end(ordervec), + [&](int i1, int i2) { return (rows[i1] < rows[i2]) || + (rows[i1] == rows[i2] && columns[i1] < columns[i2]); } ); + + + //reorder based of index-sorting. Only swap cost no extra memory. + // @todo see if extra memory creation is fine + // https://stackoverflow.com/a/22183350 + for (size_t i = 0; i < ordervec.size(); i++) { - for (int i = 0; i < this->row_indexes.size(); i++) + //permutation swap + while (ordervec[i] != ordervec[ordervec[i]]) { - if (this->row_indexes[i] == r) - { - return i; - } + std::swap(rows[ordervec[i]], rows[ordervec[ordervec[i]]]); + std::swap(columns[ordervec[i]], columns[ordervec[ordervec[i]]]); + std::swap(values[ordervec[i]], values[ordervec[ordervec[i]]]); + + //swap orderings + std::swap(ordervec[i], ordervec[ordervec[i]]); } + } - return -1; } template From b52d776654748cc9c3a3eb471267ec03d07dd0a2 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Sun, 10 Dec 2023 22:28:24 -0500 Subject: [PATCH 18/52] Jacobian Assembly, IDA + KLU Cmake, RL Circuit + Cmake configurations for Sundials and SuiteSparse + Jacobian Assembly for components + Working RL Circuit example utilizing assembly techniques --- CMake/FindSuiteSparse.cmake | 5 +- CMakeLists.txt | 4 +- .../CircuitComponent.hpp | 2 + .../Inductor/Inductor.cpp | 12 +- .../Resistor/Resistor.cpp | 9 +- .../VoltageSource/VoltageSource.cpp | 8 +- Examples/RLCircuit/CMakeLists.txt | 3 +- Examples/RLCircuit/RLCircuit.cpp | 113 +++++++++++++----- ModelEvaluator.hpp | 16 ++- ModelEvaluatorImpl.hpp | 6 +- PowerElectronicsModel.hpp | 95 ++++++++++++--- Solver/Dynamic/CMakeLists.txt | 5 + Solver/Dynamic/Ida.cpp | 90 +++++++++++--- Solver/Dynamic/Ida.hpp | 7 +- SparseMatrix/COO_Matrix.hpp | 74 +++++++++++- SystemModel.hpp | 11 ++ 16 files changed, 378 insertions(+), 82 deletions(-) diff --git a/CMake/FindSuiteSparse.cmake b/CMake/FindSuiteSparse.cmake index 2d73feb76..5a1026935 100644 --- a/CMake/FindSuiteSparse.cmake +++ b/CMake/FindSuiteSparse.cmake @@ -69,11 +69,11 @@ Author(s): set(SUITESPARSE_MODULES amd colamd - klu) + klu + suitesparseconfig) find_library(SUITESPARSE_LIBRARY NAMES - suitesparseconfig ${SUITESPARSE_MODULES} PATHS ${SUITESPARSE_DIR} $ENV{SUITESPARSE_DIR} ${SUITESPARSE_ROOT_DIR} @@ -97,6 +97,7 @@ find_path(SUITESPARSE_INCLUDE_DIR amd.h colamd.h klu.h + SuiteSparse_config.h PATHS ${SUITESPARSE_DIR} $ENV{SUITESPARSE_DIR} ${SUITESPARSE_ROOT_DIR} ${SUITESPARSE_LIBRARY_DIR}/.. PATH_SUFFIXES diff --git a/CMakeLists.txt b/CMakeLists.txt index ef6cbcf57..badea53a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ option(GRIDKIT_ENABLE_IPOPT "Enable Ipopt support" ON) option(GRIDKIT_ENABLE_SUNDIALS "Enable SUNDIALS support" ON) # Enable KLU -option(GRIDKIT_ENABLE_SUNDIALS_SPARSE "Enable SUNDIALS sparse linear solvers" OFF) +option(GRIDKIT_ENABLE_SUNDIALS_SPARSE "Enable SUNDIALS sparse linear solvers" ON) set(CMAKE_MACOSX_RPATH 1) @@ -110,7 +110,7 @@ endif("${isSystemDir}" STREQUAL "-1") # TODO: Probably beter to set a debug interface target -set(CMAKE_CXX_FLAGS_DEBUG "-Wall -O0 -g") +set(CMAKE_CXX_FLAGS_DEBUG "-Wall -O0 -g -DDEBUG") set(CMAKE_CXX_STANDARD 17) diff --git a/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp index 9e1052e43..fe2efdf96 100644 --- a/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp +++ b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp @@ -27,6 +27,8 @@ namespace ModelLib this->time_ = t; this->alpha_ = a; } + + bool hasJacobian() { return true;} size_t getExternSize() { diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp index b0b19e63b..a24b7a8e9 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -70,26 +70,30 @@ int Inductor::tagDifferentiable() template int Inductor::evaluateResidual() { + //input this->f_[0] = this->y_[2]; + //output this->f_[1] = -this->y_[2]; - this->f_[2] = - this->L_ * this->yp_[2] + this->y_[0] - this->y_[1] ; + //internal + this->f_[2] = this->L_ * this->yp_[2] + this->y_[0] - this->y_[1] ; return 0; } template int Inductor::evaluateJacobian() { - + this->J_.zeroMatrix(); + //Create dF/dy std::vector rcord{0,1,2,2}; std::vector ccord{2,2,0,1}; std::vector vals{1.0, -1.0, 1.0, -1.0}; this->J_.setValues(rcord, ccord, vals); - //Create -dF/dy' + //Create dF/dy' std::vector rcordder{2}; std::vector ccordder{2}; - std::vector valsder{-this->L_}; + std::vector valsder{this->L_}; COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); //Perform dF/dy + \alpha dF/dy' diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp index 7536f2274..45d9a34f3 100644 --- a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp @@ -69,9 +69,10 @@ int Resistor::tagDifferentiable() template int Resistor::evaluateResidual() { - - this->f_[0] = (this->y_[1] - this->y_[0])/this->R_ ; - this->f_[1] = (this->y_[0] - this->y_[1])/this->R_ ; + //input + this->f_[0] = (this->y_[0] - this->y_[1])/this->R_ ; + //ouput + this->f_[1] = (this->y_[1] - this->y_[0])/this->R_ ; return 0; } @@ -83,7 +84,7 @@ int Resistor::evaluateJacobian() //does compiler make constant??? std::vector rcord{0,0,1,1}; std::vector ccord{0,1,0,1}; - std::vector vals{-1.0 / this->R_, 1.0 / this->R_, 1.0 / this->R_, -1.0 / this->R_}; + std::vector vals{1.0 / this->R_, -1.0 / this->R_, -1.0 / this->R_, 1.0 / this->R_}; this->J_.setValues(rcord, ccord, vals); return 0; diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp index b7c18bd6f..c7cb09798 100644 --- a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp @@ -71,20 +71,22 @@ int VoltageSource::evaluateResidual() { //Note this leaves induction lumped into y. Perhaps would be better to seperate volatge and induction into seperate vectors // for easier development + //input this->f_[0] = this->y_[2]; + //ouput this->f_[1] = -this->y_[2]; - this->f_[2] = this->y_[1] - this->y_[0] - this->V_; + //internal + this->f_[2] = -this->y_[1] + this->y_[0] + this->V_; return 0; } template int VoltageSource::evaluateJacobian() { - //Create dF/dy std::vector rcord{0,1,2,2}; std::vector ccord{2,2,0,1}; - std::vector vals{1.0, -1.0, -1.0, 1.0}; + std::vector vals{1.0, -1.0, 1.0, -1.0}; this->J_.setValues(rcord, ccord, vals); return 0; diff --git a/Examples/RLCircuit/CMakeLists.txt b/Examples/RLCircuit/CMakeLists.txt index 5069566bf..476eb5e95 100644 --- a/Examples/RLCircuit/CMakeLists.txt +++ b/Examples/RLCircuit/CMakeLists.txt @@ -6,7 +6,8 @@ add_executable(rlcircuit RLCircuit.cpp) target_link_libraries(rlcircuit GRIDKIT::powerelec_capacitor GRIDKIT::powerelec_inductor GRIDKIT::powerelec_resistor - GRIDKIT::powerelec_voltagesource) + GRIDKIT::powerelec_voltagesource + GRIDKIT::solvers_dyn) add_test(NAME RLCircuit COMMAND $) install(TARGETS rlcircuit RUNTIME DESTINATION bin) diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index 124b50bc0..c71eef06d 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -12,68 +12,89 @@ #include #include +#include +#include int main(int argc, char const *argv[]) { - + double abstol = 1e-8; + double reltol = 1e-8; + bool usejac = true; + //TODO:setup as named parameters //Create circuit model - ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(); + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac); size_t idoff = 0; + //RL circuit parameters + double rinit = 1.0; + double linit = 1.0; + double vinit = 1.0; + + //inductor - ModelLib::Inductor* induct = new ModelLib::Inductor(idoff,0.1); + ModelLib::Inductor* induct = new ModelLib::Inductor(idoff,linit); //Form index to node uid realations - induct->setExternalConnectionNodes(0,2); - induct->setExternalConnectionNodes(2,1); - induct->setExternalConnectionNodes(1,0); + // input + induct->setExternalConnectionNodes(0,1); + //output + induct->setExternalConnectionNodes(1,-1); + //internal + induct->setExternalConnectionNodes(2,2); + //add component sysmodel->addComponent(induct); //resistor idoff++; - ModelLib::Resistor* resis = new ModelLib::Resistor(idoff, 1.0); + ModelLib::Resistor* resis = new ModelLib::Resistor(idoff, rinit); //Form index to node uid realations - resis->setExternalConnectionNodes(0,3); - resis->setExternalConnectionNodes(1,2); + //input + resis->setExternalConnectionNodes(0,0); + //output + resis->setExternalConnectionNodes(1,1); + //add sysmodel->addComponent(resis); //voltage source idoff++; - ModelLib::VoltageSource* vsource = new ModelLib::VoltageSource(idoff, 0.1); + ModelLib::VoltageSource* vsource = new ModelLib::VoltageSource(idoff, vinit); //Form index to node uid realations - vsource->setExternalConnectionNodes(0,0); - vsource->setExternalConnectionNodes(2,4); - vsource->setExternalConnectionNodes(1,3); + //input + vsource->setExternalConnectionNodes(0,-1); + //output + vsource->setExternalConnectionNodes(1,0); + //internal + vsource->setExternalConnectionNodes(2,3); + + sysmodel->addComponent(vsource); - - //Allocate with graph - sysmodel->allocate(5); + sysmodel->allocate(4); std::cout << sysmodel->y().size() << std::endl; + //Grounding for IDA. If no grounding then circuit is \mu > 1 + //v_0 (grounded) //Create Intial points - sysmodel->y()[0] = 1.0; - sysmodel->y()[1] = 1.0; - sysmodel->y()[2] = 1.0; - sysmodel->y()[3] = 1.0; - sysmodel->y()[4] = 1.0; - - sysmodel->yp()[0] = 1.0; - sysmodel->yp()[1] = 1.0; - sysmodel->yp()[2] = 1.0; - sysmodel->yp()[3] = 1.0; - sysmodel->yp()[4] = 1.0; + sysmodel->y()[0] = vinit; //v_1 + sysmodel->y()[1] = vinit; // v_2 + sysmodel->y()[2] = 0.0; // i_L + sysmodel->y()[3] = 0.0; // i_s + + sysmodel->yp()[0] = 0.0; // v'_1 + sysmodel->yp()[1] = 0.0; // v'_2 + sysmodel->yp()[2] = -vinit / linit; // i'_s + sysmodel->yp()[3] = -vinit / linit; // i'_L + sysmodel->initialize(); - sysmodel->evaluateResidual(); - std::cout << "Output: {"; + std::cout << "Verify Intial Resisdual is Zero: {"; for (double i : sysmodel->getResidual()) { std::cout << i << ", "; @@ -83,10 +104,44 @@ int main(int argc, char const *argv[]) sysmodel->updateTime(0.0, 1.0); sysmodel->evaluateJacobian(); + std::cout << "Intial Jacobian with alpha = 1:\n"; sysmodel->getJacobian().printMatrix(); + // Create numerical integrator and configure it for the generator model + AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + double t_init = 0.0; + double t_final = 1.0; + + // setup simulation + idas->configureSimulation(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + idas->runSimulation(t_final); + + std::vector& yfinial = sysmodel->y(); + + std::cout << "Final Vector y\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << yfinial[i] << "\n"; + } + + std::vector yexact(4); + + //analytical solution to the circuit + yexact[0] = vinit; + yexact[2] = (-vinit / rinit) * (exp((rinit / linit) * t_final) - 1.0); + yexact[3] = yexact[2]; + yexact[1] = vinit - rinit * yexact[2]; + + std::cout << "Element-wise Relative error at t=" << t_final << "\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << abs((yfinial[i] - yexact[i]) / yexact[i]) << "\n"; + } return 0; } diff --git a/ModelEvaluator.hpp b/ModelEvaluator.hpp index 5eda481de..50c5e8b77 100644 --- a/ModelEvaluator.hpp +++ b/ModelEvaluator.hpp @@ -62,6 +62,7 @@ #include #include +#include namespace ModelLib { @@ -88,11 +89,20 @@ namespace ModelLib virtual int initializeAdjoint() = 0; virtual int evaluateAdjointResidual() = 0; - //virtual int evaluateAdjointJacobian() = 0; + // virtual int evaluateAdjointJacobian() = 0; virtual int evaluateAdjointIntegrand() = 0; virtual IdxT size() = 0; virtual IdxT nnz() = 0; + + /** + * @brief Is the Jacobian defined. Used in IDA to determine wether DQ is used or not + * + * @return true + * @return false + */ + virtual bool hasJacobian() = 0; + virtual IdxT size_quad() = 0; virtual IdxT size_opt() = 0; virtual void updateTime(real_type t, real_type a) = 0; @@ -125,6 +135,10 @@ namespace ModelLib virtual std::vector& getResidual() = 0; virtual const std::vector& getResidual() const = 0; + + virtual COO_Matrix& getJacobian() = 0; + virtual const COO_Matrix& getJacobian() const = 0; + virtual std::vector& getIntegrand() = 0; virtual const std::vector& getIntegrand() const = 0; diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp index ade61feff..928d26f30 100644 --- a/ModelEvaluatorImpl.hpp +++ b/ModelEvaluatorImpl.hpp @@ -62,7 +62,6 @@ #include #include -#include namespace ModelLib { @@ -112,6 +111,11 @@ namespace ModelLib return nnz_; } + virtual bool hasJacobian() + { + return false; + } + virtual IdxT size_quad() { return size_quad_; diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp index bad48ecf0..47efcc7f7 100644 --- a/PowerElectronicsModel.hpp +++ b/PowerElectronicsModel.hpp @@ -43,13 +43,27 @@ class PowerElectronicsModel : public ModelEvaluatorImpl public: /** - * @brief Constructor for the system model + * @brief Default constructor for the system model */ PowerElectronicsModel() : ModelEvaluatorImpl(0, 0, 0) { - // Set system model tolerances - rtol_ = 1e-5; - atol_ = 1e-5; + // Set system model tolerances as default + rtol_ = 1e-4; + atol_ = 1e-4; + // By default use jacobian + usejac_ = true; + } + + /** + * @brief Constructor for the system model + */ + PowerElectronicsModel(double rt, double at, bool ju) : ModelEvaluatorImpl(0, 0, 0) + { + // Set system model tolerances from input + rtol_ = rt; + atol_ = at; + // Can choose not to use jacobain + usejac_ = ju; } /** @@ -73,6 +87,28 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 1; } + /** + * @brief Will check if each component has jacobian avalible. If one doesn't then jacobain is false. + * + * + * @return true + * @return false + */ + bool hasJacobian() + { + if (!this->usejac_) return false; + + for(const auto& component : components_) + { + if (!component->hasJacobian()) + { + return false; + } + + } + return true; + } + /** * @brief Allocate the vector data with size amount * @todo Add capability to go through component model connection to get the size of the actual vector @@ -127,8 +163,16 @@ class PowerElectronicsModel : public ModelEvaluatorImpl { for(IdxT j=0; jsize(); ++j) { - component->y()[j] = y_[component->getNodeConnection(j)]; - component->yp()[j] = yp_[component->getNodeConnection(j)]; + if(component->getNodeConnection(j) != -1) + { + component->y()[j] = y_[component->getNodeConnection(j)]; + component->yp()[j] = yp_[component->getNodeConnection(j)]; + } + else + { + component->y()[j] = 0.0; + component->yp()[j] = 0.0; + } } } return 0; @@ -148,7 +192,7 @@ class PowerElectronicsModel : public ModelEvaluatorImpl { for (IdxT i = 0; i < this->f_.size(); i++) { - f_[i] = 0; + f_[i] = 0.0; } this->distributeVectors(); @@ -157,9 +201,16 @@ class PowerElectronicsModel : public ModelEvaluatorImpl for(const auto& component : components_) { + //TODO:check return type + component->evaluateResidual(); for(IdxT j=0; jsize(); ++j) { - f_[component->getNodeConnection(j)] += component->getResidual()[j]; + //@todo should do a different grounding check + if (component->getNodeConnection(j) != -1) + { + f_[component->getNodeConnection(j)] += component->getResidual()[j]; + } + } } @@ -180,16 +231,27 @@ class PowerElectronicsModel : public ModelEvaluatorImpl for(const auto& component : components_) { component->evaluateJacobian(); - std::vector r; - std::vector c; - std::vector v; - std::tie(r, c, v) = component->getJacobian().getEntrieCopies(); + + //get references to local jacobain + std::tuple&, std::vector&, std::vector&> tpm = component->getJacobian().getEntries(); + const auto& [r, c, v] = tpm; + + //Create copies of data to handle groundings + std::vector rgr; + std::vector cgr; + std::vector vgr; for (IdxT i = 0; i < static_cast(r.size()); i++) { - r[i] = component->getNodeConnection(r[i]); - c[i] = component->getNodeConnection(c[i]); + if (component->getNodeConnection(r[i]) != -1 && component->getNodeConnection(c[i]) != -1) + { + rgr.push_back(component->getNodeConnection(r[i])); + cgr.push_back(component->getNodeConnection(c[i])); + vgr.push_back(v[i]); + } } - this->J_.AXPY(1.0, r, c, v); + + //AXPY to Global Jacobian + this->J_.AXPY(1.0, rgr, cgr, vgr); } return 0; @@ -248,6 +310,8 @@ class PowerElectronicsModel : public ModelEvaluatorImpl { component->updateTime(t, a); } + this->time_ = t; + this->alpha_ = a; } void addComponent(component_type* component) @@ -257,6 +321,7 @@ class PowerElectronicsModel : public ModelEvaluatorImpl private: std::vector components_; + bool usejac_; }; // class PowerElectronicsModel diff --git a/Solver/Dynamic/CMakeLists.txt b/Solver/Dynamic/CMakeLists.txt index 759829967..85c7ea920 100644 --- a/Solver/Dynamic/CMakeLists.txt +++ b/Solver/Dynamic/CMakeLists.txt @@ -66,6 +66,11 @@ gridkit_add_library(solvers_dyn LINK_LIBRARIES PUBLIC SUNDIALS::nvecserial PUBLIC SUNDIALS::idas + PUBLIC SUNDIALS::sunlinsolklu + PUBLIC suitesparseconfig + PUBLIC klu + PUBLIC amd + PUBLIC colamd OUTPUT_NAME gridkit_solvers_dyn) diff --git a/Solver/Dynamic/Ida.cpp b/Solver/Dynamic/Ida.cpp index c71a8fd07..5137119f1 100644 --- a/Solver/Dynamic/Ida.cpp +++ b/Solver/Dynamic/Ida.cpp @@ -61,10 +61,13 @@ #include #include -// #include #include /* access to IDADls interface */ #include +//Sundials Sparse KLU +#include +#include + #include "ModelEvaluator.hpp" #include "Ida.hpp" @@ -103,6 +106,9 @@ namespace Sundials yp_ = N_VClone(yy_); checkAllocation((void*) yp_, "N_VClone"); + //get intial conditions + this->getDefaultInitialCondition(); + // Create vectors to store restart initial condition yy0_ = N_VClone(yy_); checkAllocation((void*) yy0_, "N_VClone"); @@ -144,14 +150,7 @@ namespace Sundials } // Set up linear solver - JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); - checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); - - linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); - checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); - - retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); - checkOutput(retval, "IDASetLinearSolver"); + this->configureLinearSolver(); return retval; } @@ -160,16 +159,32 @@ namespace Sundials int Ida::configureLinearSolver() { int retval = 0; + if (model_->hasJacobian()) + { + JacobianMat_ = SUNSparseMatrix(model_->size(), model_->size(), model_->size() * model_->size(), CSR_MAT, context_); + checkAllocation((void*) JacobianMat_, "SUNSparseMatrix"); - // Set up linear solver - JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); - checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); + linearSolver_ = SUNLinSol_KLU(yy_, JacobianMat_, context_); + checkAllocation((void*) linearSolver_, "SUNLinSol_KLU"); - linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); - checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); + retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); + checkOutput(retval, "IDASetLinearSolver"); - retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); - checkOutput(retval, "IDASetLinearSolver"); + retval = IDASetJacFn(solver_, this->Jac); + checkOutput(retval, "IDASetJacFn"); + } + else + { + JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); + checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); + + linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); + checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); + + retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); + checkOutput(retval, "IDASetLinearSolver"); + + } return retval; } @@ -525,8 +540,49 @@ namespace Sundials return 0; } + template + int Ida::Jac(realtype t, realtype cj, N_Vector yy, N_Vector yp, N_Vector resvec, SUNMatrix J, void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) + { - template + ModelLib::ModelEvaluator* model = static_cast*>(user_data); + + + model->updateTime(t, cj); + copyVec(yy, model->y()); + copyVec(yp, model->yp()); + + model->evaluateJacobian(); + COO_Matrix Jac = model->getJacobian(); + + //Get reference to the jacobian entries + std::tuple&, std::vector&, std::vector&> tpm = Jac.getEntries(); + const auto [r, c, val] = tpm; + + //get the CSR row pointers from COO matrix + std::vector csrrowdata = Jac.getCSRRowData(); + + SUNMatZero(J); + + //Set row pointers + sunindextype *rowptrs = SUNSparseMatrix_IndexPointers(J); + for (unsigned int i = 0; i < csrrowdata.size() ; i++) + { + rowptrs[i] = csrrowdata[i]; + } + + sunindextype *colvals = SUNSparseMatrix_IndexValues(J); + realtype *data = SUNSparseMatrix_Data(J); + //Copy data from model jac to sundials + for (unsigned int i = 0; i < c.size(); i++ ) + { + colvals[i] = c[i]; + data[i] = val[i]; + } + + return 0; + } + + template int Ida::Integrand(realtype tt, N_Vector yy, N_Vector yp, N_Vector rhsQ, void *user_data) { ModelLib::ModelEvaluator* model = static_cast*>(user_data); diff --git a/Solver/Dynamic/Ida.hpp b/Solver/Dynamic/Ida.hpp index 3fa3368c9..a4cea9561 100644 --- a/Solver/Dynamic/Ida.hpp +++ b/Solver/Dynamic/Ida.hpp @@ -65,7 +65,7 @@ #include #include #include /* access to sparse SUNMatrix */ -// #include /* access to KLU linear solver */ +#include /* access to KLU linear solver */ #include /* access to dense linear solver */ #include "ModelEvaluator.hpp" @@ -165,6 +165,11 @@ namespace AnalysisManager static int Residual(realtype t, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data); + + static int Jac(realtype t, realtype cj, + N_Vector yy, N_Vector yp, N_Vector resvec, + SUNMatrix J, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); static int Integrand(realtype t, N_Vector yy, N_Vector yp, diff --git a/SparseMatrix/COO_Matrix.hpp b/SparseMatrix/COO_Matrix.hpp index 5b0ece80c..c256e015c 100644 --- a/SparseMatrix/COO_Matrix.hpp +++ b/SparseMatrix/COO_Matrix.hpp @@ -40,8 +40,10 @@ class COO_Matrix std::tuple, std::vector> getRowCopy(Intdx r); std::tuple&, std::vector&, std::vector&> getEntries(); std::tuple, std::vector, std::vector> getEntrieCopies(); + std::tuple, std::vector, std::vector> getEntrieCopiesSubMatrix(std::vector submap); std::tuple, std::vector, std::vector> getDataToCSR(); + std::vector getCSRRowData(); // BLAS. Will sort before running void setValues(std::vector r, std::vector c, std::vector v); @@ -61,15 +63,19 @@ class COO_Matrix //Resort values void sortSparse(); bool isSorted(); + Intdx nnz(); std::tuple getDimensions(); void printMatrix(); + + static void sortSparseCOO(std::vector &rows, std::vector &columns, std::vector &values); + private: Intdx indexStartRow(const std::vector &rows, Intdx r); Intdx sparseCordBinarySearch(const std::vector &rows, const std::vector &columns, Intdx ri, Intdx ci); - void sortSparseCOO(std::vector &rows, std::vector &columns, std::vector &values); + bool checkIncreaseSize(Intdx r, Intdx c); }; @@ -164,6 +170,35 @@ inline std::tuple, std::vector, std::vector> return {rowsizevec, this->column_indexes, this->values}; } +/** + * @brief Only creates the row data + * + * @todo swap this with having the matrix store the data and updates. This can then be passed by reference + * + * @todo fails, fix + * + * @tparam ScalarT + * @tparam Intdx + * @return std::vector + */ +template +inline std::vector COO_Matrix::getCSRRowData() +{ + if (!this->isSorted()) this->sortSparse(); + std::vector rowsizevec(this->rows_size + 1, 0); + Intdx counter = 0; + for (Intdx i = 0; i < static_cast(rowsizevec.size() - 1); i++) + { + rowsizevec[i + 1] = rowsizevec[i]; + while (counter < static_cast(this->row_indexes.size()) && i == this->row_indexes[counter]) + { + rowsizevec[i+1]++; + counter++; + } + } + return rowsizevec; +} + /** * @brief Given set of vector data it will set the values into the matrix * @@ -191,6 +226,7 @@ inline void COO_Matrix::setValues(std::vector r, std::vec this->row_indexes.push_back(r[aiter]); this->column_indexes.push_back(c[aiter]); this->values.push_back(v[aiter]); + this->checkIncreaseSize(r[aiter], c[aiter]); aiter++; } if (aiter >= static_cast(r.size())) break; @@ -208,6 +244,8 @@ inline void COO_Matrix::setValues(std::vector r, std::vec this->row_indexes.push_back(r[i]); this->column_indexes.push_back(c[i]); this->values.push_back(v[i]); + + this->checkIncreaseSize(r[i], c[i]); } this->sorted = false; @@ -256,6 +294,8 @@ inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrixcolumn_indexes.push_back(c[aiter]); this->values.push_back(alpha * val[aiter]); aiter++; + + this->checkIncreaseSize(r[aiter], c[aiter]); } if (aiter >= static_cast(r.size())) break; @@ -272,6 +312,8 @@ inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrixrow_indexes.push_back(r[i]); this->column_indexes.push_back(c[i]); this->values.push_back(alpha * val[i]); + + this->checkIncreaseSize(r[i], c[i]); } this->sorted = false; @@ -310,6 +352,8 @@ inline void COO_Matrix::AXPY(ScalarT alpha, std::vector r this->row_indexes.push_back(r[aiter]); this->column_indexes.push_back(c[aiter]); this->values.push_back(alpha * v[aiter]); + + this->checkIncreaseSize(r[aiter], c[aiter]); aiter++; } if (aiter >= static_cast(r.size())) break; @@ -327,6 +371,8 @@ inline void COO_Matrix::AXPY(ScalarT alpha, std::vector r this->row_indexes.push_back(r[i]); this->column_indexes.push_back(c[i]); this->values.push_back(alpha * v[i]); + + this->checkIncreaseSize(r[i], c[i]); } this->sorted = false; @@ -452,6 +498,12 @@ inline bool COO_Matrix::isSorted() return this->sorted; } +template +inline Intdx COO_Matrix::nnz() +{ + return static_cast(this->values.size); +} + template inline std::tuple COO_Matrix::getDimensions() { @@ -574,10 +626,28 @@ inline Intdx COO_Matrix::sparseCordBinarySearch(const std::vecto return m; } +template +inline bool COO_Matrix::checkIncreaseSize(Intdx r, Intdx c) +{ + bool changed = false; + if (r + 1 > this->rows_size) + { + this->rows_size = r + 1; + changed = true; + } + if (c + 1 > this->columns_size) + { + this->columns_size = c + 1; + changed = true; + } + + return changed; +} + /** * @brief Sort a disoreded set of values. Assume nothing on order. * - * @todo simple setup. Should add better sorting since list are pre-sorted + * @todo simple setup. Should add stable sorting since list are pre-sorted * * @tparam ScalarT * @tparam Intdx diff --git a/SystemModel.hpp b/SystemModel.hpp index 34c7ff120..77bbdd20b 100644 --- a/SystemModel.hpp +++ b/SystemModel.hpp @@ -183,6 +183,17 @@ class SystemModel : public ModelEvaluatorImpl return 0; } + /** + * @brief Assume that jacobian is not avalible + * + * @return true + * @return false + */ + bool hasJacobian() + { + return false; + } + /** * @brief Initialize buses first, then all the other components. * From cdb4662f6303ff3ecfedf113d3bd44bd3d116caf Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Tue, 30 Jan 2024 16:19:33 -0500 Subject: [PATCH 19/52] Added the Transmission Line Component --- .../PowerElectronicsComponents/CMakeLists.txt | 3 +- .../TransmissionLine/CMakeLists.txt | 8 + .../TransmissionLine/TransmissionLine.cpp | 201 ++++++++++++++++++ .../TransmissionLine/TransmissionLine.hpp | 71 +++++++ Examples/RLCircuit/RLCircuit.cpp | 1 - 5 files changed, 282 insertions(+), 2 deletions(-) create mode 100644 ComponentLib/PowerElectronicsComponents/TransmissionLine/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.hpp diff --git a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt index 9d6ad8be1..8b96aaa66 100644 --- a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt +++ b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt @@ -7,4 +7,5 @@ add_subdirectory(Inductor) add_subdirectory(LinearTransformer) add_subdirectory(InductionMotor) add_subdirectory(SynchronousMachine) -add_subdirectory(DiscreteGenerator) \ No newline at end of file +add_subdirectory(DiscreteGenerator) +add_subdirectory(TransmissionLine) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/TransmissionLine/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/TransmissionLine/CMakeLists.txt new file mode 100644 index 000000000..6e2cea4f4 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/TransmissionLine/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_tranline + SOURCES + TransmissionLine.cpp + OUTPUT_NAME + gridkit_powerelec_tranline) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.cpp b/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.cpp new file mode 100644 index 000000000..62965c68e --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.cpp @@ -0,0 +1,201 @@ + +#include +#include +#include +#include "TransmissionLine.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant TransmissionLine model + * + * Calls default ModelEvaluatorImpl constructor. + * + * This is the Medium distance form with the use of the admittance matrix. + * Since the line is of medium length then there is no real part for shunt admittance + */ + +template +TransmissionLine::TransmissionLine(IdxT id, ScalarT R,ScalarT X, ScalarT B) + : R_(R), X_(X), B_(B) +{ + // internals [Iret1, Iimt1, Iret2, Iimt2] + // externals [Vre11, Vim11, Vre12, Vim12, Vre21, Vim21, Vre22, Vim22] + this->size_ = 12; + this->n_intern = 4; + this->n_extern = 8; + this->extern_indices = {0,1,2,3,4,5,6,7}; + this->idc_ = id; + + ScalarT magImpendence = 1 / (R_*R_ + X_*X_); + YReMat_ = magImpendence * R_; + YImMatOff_ = magImpendence * X_; + YImMatDi_ = B_ / (2.0) - YImMatOff_; +} + +template +TransmissionLine::~TransmissionLine() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int TransmissionLine::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + + return 0; +} + +/** + * Initialization of the grid model + */ +template +int TransmissionLine::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int TransmissionLine::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Evaluate residual of transmission line + * + * The complex admittance matrix is: + * [[ Y/2 + 1/Z, -1/Z]; + * [ -1/Z, Y/2 + 1/Z]] = + * [[R/|Z|, -R/|Z|]; + * [-R/|Z|, R/|Z|]] + + * i [[B/2 - X/|Z|, X/|Z|]; + * [X/|Z|, B/2 - X/|Z|]] + * = Dre + i Dim + * + * Then + * Ire = Dre Vre - Dim Vim + * Iim = Dre Vim + Dim Vre + * + * To express this for Modified Nodal Analysis the Voltages of the admittance matrix are put into voltage drops + */ +template +int TransmissionLine::evaluateResidual() +{ + //input + this->f_[0] = y_[8] ; + this->f_[1] = y_[9] ; + + this->f_[2] = y_[10] ; + this->f_[3] = y_[11] ; + //ouput + this->f_[4] = -y_[8] ; + this->f_[5] = -y_[9] ; + + this->f_[6] = -y_[10] ; + this->f_[7] = -y_[11] ; + + //Voltage drop accross terminals + ScalarT V1re = y_[0] - y_[4]; + ScalarT V1im = y_[1] - y_[5]; + ScalarT V2re = y_[2] - y_[6]; + ScalarT V2im = y_[3] - y_[7]; + + //Internal variables + //row 1 + this->f_[8] = YReMat_ * (V1re - V2re) - (YImMatDi_ * V1im + YImMatOff_ * V2im) - y_[8] ; + this->f_[9] = YReMat_ * (V1im - V2im) + (YImMatDi_ * V1re + YImMatOff_ * V2re) - y_[9] ; + + //row2 + this->f_[10] = YReMat_ * (V2re - V1re) - (YImMatOff_ * V1im + YImMatDi_ * V2im) - y_[10]; + this->f_[11] = YReMat_ * (V2im - V1im) + (YImMatOff_ * V1re + YImMatDi_ * V2re) - y_[11]; + + + return 0; +} + +/** + * @brief Generate Jacobian for Transmission Line + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ +template +int TransmissionLine::evaluateJacobian() +{ + + //Create dF/dy + std::vector rtemp{0,1,2,3,4,5,6,7,8,9,10,11}; + std::vector ctemp{8,9,10,11,8,9,10,11,8,9,10,11}; + std::vector vals{1.0,1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::vector ccord{0,1,2,3,4,5,6,7}; + + std::vector rcord(ccord.size(),8); + vals = {YReMat_, -YImMatDi_ ,-YReMat_, -YImMatOff_,-YReMat_, YImMatDi_ ,YReMat_, YImMatOff_}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::fill(rcord.begin(), rcord.end(), 9); + vals = {YImMatDi_ ,YReMat_, YImMatOff_, -YReMat_,-YImMatDi_ ,-YReMat_, -YImMatOff_, YReMat_}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::fill(rcord.begin(), rcord.end(), 10); + vals = {-YReMat_, -YImMatDi_ ,YReMat_, -YImMatOff_,YReMat_, YImMatDi_ ,-YReMat_, YImMatOff_}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::fill(rcord.begin(), rcord.end(), 11); + vals = {YImMatDi_ ,-YReMat_, YImMatOff_, YReMat_,-YImMatDi_ ,YReMat_, -YImMatOff_, -YReMat_}; + this->J_.setValues(rtemp, ctemp, vals); + + return 0; +} + +template +int TransmissionLine::evaluateIntegrand() +{ + return 0; +} + +template +int TransmissionLine::initializeAdjoint() +{ + return 0; +} + +template +int TransmissionLine::evaluateAdjointResidual() +{ + return 0; +} + +template +int TransmissionLine::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class TransmissionLine; +template class TransmissionLine; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.hpp b/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.hpp new file mode 100644 index 000000000..0f729d449 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.hpp @@ -0,0 +1,71 @@ + + +#ifndef _TRANLINE_HPP_ +#define _TRANLINE_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive TransmissionLine class. + * + */ + template + class TransmissionLine : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::J_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + TransmissionLine(IdxT id, ScalarT R, ScalarT X, ScalarT B); + virtual ~TransmissionLine(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT R_; + ScalarT X_; + ScalarT B_; + ScalarT YReMat_; + ScalarT YImMatDi_; + ScalarT YImMatOff_; + }; +} + +#endif diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index c71eef06d..e902b1242 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -89,7 +89,6 @@ int main(int argc, char const *argv[]) sysmodel->yp()[2] = -vinit / linit; // i'_s sysmodel->yp()[3] = -vinit / linit; // i'_L - sysmodel->initialize(); sysmodel->evaluateResidual(); From 7e7937c609c074dd457b24249e18fa815cd919f0 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 19 Feb 2024 13:31:19 -0500 Subject: [PATCH 20/52] Added Microgrid Example - Added MicrogridBusDQ - Added MicrogridLine - Added MicrogridLoad - Updated DiscreteGenerator - Added Output Testing for DG - Added Microgrid Assmebly Example - Updated Capacitor, Inductor, and Voltage residuals - Updated RLCircuit Example --- .../PowerElectronicsComponents/CMakeLists.txt | 5 +- .../Capacitor/Capacitor.cpp | 13 +- .../DiscreteGenerator/DiscreteGenerator.cpp | 211 ++++++---- .../DiscreteGenerator/DiscreteGenerator.hpp | 5 +- .../Inductor/Inductor.cpp | 10 +- .../MicrogridBusDQ/CMakeLists.txt | 8 + .../MicrogridBusDQ/MicrogridBusDQ.cpp | 132 +++++++ .../MicrogridBusDQ/MicrogridBusDQ.hpp | 66 ++++ .../MicrogridLine/CMakeLists.txt | 8 + .../MicrogridLine/MicrogridLine.cpp | 172 +++++++++ .../MicrogridLine/MicrogridLine.hpp | 67 ++++ .../MicrogridLoad/CMakeLists.txt | 8 + .../MicrogridLoad/MicrogridLoad.cpp | 169 ++++++++ .../MicrogridLoad/MicrogridLoad.hpp | 67 ++++ .../VoltageSource/VoltageSource.cpp | 8 +- Examples/CMakeLists.txt | 1 + Examples/DiscreteGeneratorTest/CMakeLists.txt | 5 +- Examples/DiscreteGeneratorTest/DGTest.cpp | 30 +- Examples/Microgrid/CMakeLists.txt | 13 + Examples/Microgrid/Microgrid.cpp | 361 ++++++++++++++++++ Examples/RLCircuit/RLCircuit.cpp | 8 +- SparseMatrix/COO_Matrix.hpp | 9 + 22 files changed, 1279 insertions(+), 97 deletions(-) create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLine/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLoad/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.hpp create mode 100644 Examples/Microgrid/CMakeLists.txt create mode 100644 Examples/Microgrid/Microgrid.cpp diff --git a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt index 8b96aaa66..3fba4be7f 100644 --- a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt +++ b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt @@ -8,4 +8,7 @@ add_subdirectory(LinearTransformer) add_subdirectory(InductionMotor) add_subdirectory(SynchronousMachine) add_subdirectory(DiscreteGenerator) -add_subdirectory(TransmissionLine) \ No newline at end of file +add_subdirectory(TransmissionLine) +add_subdirectory(MicrogridLoad) +add_subdirectory(MicrogridLine) +add_subdirectory(MicrogridBusDQ) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp index 79faefe89..b6287b359 100644 --- a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp @@ -69,15 +69,20 @@ int Capacitor::tagDifferentiable() template int Capacitor::evaluateResidual() { - this->f_[0] = this->yp_[2]; - this->f_[1] = -this->yp_[2]; - this->f_[2] = -this->C_ * this->yp_[2] + this->y_[0] - this->y_[1] - this->y_[2]; + //input + this->f_[0] = C_ * this->yp_[2]; + //output + this->f_[1] = -C_ * this->yp_[2]; + + //internal + this->f_[2] = -C_ * this->yp_[2] + this->y_[0] - this->y_[1] - this->y_[2]; return 0; } template int Capacitor::evaluateJacobian() { + this->J_.zeroMatrix(); //Create dF/dy std::vector rcord{2,2,2}; std::vector ccord{0,1,2}; @@ -87,7 +92,7 @@ int Capacitor::evaluateJacobian() //Create -dF/dy' std::vector rcordder{0,1,2}; std::vector ccordder{2,2,2}; - std::vector valsder{1.0, -1.0, -this->C_}; + std::vector valsder{C_, -C_, -this->C_}; COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); //Perform dF/dy + \alpha dF/dy' diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp index c66c5b0f9..607ec5312 100644 --- a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp @@ -17,11 +17,11 @@ namespace ModelLib { */ template -DiscreteGenerator::DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm) - : wb_(parm.wb), wc_(parm.wc), mp_(parm.mp), refmp_(parm.refmp), Vn_(parm.Vn), nq_(parm.nq), F_(parm.F), Kiv_(parm.Kiv), Kpv_(parm.Kpv), Kic_(parm.Kic), Kpc_(parm.Kpc), Cf_(parm.Cf), rLf_(parm.rLf), Lf_(parm.Lf), rLc_(parm.rLc), Lc_(parm.Lc) +DiscreteGenerator::DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm, bool reference_frame) + : wb_(parm.wb), wc_(parm.wc), mp_(parm.mp), Vn_(parm.Vn), nq_(parm.nq), F_(parm.F), Kiv_(parm.Kiv), Kpv_(parm.Kpv), Kic_(parm.Kic), Kpc_(parm.Kpc), Cf_(parm.Cf), rLf_(parm.rLf), Lf_(parm.Lf), rLc_(parm.rLc), Lc_(parm.Lc), refframe_(reference_frame) { - // internals [delta_i, Pi, Qi, phi_di, phi_qi, gamma_di, gamma_qi, il_di, il_qi, vo_di, vo_qi, io_di, io_qi] - // externals [Pref, Pbus, QBus] + // internals [\delta_i, Pi, Qi, phi_di, phi_qi, gamma_di, gamma_qi, il_di, il_qi, vo_di, vo_qi, io_di, io_qi] + // externals [\omega_ref, vba_out, vbb_out] this->size_ = 16; this->n_intern = 13; this->n_extern = 3; @@ -74,42 +74,64 @@ template int DiscreteGenerator::evaluateResidual() { // ### Externals Componenets ### - //Reference P - ScalarT wcom = this->wb_ - this->refmp_ * this->y_[0]; - this->f_[0] = 0; - this->f_[1] = 0; - this->f_[2] = 0; + ScalarT omega = wb_ - mp_ * y_[4]; + //ref common ref motor angle + if (refframe_) + { + f_[0] = omega - y_[0]; + } + else + { + f_[0] = 0.0; + } + + + //output + //current transformed to common frame + f_[1] = cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15]; + f_[2] = sin(y_[3]) * y_[14] + cos(y_[3]) * y_[15]; - // ### Internal Componenets ## - f_[3] = -yp_[3] + wb_ - mp_ * y_[4] - wcom; + //Take incoming voltages to current rotator reference frame + ScalarT vbd_in = cos(y_[3]) * y_[1] + sin(y_[3]) * y_[2]; + ScalarT vbq_in = -sin(y_[3]) * y_[1] + cos(y_[3]) * y_[2]; + // ### Internal Componenets ## + // Rotator difference angle + f_[3] = -yp_[3] + omega - y_[0]; + + // P and Q equations f_[4] = -yp_[4] + wc_ * (y_[12] * y_[14] + y_[13] * y_[15] - y_[4]); - f_[5] = -yp_[4] + wc_ * (-y_[12] * y_[15] + y_[13] * y_[14] - y_[5]); + f_[5] = -yp_[5] + wc_ * (-y_[12] * y_[15] + y_[13] * y_[14] - y_[5]); + //Voltage control ScalarT vod_star = Vn_ - nq_ * y_[5]; - ScalarT voq_star = 0; + ScalarT voq_star = 0.0; f_[6] = -yp_[6] + vod_star - y_[12]; f_[7] = -yp_[7] + voq_star - y_[13]; - ScalarT ild_star = F_ * y_[14] - wb_ * Cf_ * y_[13] + Kpv_ * (vod_star - y_[12]) + Kiv_ * y_[6] ; + + ScalarT ild_star = F_ * y_[14] - wb_ * Cf_ * y_[13] + Kpv_ * (vod_star - y_[12]) + Kiv_ * y_[6]; ScalarT ilq_star = F_ * y_[15] + wb_ * Cf_ * y_[12] + Kpv_ * (voq_star - y_[13]) + Kiv_ * y_[7]; + //Current control f_[8] = -yp_[8] + ild_star - y_[10]; f_[9] = -yp_[9] + ilq_star - y_[11]; ScalarT vid_star = -wb_ * Lf_ * y_[11] + Kpc_ * (ild_star - y_[10]) + Kic_ * y_[8]; ScalarT viq_star = wb_ * Lf_ * y_[10] + Kpc_ * (ilq_star - y_[11]) + Kic_ * y_[9]; - f_[10] = -yp_[10] - (rLf_ / Lf_) * y_[10] + wcom * y_[11] + (1/Lf_) * (vid_star - y_[12]); - f_[11] = -yp_[11] - (rLf_ / Lf_) * y_[11] - wcom * y_[10] + (1/Lf_) * (viq_star - y_[13]); + //Output LC Filter + f_[10] = -yp_[10] - (rLf_ / Lf_) * y_[10] + omega * y_[11] + (vid_star - y_[12]) / Lf_; + f_[11] = -yp_[11] - (rLf_ / Lf_) * y_[11] - omega * y_[10] + (viq_star - y_[13]) / Lf_; - f_[12] = -yp_[12] + wcom * y_[13] + (1/Cf_) * (y_[10] - y_[14]); - f_[13] = -yp_[13] - wcom * y_[12] + (1/Cf_) * (y_[11] - y_[15]); + f_[12] = -yp_[12] + omega * y_[13] + (y_[10] - y_[14]) / Cf_; + f_[13] = -yp_[13] - omega * y_[12] + (y_[11] - y_[15]) / Cf_; - f_[14] = -yp_[14] - (rLc_ / Lc_) * y_[14] + wcom * y_[15] + (1/Lc_)*(y_[12] - y_[1]); - f_[15] = -yp_[15] - (rLc_ / Lc_) * y_[15] - wcom * y_[14] + (1/Lc_)*(y_[13] - y_[2]); + //Output Connector + f_[14] = -yp_[14] - (rLc_ / Lc_) * y_[14] + omega * y_[15] + (y_[12] - vbd_in) / Lc_; + f_[15] = -yp_[15] - (rLc_ / Lc_) * y_[15] - omega * y_[14] + (y_[13] - vbq_in) / Lc_; return 0; } @@ -117,24 +139,24 @@ int DiscreteGenerator::evaluateResidual() * @brief Compute the jacobian of the DiscreteGenerator for iteration. dF/dy - \alpha dF/dy' * * The matrix dF/dy should be - * [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -[ mpref, 0, 0, 0, -mp, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -[ 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, 0, wc*x15, wc*x16, wc*x13, wc*x14] -[ 0, 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, -wc*x16, wc*x15, wc*x14, -wc*x13] -[ 0, 0, 0, 0, 0, -nq, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0] -[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0] -[ 0, 0, 0, 0, 0, -Kpv*nq, Kiv, 0, 0, 0, -1, 0, -Kpv, -Cf*wb, F, 0] -[ 0, 0, 0, 0, 0, 0, 0, Kiv, 0, 0, 0, -1, Cf*wb, -Kpv, 0, F] -[-mpref*x12, 0, 0, 0, 0, -(Kpc*Kpv*nq)/Lf, (Kiv*Kpc)/Lf, 0, Kic/Lf, 0, - Kpc/Lf - rLf/Lf, -mpref*x1, -(Kpc*Kpv + 1)/Lf, -(Cf*Kpc*wb)/Lf, (F*Kpc)/Lf, 0] -[ mpref*x11, 0, 0, 0, 0, 0, 0, (Kiv*Kpc)/Lf, 0, Kic/Lf, mpref*x1, - Kpc/Lf - rLf/Lf, (Cf*Kpc*wb)/Lf, -(Kpc*Kpv + 1)/Lf, 0, (F*Kpc)/Lf] -[-mpref*x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Cf, 0, 0, wb - mpref*x1, -1/Cf, 0] -[ mpref*x13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Cf, mpref*x1 - wb, 0, 0, -1/Cf] -[-mpref*x16, -1/Lc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, 0, -rLc/Lc, wb - mpref*x1] -[ mpref*x15, 0, -1/Lc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, mpref*x1 - wb, -rLc/Lc] + * +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[-1, 0, 0, 0, -mp, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, 0, wc*x15, wc*x16, wc*x13, wc*x14] +[ 0, 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, -wc*x16, wc*x15, wc*x14, -wc*x13] +[ 0, 0, 0, 0, 0, -nq, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0] +[ 0, 0, 0, 0, 0, -Kpv*nq, Kiv, 0, 0, 0, -1, 0, -Kpv, -Cf*wb, F, 0] +[ 0, 0, 0, 0, 0, 0, 0, Kiv, 0, 0, 0, -1, Cf*wb, -Kpv, 0, F] +[ 0, 0, 0, 0, -mp*x12, -(Kpc*Kpv*nq)/Lf, (Kiv*Kpc)/Lf, 0, Kic/Lf, 0, - Kpc/Lf - rLf/Lf, -mp*x5, -(Kpc*Kpv + 1)/Lf, -(Cf*Kpc*wb)/Lf, (F*Kpc)/Lf, 0] +[ 0, 0, 0, 0, mp*x11, 0, 0, (Kiv*Kpc)/Lf, 0, Kic/Lf, mp*x5, - Kpc/Lf - rLf/Lf, (Cf*Kpc*wb)/Lf, -(Kpc*Kpv + 1)/Lf, 0, (F*Kpc)/Lf] +[ 0, 0, 0, 0, -mp*x14, 0, 0, 0, 0, 0, 1/Cf, 0, 0, wb - mp*x5, -1/Cf, 0] +[ 0, 0, 0, 0, mp*x13, 0, 0, 0, 0, 0, 0, 1/Cf, mp*x5 - wb, 0, 0, -1/Cf] +[ 0, -cos(x4)/Lc, -sin(x4)/Lc, -(x3*cos(x4) - x2*sin(x4))/Lc, -mp*x16, 0, 0, 0, 0, 0, 0, 0, 1/Lc, 0, -rLc/Lc, wb - mp*x5] +[ 0, sin(x4)/Lc, -cos(x4)/Lc, (x2*cos(x4) + x3*sin(x4))/Lc, mp*x15, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, mp*x5 - wb, -rLc/Lc] * 'Generated from MATLAB symbolic' - * Jacobian is mostly constant besides reference and rows 4 & 5 * * @tparam ScalarT * @tparam IdxT @@ -145,99 +167,146 @@ int DiscreteGenerator::evaluateJacobian() { //Create dF/dy' std::vector rcordder(13); - std::vector valsder(13,1.0); + std::vector valsder(13, -1.0); for (int i = 0; i < 13; i++) { rcordder[i] = i + 3; } COO_Matrix Jacder = COO_Matrix(rcordder, rcordder, valsder,16,16); + std::vector ctemp{}; + std::vector rtemp{}; + std::vector valtemp{}; + + + //Create dF/dy + //r = 1 + + ctemp = {3, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(1); + valtemp = { - sin(y_[3]) * y_[14] - cos(y_[3]) * y_[15], cos(y_[3]),sin(y_[3])}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 2 + + ctemp = {3, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(2); + valtemp = { - cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15], -sin(y_[3]),cos(y_[3])}; + this->J_.setValues(rtemp, ctemp, valtemp); + //r = 3 - std::vector ctemp{0, 4}; - std::vector rtemp(ctemp.size(),3); - std::vector valtemp{this->refmp_, -this->mp_}; + + ctemp = {0, 4}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(3); + valtemp = {-1.0, -mp_}; this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 0 + if (refframe_) + { + ctemp = {0, 4}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(0); + valtemp = {-1.0, -mp_}; + this->J_.setValues(rtemp, ctemp, valtemp); + } + //r = 4 ctemp = {4, 12, 13, 14, 15}; - std::fill(rtemp.begin(), rtemp.end(), 4); - valtemp = {-this->wc_, this->wc_*y_[14], this->wc_*y_[15], this->wc_*y_[12], this->wc_*y_[13]}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(4); + valtemp = {-wc_, wc_*y_[14], wc_*y_[15], wc_*y_[12], wc_*y_[13]}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 5 ctemp = {5, 12, 13, 14, 15}; - std::fill(rtemp.begin(), rtemp.end(), 5); - valtemp = {-this->wc_, -this->wc_*y_[15], this->wc_*y_[14], this->wc_*y_[13], -this->wc_*y_[12]}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(5); + valtemp = {-wc_, -wc_*y_[15], wc_*y_[14], wc_*y_[13], -wc_*y_[12]}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 6 ctemp = {5, 12}; - std::fill(rtemp.begin(), rtemp.end(), 6); - valtemp = {-this->nq_, -1.0}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(6); + valtemp = {-nq_, -1.0}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 7 ctemp = {13}; - std::fill(rtemp.begin(), rtemp.end(), 7); + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(7); valtemp = {-1.0}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 8 ctemp = {5,6,10,12,13,14}; - std::fill(rtemp.begin(), rtemp.end(), 8); - valtemp = {-this->Kpv_*this->nq_, this->Kiv_, -1.0, -this->Kpv_, -this->Cf_*this->wb_, this->F_}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(8); + valtemp = {-Kpv_*nq_, Kiv_, -1.0, -Kpv_, -Cf_*wb_, F_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 9 ctemp = {7, 11, 12, 13, 15}; - std::fill(rtemp.begin(), rtemp.end(), 9); - valtemp = {this->Kiv_, -1.0, this->Cf_*this->wb_,-this->Kpv_,this->F_}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(9); + valtemp = {Kiv_, -1.0, Cf_*wb_,-Kpv_,F_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 10 - ctemp = {0, 5, 6, 8, 10, 11, 12, 13, 14}; - std::fill(rtemp.begin(), rtemp.end(), 10); - valtemp = {-this->refmp_ * y_[11], -(this->Kpc_ * this->Kpv_ * this->nq_) / this->Lf_, (this->Kpc_ * this->Kiv_) / this->Lf_, this->Kic_ / this->Lf_, -(this->Kpc_ + this->rLf_) / this->Lf_, -this->refmp_ * y_[0], -(this->Kpc_ * this->Kpv_ + 1.0) / this->Lf_, -(this->Cf_ * this->Kpc_ * this->wb_) / this->Lf_, (this->F_ * this->Kpc_) / this->Lf_}; + ctemp = {4, 5, 6, 8, 10, 11, 12, 13, 14}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(10); + valtemp = {-mp_ * y_[11], -(Kpc_ * Kpv_ * nq_) / Lf_, (Kpc_ * Kiv_) / Lf_, Kic_ / Lf_, -(Kpc_ + rLf_) / Lf_, -mp_ * y_[4], -(Kpc_ * Kpv_ + 1.0) / Lf_, -(Cf_ * Kpc_ * wb_) / Lf_, (F_ * Kpc_) / Lf_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 11 - ctemp = {0, 7, 9, 10, 11, 12, 13, 15}; - std::fill(rtemp.begin(), rtemp.end(), 11); - valtemp = {this->refmp_ * y_[10], (this->Kiv_ * this->Kpc_) / this->Lf_, this->Kic_ / this->Lf_, this->refmp_ * y_[0], -(this->Kpc_ + this->rLf_) / this->Lf_, (this->Cf_ * this->Kpc_ * this->wb_) / this->Lf_, -(this->Kpc_ * this->Kpv_ + 1.0) / this->Lf_, (this->F_ * this->Kpc_) / this->Lf_}; + ctemp = {4, 7, 9, 10, 11, 12, 13, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(11); + valtemp = {mp_ * y_[10], (Kiv_ * Kpc_) / Lf_, Kic_ / Lf_, mp_ * y_[4], -(Kpc_ + rLf_) / Lf_, (Cf_ * Kpc_ * wb_) / Lf_, -(Kpc_ * Kpv_ + 1.0) / Lf_, (F_ * Kpc_) / Lf_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 12 - ctemp = {0, 10, 13, 14}; - std::fill(rtemp.begin(), rtemp.end(), 12); - valtemp = {-this->refmp_ * y_[13], 1.0 / this->Cf_, this->wb_ - this->refmp_ * y_[0], -1.0 / this->Cf_}; + ctemp = {4, 10, 13, 14}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(12); + valtemp = {-mp_ * y_[13], 1.0 / Cf_, wb_ - mp_ * y_[4], -1.0 / Cf_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 13 - ctemp = {0, 11, 12, 15}; - std::fill(rtemp.begin(), rtemp.end(), 13); - valtemp = {this->refmp_ * y_[12], 1.0 / this->Cf_, -this->wb_ + this->refmp_ * y_[0], -1.0 / this->Cf_}; + ctemp = {4, 11, 12, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(13); + valtemp = {mp_ * y_[12], 1.0 / Cf_, -wb_ + mp_ * y_[4], -1.0 / Cf_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 14 - ctemp = {0, 1, 12, 14, 15}; - std::fill(rtemp.begin(), rtemp.end(), 14); - valtemp = {-this->refmp_ * y_[15], -1.0 / this->Lc_, 1.0 / this->Lc_, -this->rLc_ / this->Lc_, this->wb_ - this->refmp_ * y_[0]}; + ctemp = {1, 2, 3, 4, 12, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(14); + valtemp = {(1.0/Lc_) * -cos(y_[3]) , (1.0/Lc_) * -sin(y_[3]) , (1.0/Lc_) * (sin(y_[3]) * y_[1] - cos(y_[3]) * y_[2]), -mp_ * y_[15], 1.0 / Lc_, -rLc_ / Lc_, wb_ - mp_ * y_[4]}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 15 - ctemp = {0, 2, 13, 14, 15}; - std::fill(rtemp.begin(), rtemp.end(), 15); - valtemp = {-this->refmp_ * y_[14], -1.0 / this->Lc_, 1.0 / this->Lc_, -this->wb_ + this->refmp_ * y_[0], -this->rLc_ / this->Lc_}; + ctemp = {1, 2, 3, 4, 13, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(15); + valtemp = {(1.0/Lc_) * sin(y_[3]) , (1.0/Lc_) * -cos(y_[3]), (1.0/Lc_) * (cos(y_[3]) * y_[1] + sin(y_[3]) * y_[2]), mp_ * y_[14], 1.0 / Lc_, -wb_ + mp_ * y_[4], -rLc_ / Lc_}; this->J_.setValues(rtemp, ctemp, valtemp); //Perform dF/dy + \alpha dF/dy' - this->J_.AXPY(-this->alpha_, Jacder); + this->J_.AXPY(this->alpha_, Jacder); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp index f5ce86899..bca984460 100644 --- a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp @@ -18,7 +18,6 @@ namespace ModelLib ScalarT wb; ScalarT wc; ScalarT mp; - ScalarT refmp; ScalarT Vn; ScalarT nq; ScalarT F; @@ -63,7 +62,7 @@ namespace ModelLib public: - DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm); + DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm, bool reference_frame); virtual ~DiscreteGenerator(); int allocate(); @@ -81,7 +80,6 @@ namespace ModelLib ScalarT wb_; ScalarT wc_; ScalarT mp_; - ScalarT refmp_; ScalarT Vn_; ScalarT nq_; ScalarT F_; @@ -94,6 +92,7 @@ namespace ModelLib ScalarT Lf_; ScalarT rLc_; ScalarT Lc_; + bool refframe_; }; } diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp index a24b7a8e9..885153d41 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -71,11 +71,11 @@ template int Inductor::evaluateResidual() { //input - this->f_[0] = this->y_[2]; + this->f_[0] = -this->y_[2]; //output - this->f_[1] = -this->y_[2]; + this->f_[1] = this->y_[2]; //internal - this->f_[2] = this->L_ * this->yp_[2] + this->y_[0] - this->y_[1] ; + this->f_[2] = -this->L_ * this->yp_[2] + this->y_[1] - this->y_[0] ; return 0; } @@ -87,13 +87,13 @@ int Inductor::evaluateJacobian() //Create dF/dy std::vector rcord{0,1,2,2}; std::vector ccord{2,2,0,1}; - std::vector vals{1.0, -1.0, 1.0, -1.0}; + std::vector vals{-1.0, 1.0, -1.0, 1.0}; this->J_.setValues(rcord, ccord, vals); //Create dF/dy' std::vector rcordder{2}; std::vector ccordder{2}; - std::vector valsder{this->L_}; + std::vector valsder{-this->L_}; COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); //Perform dF/dy + \alpha dF/dy' diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/CMakeLists.txt new file mode 100644 index 000000000..1bfb8dc3d --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_mircobusdq + SOURCES + MicrogridBusDQ.cpp + OUTPUT_NAME + gridkit_powerelec_mircobusdq) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.cpp b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.cpp new file mode 100644 index 000000000..206108221 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.cpp @@ -0,0 +1,132 @@ + +#include +#include +#include +#include "MicrogridBusDQ.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant MicrogridBusDQ model + * + * Calls default ModelEvaluatorImpl constructor. + * + * Each microgrid line has a virtual resistance RN + */ + +template +MicrogridBusDQ::MicrogridBusDQ(IdxT id, ScalarT RN) + : RN_(RN) +{ + // externals [vbus_d, vbus_q] + this->size_ = 2; + this->n_intern = 0; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +MicrogridBusDQ::~MicrogridBusDQ() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int MicrogridBusDQ::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + + return 0; +} + +/** + * Initialization of the grid model + */ +template +int MicrogridBusDQ::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int MicrogridBusDQ::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Evaluate residual of microgrid line + * This model has "Virtual resistors" on both ends with parameters RN1 and RN2 + * + */ +template +int MicrogridBusDQ::evaluateResidual() +{ + //bus voltage + f_[0] = -y_[0] / RN_; + f_[1] = -y_[1] / RN_; + + return 0; +} + +/** + * @brief Generate Jacobian for Transmission Line + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ +template +int MicrogridBusDQ::evaluateJacobian() +{ + this->J_.zeroMatrix(); + + //Create dF/dy + std::vector rtemp{0,1}; + std::vector ctemp{0,1}; + std::vector vals{-1.0 / RN_,-1.0 / RN_}; + this->J_.setValues(rtemp, ctemp, vals); + + return 0; +} + +template +int MicrogridBusDQ::evaluateIntegrand() +{ + return 0; +} + +template +int MicrogridBusDQ::initializeAdjoint() +{ + return 0; +} + +template +int MicrogridBusDQ::evaluateAdjointResidual() +{ + return 0; +} + +template +int MicrogridBusDQ::evaluateAdjointIntegrand() +{ + return 0; +} + + +// Available template instantiations +template class MicrogridBusDQ; +template class MicrogridBusDQ; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.hpp b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.hpp new file mode 100644 index 000000000..44154da38 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.hpp @@ -0,0 +1,66 @@ + + +#ifndef _VIRBUSDQ_HPP_ +#define _VIRBUSDQ_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive MicrogridBusDQ class. + * + */ + template + class MicrogridBusDQ : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::J_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + MicrogridBusDQ(IdxT id, ScalarT RN); + virtual ~MicrogridBusDQ(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT RN_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLine/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/MicrogridLine/CMakeLists.txt new file mode 100644 index 000000000..d59cebb9c --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLine/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_mircoline + SOURCES + MicrogridLine.cpp + OUTPUT_NAME + gridkit_powerelec_mircoline) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.cpp b/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.cpp new file mode 100644 index 000000000..e040ceb70 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.cpp @@ -0,0 +1,172 @@ + +#include +#include +#include +#include "MicrogridLine.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant MicrogridLine model + * + * Calls default ModelEvaluatorImpl constructor. + * + * Each microgrid line has a virtual resistance RN + */ + +template +MicrogridLine::MicrogridLine(IdxT id, ScalarT R,ScalarT L) + : R_(R), L_(L) +{ + // internals [id, iq] + // externals [\omegaref, vbd_in, vbq_in, vbd_out, vbq_out] + this->size_ = 7; + this->n_intern = 2; + this->n_extern = 5; + this->extern_indices = {0,1,2,3,4}; + this->idc_ = id; +} + +template +MicrogridLine::~MicrogridLine() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int MicrogridLine::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + + return 0; +} + +/** + * Initialization of the grid model + */ +template +int MicrogridLine::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int MicrogridLine::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Evaluate residual of microgrid line + * This model has "Virtual resistors" on both ends with parameters RN1 and RN2 + * + */ +template +int MicrogridLine::evaluateResidual() +{ + //ref motor + this->f_[0] = 0.0; + + //input + this->f_[1] = -y_[5] ; + this->f_[2] = -y_[6] ; + + //output + this->f_[3] = y_[5] ; + this->f_[4] = y_[6] ; + + //Internal variables + this->f_[5] = -yp_[5] - (R_ / L_) * y_[5] + y_[0]*y_[6] + (y_[1] - y_[3])/L_; + this->f_[6] = -yp_[6] - (R_ / L_) * y_[6] - y_[0]*y_[5] + (y_[2] - y_[4])/L_; + + + return 0; +} + +/** + * @brief Generate Jacobian for Transmission Line + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ +template +int MicrogridLine::evaluateJacobian() +{ + this->J_.zeroMatrix(); + + //Create dF/dy + std::vector rtemp{1,2,3,4}; + std::vector ctemp{5,6,5,6}; + std::vector vals{-1.0,-1.0,1.0,1.0}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::vector ccord{0, 1, 3, 5, 6}; + + std::vector rcord(ccord.size(),5); + vals = {y_[6], (1.0 / L_) , -(1.0 / L_), - (R_ / L_) , y_[0]}; + this->J_.setValues(rcord, ccord, vals); + + + std::vector ccor2{0, 2, 4, 5, 6}; + std::fill(rcord.begin(), rcord.end(), 6); + vals = {-y_[5], (1.0 / L_) , -(1.0 / L_), -y_[0], - (R_ / L_)}; + this->J_.setValues(rcord, ccor2, vals); + + + //Create -dF/dy' + std::vector rcordder{5,6}; + std::vector ccordder{5,6}; + std::vector valsder{-1.0, -1.0}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,7,7); + + //Perform dF/dy + \alpha dF/dy' + this->J_.AXPY(this->alpha_, Jacder); + + + return 0; +} + +template +int MicrogridLine::evaluateIntegrand() +{ + return 0; +} + +template +int MicrogridLine::initializeAdjoint() +{ + return 0; +} + +template +int MicrogridLine::evaluateAdjointResidual() +{ + return 0; +} + +template +int MicrogridLine::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class MicrogridLine; +template class MicrogridLine; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.hpp b/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.hpp new file mode 100644 index 000000000..11ef78617 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.hpp @@ -0,0 +1,67 @@ + + +#ifndef _TRANLINE_HPP_ +#define _TRANLINE_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive MicrogridLine class. + * + */ + template + class MicrogridLine : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::J_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + MicrogridLine(IdxT id, ScalarT R, ScalarT L); + virtual ~MicrogridLine(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT R_; + ScalarT L_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLoad/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/CMakeLists.txt new file mode 100644 index 000000000..313d47688 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_microload + SOURCES + MicrogridLoad.cpp + OUTPUT_NAME + gridkit_powerelec_microload) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.cpp b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.cpp new file mode 100644 index 000000000..c39f53388 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.cpp @@ -0,0 +1,169 @@ + +#include +#include +#include +#include "MicrogridLoad.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant MicrogridLoad model + * + * Calls default ModelEvaluatorImpl constructor. + * + * This is the Medium distance form with the use of the admittance matrix. + * Since the line is of medium length then there is no real part for shunt admittance + */ + +template +MicrogridLoad::MicrogridLoad(IdxT id, ScalarT R,ScalarT L) + : R_(R), L_(L) +{ + // internals [id, iq] + // externals [\omegaref, vbd_out, vbq_out] + this->size_ = 5; + this->n_intern = 2; + this->n_extern = 3; + this->extern_indices = {0,1,2}; + this->idc_ = id; + +} + +template +MicrogridLoad::~MicrogridLoad() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int MicrogridLoad::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + + return 0; +} + +/** + * Initialization of the grid model + */ +template +int MicrogridLoad::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int MicrogridLoad::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Eval Micro Load + */ +template +int MicrogridLoad::evaluateResidual() +{ + //ref motor + this->f_[0] = 0.0; + + //only input for loads + + //input + this->f_[1] = -y_[3] ; + this->f_[2] = -y_[4] ; + + //Internal variables + this->f_[3] = -yp_[3] - (R_ / L_) * y_[3] + y_[0]*y_[4] + y_[1] / L_; + this->f_[4] = -yp_[4] - (R_ / L_) * y_[4] - y_[0]*y_[3] + y_[2] / L_; + + + return 0; +} + +/** + * @brief Generate Jacobian for Micro Load + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ +template +int MicrogridLoad::evaluateJacobian() +{ + this->J_.zeroMatrix(); + + //Create dF/dy + std::vector rtemp{1,2}; + std::vector ctemp{3,4}; + std::vector vals{-1.0,-1.0}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::vector ccord{0, 1, 3, 4}; + + std::vector rcord(ccord.size(),3); + vals = {y_[4], (1.0 / L_) , - (R_ / L_) , y_[0]}; + this->J_.setValues(rcord, ccord, vals); + + + std::vector ccor2{0, 2, 3, 4}; + std::fill(rcord.begin(), rcord.end(), 4); + vals = {-y_[3], (1.0 / L_) , -y_[0], - (R_ / L_)}; + this->J_.setValues(rcord, ccor2, vals); + + + //Create -dF/dy' + std::vector rcordder{3,4}; + std::vector ccordder{3,4}; + std::vector valsder{-1.0, -1.0}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,5,5); + + //Perform dF/dy + \alpha dF/dy' + this->J_.AXPY(this->alpha_, Jacder); + + return 0; +} + +template +int MicrogridLoad::evaluateIntegrand() +{ + return 0; +} + +template +int MicrogridLoad::initializeAdjoint() +{ + return 0; +} + +template +int MicrogridLoad::evaluateAdjointResidual() +{ + return 0; +} + +template +int MicrogridLoad::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class MicrogridLoad; +template class MicrogridLoad; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.hpp b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.hpp new file mode 100644 index 000000000..22694f614 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.hpp @@ -0,0 +1,67 @@ + + +#ifndef _TRANLOAD_HPP_ +#define _TRANLOAD_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive MicrogridLoad class. + * + */ + template + class MicrogridLoad : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::J_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + MicrogridLoad(IdxT id, ScalarT R, ScalarT L); + virtual ~MicrogridLoad(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT R_; + ScalarT L_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp index c7cb09798..e58e50556 100644 --- a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp @@ -72,11 +72,11 @@ int VoltageSource::evaluateResidual() //Note this leaves induction lumped into y. Perhaps would be better to seperate volatge and induction into seperate vectors // for easier development //input - this->f_[0] = this->y_[2]; + this->f_[0] = -this->y_[2]; //ouput - this->f_[1] = -this->y_[2]; + this->f_[1] = this->y_[2]; //internal - this->f_[2] = -this->y_[1] + this->y_[0] + this->V_; + this->f_[2] = this->y_[1] - this->y_[0] - this->V_; return 0; } @@ -86,7 +86,7 @@ int VoltageSource::evaluateJacobian() //Create dF/dy std::vector rcord{0,1,2,2}; std::vector ccord{2,2,0,1}; - std::vector vals{1.0, -1.0, 1.0, -1.0}; + std::vector vals{-1.0, 1.0, -1.0, 1.0}; this->J_.setValues(rcord, ccord, vals); return 0; diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index e15774642..2c53fcc25 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -57,6 +57,7 @@ add_subdirectory(MatPowerTesting) add_subdirectory(RLCircuit) +add_subdirectory(Microgrid) add_subdirectory(SparseTest) add_subdirectory(DiscreteGeneratorTest) diff --git a/Examples/DiscreteGeneratorTest/CMakeLists.txt b/Examples/DiscreteGeneratorTest/CMakeLists.txt index b1100b91a..9238fb346 100644 --- a/Examples/DiscreteGeneratorTest/CMakeLists.txt +++ b/Examples/DiscreteGeneratorTest/CMakeLists.txt @@ -3,7 +3,10 @@ add_executable(dgtest DGTest.cpp) -target_link_libraries(dgtest GRIDKIT::powerelec_disgen) +target_link_libraries(dgtest GRIDKIT::powerelec_disgen + GRIDKIT::powerelec_mircoline + GRIDKIT::powerelec_microload + GRIDKIT::solvers_dyn) add_test(NAME DiscreteGeneratorTest COMMAND $) install(TARGETS dgtest RUNTIME DESTINATION bin) diff --git a/Examples/DiscreteGeneratorTest/DGTest.cpp b/Examples/DiscreteGeneratorTest/DGTest.cpp index 7d4aeda6f..d3dd2c68b 100644 --- a/Examples/DiscreteGeneratorTest/DGTest.cpp +++ b/Examples/DiscreteGeneratorTest/DGTest.cpp @@ -15,11 +15,9 @@ int main(int argc, char const *argv[]) ModelLib::DiscreteGeneratorParameters parms; //Parameters from MATLAB Microgrid code for first DG - //refmp is need for reference input parms.wb = 2.0*M_PI*50.0; parms.wc = 31.41; parms.mp = 9.4e-5; - parms.refmp = 9.4e-5; parms.Vn = 380; parms.nq = 1.3e-3; parms.F = 0.75; @@ -33,7 +31,7 @@ int main(int argc, char const *argv[]) parms.rLc = 0.03; parms.Lc = 0.35e-3; - ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(0, parms); + ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(0, parms, true); std::vector t1(16,0.0); std::vector t2{0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.1,1.2,1.3,1.4,1.5}; @@ -48,9 +46,33 @@ int main(int argc, char const *argv[]) std::cout << "Output: {"; for (double i : dg->getResidual()) { - std::cout << i << ", "; + printf("%e ,", i); } std::cout << "}\n"; + //Generated from matlab code with same parameters and inputs + std::vector true_vec{3.141592277589793e+02, + 8.941907747838389e-01, + 1.846733023014284e+00, + 3.141592277589793e+02, + 1.014543000000000e+02, + -1.507680000000000e+01, + 3.787993500000000e+02, + -1.300000000000000e+00, + 2.899095146477517e+02, + 2.939138495559215e+02, + 1.507210571826699e+07, + 1.659799832843673e+07, + -7.591593003913325e+03, + -8.376991073310774e+03, + 3.337988298081817e+03, + 2.684419146397466e+03}; + + std::cout << "Test the Relative Error\n"; + for (size_t i = 0; i < true_vec.size(); i++) + { + printf("%e ,\n", (true_vec[i] - dg->getResidual()[i]) / true_vec[i]); + } + return 0; } diff --git a/Examples/Microgrid/CMakeLists.txt b/Examples/Microgrid/CMakeLists.txt new file mode 100644 index 000000000..0958144c4 --- /dev/null +++ b/Examples/Microgrid/CMakeLists.txt @@ -0,0 +1,13 @@ + + + + +add_executable(microgrid Microgrid.cpp) +target_link_libraries(microgrid GRIDKIT::powerelec_disgen + GRIDKIT::powerelec_mircoline + GRIDKIT::powerelec_microload + GRIDKIT::solvers_dyn + GRIDKIT::powerelec_mircobusdq) + +add_test(NAME Microgrid COMMAND $) +install(TARGETS microgrid RUNTIME DESTINATION bin) diff --git a/Examples/Microgrid/Microgrid.cpp b/Examples/Microgrid/Microgrid.cpp new file mode 100644 index 000000000..a0cf8dc9b --- /dev/null +++ b/Examples/Microgrid/Microgrid.cpp @@ -0,0 +1,361 @@ + + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include +#include +#include + + +int main(int argc, char const *argv[]) +{ + double abstol = 1.0e-4; + double reltol = 1.0e-4; + bool usejac = true; + + //TODO:setup as named parameters + //Create circuit model + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac); + + //Modeled after the problem in the paper + double RN = 1.0e4; + + //DG Params + + ModelLib::DiscreteGeneratorParameters parms1; + parms1.wb = 2.0*M_PI*50.0; + parms1.wc = 31.41; + parms1.mp = 9.4e-5; + parms1.Vn = 380; + parms1.nq = 1.3e-3; + parms1.F = 0.75; + parms1.Kiv = 420.0; + parms1.Kpv = 0.1; + parms1.Kic = 20.0 * 1.0e3; + parms1.Kpc = 15.0; + parms1.Cf = 50.0e-6; + parms1.rLf = 0.1; + parms1.Lf = 1.35e-3; + parms1.rLc = 0.03; + parms1.Lc = 0.35e-3; + + ModelLib::DiscreteGeneratorParameters parms2; + //Parameters from MATLAB Microgrid code for first DG + parms2.wb = 2.0*M_PI*50.0; + parms2.wc = 31.41; + parms2.mp = 12.5e-5; + parms2.Vn = 380; + parms2.nq = 1.5e-3; + parms2.F = 0.75; + parms2.Kiv = 390.0; + parms2.Kpv = 0.05; + parms2.Kic = 16.0 * 1.0e3; + parms2.Kpc = 10.5; + parms2.Cf = 50.0e-6; + parms2.rLf = 0.1; + parms2.Lf = 1.35e-3; + parms2.rLc = 0.03; + parms2.Lc = 0.35e-3; + + //Line params + double rline1 = 0.23; + double Lline1 = 0.1 / (2.0 * M_PI * 50.0); + + double rline2 = 0.35; + double Lline2 = 0.58 / (2.0 * M_PI * 50.0); + + double rline3 = 0.23; + double Lline3 = 0.1 / (2.0 * M_PI * 50.0); + + //load parms + double rload1 = 3.0; + double Lload1 = 2.0 / (2.0 * M_PI * 50.0); + + double rload2 = 2.0; + double Lload2 = 1.0 / (2.0 * M_PI * 50.0); + + + //indexing sets + size_t Nsize = 2; + // DGs + Lines + Loads + size_t vec_size_internals = 13*(2*Nsize) + (2 + 4*(Nsize - 1)) + 2*Nsize; + // \omegaref + BusDQ + size_t vec_size_externals = 1 + 2*(2*Nsize); + size_t dqbus1 = vec_size_externals + 1; + size_t dqbus2 = vec_size_externals + 3; + size_t dqbus3 = vec_size_externals + 5; + size_t dqbus4 = vec_size_externals + 7; + + size_t vec_size_total = vec_size_internals + vec_size_externals; + + + size_t indexv = 0; + + //dg 1 + ModelLib::DiscreteGenerator *dg1 = new ModelLib::DiscreteGenerator(0, parms1, true); + //ref motor + dg1->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg1->setExternalConnectionNodes(1,dqbus1); + dg1->setExternalConnectionNodes(2,dqbus1 + 1); + //internal connections + for (size_t i = 0; i < 13; i++) + { + + dg1->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg1); + + //dg 2 + ModelLib::DiscreteGenerator *dg2 = new ModelLib::DiscreteGenerator(1, parms1, false); + //ref motor + dg2->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg2->setExternalConnectionNodes(1,dqbus2); + dg2->setExternalConnectionNodes(2,dqbus2 + 1); + //internal connections + for (size_t i = 0; i < 13; i++) + { + + dg2->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg2); + + + //dg 3 + ModelLib::DiscreteGenerator *dg3 = new ModelLib::DiscreteGenerator(2, parms2, false); + //ref motor + dg3->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg3->setExternalConnectionNodes(1,dqbus3); + dg3->setExternalConnectionNodes(2,dqbus3 + 1); + //internal connections + for (size_t i = 0; i < 13; i++) + { + + dg3->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg3); + + + //dg 4 + ModelLib::DiscreteGenerator *dg4 = new ModelLib::DiscreteGenerator(3, parms2, false); + //ref motor + dg4->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg4->setExternalConnectionNodes(1,dqbus4); + dg4->setExternalConnectionNodes(2,dqbus4 + 1); + + //internal connections + for (size_t i = 0; i < 13; i++) + { + + dg4->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg4); + + // Lines + + //line 1 + ModelLib::MicrogridLine *l1 = new ModelLib::MicrogridLine(4, rline1, Lline1); + //ref motor + l1->setExternalConnectionNodes(0,vec_size_internals); + //input connections + l1->setExternalConnectionNodes(1,dqbus1); + l1->setExternalConnectionNodes(2,dqbus1 + 1); + //output connections + l1->setExternalConnectionNodes(3,dqbus2); + l1->setExternalConnectionNodes(4,dqbus2 + 1); + //internal connections + for (size_t i = 0; i < 2; i++) + { + + l1->setExternalConnectionNodes(5 + i,indexv + i); + } + indexv += 2; + sysmodel->addComponent(l1); + + + //line 2 + ModelLib::MicrogridLine *l2 = new ModelLib::MicrogridLine(5, rline2, Lline2); + //ref motor + l2->setExternalConnectionNodes(0,vec_size_internals); + //input connections + l2->setExternalConnectionNodes(1,dqbus2); + l2->setExternalConnectionNodes(2,dqbus2 + 1); + //output connections + l2->setExternalConnectionNodes(3,dqbus3); + l2->setExternalConnectionNodes(4,dqbus3 + 1); + //internal connections + for (size_t i = 0; i < 2; i++) + { + + l2->setExternalConnectionNodes(5 + i,indexv + i); + } + indexv += 2; + sysmodel->addComponent(l2); + + //line 3 + ModelLib::MicrogridLine *l3 = new ModelLib::MicrogridLine(6, rline3, Lline3); + //ref motor + l3->setExternalConnectionNodes(0,vec_size_internals); + //input connections + l3->setExternalConnectionNodes(1,dqbus3); + l3->setExternalConnectionNodes(2,dqbus3 + 1); + //output connections + l3->setExternalConnectionNodes(3,dqbus4); + l3->setExternalConnectionNodes(4,dqbus4 + 1); + //internal connections + for (size_t i = 0; i < 2; i++) + { + + l3->setExternalConnectionNodes(5 + i,indexv + i); + } + indexv += 2; + sysmodel->addComponent(l3); + + // loads + + //load 1 + ModelLib::MicrogridLoad *load1 = new ModelLib::MicrogridLoad(7, rload1, Lload1); + //ref motor + load1->setExternalConnectionNodes(0,vec_size_internals); + //input connections + load1->setExternalConnectionNodes(1,dqbus1); + load1->setExternalConnectionNodes(2,dqbus1 + 1); + //internal connections + for (size_t i = 0; i < 2; i++) + { + + load1->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 2; + sysmodel->addComponent(load1); + + //load 2 + ModelLib::MicrogridLoad *load2 = new ModelLib::MicrogridLoad(8, rload2, Lload2); + //ref motor + load2->setExternalConnectionNodes(0,vec_size_internals); + //input connections + load2->setExternalConnectionNodes(1,dqbus3); + load2->setExternalConnectionNodes(2,dqbus3 + 1); + //internal connections + for (size_t i = 0; i < 2; i++) + { + + load2->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 2; + sysmodel->addComponent(load2); + + //Virtual PQ Buses + ModelLib::MicrogridBusDQ *bus1 = new ModelLib::MicrogridBusDQ(9, RN); + + bus1->setExternalConnectionNodes(0,dqbus1); + bus1->setExternalConnectionNodes(1,dqbus1 + 1); + sysmodel->addComponent(bus1); + + ModelLib::MicrogridBusDQ *bus2 = new ModelLib::MicrogridBusDQ(10, RN); + + bus2->setExternalConnectionNodes(0,dqbus2); + bus2->setExternalConnectionNodes(1,dqbus2 + 1); + sysmodel->addComponent(bus2); + + ModelLib::MicrogridBusDQ *bus3 = new ModelLib::MicrogridBusDQ(11, RN); + + bus3->setExternalConnectionNodes(0,dqbus3); + bus3->setExternalConnectionNodes(1,dqbus3 + 1); + sysmodel->addComponent(bus3); + + ModelLib::MicrogridBusDQ *bus4 = new ModelLib::MicrogridBusDQ(12, RN); + + bus4->setExternalConnectionNodes(0,dqbus4); + bus4->setExternalConnectionNodes(1,dqbus4 + 1); + sysmodel->addComponent(bus4); + + sysmodel->allocate(vec_size_total); + + std::cout << sysmodel->y().size() << std::endl; + std::cout << vec_size_internals << ", " << vec_size_externals << "\n"; + + //Create Intial points for states + for (size_t i = 0; i < vec_size_total; i++) + { + sysmodel->y()[i] = 0.0; + sysmodel->yp()[i] = 0.0; + } + + // Create Intial derivatives specifics generated in MATLAB + //DGs + for (size_t i = 0; i < 2; i++) + { + sysmodel->yp()[13*i + 3] = parms1.Vn; + sysmodel->yp()[13*i + 5] = parms1.Kpv * parms1.Vn; + sysmodel->yp()[13*i + 7] = (parms1.Kpc * parms1.Kpv * parms1.Vn) / parms1.Lf; + } + for (size_t i = 2; i < 4; i++) + { + sysmodel->yp()[13*i + 3] = parms2.Vn; + sysmodel->yp()[13*i + 5] = parms2.Kpv * parms2.Vn; + sysmodel->yp()[13*i + 7] = (parms2.Kpc * parms2.Kpv * parms2.Vn) / parms2.Lf; + } + + //since the intial P_com = 0 + sysmodel->y()[62] = parms1.wb; + + + + sysmodel->initialize(); + sysmodel->evaluateResidual(); + + std::vector& fres = sysmodel->getResidual(); + std::cout << "Verify Intial Resisdual is Zero: {\n"; + for (size_t i = 0; i < fres.size(); i++) + { + printf("%u : %e \n", i, fres[i]); + } + std::cout << "}\n"; + + sysmodel->updateTime(0.0, 1.0e-8); + sysmodel->evaluateJacobian(); + std::cout << "Intial Jacobian with alpha:\n"; + // std::cout << sysmodel->getJacobian().frobnorm() << "\n"; + + + // //Create numerical integrator and configure it for the generator model + // AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + // double t_init = 0.0; + // double t_final = 1.0; + + // // setup simulation + // idas->configureSimulation(); + // idas->getDefaultInitialCondition(); + // idas->initializeSimulation(t_init); + + // idas->runSimulation(t_final); + + // std::vector& yfinial = sysmodel->y(); + + // std::cout << "Final Vector y\n"; + // for (size_t i = 0; i < yfinial.size(); i++) + // { + // std::cout << yfinial[i] << "\n"; + // } + + return 0; +} diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index e902b1242..55fe476b9 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -18,8 +18,8 @@ int main(int argc, char const *argv[]) { - double abstol = 1e-8; - double reltol = 1e-8; + double abstol = 1.0e-8; + double reltol = 1.0e-8; bool usejac = true; //TODO:setup as named parameters @@ -132,9 +132,9 @@ int main(int argc, char const *argv[]) //analytical solution to the circuit yexact[0] = vinit; - yexact[2] = (-vinit / rinit) * (exp((rinit / linit) * t_final) - 1.0); + yexact[2] = (vinit / rinit) * (exp(-(rinit / linit) * t_final) - 1.0); yexact[3] = yexact[2]; - yexact[1] = vinit - rinit * yexact[2]; + yexact[1] = vinit + rinit * yexact[2]; std::cout << "Element-wise Relative error at t=" << t_final << "\n"; for (size_t i = 0; i < yfinial.size(); i++) diff --git a/SparseMatrix/COO_Matrix.hpp b/SparseMatrix/COO_Matrix.hpp index c256e015c..716748fa8 100644 --- a/SparseMatrix/COO_Matrix.hpp +++ b/SparseMatrix/COO_Matrix.hpp @@ -50,6 +50,7 @@ class COO_Matrix void AXPY(ScalarT alpha, COO_Matrix& a); void AXPY(ScalarT alpha, std::vector r, std::vector c, std::vector v); void SCAL(ScalarT alpha); + ScalarT frobnorm(); // --- Permutation Operations --- //No sorting is actually done. Only done when nesscary @@ -391,6 +392,14 @@ inline void COO_Matrix::SCAL(ScalarT alpha) for (auto i = this->values.begin(); i < this->values.end(); i++) *i *= alpha; } +template +inline ScalarT COO_Matrix::frobnorm() +{ + ScalarT totsum = 0.0; + for (auto i = this->values.begin(); i < this->values.end(); i++) totsum += abs(*i)^2; + return totsum; +} + /** * @brief Permutate the matrix to a different one. Only changes the coordinates * From 77827febc85c5a1e76badb0c3c9cc9d7a764070f Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 19 Feb 2024 18:53:44 -0500 Subject: [PATCH 21/52] Working Microgrid (Finite Difference) - "grounded" the rotor difference in reference - Comparing agianst reference from MATLAB --- Examples/Microgrid/Microgrid.cpp | 168 +++++++++++++++++++++++-------- Solver/Dynamic/Ida.cpp | 6 +- 2 files changed, 130 insertions(+), 44 deletions(-) diff --git a/Examples/Microgrid/Microgrid.cpp b/Examples/Microgrid/Microgrid.cpp index a0cf8dc9b..5f788080a 100644 --- a/Examples/Microgrid/Microgrid.cpp +++ b/Examples/Microgrid/Microgrid.cpp @@ -19,9 +19,9 @@ int main(int argc, char const *argv[]) { - double abstol = 1.0e-4; - double reltol = 1.0e-4; - bool usejac = true; + double abstol = 1.0e-8; + double reltol = 1.0e-8; + bool usejac = false; //TODO:setup as named parameters //Create circuit model @@ -36,14 +36,14 @@ int main(int argc, char const *argv[]) parms1.wb = 2.0*M_PI*50.0; parms1.wc = 31.41; parms1.mp = 9.4e-5; - parms1.Vn = 380; + parms1.Vn = 380.0; parms1.nq = 1.3e-3; parms1.F = 0.75; parms1.Kiv = 420.0; parms1.Kpv = 0.1; - parms1.Kic = 20.0 * 1.0e3; + parms1.Kic = 2.0e4; parms1.Kpc = 15.0; - parms1.Cf = 50.0e-6; + parms1.Cf = 5.0e-5; parms1.rLf = 0.1; parms1.Lf = 1.35e-3; parms1.rLc = 0.03; @@ -54,12 +54,12 @@ int main(int argc, char const *argv[]) parms2.wb = 2.0*M_PI*50.0; parms2.wc = 31.41; parms2.mp = 12.5e-5; - parms2.Vn = 380; + parms2.Vn = 380.0; parms2.nq = 1.5e-3; parms2.F = 0.75; parms2.Kiv = 390.0; parms2.Kpv = 0.05; - parms2.Kic = 16.0 * 1.0e3; + parms2.Kic = 16.0e3; parms2.Kpc = 10.5; parms2.Cf = 50.0e-6; parms2.rLf = 0.1; @@ -87,14 +87,14 @@ int main(int argc, char const *argv[]) //indexing sets size_t Nsize = 2; - // DGs + Lines + Loads - size_t vec_size_internals = 13*(2*Nsize) + (2 + 4*(Nsize - 1)) + 2*Nsize; + // DGs + - refframe Lines + Loads + size_t vec_size_internals = 13*(2*Nsize) - 1 + (2 + 4*(Nsize - 1)) + 2*Nsize; // \omegaref + BusDQ size_t vec_size_externals = 1 + 2*(2*Nsize); - size_t dqbus1 = vec_size_externals + 1; - size_t dqbus2 = vec_size_externals + 3; - size_t dqbus3 = vec_size_externals + 5; - size_t dqbus4 = vec_size_externals + 7; + size_t dqbus1 = vec_size_internals + 1; + size_t dqbus2 = vec_size_internals + 3; + size_t dqbus3 = vec_size_internals + 5; + size_t dqbus4 = vec_size_internals + 7; size_t vec_size_total = vec_size_internals + vec_size_externals; @@ -108,13 +108,15 @@ int main(int argc, char const *argv[]) //outputs dg1->setExternalConnectionNodes(1,dqbus1); dg1->setExternalConnectionNodes(2,dqbus1 + 1); + //"grounding" of the difference + dg1->setExternalConnectionNodes(3,-1); //internal connections - for (size_t i = 0; i < 13; i++) + for (size_t i = 0; i < 12; i++) { - dg1->setExternalConnectionNodes(3 + i,indexv + i); + dg1->setExternalConnectionNodes(4 + i,indexv + i); } - indexv += 13; + indexv += 12; sysmodel->addComponent(dg1); //dg 2 @@ -300,22 +302,22 @@ int main(int argc, char const *argv[]) } // Create Intial derivatives specifics generated in MATLAB - //DGs - for (size_t i = 0; i < 2; i++) - { - sysmodel->yp()[13*i + 3] = parms1.Vn; - sysmodel->yp()[13*i + 5] = parms1.Kpv * parms1.Vn; - sysmodel->yp()[13*i + 7] = (parms1.Kpc * parms1.Kpv * parms1.Vn) / parms1.Lf; - } + //DGs 1 + sysmodel->yp()[2] = parms1.Vn; + sysmodel->yp()[4] = parms1.Kpv * parms1.Vn; + sysmodel->yp()[6] = (parms1.Kpc * parms1.Kpv * parms1.Vn) / parms1.Lf; + sysmodel->yp()[12 + 3] = parms1.Vn; + sysmodel->yp()[12 + 5] = parms1.Kpv * parms1.Vn; + sysmodel->yp()[12 + 7] = (parms1.Kpc * parms1.Kpv * parms1.Vn) / parms1.Lf; for (size_t i = 2; i < 4; i++) { - sysmodel->yp()[13*i + 3] = parms2.Vn; - sysmodel->yp()[13*i + 5] = parms2.Kpv * parms2.Vn; - sysmodel->yp()[13*i + 7] = (parms2.Kpc * parms2.Kpv * parms2.Vn) / parms2.Lf; + sysmodel->yp()[13*i - 1 + 3] = parms2.Vn; + sysmodel->yp()[13*i - 1 + 5] = parms2.Kpv * parms2.Vn; + sysmodel->yp()[13*i - 1 + 7] = (parms2.Kpc * parms2.Kpv * parms2.Vn) / parms2.Lf; } //since the intial P_com = 0 - sysmodel->y()[62] = parms1.wb; + sysmodel->y()[vec_size_internals] = parms1.wb; @@ -336,26 +338,106 @@ int main(int argc, char const *argv[]) // std::cout << sysmodel->getJacobian().frobnorm() << "\n"; - // //Create numerical integrator and configure it for the generator model - // AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + //Create numerical integrator and configure it for the generator model + AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + double t_init = 0.0; + double t_final = 1.0; - // double t_init = 0.0; - // double t_final = 1.0; + // setup simulation + idas->configureSimulation(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); - // // setup simulation - // idas->configureSimulation(); - // idas->getDefaultInitialCondition(); - // idas->initializeSimulation(t_init); + idas->runSimulation(t_final); - // idas->runSimulation(t_final); + std::vector& yfinial = sysmodel->y(); - // std::vector& yfinial = sysmodel->y(); + std::cout << "Final Vector y\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << yfinial[i] << "\n"; + } - // std::cout << "Final Vector y\n"; - // for (size_t i = 0; i < yfinial.size(); i++) - // { - // std::cout << yfinial[i] << "\n"; - // } + //Generate from MATLAB code ODE form with tolerances of 1e-12 + std::vectortrue_vec{ + 2.297543153595780e+04, + 1.275311524125022e+04, + 3.763060183116022e-02, + -2.098153459325261e-02, + 1.848285659119097e-02, + -1.563291404944864e-04, + 6.321941907011718e+01, + -2.942264300846256e+01, + 3.634209302905854e+02, + -2.668928293656362e-06, + 6.321941919221522e+01, + -3.509200178595996e+01, + -7.555954467454730e-03, + 2.297580486511343e+04, + 8.742028429066131e+03, + 3.710079564796484e-02, + -1.421122598056797e-02, + 1.874079517807597e-02, + -9.891304812687215e-05, + 6.232933298360234e+01, + -1.796494061423331e+01, + 3.686353885026506e+02, + 3.465673854181523e-05, + 6.232933406188410e+01, + -2.371564475187742e+01, + -8.273939686941580e-02, + 1.727775042678524e+04, + 1.649365247247288e+04, + 3.116555157570849e-02, + -2.985990066758010e-02, + 2.250012115906506e-02, + -2.643873146501096e-04, + 4.861823510250247e+01, + -4.088592755441309e+01, + 3.552597163751238e+02, + -1.496407194199739e-04, + 4.861823504694532e+01, + -4.642797132602495e+01, + -8.445727984408551e-02, + 1.727723725566433e+04, + 9.182386962936238e+03, + 3.024959333190777e-02, + -1.617250828202081e-02, + 2.318056864131751e-02, + -1.295918667730514e-04, + 4.718938244522050e+01, + -1.935782085675469e+01, + 3.662262287803608e+02, + 1.076423957830039e-04, + 4.718938116520511e+01, + -2.507094256286497e+01, + -1.881248349415025e+01, + 2.114714832305742e+01, + 4.329946674909793e+01, + -3.037887936225145e+00, + -4.487023117352992e+01, + 2.895883729832657e+01, + 8.199613345691378e+01, + -5.623856502948122e+01, + 1.327498499660322e+02, + -8.228065162347022e+01, + 3.119995747945993e+02, + 3.576922945168803e+02, + -5.850795361581618e+00, + 3.641193316268954e+02, + -8.846325267612976e+00, + 3.472146752739036e+02, + -3.272400970143252e+01, + 3.604108939430972e+02, + -3.492842627398574e+01 + }; + + std::cout << "Test the Relative Error\n"; + for (size_t i = 0; i < true_vec.size(); i++) + { + printf("%u : %e ,\n", i, abs(true_vec[i] - yfinial[i]) / abs(true_vec[i])); + } return 0; } diff --git a/Solver/Dynamic/Ida.cpp b/Solver/Dynamic/Ida.cpp index 5137119f1..1bae455f1 100644 --- a/Solver/Dynamic/Ida.cpp +++ b/Solver/Dynamic/Ida.cpp @@ -134,6 +134,10 @@ namespace Sundials retval = IDASStolerances(solver_, rtol, atol); checkOutput(retval, "IDASStolerances"); + /// \todo Need to set max number of steps based on user input! + retval = IDASetMaxNumSteps(solver_, 5000); + checkOutput(retval, "IDASetMaxNumSteps"); + // Tag differential variables std::vector& tag = model_->tag(); if (static_cast(tag.size()) == model_->size()) @@ -415,7 +419,7 @@ namespace Sundials checkOutput(retval, "IDASetUserDataB"); /// \todo Need to set max number of steps based on user input! - retval = IDASetMaxNumStepsB(solver_, backwardID_, 2000); + retval = IDASetMaxNumStepsB(solver_, backwardID_, 200); checkOutput(retval, "IDASetMaxNumSteps"); // Set up linear solver From a3077ebc356b5efe6e95b24b5ca1608355ca0f61 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Thu, 22 Feb 2024 14:11:25 -0500 Subject: [PATCH 22/52] Fixed the Jacobian in Microgrid Example --- .../DiscreteGenerator/DiscreteGenerator.cpp | 5 +++-- Examples/Microgrid/Microgrid.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp index 607ec5312..038a24ea2 100644 --- a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp @@ -165,6 +165,7 @@ int DiscreteGenerator::evaluateResidual() template int DiscreteGenerator::evaluateJacobian() { + this->J_.zeroMatrix(); //Create dF/dy' std::vector rcordder(13); std::vector valsder(13, -1.0); @@ -186,7 +187,7 @@ int DiscreteGenerator::evaluateJacobian() ctemp = {3, 14, 15}; rtemp.clear(); for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(1); - valtemp = { - sin(y_[3]) * y_[14] - cos(y_[3]) * y_[15], cos(y_[3]),sin(y_[3])}; + valtemp = { - sin(y_[3]) * y_[14] - cos(y_[3]) * y_[15], cos(y_[3]),-sin(y_[3])}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 2 @@ -194,7 +195,7 @@ int DiscreteGenerator::evaluateJacobian() ctemp = {3, 14, 15}; rtemp.clear(); for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(2); - valtemp = { - cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15], -sin(y_[3]),cos(y_[3])}; + valtemp = { cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15], sin(y_[3]),cos(y_[3])}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 3 diff --git a/Examples/Microgrid/Microgrid.cpp b/Examples/Microgrid/Microgrid.cpp index 5f788080a..dddd4f291 100644 --- a/Examples/Microgrid/Microgrid.cpp +++ b/Examples/Microgrid/Microgrid.cpp @@ -21,7 +21,7 @@ int main(int argc, char const *argv[]) { double abstol = 1.0e-8; double reltol = 1.0e-8; - bool usejac = false; + bool usejac = true; //TODO:setup as named parameters //Create circuit model From bff132735d0fc981893c3a06d7af1464b75ef73f Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Thu, 22 Feb 2024 14:26:46 -0500 Subject: [PATCH 23/52] Added a max step size control for model objects --- Examples/Microgrid/Microgrid.cpp | 3 ++- ModelEvaluator.hpp | 1 + ModelEvaluatorImpl.hpp | 7 +++++++ PowerElectronicsModel.hpp | 7 +++++-- Solver/Dynamic/Ida.cpp | 5 ++++- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Examples/Microgrid/Microgrid.cpp b/Examples/Microgrid/Microgrid.cpp index dddd4f291..acc8be386 100644 --- a/Examples/Microgrid/Microgrid.cpp +++ b/Examples/Microgrid/Microgrid.cpp @@ -21,11 +21,12 @@ int main(int argc, char const *argv[]) { double abstol = 1.0e-8; double reltol = 1.0e-8; + size_t max_step_amount = 3000; bool usejac = true; //TODO:setup as named parameters //Create circuit model - ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac); + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac, max_step_amount); //Modeled after the problem in the paper double RN = 1.0e4; diff --git a/ModelEvaluator.hpp b/ModelEvaluator.hpp index 50c5e8b77..ad56fbd48 100644 --- a/ModelEvaluator.hpp +++ b/ModelEvaluator.hpp @@ -107,6 +107,7 @@ namespace ModelLib virtual IdxT size_opt() = 0; virtual void updateTime(real_type t, real_type a) = 0; virtual void setTolerances(real_type& rtol, real_type& atol) const = 0; + virtual void setMaxSteps(IdxT& msa) const = 0; virtual std::vector& y() = 0; virtual const std::vector& y() const = 0; diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp index 928d26f30..0f8969f0b 100644 --- a/ModelEvaluatorImpl.hpp +++ b/ModelEvaluatorImpl.hpp @@ -139,6 +139,11 @@ namespace ModelLib atol = atol_; } + virtual void setMaxSteps(IdxT& msa) const + { + msa = max_steps_; + } + std::vector& y() { return y_; @@ -306,6 +311,8 @@ namespace ModelLib real_type rtol_; real_type atol_; + IdxT max_steps_; + IdxT idc_; }; diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp index 47efcc7f7..04508607f 100644 --- a/PowerElectronicsModel.hpp +++ b/PowerElectronicsModel.hpp @@ -50,18 +50,21 @@ class PowerElectronicsModel : public ModelEvaluatorImpl // Set system model tolerances as default rtol_ = 1e-4; atol_ = 1e-4; + this->max_steps_ = 2000; // By default use jacobian - usejac_ = true; + usejac_ = false; + } /** * @brief Constructor for the system model */ - PowerElectronicsModel(double rt, double at, bool ju) : ModelEvaluatorImpl(0, 0, 0) + PowerElectronicsModel(double rt=1e-4, double at=1e-4, bool ju=false, IdxT msa=2000) : ModelEvaluatorImpl(0, 0, 0) { // Set system model tolerances from input rtol_ = rt; atol_ = at; + this->max_steps_ = msa; // Can choose not to use jacobain usejac_ = ju; } diff --git a/Solver/Dynamic/Ida.cpp b/Solver/Dynamic/Ida.cpp index 1bae455f1..2be2913a9 100644 --- a/Solver/Dynamic/Ida.cpp +++ b/Solver/Dynamic/Ida.cpp @@ -133,9 +133,12 @@ namespace Sundials model_->setTolerances(rtol, atol); ///< \todo Function name should be "getTolerances"! retval = IDASStolerances(solver_, rtol, atol); checkOutput(retval, "IDASStolerances"); + + IdxT msa; + model_->setMaxSteps(msa); /// \todo Need to set max number of steps based on user input! - retval = IDASetMaxNumSteps(solver_, 5000); + retval = IDASetMaxNumSteps(solver_, msa); checkOutput(retval, "IDASetMaxNumSteps"); // Tag differential variables From 7919fb653223c02b650ed912ebd62aa93dce749e Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 26 Feb 2024 17:51:38 -0500 Subject: [PATCH 24/52] Working example with the scalable microgrid - not correct residuals --- Examples/CMakeLists.txt | 1 + Examples/Microgrid/Microgrid.cpp | 2 +- Examples/Scale_Microgrid/CMakeLists.txt | 13 + Examples/Scale_Microgrid/Scale_Microgrid.cpp | 366 +++++++++++++++++++ 4 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 Examples/Scale_Microgrid/CMakeLists.txt create mode 100644 Examples/Scale_Microgrid/Scale_Microgrid.cpp diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 2c53fcc25..3df418ba2 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -58,6 +58,7 @@ add_subdirectory(MatPowerTesting) add_subdirectory(RLCircuit) add_subdirectory(Microgrid) +add_subdirectory(Scale_Microgrid) add_subdirectory(SparseTest) add_subdirectory(DiscreteGeneratorTest) diff --git a/Examples/Microgrid/Microgrid.cpp b/Examples/Microgrid/Microgrid.cpp index acc8be386..275974b19 100644 --- a/Examples/Microgrid/Microgrid.cpp +++ b/Examples/Microgrid/Microgrid.cpp @@ -360,7 +360,7 @@ int main(int argc, char const *argv[]) std::cout << yfinial[i] << "\n"; } - //Generate from MATLAB code ODE form with tolerances of 1e-12 + //Generate from MATLAB code ODE form with tolerances of 1e-14 std::vectortrue_vec{ 2.297543153595780e+04, 1.275311524125022e+04, diff --git a/Examples/Scale_Microgrid/CMakeLists.txt b/Examples/Scale_Microgrid/CMakeLists.txt new file mode 100644 index 000000000..8ffc91d81 --- /dev/null +++ b/Examples/Scale_Microgrid/CMakeLists.txt @@ -0,0 +1,13 @@ + + + + +add_executable(scalemicrogrid Scale_Microgrid.cpp) +target_link_libraries(scalemicrogrid GRIDKIT::powerelec_disgen + GRIDKIT::powerelec_mircoline + GRIDKIT::powerelec_microload + GRIDKIT::solvers_dyn + GRIDKIT::powerelec_mircobusdq) + +add_test(NAME ScaleMicrogrid COMMAND $) +install(TARGETS scalemicrogrid RUNTIME DESTINATION bin) diff --git a/Examples/Scale_Microgrid/Scale_Microgrid.cpp b/Examples/Scale_Microgrid/Scale_Microgrid.cpp new file mode 100644 index 000000000..de5174e5e --- /dev/null +++ b/Examples/Scale_Microgrid/Scale_Microgrid.cpp @@ -0,0 +1,366 @@ + + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include +#include +#include + +int main(int argc, char const *argv[]) +{ + double abstol = 1.0e-8; + double reltol = 1.0e-8; + size_t max_step_amount = 3000; + bool usejac = true; + + //TODO:setup as named parameters + //Create circuit model + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac, max_step_amount); + + + //The amount of DG line load cobinations to generate for scale + size_t Nsize = 2; + + //Modeled after the problem in the paper + // Every Bus has the same virtual resistance. This is due to the numerical stability as mentioned in the paper. + double RN = 1.0e4; + + //DG Params Vector + //All DGs have the same set of parameters except for the first two. + ModelLib::DiscreteGeneratorParameters DG_parms1; + DG_parms1.wb = 2.0*M_PI*50.0; + DG_parms1.wc = 31.41; + DG_parms1.mp = 9.4e-5; + DG_parms1.Vn = 380.0; + DG_parms1.nq = 1.3e-3; + DG_parms1.F = 0.75; + DG_parms1.Kiv = 420.0; + DG_parms1.Kpv = 0.1; + DG_parms1.Kic = 2.0e4; + DG_parms1.Kpc = 15.0; + DG_parms1.Cf = 5.0e-5; + DG_parms1.rLf = 0.1; + DG_parms1.Lf = 1.35e-3; + DG_parms1.rLc = 0.03; + DG_parms1.Lc = 0.35e-3; + + ModelLib::DiscreteGeneratorParameters DG_parms2; + DG_parms2.wb = 2.0*M_PI*50.0; + DG_parms2.wc = 31.41; + DG_parms2.mp = 12.5e-5; + DG_parms2.Vn = 380.0; + DG_parms2.nq = 1.5e-3; + DG_parms2.F = 0.75; + DG_parms2.Kiv = 390.0; + DG_parms2.Kpv = 0.05; + DG_parms2.Kic = 16.0e3; + DG_parms2.Kpc = 10.5; + DG_parms2.Cf = 50.0e-6; + DG_parms2.rLf = 0.1; + DG_parms2.Lf = 1.35e-3; + DG_parms2.rLc = 0.03; + DG_parms2.Lc = 0.35e-3; + + std::vector> DGParams_list(2*Nsize, DG_parms2); + + DGParams_list[0] = DG_parms1; + DGParams_list[1] = DG_parms1; + + //line vector params + //Every odd line has the same parameters and every even line has the same parameters + double rline1 = 0.23; + double Lline1 = 0.1 / (2.0 * M_PI * 50.0); + double rline2 = 0.35; + double Lline2 = 0.58 / (2.0 * M_PI * 50.0); + std::vector rline_list(2*Nsize-1, 0.0); + std::vector Lline_list(2*Nsize-1, 0.0); + for (size_t i = 0; i < rline_list.size(); i++) + { + rline_list[i] = (i % 2) ? rline1 : rline2; + Lline_list[i] = (i % 2) ? Lline1 : Lline2; + } + + + //load parms + //Only the first load has the same paramaters. + double rload1 = 3.0; + double Lload1 = 2.0 / (2.0 * M_PI * 50.0); + double rload2 = 2.0; + double Lload2 = 1.0 / (2.0 * M_PI * 50.0); + + std::vector rload_list(Nsize, rload2); + std::vector Lload_list(Nsize, Lload2); + rload_list[0] = rload1; + Lload_list[0] = Lload1; + + // DGs + - refframe Lines + Loads + size_t vec_size_internals = 13*(2*Nsize) - 1 + (2 + 4*(Nsize - 1)) + 2*Nsize; + // \omegaref + BusDQ + size_t vec_size_externals = 1 + 2*(2*Nsize); + + std::vector vdqbus_index(2*Nsize,0); + vdqbus_index[0] = vec_size_internals + 1; + for (size_t i = 1; i < vdqbus_index.size(); i++) + { + vdqbus_index[i] = vdqbus_index[i-1] + 2; + } + + //Total size of the vector setup + size_t vec_size_total = vec_size_internals + vec_size_externals; + + + //Create the reference DG + ModelLib::DiscreteGenerator *dg_ref = new ModelLib::DiscreteGenerator(0, DGParams_list[0], true); + //ref motor + dg_ref->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg_ref->setExternalConnectionNodes(1,vdqbus_index[0]); + dg_ref->setExternalConnectionNodes(2,vdqbus_index[0] + 1); + //"grounding" of the difference + dg_ref->setExternalConnectionNodes(3,-1); + //internal connections + for (size_t i = 0; i < 12; i++) + { + + dg_ref->setExternalConnectionNodes(4 + i,i); + } + sysmodel->addComponent(dg_ref); + + //Keep track of models and index location + size_t indexv = 12; + size_t model_id = 1; + //Add all other DGs + for (size_t i = 1; i < 2*Nsize; i++) + { + + //current DG to add + ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(model_id, DGParams_list[i], false); + //ref motor + dg->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg->setExternalConnectionNodes(1,vdqbus_index[i]); + dg->setExternalConnectionNodes(2,vdqbus_index[i] + 1); + //internal connections + for (size_t j = 0; j < 13; j++) + { + + dg->setExternalConnectionNodes(3 + j,indexv + j); + } + indexv += 13; + sysmodel->addComponent(dg); + model_id++; + } + + // Load all the Line compoenents + for (size_t i = 0; i < 2*Nsize - 1; i++) + { + //line + ModelLib::MicrogridLine *line_model = new ModelLib::MicrogridLine(model_id, rline_list[i], Lline_list[i]); + //ref motor + line_model->setExternalConnectionNodes(0,vec_size_internals); + //input connections + line_model->setExternalConnectionNodes(1,vdqbus_index[i]); + line_model->setExternalConnectionNodes(2,vdqbus_index[i] + 1); + //output connections + line_model->setExternalConnectionNodes(3,vdqbus_index[i+1]); + line_model->setExternalConnectionNodes(4,vdqbus_index[i+1] + 1); + //internal connections + for (size_t j = 0; j < 2; j++) + { + line_model->setExternalConnectionNodes(5 + j,indexv + j); + } + indexv += 2; + sysmodel->addComponent(line_model); + model_id++; + } + + // Load all the Load components + for (size_t i = 0; i < Nsize; i++) + { + ModelLib::MicrogridLoad *load_model = new ModelLib::MicrogridLoad(model_id, rload_list[i], Lload_list[i]); + //ref motor + load_model->setExternalConnectionNodes(0,vec_size_internals); + //input connections + load_model->setExternalConnectionNodes(1,vdqbus_index[2*i]); + load_model->setExternalConnectionNodes(2,vdqbus_index[2*i] + 1); + //internal connections + for (size_t j = 0; j < 2; j++) + { + + load_model->setExternalConnectionNodes(3 + j,indexv + j); + } + indexv += 2; + sysmodel->addComponent(load_model); + model_id++; + } + + //Add all the microgrid Virtual DQ Buses + for (size_t i = 0; i < 2*Nsize; i++) + { + ModelLib::MicrogridBusDQ *virDQbus_model = new ModelLib::MicrogridBusDQ( + model_id, RN); + + virDQbus_model->setExternalConnectionNodes(0, vdqbus_index[i]); + virDQbus_model->setExternalConnectionNodes(1, vdqbus_index[i] + 1); + sysmodel->addComponent(virDQbus_model); + + model_id++; + } + + //allocate all the intial conditions + sysmodel->allocate(vec_size_total); + + std::cout << sysmodel->y().size() << std::endl; + std::cout << vec_size_internals << ", " << vec_size_externals << "\n"; + + //Create Intial points for states. Every state is to specified to the zero intially + for (size_t i = 0; i < vec_size_total; i++) + { + sysmodel->y()[i] = 0.0; + sysmodel->yp()[i] = 0.0; + } + + // Create Intial derivatives specifics generated in MATLAB + for (size_t i = 0; i < 2*Nsize; i++) + { + sysmodel->yp()[13*i - 1 + 3] = DGParams_list[i].Vn; + sysmodel->yp()[13*i - 1 + 5] = DGParams_list[i].Kpv * DGParams_list[i].Vn; + sysmodel->yp()[13*i - 1 + 7] = (DGParams_list[i].Kpc * DGParams_list[i].Kpv * DGParams_list[i].Vn) / DGParams_list[i].Lf; + } + + //since the intial P_com = 0, the set the intial vector to the reference frame + sysmodel->y()[vec_size_internals] = DG_parms1.wb; + + sysmodel->initialize(); + sysmodel->evaluateResidual(); + + std::vector& fres = sysmodel->getResidual(); + std::cout << "Verify Intial Resisdual is Zero: {\n"; + for (size_t i = 0; i < fres.size(); i++) + { + printf("%u : %e \n", i, fres[i]); + } + std::cout << "}\n"; + + sysmodel->updateTime(0.0, 1.0e-8); + sysmodel->evaluateJacobian(); + std::cout << "Intial Jacobian with alpha:\n"; + // std::cout << sysmodel->getJacobian().frobnorm() << "\n"; + + + //Create numerical integrator and configure it for the generator model + AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + double t_init = 0.0; + double t_final = 1.0; + + // setup simulation + idas->configureSimulation(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + + idas->runSimulation(t_final); + + std::vector& yfinial = sysmodel->y(); + + std::cout << "Final Vector y\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << yfinial[i] << "\n"; + } + + if(Nsize == 2) + { + //Generate from MATLAB code ODE form with tolerances of 1e-14 + std::vectortrue_vec{ + 2.297543153595780e+04, + 1.275311524125022e+04, + 3.763060183116022e-02, + -2.098153459325261e-02, + 1.848285659119097e-02, + -1.563291404944864e-04, + 6.321941907011718e+01, + -2.942264300846256e+01, + 3.634209302905854e+02, + -2.668928293656362e-06, + 6.321941919221522e+01, + -3.509200178595996e+01, + -7.555954467454730e-03, + 2.297580486511343e+04, + 8.742028429066131e+03, + 3.710079564796484e-02, + -1.421122598056797e-02, + 1.874079517807597e-02, + -9.891304812687215e-05, + 6.232933298360234e+01, + -1.796494061423331e+01, + 3.686353885026506e+02, + 3.465673854181523e-05, + 6.232933406188410e+01, + -2.371564475187742e+01, + -8.273939686941580e-02, + 1.727775042678524e+04, + 1.649365247247288e+04, + 3.116555157570849e-02, + -2.985990066758010e-02, + 2.250012115906506e-02, + -2.643873146501096e-04, + 4.861823510250247e+01, + -4.088592755441309e+01, + 3.552597163751238e+02, + -1.496407194199739e-04, + 4.861823504694532e+01, + -4.642797132602495e+01, + -8.445727984408551e-02, + 1.727723725566433e+04, + 9.182386962936238e+03, + 3.024959333190777e-02, + -1.617250828202081e-02, + 2.318056864131751e-02, + -1.295918667730514e-04, + 4.718938244522050e+01, + -1.935782085675469e+01, + 3.662262287803608e+02, + 1.076423957830039e-04, + 4.718938116520511e+01, + -2.507094256286497e+01, + -1.881248349415025e+01, + 2.114714832305742e+01, + 4.329946674909793e+01, + -3.037887936225145e+00, + -4.487023117352992e+01, + 2.895883729832657e+01, + 8.199613345691378e+01, + -5.623856502948122e+01, + 1.327498499660322e+02, + -8.228065162347022e+01, + 3.119995747945993e+02, + 3.576922945168803e+02, + -5.850795361581618e+00, + 3.641193316268954e+02, + -8.846325267612976e+00, + 3.472146752739036e+02, + -3.272400970143252e+01, + 3.604108939430972e+02, + -3.492842627398574e+01 + }; + + std::cout << "Test the Relative Error\n"; + for (size_t i = 0; i < true_vec.size(); i++) + { + printf("%u : %e ,\n", i, abs(true_vec[i] - yfinial[i]) / abs(true_vec[i])); + } + } + + return 0; +} From 5baeb0328470668deedacbdf0b28f9e0f9620ea3 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 26 Feb 2024 18:01:35 -0500 Subject: [PATCH 25/52] Fixed N=2 case --- Examples/Scale_Microgrid/Scale_Microgrid.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Examples/Scale_Microgrid/Scale_Microgrid.cpp b/Examples/Scale_Microgrid/Scale_Microgrid.cpp index de5174e5e..c4be8df86 100644 --- a/Examples/Scale_Microgrid/Scale_Microgrid.cpp +++ b/Examples/Scale_Microgrid/Scale_Microgrid.cpp @@ -86,8 +86,8 @@ int main(int argc, char const *argv[]) std::vector Lline_list(2*Nsize-1, 0.0); for (size_t i = 0; i < rline_list.size(); i++) { - rline_list[i] = (i % 2) ? rline1 : rline2; - Lline_list[i] = (i % 2) ? Lline1 : Lline2; + rline_list[i] = (i % 2) ? rline2 : rline1; + Lline_list[i] = (i % 2) ? Lline2 : Lline1; } @@ -144,7 +144,7 @@ int main(int argc, char const *argv[]) { //current DG to add - ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(model_id, DGParams_list[i], false); + ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(model_id++, DGParams_list[i], false); //ref motor dg->setExternalConnectionNodes(0,vec_size_internals); //outputs @@ -158,14 +158,13 @@ int main(int argc, char const *argv[]) } indexv += 13; sysmodel->addComponent(dg); - model_id++; } // Load all the Line compoenents for (size_t i = 0; i < 2*Nsize - 1; i++) { //line - ModelLib::MicrogridLine *line_model = new ModelLib::MicrogridLine(model_id, rline_list[i], Lline_list[i]); + ModelLib::MicrogridLine *line_model = new ModelLib::MicrogridLine(model_id++, rline_list[i], Lline_list[i]); //ref motor line_model->setExternalConnectionNodes(0,vec_size_internals); //input connections @@ -181,13 +180,12 @@ int main(int argc, char const *argv[]) } indexv += 2; sysmodel->addComponent(line_model); - model_id++; } // Load all the Load components for (size_t i = 0; i < Nsize; i++) { - ModelLib::MicrogridLoad *load_model = new ModelLib::MicrogridLoad(model_id, rload_list[i], Lload_list[i]); + ModelLib::MicrogridLoad *load_model = new ModelLib::MicrogridLoad(model_id++, rload_list[i], Lload_list[i]); //ref motor load_model->setExternalConnectionNodes(0,vec_size_internals); //input connections @@ -201,20 +199,17 @@ int main(int argc, char const *argv[]) } indexv += 2; sysmodel->addComponent(load_model); - model_id++; } //Add all the microgrid Virtual DQ Buses for (size_t i = 0; i < 2*Nsize; i++) { ModelLib::MicrogridBusDQ *virDQbus_model = new ModelLib::MicrogridBusDQ( - model_id, RN); + model_id++, RN); virDQbus_model->setExternalConnectionNodes(0, vdqbus_index[i]); virDQbus_model->setExternalConnectionNodes(1, vdqbus_index[i] + 1); sysmodel->addComponent(virDQbus_model); - - model_id++; } //allocate all the intial conditions From 2d4ad96960fb7eb629cc39b70db5b2ca9d494a31 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 26 Feb 2024 19:04:44 -0500 Subject: [PATCH 26/52] Multiple Scaled Problems with References - Added N = 2,4,8 reference solutions from MATLAB - Microgrid Matches results for given sizes --- Examples/Scale_Microgrid/Scale_Microgrid.cpp | 123 ++++---- Examples/Scale_Microgrid/microgrid_N2.txt | 70 +++++ Examples/Scale_Microgrid/microgrid_N4.txt | 142 +++++++++ Examples/Scale_Microgrid/microgrid_N8.txt | 286 +++++++++++++++++++ 4 files changed, 546 insertions(+), 75 deletions(-) create mode 100644 Examples/Scale_Microgrid/microgrid_N2.txt create mode 100644 Examples/Scale_Microgrid/microgrid_N4.txt create mode 100644 Examples/Scale_Microgrid/microgrid_N8.txt diff --git a/Examples/Scale_Microgrid/Scale_Microgrid.cpp b/Examples/Scale_Microgrid/Scale_Microgrid.cpp index c4be8df86..15b54abff 100644 --- a/Examples/Scale_Microgrid/Scale_Microgrid.cpp +++ b/Examples/Scale_Microgrid/Scale_Microgrid.cpp @@ -29,7 +29,10 @@ int main(int argc, char const *argv[]) //The amount of DG line load cobinations to generate for scale - size_t Nsize = 2; + size_t Nsize = 8; + + //Set to false if the parameters choosen are not used to generate data files + bool orgparams = true; //Modeled after the problem in the paper // Every Bus has the same virtual resistance. This is due to the numerical stability as mentioned in the paper. @@ -274,88 +277,58 @@ int main(int argc, char const *argv[]) std::cout << yfinial[i] << "\n"; } - if(Nsize == 2) + //if proper MATLAB results are avalible and model is using origional parameters + //All data generated with abstol=1e-12 and reltol=1e-12 with ode23tb + if (orgparams && (Nsize == 2 || Nsize == 4 || Nsize == 8)) { - //Generate from MATLAB code ODE form with tolerances of 1e-14 - std::vectortrue_vec{ - 2.297543153595780e+04, - 1.275311524125022e+04, - 3.763060183116022e-02, - -2.098153459325261e-02, - 1.848285659119097e-02, - -1.563291404944864e-04, - 6.321941907011718e+01, - -2.942264300846256e+01, - 3.634209302905854e+02, - -2.668928293656362e-06, - 6.321941919221522e+01, - -3.509200178595996e+01, - -7.555954467454730e-03, - 2.297580486511343e+04, - 8.742028429066131e+03, - 3.710079564796484e-02, - -1.421122598056797e-02, - 1.874079517807597e-02, - -9.891304812687215e-05, - 6.232933298360234e+01, - -1.796494061423331e+01, - 3.686353885026506e+02, - 3.465673854181523e-05, - 6.232933406188410e+01, - -2.371564475187742e+01, - -8.273939686941580e-02, - 1.727775042678524e+04, - 1.649365247247288e+04, - 3.116555157570849e-02, - -2.985990066758010e-02, - 2.250012115906506e-02, - -2.643873146501096e-04, - 4.861823510250247e+01, - -4.088592755441309e+01, - 3.552597163751238e+02, - -1.496407194199739e-04, - 4.861823504694532e+01, - -4.642797132602495e+01, - -8.445727984408551e-02, - 1.727723725566433e+04, - 9.182386962936238e+03, - 3.024959333190777e-02, - -1.617250828202081e-02, - 2.318056864131751e-02, - -1.295918667730514e-04, - 4.718938244522050e+01, - -1.935782085675469e+01, - 3.662262287803608e+02, - 1.076423957830039e-04, - 4.718938116520511e+01, - -2.507094256286497e+01, - -1.881248349415025e+01, - 2.114714832305742e+01, - 4.329946674909793e+01, - -3.037887936225145e+00, - -4.487023117352992e+01, - 2.895883729832657e+01, - 8.199613345691378e+01, - -5.623856502948122e+01, - 1.327498499660322e+02, - -8.228065162347022e+01, - 3.119995747945993e+02, - 3.576922945168803e+02, - -5.850795361581618e+00, - 3.641193316268954e+02, - -8.846325267612976e+00, - 3.472146752739036e+02, - -3.272400970143252e+01, - 3.604108939430972e+02, - -3.492842627398574e+01 - }; + + //get relative path + std::string rel_path = std::filesystem::current_path(); + + const std::regex base_regex("(.+)\\/build.*"); + std::smatch base_match; + std::regex_match(rel_path, base_match, base_regex); + std::string base_path = base_match[1].str(); + + base_path += "/Examples/Scale_Microgrid"; + + switch (Nsize) + { + case 2: + base_path += "/microgrid_N2.txt"; + break; + case 4: + base_path += "/microgrid_N4.txt"; + break; + case 8: + base_path += "/microgrid_N8.txt"; + break; + default: + //shouldn't end up here bust just incase + assert(0==1); + break; + } + std::cout << base_path << std::endl; + + //load vector from data file + std::vector true_vec(vec_size_total, 0.0); + double val_cur = 0.0; + std::ifstream data_file(base_path); + size_t i = 0; + while (data_file >> val_cur && i < true_vec.size()) + { + true_vec[i++] = val_cur; + } + data_file.close(); + //check relative error std::cout << "Test the Relative Error\n"; for (size_t i = 0; i < true_vec.size(); i++) { printf("%u : %e ,\n", i, abs(true_vec[i] - yfinial[i]) / abs(true_vec[i])); } } + return 0; } diff --git a/Examples/Scale_Microgrid/microgrid_N2.txt b/Examples/Scale_Microgrid/microgrid_N2.txt new file mode 100644 index 000000000..d0edf2a51 --- /dev/null +++ b/Examples/Scale_Microgrid/microgrid_N2.txt @@ -0,0 +1,70 @@ +22975.4182636905 +12753.1173017451 +0.0376305671131306 +-0.0209815421114537 +0.0184828563235406 +-0.00015632917065729 +63.2193617412383 +-29.4226556659582 +363.420924977355 +-3.01001804456668e-06 +63.2193618667302 +-35.0920143829141 +-0.00755583999797958 +22975.8457840701 +8742.0172166684 +0.0371009878165673 +-0.0142112776774797 +0.0187407972932474 +-9.8913852531819e-05 +62.3296548917654 +-17.9650261562766 +368.635407345931 +3.79041261513032e-05 +62.3296560841534 +-23.7157298601546 +-0.0827401584095097 +17277.712521392 +16493.7578328327 +0.0311645357391787 +-0.0298601153771274 +0.0225001003469904 +-0.000264388302121386 +48.6166482764357 +-40.8862612232969 +355.25957014696 +-0.000167008045114112 +48.6166481095298 +-46.4283022775928 +-0.0844566209033113 +17277.2493364959 +9182.29479881977 +0.0302503981389185 +-0.0161722538457184 +0.023180586071601 +-0.000129590157483103 +47.1906392248137 +-19.3574255862892 +366.226354188735 +0.000121054462396047 +47.19063792117 +-25.0705499054599 +-18.8125403122072 +21.1471334522508 +43.2997340692497 +-3.03798323340816 +-44.8715356440453 +28.9585224749495 +81.99613295014 +-56.2385627562355 +132.749774614687 +-82.280664729262 +311.999576042192 +357.692287974629 +-5.85078929333349 +364.119335219897 +-8.84631033126304 +347.214535767435 +-32.7241067379802 +360.411028950125 +-34.9283280833745 diff --git a/Examples/Scale_Microgrid/microgrid_N4.txt b/Examples/Scale_Microgrid/microgrid_N4.txt new file mode 100644 index 000000000..29a0b71b8 --- /dev/null +++ b/Examples/Scale_Microgrid/microgrid_N4.txt @@ -0,0 +1,142 @@ +27828.3291148094 +10602.3611530864 +0.0452452394028709 +-0.0173410584955486 +0.018686818367312 +-0.000129595027000909 +76.0120809944985 +-23.2367034227098 +366.216582730654 +-0.000167782960864797 +76.0120710728117 +-28.9413214479885 +-0.0154989336357971 +27832.0772154743 +7838.80352597054 +0.0448129806183038 +-0.0127296381144373 +0.0188642014642206 +-9.04502393904097e-05 +75.2859236720964 +-15.4316980534341 +369.809174828127 +-5.17440472732025e-05 +75.285919083362 +-21.1922719962368 +-0.142596248886844 +20950.1519748442 +16334.3924580166 +0.0377787488551238 +-0.0295717781600636 +0.0225780601074885 +-0.000265567743682681 +58.9348270364006 +-40.4081583028089 +355.498460539903 +-8.66167274613643e-05 +58.9348242715342 +-45.9457664944992 +-0.164628885385433 +20956.2846481359 +12345.7855779785 +0.0371673110634281 +-0.0220171188824754 +0.0229486760225139 +-0.000191111142238558 +57.9810673844105 +-28.5265491599081 +361.481100853144 +8.24481547667206e-05 +57.9810719040216 +-34.1573355283559 +-0.245126576498858 +20978.9206932923 +17875.6825958711 +0.0380785081131898 +-0.0325621468970297 +0.0224354615928625 +-0.000295085318936756 +59.4025243779293 +-45.1101946009202 +353.186117339098 +5.52721744209165e-05 +59.4025238741703 +-50.6117204294148 +-0.253672269778405 +20990.6142554844 +11779.5685373245 +0.0371243965775962 +-0.0209716906203726 +0.0230016494389548 +-0.000180846578022512 +57.9140614794815 +-26.8817831662193 +362.331254349606 +0.000209247259473183 +57.9140782926947 +-32.5257339504705 +-0.288747285297145 +21004.5418902462 +16686.981801999 +0.0379131316203435 +-0.0302602142538338 +0.0225460339603269 +-0.000272422675391038 +59.1444740212228 +-41.4902940591195 +354.969993387113 +8.14114753778542e-05 +59.1444846638236 +-47.0195494892644 +-0.285876486857154 +21005.895228757 +8274.13913126834 +0.0366267978764156 +-0.0145584209340773 +0.0233276948336748 +-0.000117627382397687 +57.1378568500881 +-16.7923279871216 +367.58883605301 +0.000263351556352378 +57.1378679159653 +-22.518140603782 +-6.57009481597077 +28.1053117219546 +68.341829672125 +5.75010361666728 +-7.27398138223966 +42.3413009908014 +44.2901915856089 +-0.850144510998897 +-26.9214526328474 +37.7939474726438 +20.9421230166698 +-8.2155394685309 +-48.4341275019927 +37.706248875936 +82.5460878639016 +-57.0458911301263 +127.388509162578 +-90.4406093871607 +116.522583626035 +-102.149734009655 +112.650118587972 +-107.825883544914 +311.543402422187 +360.780248808368 +-7.42039816792328 +365.078323407317 +-13.2331839185884 +344.46378568747 +-54.5546252592288 +350.335287885457 +-63.572021962256 +334.342198258035 +-88.749585714325 +344.281369936645 +-94.7726681838823 +332.2248206198 +-103.942854393111 +347.103721199815 +-107.812479611979 diff --git a/Examples/Scale_Microgrid/microgrid_N8.txt b/Examples/Scale_Microgrid/microgrid_N8.txt new file mode 100644 index 000000000..3e1ba779b --- /dev/null +++ b/Examples/Scale_Microgrid/microgrid_N8.txt @@ -0,0 +1,286 @@ +29266.6517718661 +9842.93617289812 +0.0475360674334622 +-0.0160323945316821 +0.0187557247105805 +-0.000119821248231538 +79.8612117213119 +-21.0144010498971 +367.201497494684 +-0.00135963018489767 +79.8611351716573 +-26.7318789917162 +-0.018074876389402 +29296.9645459408 +7415.51099954903 +0.0471789367393934 +-0.0120180219897291 +0.0189117902285582 +-8.57914733703415e-05 +79.2614266664798 +-14.2194852461262 +370.357116139458 +-0.00065261697325357 +79.261388452934 +-19.9860446882469 +-0.161178046356866 +22178.7337755581 +15750.48869542 +0.0399575496599213 +-0.028431003000158 +0.0226540351215628 +-0.000255811047442045 +62.3338080750298 +-38.6061338491152 +356.372404460464 +-0.000888421043595241 +62.3337589017493 +-44.1546192236143 +-0.191206982234175 +22245.3587939821 +12476.0312983393 +0.0395296431152022 +-0.0222832972915751 +0.0229591349358969 +-0.000195357283522886 +61.6667253463805 +-28.9363062720176 +361.284131747149 +0.000606091049765824 +61.6667589580497 +-34.5611135316627 +-0.300475535038271 +22471.354929649 +17410.9400696732 +0.0407475331761201 +-0.0316496339533813 +0.0225047347006168 +-0.000287941144857336 +63.5662158978541 +-43.6654709736205 +353.882194971394 +-0.00050508442766251 +63.5661867600733 +-49.1745383652835 +-0.321406735230742 +22562.1063953332 +12532.040739496 +0.0400730650460856 +-0.0224103188019356 +0.0229590093469276 +-0.000197040279593967 +62.5145400797163 +-29.1337602252211 +361.200953962968 +0.00123813270414561 +62.5146115608051 +-34.7565572443792 +-0.398765881347133 +22822.9625175864 +17526.9123376124 +0.0413769691613727 +-0.0318846988884131 +0.0224996948233429 +-0.000290724959665147 +64.5480523645119 +-44.0326735095454 +353.709220392926 +-0.000255137918253834 +64.548036917491 +-49.5382706457328 +-0.409294621792759 +22917.4640781459 +11700.1980576741 +0.0405370737861658 +-0.0208717910251266 +0.0230419643488667 +-0.000182321342412399 +63.2383663569188 +-26.7111380754575 +362.449323338104 +0.00143605100750772 +63.2384503029344 +-32.3525635247183 +-0.460038982115987 +23175.0870418607 +17429.0372806116 +0.0419717095772374 +-0.0317010913432995 +0.0225145433123769 +-0.000289381352876061 +65.4757968347883 +-43.7415548084125 +353.856643943042 +-0.000116590766441278 +65.4757901489451 +-49.2486679790579 +-0.461848591689221 +23264.6732405303 +10919.0360806903 +0.0409947737541995 +-0.0194331296392293 +0.0231200668519233 +-0.000168575863901554 +63.9522672718067 +-24.4455560147541 +363.621937642842 +0.00154556746783549 +63.9523565934322 +-30.1044436917781 +-0.491529580804623 +23488.6137650364 +17313.8654584652 +0.0424952351974662 +-0.0314883547842804 +0.0225303364455447 +-0.000287714847080755 +66.2924442955506 +-43.4048501801219 +354.030311475628 +0.000169934086992562 +66.2924545883603 +-48.9139721676174 +-0.486548093474613 +23557.6136117665 +10241.0790360359 +0.0413774884672506 +-0.0181860120867723 +0.0231877453638413 +-0.000156639599075328 +64.5492156984859 +-22.4816084883194 +364.639179755733 +0.00142420279185394 +64.5492984953198 +-28.1556597465189 +-0.499726325044563 +23722.4168131373 +16958.7765974266 +0.0428487548646152 +-0.0308090857078185 +0.0225672437721518 +-0.000281355782039133 +66.8440182379463 +-42.3350991467661 +354.562942832682 +0.000573219240561573 +66.844044569212 +-47.8519918014414 +-0.490219448053285 +23769.8747006891 +9267.5206785042 +0.0415639300026818 +-0.0164109903099032 +0.0232814268213158 +-0.000139385907988285 +64.8399200066663 +-19.6874999818575 +366.100410278813 +0.00128332197988872 +64.8400012051758 +-25.3838027935624 +-0.491586583798841 +23854.0240861864 +15160.7060140903 +0.0427385845553072 +-0.0273659210853948 +0.0227360281885303 +-0.00024756822257102 +66.6722121992594 +-36.9193366680176 +357.260483774461 +0.000734666517031364 +66.6722602990682 +-42.4779079553274 +-0.482907936930927 +23870.5548740189 +6166.60742794455 +0.0412253604361869 +-0.0108406830677542 +0.0235710268609798 +-8.45378382385454e-05 +64.3117067426907 +-10.9219886629635 +370.751596332923 +0.00130490570318174 +64.3117765573399 +-16.6904284244068 +-2.9267653635869 +30.5878043390112 +75.9238910016987 +9.17392754248112 +4.3701560041079 +48.7765765968327 +58.3101300775815 +3.13323809951331 +-6.37573932293514 +46.1701408549949 +41.9244199648313 +-6.5432868117422 +-17.3691293511209 +41.8611610718482 +27.7383173553277 +-12.9709065074016 +-27.5322418670623 +38.9032728624808 +16.2733736528389 +-16.5280348065045 +-36.4800564569504 +37.0627808819117 +7.38198504755967 +-17.9899033675727 +-44.0731708800056 +36.9539474625741 +1.14781892918688 +-15.9507601441003 +-49.1751072411967 +44.6278268007059 +82.7517114852138 +-57.3188928805757 +125.959171148664 +-93.1822145893453 +110.816672146529 +-108.811406393296 +99.5107131550674 +-119.104827911048 +92.0427992280762 +-125.056967118294 +88.0811872722293 +-127.985464658329 +87.1649116220972 +-128.957730829954 +89.0189233593932 +-129.480383815729 +311.408200092424 +361.890500304156 +-7.90450151715305 +365.594288034004 +-14.6504114199963 +344.278948204657 +-61.517809887448 +348.104769580715 +-73.1715704285651 +329.472137794467 +-107.797643650827 +335.509251816504 +-117.787067889008 +317.044841017058 +-139.602945170765 +325.182412285621 +-147.51178633583 +307.989533967543 +-158.91998673915 +318.171184823086 +-165.141414351062 +302.951769665185 +-168.712626964975 +315.009688292198 +-173.624287308414 +302.070219389208 +-171.572667424371 +315.86470341008 +-175.706947618597 +306.288884765777 +-170.785573848562 +322.018589824395 +-176.179397251772 From 171db62d6f1dc2663bd2d3f8e4494b781cfc2fa6 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 20 Oct 2022 17:20:51 -0500 Subject: [PATCH 27/52] Add bus factory. --- ComponentLib/Bus/BaseBus.hpp | 9 +-------- ComponentLib/Bus/BusFactory.hpp | 27 ++++++++++++--------------- ComponentLib/Bus/BusPQ.cpp | 10 ++++++++++ ComponentLib/Bus/BusPQ.hpp | 8 ++++---- ComponentLib/Bus/BusPV.cpp | 10 ++++++++++ ComponentLib/Bus/BusPV.hpp | 10 +++++----- ComponentLib/Bus/BusSlack.cpp | 9 +++++++++ ComponentLib/Bus/BusSlack.hpp | 9 +++++---- 8 files changed, 56 insertions(+), 36 deletions(-) diff --git a/ComponentLib/Bus/BaseBus.hpp b/ComponentLib/Bus/BaseBus.hpp index 4e8cbd5f1..2fcb9a629 100644 --- a/ComponentLib/Bus/BaseBus.hpp +++ b/ComponentLib/Bus/BaseBus.hpp @@ -61,6 +61,7 @@ #define _BASE_BUS_HPP_ #include +// #include namespace ModelLib { @@ -141,14 +142,6 @@ namespace ModelLib virtual const ScalarT& QB() const = 0; virtual const int BusType() const = 0; - - virtual const IdxT BusID() const - { - return busID_; - } - - protected: - const IdxT busID_; }; // class BaseBus } // namespace ModelLib diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp index 68fc5578e..fc03c852b 100644 --- a/ComponentLib/Bus/BusFactory.hpp +++ b/ComponentLib/Bus/BusFactory.hpp @@ -59,35 +59,30 @@ #pragma once -#include -#include -#include -#include +#include +#include namespace ModelLib { - template + template class BusFactory { public: - using real_type = typename ModelEvaluatorImpl::real_type; - using BusData = GridKit::PowerSystemData::BusData; + using BusData = GridKit::MatPowerUtils::BusRow; - BusFactory() = delete; - - static BaseBus* create(BusData& data) + BaseBus* create(BusData& data) { - BaseBus* bus = nullptr; + BaseBus* bus = nullptr; switch(data.type) { case 1: - bus = new BusPQ(data); + bus = new BusPQ(data); break; case 2: - bus = new BusPV(data); + bus = new BusPV(data); break; case 3: - bus = new BusSlack(data); + bus = new BusSlack(data); break; default: // Throw exception @@ -95,6 +90,8 @@ namespace ModelLib { } return bus; } + private: + BusFactory(){} }; -} // namespace ModelLib \ No newline at end of file +} diff --git a/ComponentLib/Bus/BusPQ.cpp b/ComponentLib/Bus/BusPQ.cpp index 18c6ec22c..5ef2711b8 100644 --- a/ComponentLib/Bus/BusPQ.cpp +++ b/ComponentLib/Bus/BusPQ.cpp @@ -113,6 +113,16 @@ BusPQ::BusPQ(BusData& data) size_ = 2; } +template +BusPQ::BusPQ(BusData& data) + : V0_(data.Vm), theta0_(data.Va) +{ + //std::cout << "Create BusPQ..." << std::endl; + //std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 2; +} + template BusPQ::~BusPQ() { diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp index 45ed81a65..9fff6f6c5 100644 --- a/ComponentLib/Bus/BusPQ.hpp +++ b/ComponentLib/Bus/BusPQ.hpp @@ -61,7 +61,7 @@ #define _BUS_PQ_HPP_ #include "BaseBus.hpp" -#include +#include namespace ModelLib { @@ -86,8 +86,8 @@ namespace ModelLib using BaseBus::tag_; public: - using real_type = typename ModelEvaluatorImpl::real_type; - using BusData = GridKit::PowerSystemData::BusData; + typedef typename ModelEvaluatorImpl::real_type real_type; + using BusData = GridKit::MatPowerUtils::BusRow; BusPQ(); BusPQ(ScalarT V, ScalarT theta); @@ -183,7 +183,7 @@ namespace ModelLib virtual const int BusType() const { - return BaseBus::BusType::PQ; + return 1; } private: diff --git a/ComponentLib/Bus/BusPV.cpp b/ComponentLib/Bus/BusPV.cpp index d5a05dc98..cdd377bdb 100644 --- a/ComponentLib/Bus/BusPV.cpp +++ b/ComponentLib/Bus/BusPV.cpp @@ -111,6 +111,16 @@ BusPV::BusPV(BusData& data) size_ = 1; } +template +BusPV::BusPV(BusData& data) + : V_(data.Vm), theta0_(data.Va) //, Pg_(Pg) +{ + //std::cout << "Create BusPV ..." << std::endl; + //std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 1; +} + template BusPV::~BusPV() { diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index cf645d591..06165e2d2 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -62,7 +62,7 @@ #include #include "BaseBus.hpp" -#include +#include namespace ModelLib { @@ -87,11 +87,11 @@ namespace ModelLib using BaseBus::tag_; public: - using real_type = typename ModelEvaluatorImpl::real_type; - using BusData = GridKit::PowerSystemData::BusData; + typedef typename ModelEvaluatorImpl::real_type real_type; + using BusData = GridKit::MatPowerUtils::BusRow; BusPV(); - BusPV(ScalarT V, ScalarT theta0); + BusPV(ScalarT V, ScalarT theta0, ScalarT P); BusPV(BusData& data); virtual ~BusPV(); @@ -193,7 +193,7 @@ namespace ModelLib virtual const int BusType() const { - return BaseBus::BusType::PV; + return 2; } private: diff --git a/ComponentLib/Bus/BusSlack.cpp b/ComponentLib/Bus/BusSlack.cpp index 80a5ae091..2a961e8f8 100644 --- a/ComponentLib/Bus/BusSlack.cpp +++ b/ComponentLib/Bus/BusSlack.cpp @@ -109,6 +109,15 @@ BusSlack::BusSlack(BusData& data) size_ = 0; } +template +BusSlack::BusSlack(BusData& data) + : V_(data.Vm), theta_(data.Va) //, P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) +{ + //std::cout << "Create BusSlack..." << std::endl; + //std::cout << "Number of equations is " << size_ << std::endl; + size_ = 0; +} + template BusSlack::~BusSlack() { diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index 19c27d96a..95f6d4a32 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -61,7 +61,7 @@ #define _BUS_SLACK_HPP_ #include "BaseBus.hpp" -#include +#include namespace ModelLib { @@ -86,12 +86,13 @@ namespace ModelLib using BaseBus::rtol_; public: - using real_type = typename ModelEvaluatorImpl::real_type; - using BusData = GridKit::PowerSystemData::BusData; + typedef typename ModelEvaluatorImpl::real_type real_type; + using BusData = GridKit::MatPowerUtils::BusRow; BusSlack(); BusSlack(ScalarT V, ScalarT theta); BusSlack(BusData& data); + BusSlack(BusData& data); virtual ~BusSlack(); virtual int evaluateResidual(); virtual int evaluateAdjointResidual(); @@ -182,7 +183,7 @@ namespace ModelLib virtual const int BusType() const { - return BaseBus::BusType::Slack; + return 3; } private: From c6bb7876bd76f18e13c61919a2caba8a653cad11 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 20 Oct 2022 17:22:31 -0500 Subject: [PATCH 28/52] Parse load data from the input file. --- .../MatPowerTesting/test_parse_bus_row.cpp | 18 +- Utilities/FileIO.hpp | 41 ++- Utilities/MatPowerUtils.hpp | 243 ++++++++++++++++++ Utilities/Testing.hpp | 20 +- 4 files changed, 277 insertions(+), 45 deletions(-) create mode 100644 Utilities/MatPowerUtils.hpp diff --git a/Examples/MatPowerTesting/test_parse_bus_row.cpp b/Examples/MatPowerTesting/test_parse_bus_row.cpp index 38695c5fa..adfb38a16 100644 --- a/Examples/MatPowerTesting/test_parse_bus_row.cpp +++ b/Examples/MatPowerTesting/test_parse_bus_row.cpp @@ -28,15 +28,15 @@ mpc.bus = [ int main(int argc, char** argv) { int fail = 0; - std::vector> bus_answer{ - {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {4, 3, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, + std::vector> bus_answer{ + {1, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {2, 1, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {3, 2, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {4, 3, 400, 131.47, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {5, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; - std::vector> load_answer{ + std::vector> load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, @@ -45,7 +45,7 @@ int main(int argc, char** argv) { }; { - SystemModelData mp; + MatPower mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.bus, bus_answer)) fail++; @@ -53,7 +53,7 @@ int main(int argc, char** argv) { } { - SystemModelData mp; + MatPower mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.load, load_answer)) fail++; diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp index 825123c97..0db5df0c0 100644 --- a/Utilities/FileIO.hpp +++ b/Utilities/FileIO.hpp @@ -155,29 +155,22 @@ void checkEndOfMatrixRow(std::istream& is) throw std::runtime_error(matlab_syntax_error); } -template -void readMatPowerBusRow(const std::string& row, BusData& br, LoadData& lr) +template +// BusRow +void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow& lr) { logs() << "Parsing MATPOWER bus row\n"; std::stringstream is(row); - is >> br.bus_i // Bus ID - >> br.type // Bus type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated - >> lr.Pd // Active power demand [MW] - >> lr.Qd // Reactive power demand [MVAr] - >> br.Gs // Shunt conductance (MW demanded at V = 1.0 p.u.) - >> br.Bs // Shunt susceptance (MVAr injected at V = 1.0 p.u.) - >> br.area // Area number (>0) - >> br.Vm // Voltage magnitude (p.u.) - >> br.Va // Voltage phase (deg) - >> br.baseKV // Base voltage [kV] - >> br.zone // Loss zone number (>0) - >> br.Vmax // Maximum voltage magnitude (p.u.) - >> br.Vmin; // Minimum voltage magnitude (p.u.) + // BusRow br; + // LoadRow lr; + is >> br.bus_i >> br.type >> br.Pd >> br.Qd >> br.Gs >> br.Bs >> br.area + >> br.Vm >> br.Va >> br.baseKV >> br.zone >> br.Vmax >> br.Vmin; lr.bus_i = br.bus_i; - + lr.Pd = br.Pd; + lr.Qd = br.Qd; // std::cout << br.str(); - // logs() << "Read BusData with the following values:\n" << br.str(); + // logs() << "Read BusRow with the following values:\n" << br.str(); // return br; } @@ -308,11 +301,11 @@ template void readMatPower(SystemModelData& mp, std::istream& is) { - using BusDataT = BusData; - using GenDataT = GenData; - using BranchDataT = BranchData; - using GenCostDataT = GenCostData; - using LoadDataT = LoadData; + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; + using GenCostRowT = GenCostRow; + using LoadRowT = LoadRow; for (std::string line; std::getline(is, line);) { // Trim whitespace and remove comments @@ -335,8 +328,8 @@ void readMatPower(SystemModelData& mp, std::istream& is) if (component == "bus") { while (std::getline(is, line)) { if (line.find("];") != std::string::npos) break; - BusDataT br; - LoadDataT lr; + BusRowT br; + LoadRowT lr; readMatPowerBusRow(line, br, lr); mp.bus.push_back(std::move(br)); mp.load.push_back(std::move(lr)); diff --git a/Utilities/MatPowerUtils.hpp b/Utilities/MatPowerUtils.hpp new file mode 100644 index 000000000..a9d52e537 --- /dev/null +++ b/Utilities/MatPowerUtils.hpp @@ -0,0 +1,243 @@ +#pragma once +#include +#include +#include +#include + +/** + * + * @file Utilities/MatPowerUtils.hpp + * @author Asher Mancinelli + * + * @remark `std::stringstream` is preferred over `operator+(std::string, ...)` + * due to stringstream's lack of reallocation on append. + * + */ + +namespace GridKit +{ + +namespace MatPowerUtils +{ + + template + struct BusRow + { + IntT bus_i; ///< Bus ID + IntT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + RealT Pd; ///< Active power demand [MW] + RealT Qd; ///< Reactive power demand [MVAr] + RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) + RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) + IntT area; ///< Area number (>0) + RealT Vm; ///< Voltage magnitude (p.u.) + RealT Va; ///< Voltage phase (deg) + RealT baseKV; ///< Base voltage [kV] + IntT zone; ///< Loss zone number (>0) + RealT Vmax; ///< Maximum voltage magnitude (p.u.) + RealT Vmin; ///< Minimum voltage magnitude (p.u.) + + inline std::string str() const + { + std::stringstream ss; + std::cerr << std::setw(10) << bus_i + << std::setw(10) << type + << std::setw(10) << Pd + << std::setw(10) << Qd + << std::setw(10) << Gs + << std::setw(10) << Bs + << std::setw(10) << area + << std::setw(10) << Vm + << std::setw(10) << Va + << std::setw(10) << baseKV + << std::setw(10) << zone + << std::setw(10) << Vmax + << std::setw(10) << Vmin; + ss << "\n"; + return ss.str(); + } + }; + + template + struct LoadRow + { + IntT bus_i; ///< Bus ID + RealT Pd; ///< Active power demand [MW] + RealT Qd; ///< Reactive power demand [MVAr] + + inline std::string str() const + { + std::stringstream ss; + std::cerr << std::setw(10) << bus_i + << std::setw(10) << Pd + << std::setw(10) << Qd; + ss << "\n"; + return ss.str(); + } + }; + + template + struct GenRow + { + IntT bus; ///< Bus ID + RealT Pg; ///< Active power output [MW] + RealT Qg; ///< Reactive power output [MVAr] + RealT Qmax; ///< Maximum reactive power output [MVAr] + RealT Qmin; ///< Minimum reactive power output [MVAr] + RealT Vg; ///< + RealT mBase; ///< Total MVA base of machine + IntT status; ///< Service status (>0 in service, <=0 out of service) + RealT Pmax; ///< Maximum active power output [MVAr] + RealT Pmin; ///< Minimum active power output [MVAr] + RealT Pc1; ///< + RealT Pc2; ///< + RealT Qc1min; ///< + RealT Qc1max; ///< + RealT Qc2min; ///< + RealT Qc2max; ///< + RealT ramp_agc; ///< + RealT ramp_10; ///< + RealT ramp_30; ///< + RealT ramp_q; ///< + RealT apf; ///< + + inline std::string str() const + { + std::stringstream ss; + ss << std::setw(10) << bus + << std::setw(10) << Pg + << std::setw(10) << Qg + << std::setw(10) << Qmax + << std::setw(10) << Qmin + << std::setw(10) << Vg + << std::setw(10) << mBase + << std::setw(10) << status + << std::setw(10) << Pmax + << std::setw(10) << Pmin + << std::setw(10) << Pc1 + << std::setw(10) << Pc2 + << std::setw(10) << Qc1min + << std::setw(10) << Qc1max + << std::setw(10) << Qc2min + << std::setw(10) << Qc2max + << std::setw(10) << ramp_agc + << std::setw(10) << ramp_10 + << std::setw(10) << ramp_30 + << std::setw(10) << ramp_q + << std::setw(10) << apf; + ss << "\n"; + return ss.str(); + } + }; + + template + struct BranchRow + { + IntT fbus; ///< "From" bus ID + IntT tbus; ///< "To" bus ID + RealT r; ///< Resistance (p.u.) + RealT x; ///< Reactance (p.u.) + RealT b; ///< Total line charging susceptance (p.u.) + RealT rateA; ///< MVA rating A (long term rating), 0=unlimited + RealT rateB; ///< MVA rating B (short term rating), 0=unlimited + RealT rateC; ///< MVA rating C (emergency rating), 0=unlimited + RealT ratio; ///< Transformer off nominal turns ratio + RealT angle; ///< Transformer phase shift angle [deg], positive ⇒ delay + IntT status; ///< Initial service status: 1=in-service, 0=out-of-service + RealT angmin; ///< Minimum anngle difference af - at [deg] + RealT angmax; ///< Maximum anngle difference af - at [deg] + + inline std::string str() const + { + std::stringstream ss; + ss << std::setw(10) << fbus + << std::setw(10) << tbus + << std::setw(10) << r + << std::setw(10) << x + << std::setw(10) << b + << std::setw(10) << rateA + << std::setw(10) << rateB + << std::setw(10) << rateC + << std::setw(10) << ratio + << std::setw(10) << angle + << std::setw(10) << status + << std::setw(10) << angmin + << std::setw(10) << angmax; + ss << "\n"; + return ss.str(); + } + }; + + template + struct GenCostRow + { + IntT kind; + IntT startup; + IntT shutdown; + IntT n; + std::vector rest; + + inline std::string str() const + { + std::stringstream ss; + ss << std::setw(10) << kind << std::setw(10) << startup << std::setw(10) + << shutdown << std::setw(10) << n; + for (const auto& val : rest) + ss << std::setw(10) << val; + ss << "\n"; + return ss.str(); + } + }; + + template + struct MatPower { + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; + using GenCostRowT = GenCostRow; + using LoadRowT = LoadRow; + + std::string version; + IntT baseMVA; + std::vector bus; + std::vector gen; + std::vector branch; + std::vector gencost; + std::vector load; + + // Not sure if these should be in this struct... Not all matpower files + // I found contained them. + // + // std::string name; + // std::vector bus_name; + + inline std::string str() const + { + std::stringstream ss; + ss << "Version: " << version << "\n" + << "Base MVA: " << baseMVA << "\n"; + + ss << "Bus:\n"; + for (const auto& v : bus) + ss << bus.str() << "\n"; + + ss << "Gen:\n"; + for (const auto& v : gen) + ss << gen.str(); + + ss << "Branch:\n"; + for (const auto& v : branch) + ss << branch.str(); + + ss << "GenCost:\n"; + for (const auto& v : gencost) + ss << gencost.str(); + + ss << "\n"; + + return ss.str(); + } + }; + +} // namespace MatPower +} // namespace GridKit diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index f061cdbd1..ef676bad2 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -172,28 +172,24 @@ inline bool isEqual(PowerSystemData::BusData a, return fail == 0; } -template -inline bool isEqual(PowerSystemData::LoadData a, - PowerSystemData::LoadData b, - RealT tol = tol_) -{ +template +inline bool isEqual(MatPowerUtils::LoadRow a, + MatPowerUtils::LoadRow b, RealT tol = tol_) { int fail = 0; fail += a.bus_i != b.bus_i; fail += !isEqual(a.Pd, b.Pd, tol); fail += !isEqual(a.Qd, b.Qd, tol); if (fail) { errs() << "bus_i: a=" << a.bus_i << ", b=" << b.bus_i << "\n" - << "Pd: a=" << a.Pd << ", b=" << b.Pd << "\n" - << "Qd: a=" << a.Qd << ", b=" << b.Qd << "\n"; + << "Pd: a=" << a.Pd << ", b=" << b.Pd << "\n" + << "Qd: a=" << a.Qd << ", b=" << b.Qd << "\n"; } return fail == 0; } -template -inline bool isEqual(PowerSystemData::BranchData a, - PowerSystemData::BranchData b, - RealT tol = tol_) -{ +template +inline bool isEqual(MatPowerUtils::BranchRow a, + MatPowerUtils::BranchRow b, RealT tol = tol_) { int fail = 0; fail += a.fbus != b.fbus; fail += a.tbus != b.tbus; From 7cf0b3e1155514cbb3aaf156b673436b1dbc5c92 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 20 Oct 2022 17:44:05 -0500 Subject: [PATCH 29/52] Check load data when testing Matpower parser. --- .../MatPowerTesting/test_parse_matpower.cpp | 26 +++++++++---------- Utilities/Testing.hpp | 4 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index fa926cad2..e0e4c7da1 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -85,12 +85,12 @@ int main(int argc, char **argv) { int fail = 0; // All types will use the scalar types at the top of the file - using BusDataT = BusData; - using GenDataT = GenData; - using BranchDataT = BranchData; - using GenCostDataT = GenCostData; - using SystemModelDataT = SystemModelData; - using LoadDataT = LoadData; + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; + using GenCostRowT = GenCostRow; + using MatPowerT = MatPower; + using LoadRowT = LoadRow; // Create the struct of expected values std::vector branch_answer{ @@ -101,12 +101,12 @@ int main(int argc, char **argv) { {3, 4, 0.00297, 0.0297, 0.00674, 0, 0, 0, 0, 0, 1, -360, 360}, {4, 5, 0.00297, 0.0297, 0.00674, 240, 240, 240, 0, 0, 1, -360, 360}, }; - std::vector bus_answer{ - {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {4, 3, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, + std::vector bus_answer{ + {1, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {2, 1, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {3, 2, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {4, 3, 400, 131.47, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {5, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; std::vector gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -122,7 +122,7 @@ int main(int argc, char **argv) { {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - std::vector load_answer{ + std::vector> load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index ef676bad2..fe8b9d230 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -181,8 +181,8 @@ inline bool isEqual(MatPowerUtils::LoadRow a, fail += !isEqual(a.Qd, b.Qd, tol); if (fail) { errs() << "bus_i: a=" << a.bus_i << ", b=" << b.bus_i << "\n" - << "Pd: a=" << a.Pd << ", b=" << b.Pd << "\n" - << "Qd: a=" << a.Qd << ", b=" << b.Qd << "\n"; + << "Pd: a=" << a.Pd << ", b=" << b.Pd << "\n" + << "Qd: a=" << a.Qd << ", b=" << b.Qd << "\n"; } return fail == 0; } From 91c7c092253562a7840a0c105a792ecc160f3098 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 20 Oct 2022 21:34:56 -0500 Subject: [PATCH 30/52] Do not store load data in bus data structure. --- .../MatPowerTesting/test_parse_bus_row.cpp | 10 +++---- .../MatPowerTesting/test_parse_matpower.cpp | 10 +++---- Utilities/FileIO.hpp | 29 ++++++++++++------- Utilities/MatPowerUtils.hpp | 10 +++---- 4 files changed, 32 insertions(+), 27 deletions(-) diff --git a/Examples/MatPowerTesting/test_parse_bus_row.cpp b/Examples/MatPowerTesting/test_parse_bus_row.cpp index adfb38a16..dfb9fec47 100644 --- a/Examples/MatPowerTesting/test_parse_bus_row.cpp +++ b/Examples/MatPowerTesting/test_parse_bus_row.cpp @@ -29,11 +29,11 @@ mpc.bus = [ int main(int argc, char** argv) { int fail = 0; std::vector> bus_answer{ - {1, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {2, 1, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {3, 2, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {4, 3, 400, 131.47, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {5, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, + {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {4, 3, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; std::vector> load_answer{ diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index e0e4c7da1..239839060 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -102,11 +102,11 @@ int main(int argc, char **argv) { {4, 5, 0.00297, 0.0297, 0.00674, 240, 240, 240, 0, 0, 1, -360, 360}, }; std::vector bus_answer{ - {1, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {2, 1, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {3, 2, 300, 98.61, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {4, 3, 400, 131.47, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, - {5, 2, 0, 0, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, + {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {4, 3, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, + {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; std::vector gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp index 0db5df0c0..078d7d823 100644 --- a/Utilities/FileIO.hpp +++ b/Utilities/FileIO.hpp @@ -156,19 +156,26 @@ void checkEndOfMatrixRow(std::istream& is) } template -// BusRow void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow& lr) { logs() << "Parsing MATPOWER bus row\n"; std::stringstream is(row); - // BusRow br; - // LoadRow lr; - is >> br.bus_i >> br.type >> br.Pd >> br.Qd >> br.Gs >> br.Bs >> br.area - >> br.Vm >> br.Va >> br.baseKV >> br.zone >> br.Vmax >> br.Vmin; + is >> br.bus_i + >> br.type + >> lr.Pd + >> lr.Qd + >> br.Gs + >> br.Bs + >> br.area + >> br.Vm + >> br.Va + >> br.baseKV + >> br.zone + >> br.Vmax + >> br.Vmin; lr.bus_i = br.bus_i; - lr.Pd = br.Pd; - lr.Qd = br.Qd; + // std::cout << br.str(); // logs() << "Read BusRow with the following values:\n" << br.str(); // return br; @@ -301,11 +308,11 @@ template void readMatPower(SystemModelData& mp, std::istream& is) { - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; using GenCostRowT = GenCostRow; - using LoadRowT = LoadRow; + using LoadRowT = LoadRow; for (std::string line; std::getline(is, line);) { // Trim whitespace and remove comments diff --git a/Utilities/MatPowerUtils.hpp b/Utilities/MatPowerUtils.hpp index a9d52e537..5dab48dcd 100644 --- a/Utilities/MatPowerUtils.hpp +++ b/Utilities/MatPowerUtils.hpp @@ -25,8 +25,6 @@ namespace MatPowerUtils { IntT bus_i; ///< Bus ID IntT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated - RealT Pd; ///< Active power demand [MW] - RealT Qd; ///< Reactive power demand [MVAr] RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) IntT area; ///< Area number (>0) @@ -42,8 +40,6 @@ namespace MatPowerUtils std::stringstream ss; std::cerr << std::setw(10) << bus_i << std::setw(10) << type - << std::setw(10) << Pd - << std::setw(10) << Qd << std::setw(10) << Gs << std::setw(10) << Bs << std::setw(10) << area @@ -180,8 +176,10 @@ namespace MatPowerUtils inline std::string str() const { std::stringstream ss; - ss << std::setw(10) << kind << std::setw(10) << startup << std::setw(10) - << shutdown << std::setw(10) << n; + ss << std::setw(10) << kind + << std::setw(10) << startup + << std::setw(10) << shutdown + << std::setw(10) << n; for (const auto& val : rest) ss << std::setw(10) << val; ss << "\n"; From d8570d578b6db7bf7835ff5b3a1e3065a490a31d Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Fri, 21 Oct 2022 08:52:58 -0500 Subject: [PATCH 31/52] Changed names and order of template parameters in power system data structures. --- ComponentLib/Bus/BusFactory.hpp | 10 ++-- ComponentLib/Bus/BusPQ.hpp | 2 +- ComponentLib/Bus/BusPV.hpp | 2 +- ComponentLib/Bus/BusSlack.hpp | 2 +- .../MatPowerTesting/test_parse_branch_row.cpp | 4 +- .../MatPowerTesting/test_parse_bus_row.cpp | 8 +-- .../MatPowerTesting/test_parse_gen_row.cpp | 4 +- .../test_parse_gencost_row.cpp | 4 +- .../MatPowerTesting/test_parse_matpower.cpp | 14 ++--- Utilities/FileIO.hpp | 28 +++++----- Utilities/MatPowerUtils.hpp | 54 +++++++++---------- Utilities/Testing.hpp | 36 ++++++------- 12 files changed, 81 insertions(+), 87 deletions(-) diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp index fc03c852b..356db471f 100644 --- a/ComponentLib/Bus/BusFactory.hpp +++ b/ComponentLib/Bus/BusFactory.hpp @@ -68,9 +68,11 @@ namespace ModelLib { class BusFactory { public: - using BusData = GridKit::MatPowerUtils::BusRow; + using BusData = GridKit::PowerSystemData::BusRow; - BaseBus* create(BusData& data) + BusFactory() = delete; + + static BaseBus* create(BusData& data) { BaseBus* bus = nullptr; switch(data.type) @@ -90,8 +92,6 @@ namespace ModelLib { } return bus; } - private: - BusFactory(){} }; -} +} // namespace ModelLib diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp index 9fff6f6c5..d2f21f8ef 100644 --- a/ComponentLib/Bus/BusPQ.hpp +++ b/ComponentLib/Bus/BusPQ.hpp @@ -87,7 +87,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::MatPowerUtils::BusRow; + using BusData = GridKit::PowerSystemData::BusRow; BusPQ(); BusPQ(ScalarT V, ScalarT theta); diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index 06165e2d2..0162eea1a 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -88,7 +88,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::MatPowerUtils::BusRow; + using BusData = GridKit::PowerSystemData::BusRow; BusPV(); BusPV(ScalarT V, ScalarT theta0, ScalarT P); diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index 95f6d4a32..4c65290d6 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -87,7 +87,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::MatPowerUtils::BusRow; + using BusData = GridKit::PowerSystemData::BusRow; BusSlack(); BusSlack(ScalarT V, ScalarT theta); diff --git a/Examples/MatPowerTesting/test_parse_branch_row.cpp b/Examples/MatPowerTesting/test_parse_branch_row.cpp index 8d87d9e82..87dd67911 100644 --- a/Examples/MatPowerTesting/test_parse_branch_row.cpp +++ b/Examples/MatPowerTesting/test_parse_branch_row.cpp @@ -33,7 +33,7 @@ mpc.branch = [ int main(int argc, char **argv) { int fail = 0; - std::vector> branch_answer{ + std::vector> branch_answer{ {1, 2, 0.00281, 0.0281, 0.00712, 400, 400, 400, 0, 0, 1, -360, 360}, {1, 4, 0.00304, 0.0304, 0.00658, 0, 0, 0, 0, 0, 1, -360, 360}, {1, 5, 0.00064, 0.0064, 0.03126, 0, 0, 0, 0, 0, 1, -360, 360}, @@ -41,7 +41,7 @@ int main(int argc, char **argv) { {3, 4, 0.00297, 0.0297, 0.00674, 0, 0, 0, 0, 0, 1, -360, 360}, {4, 5, 0.00297, 0.0297, 0.00674, 240, 240, 240, 0, 0, 1, -360, 360}, }; - SystemModelData mp; + MatPower mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_bus_row.cpp b/Examples/MatPowerTesting/test_parse_bus_row.cpp index dfb9fec47..0e44a96f6 100644 --- a/Examples/MatPowerTesting/test_parse_bus_row.cpp +++ b/Examples/MatPowerTesting/test_parse_bus_row.cpp @@ -28,7 +28,7 @@ mpc.bus = [ int main(int argc, char** argv) { int fail = 0; - std::vector> bus_answer{ + std::vector> bus_answer{ {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, @@ -36,7 +36,7 @@ int main(int argc, char** argv) { {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; - std::vector> load_answer{ + std::vector> load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, @@ -45,7 +45,7 @@ int main(int argc, char** argv) { }; { - MatPower mp; + MatPower mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.bus, bus_answer)) fail++; @@ -53,7 +53,7 @@ int main(int argc, char** argv) { } { - MatPower mp; + MatPower mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.load, load_answer)) fail++; diff --git a/Examples/MatPowerTesting/test_parse_gen_row.cpp b/Examples/MatPowerTesting/test_parse_gen_row.cpp index b524ae899..65b152903 100644 --- a/Examples/MatPowerTesting/test_parse_gen_row.cpp +++ b/Examples/MatPowerTesting/test_parse_gen_row.cpp @@ -30,7 +30,7 @@ mpc.gen = [ int main(int argc, char **argv) { int fail = 0; - std::vector> gen_answer{ + std::vector> gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 170, 0, 127.5, -127.5, 1, 100, 1, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -39,7 +39,7 @@ int main(int argc, char **argv) { {4, 0, 0, 150, -150, 1, 100, 1, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 466.51, 0, 450, -450, 1, 100, 1, 600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - SystemModelData mp; + MatPower mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_gencost_row.cpp b/Examples/MatPowerTesting/test_parse_gencost_row.cpp index efc409d89..aa94c3ea4 100644 --- a/Examples/MatPowerTesting/test_parse_gencost_row.cpp +++ b/Examples/MatPowerTesting/test_parse_gencost_row.cpp @@ -33,12 +33,12 @@ mpc.gencost = [ int main(int argc, char **argv) { int fail = 0; - std::vector> gencost_answer{ + std::vector> gencost_answer{ {2, 0, 0, 3, {0, 14, 0}}, {2, 0, 0, 3, {0, 15, 0}}, {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - SystemModelData mp; + MatPower mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index 239839060..5729442c2 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -85,12 +85,12 @@ int main(int argc, char **argv) { int fail = 0; // All types will use the scalar types at the top of the file - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using MatPowerT = MatPower; - using LoadRowT = LoadRow; + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; + using GenCostRowT = GenCostRow; + using MatPowerT = MatPower; + using LoadRowT = LoadRow; // Create the struct of expected values std::vector branch_answer{ @@ -122,7 +122,7 @@ int main(int argc, char **argv) { {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - std::vector> load_answer{ + std::vector> load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp index 078d7d823..0e47c5ee7 100644 --- a/Utilities/FileIO.hpp +++ b/Utilities/FileIO.hpp @@ -155,8 +155,8 @@ void checkEndOfMatrixRow(std::istream& is) throw std::runtime_error(matlab_syntax_error); } -template -void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow& lr) +template +void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow& lr) { logs() << "Parsing MATPOWER bus row\n"; std::stringstream is(row); @@ -182,7 +182,7 @@ void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow } template -void readMatPowerGenRow(GenData& gr, std::string& row) +void readMatPowerGenRow(GenRow& gr, std::string& row) { logs() << "Parsing MATPOWER gen row\n"; std::stringstream is(row); @@ -194,7 +194,7 @@ void readMatPowerGenRow(GenData& gr, std::string& row) } template -void readMatPowerBranchRow(BranchData& br, std::string& row) +void readMatPowerBranchRow(BranchRow& br, std::string& row) { logs() << "Parsing MATPOWER branch row\n"; std::stringstream is(row); @@ -205,7 +205,7 @@ void readMatPowerBranchRow(BranchData& br, std::string& row) } template -void readMatPowerGenCostRow(GenCostData& gcr, std::string& row) +void readMatPowerGenCostRow(GenCostRow& gcr, std::string& row) { logs() << "Parsing MATPOWER gen cost row\n"; // Ensure last character is semicolon. @@ -222,7 +222,7 @@ void readMatPowerGenCostRow(GenCostData& gcr, std::string& row) } template -void readMatPowerVersion(SystemModelData& mp, std::string& line) +void readMatPowerVersion(MatPower& mp, std::string& line) { logs() << "Parsing matpower version\n"; std::regex pat("mpc\\.version\\s*=\\s*'([0-9])';"); @@ -235,7 +235,7 @@ void readMatPowerVersion(SystemModelData& mp, std::string& line) } template -void readMatPowerBaseMVA(SystemModelData& mp, std::string& line) +void readMatPowerBaseMVA(MatPower& mp, std::string& line) { std::regex pat("mpc\\.baseMVA\\s*=\\s*([0-9]+);"); std::smatch matches; @@ -297,7 +297,7 @@ void printLookupTable(std::vector> const& table) } template -void readMatPowerFile(SystemModelData& mp, std::string& filename) +void readMatPowerFile(MatPower& mp, std::string& filename) { std::ifstream ifs{filename}; readMatPower(mp, ifs); @@ -306,13 +306,13 @@ void readMatPowerFile(SystemModelData& mp, std::string& filename) template -void readMatPower(SystemModelData& mp, std::istream& is) +void readMatPower(MatPower& mp, std::istream& is) { - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using LoadRowT = LoadRow; + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; + using GenCostRowT = GenCostRow; + using LoadRowT = LoadRow; for (std::string line; std::getline(is, line);) { // Trim whitespace and remove comments diff --git a/Utilities/MatPowerUtils.hpp b/Utilities/MatPowerUtils.hpp index 5dab48dcd..618c0ca2e 100644 --- a/Utilities/MatPowerUtils.hpp +++ b/Utilities/MatPowerUtils.hpp @@ -17,21 +17,21 @@ namespace GridKit { -namespace MatPowerUtils +namespace PowerSystemData { - template + template struct BusRow { - IntT bus_i; ///< Bus ID - IntT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + IdxT bus_i; ///< Bus ID + IdxT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) - IntT area; ///< Area number (>0) + IdxT area; ///< Area number (>0) RealT Vm; ///< Voltage magnitude (p.u.) RealT Va; ///< Voltage phase (deg) RealT baseKV; ///< Base voltage [kV] - IntT zone; ///< Loss zone number (>0) + IdxT zone; ///< Loss zone number (>0) RealT Vmax; ///< Maximum voltage magnitude (p.u.) RealT Vmin; ///< Minimum voltage magnitude (p.u.) @@ -54,10 +54,10 @@ namespace MatPowerUtils } }; - template + template struct LoadRow { - IntT bus_i; ///< Bus ID + IdxT bus_i; ///< Bus ID RealT Pd; ///< Active power demand [MW] RealT Qd; ///< Reactive power demand [MVAr] @@ -72,17 +72,17 @@ namespace MatPowerUtils } }; - template + template struct GenRow { - IntT bus; ///< Bus ID + IdxT bus; ///< Bus ID RealT Pg; ///< Active power output [MW] RealT Qg; ///< Reactive power output [MVAr] RealT Qmax; ///< Maximum reactive power output [MVAr] RealT Qmin; ///< Minimum reactive power output [MVAr] RealT Vg; ///< RealT mBase; ///< Total MVA base of machine - IntT status; ///< Service status (>0 in service, <=0 out of service) + IdxT status; ///< Service status (>0 in service, <=0 out of service) RealT Pmax; ///< Maximum active power output [MVAr] RealT Pmin; ///< Minimum active power output [MVAr] RealT Pc1; ///< @@ -126,11 +126,11 @@ namespace MatPowerUtils } }; - template + template struct BranchRow { - IntT fbus; ///< "From" bus ID - IntT tbus; ///< "To" bus ID + IdxT fbus; ///< "From" bus ID + IdxT tbus; ///< "To" bus ID RealT r; ///< Resistance (p.u.) RealT x; ///< Reactance (p.u.) RealT b; ///< Total line charging susceptance (p.u.) @@ -139,7 +139,7 @@ namespace MatPowerUtils RealT rateC; ///< MVA rating C (emergency rating), 0=unlimited RealT ratio; ///< Transformer off nominal turns ratio RealT angle; ///< Transformer phase shift angle [deg], positive ⇒ delay - IntT status; ///< Initial service status: 1=in-service, 0=out-of-service + IdxT status; ///< Initial service status: 1=in-service, 0=out-of-service RealT angmin; ///< Minimum anngle difference af - at [deg] RealT angmax; ///< Maximum anngle difference af - at [deg] @@ -164,13 +164,13 @@ namespace MatPowerUtils } }; - template + template struct GenCostRow { - IntT kind; - IntT startup; - IntT shutdown; - IntT n; + IdxT kind; + IdxT startup; + IdxT shutdown; + IdxT n; std::vector rest; inline std::string str() const @@ -187,16 +187,16 @@ namespace MatPowerUtils } }; - template + template struct MatPower { - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using LoadRowT = LoadRow; + using BusRowT = BusRow; + using GenRowT = GenRow; + using BranchRowT = BranchRow; + using GenCostRowT = GenCostRow; + using LoadRowT = LoadRow; std::string version; - IntT baseMVA; + IdxT baseMVA; std::vector bus; std::vector gen; std::vector branch; diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index fe8b9d230..9b958ef14 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -91,10 +91,9 @@ template bool isEqual(const T value, const T ref, const T tol) } template -inline bool isEqual(PowerSystemData::GenCostData a, - PowerSystemData::GenCostData b, - RealT tol = tol_) -{ +inline bool isEqual(PowerSystemData::GenCostRow a, + PowerSystemData::GenCostRow b, + RealT tol = tol_) { int fail = 0; fail += a.kind != b.kind; fail += a.startup != b.startup; @@ -107,10 +106,8 @@ inline bool isEqual(PowerSystemData::GenCostData a, } template -inline bool isEqual(PowerSystemData::GenData a, - PowerSystemData::GenData b, - RealT tol = tol_) -{ +inline bool isEqual(PowerSystemData::GenRow a, + PowerSystemData::GenRow b, RealT tol = tol_) { int fail = 0; fail += a.bus != b.bus; fail += !isEqual(a.Pg, b.Pg, tol); @@ -140,10 +137,8 @@ inline bool isEqual(PowerSystemData::GenData a, } template -inline bool isEqual(PowerSystemData::BusData a, - PowerSystemData::BusData b, - RealT tol = tol_) -{ +inline bool isEqual(PowerSystemData::BusRow a, + PowerSystemData::BusRow b, RealT tol = tol_) { int fail = 0; fail += a.bus_i != b.bus_i; fail += a.type != b.type; @@ -172,9 +167,9 @@ inline bool isEqual(PowerSystemData::BusData a, return fail == 0; } -template -inline bool isEqual(MatPowerUtils::LoadRow a, - MatPowerUtils::LoadRow b, RealT tol = tol_) { +template +inline bool isEqual(PowerSystemData::LoadRow a, + PowerSystemData::LoadRow b, RealT tol = tol_) { int fail = 0; fail += a.bus_i != b.bus_i; fail += !isEqual(a.Pd, b.Pd, tol); @@ -187,9 +182,9 @@ inline bool isEqual(MatPowerUtils::LoadRow a, return fail == 0; } -template -inline bool isEqual(MatPowerUtils::BranchRow a, - MatPowerUtils::BranchRow b, RealT tol = tol_) { +template +inline bool isEqual(PowerSystemData::BranchRow a, + PowerSystemData::BranchRow b, RealT tol = tol_) { int fail = 0; fail += a.fbus != b.fbus; fail += a.tbus != b.tbus; @@ -234,9 +229,8 @@ inline bool isEqual(std::vector a, std::vector b, double tol = tol_) } template -inline bool isEqual(PowerSystemData::SystemModelData a, - PowerSystemData::SystemModelData b) -{ +inline bool isEqual(PowerSystemData::MatPower a, + PowerSystemData::MatPower b) { int fail = 0; fail += a.version != b.version; fail += a.baseMVA != b.baseMVA; From 0873ac7c2e0f01410c9cad048f36066011c919d8 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Fri, 21 Oct 2022 17:37:24 -0400 Subject: [PATCH 32/52] More intuitieve data structures names Changed names of data structures to distinguish Matpower specific data and general power system description data. --- ComponentLib/Bus/BusFactory.hpp | 4 +- ComponentLib/Bus/BusPQ.hpp | 4 +- ComponentLib/Bus/BusPV.hpp | 4 +- ComponentLib/Bus/BusSlack.hpp | 4 +- .../MatPowerTesting/test_parse_branch_row.cpp | 4 +- .../MatPowerTesting/test_parse_bus_row.cpp | 8 +- .../MatPowerTesting/test_parse_gen_row.cpp | 4 +- .../test_parse_gencost_row.cpp | 4 +- .../MatPowerTesting/test_parse_matpower.cpp | 16 +- PowerSystemData.hpp | 2 +- Utilities/FileIO.hpp | 32 +-- Utilities/MatPowerUtils.hpp | 241 ------------------ Utilities/Testing.hpp | 24 +- 13 files changed, 55 insertions(+), 296 deletions(-) delete mode 100644 Utilities/MatPowerUtils.hpp diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp index 356db471f..f051aa0a2 100644 --- a/ComponentLib/Bus/BusFactory.hpp +++ b/ComponentLib/Bus/BusFactory.hpp @@ -59,7 +59,7 @@ #pragma once -#include +#include #include namespace ModelLib { @@ -68,7 +68,7 @@ namespace ModelLib { class BusFactory { public: - using BusData = GridKit::PowerSystemData::BusRow; + using BusData = GridKit::PowerSystemData::BusData; BusFactory() = delete; diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp index d2f21f8ef..56798b6e2 100644 --- a/ComponentLib/Bus/BusPQ.hpp +++ b/ComponentLib/Bus/BusPQ.hpp @@ -61,7 +61,7 @@ #define _BUS_PQ_HPP_ #include "BaseBus.hpp" -#include +#include namespace ModelLib { @@ -87,7 +87,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusRow; + using BusData = GridKit::PowerSystemData::BusData; BusPQ(); BusPQ(ScalarT V, ScalarT theta); diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index 0162eea1a..62f7773ae 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -62,7 +62,7 @@ #include #include "BaseBus.hpp" -#include +#include namespace ModelLib { @@ -88,7 +88,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusRow; + using BusData = GridKit::PowerSystemData::BusData; BusPV(); BusPV(ScalarT V, ScalarT theta0, ScalarT P); diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index 4c65290d6..6ae58dce2 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -61,7 +61,7 @@ #define _BUS_SLACK_HPP_ #include "BaseBus.hpp" -#include +#include namespace ModelLib { @@ -87,7 +87,7 @@ namespace ModelLib public: typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusRow; + using BusData = GridKit::PowerSystemData::BusData; BusSlack(); BusSlack(ScalarT V, ScalarT theta); diff --git a/Examples/MatPowerTesting/test_parse_branch_row.cpp b/Examples/MatPowerTesting/test_parse_branch_row.cpp index 87dd67911..8d87d9e82 100644 --- a/Examples/MatPowerTesting/test_parse_branch_row.cpp +++ b/Examples/MatPowerTesting/test_parse_branch_row.cpp @@ -33,7 +33,7 @@ mpc.branch = [ int main(int argc, char **argv) { int fail = 0; - std::vector> branch_answer{ + std::vector> branch_answer{ {1, 2, 0.00281, 0.0281, 0.00712, 400, 400, 400, 0, 0, 1, -360, 360}, {1, 4, 0.00304, 0.0304, 0.00658, 0, 0, 0, 0, 0, 1, -360, 360}, {1, 5, 0.00064, 0.0064, 0.03126, 0, 0, 0, 0, 0, 1, -360, 360}, @@ -41,7 +41,7 @@ int main(int argc, char **argv) { {3, 4, 0.00297, 0.0297, 0.00674, 0, 0, 0, 0, 0, 1, -360, 360}, {4, 5, 0.00297, 0.0297, 0.00674, 240, 240, 240, 0, 0, 1, -360, 360}, }; - MatPower mp; + SystemModelData mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_bus_row.cpp b/Examples/MatPowerTesting/test_parse_bus_row.cpp index 0e44a96f6..38695c5fa 100644 --- a/Examples/MatPowerTesting/test_parse_bus_row.cpp +++ b/Examples/MatPowerTesting/test_parse_bus_row.cpp @@ -28,7 +28,7 @@ mpc.bus = [ int main(int argc, char** argv) { int fail = 0; - std::vector> bus_answer{ + std::vector> bus_answer{ {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, @@ -36,7 +36,7 @@ int main(int argc, char** argv) { {5, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.9}, }; - std::vector> load_answer{ + std::vector> load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, @@ -45,7 +45,7 @@ int main(int argc, char** argv) { }; { - MatPower mp; + SystemModelData mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.bus, bus_answer)) fail++; @@ -53,7 +53,7 @@ int main(int argc, char** argv) { } { - MatPower mp; + SystemModelData mp; std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); if (!isEqual(mp.load, load_answer)) fail++; diff --git a/Examples/MatPowerTesting/test_parse_gen_row.cpp b/Examples/MatPowerTesting/test_parse_gen_row.cpp index 65b152903..b524ae899 100644 --- a/Examples/MatPowerTesting/test_parse_gen_row.cpp +++ b/Examples/MatPowerTesting/test_parse_gen_row.cpp @@ -30,7 +30,7 @@ mpc.gen = [ int main(int argc, char **argv) { int fail = 0; - std::vector> gen_answer{ + std::vector> gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 170, 0, 127.5, -127.5, 1, 100, 1, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -39,7 +39,7 @@ int main(int argc, char **argv) { {4, 0, 0, 150, -150, 1, 100, 1, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 466.51, 0, 450, -450, 1, 100, 1, 600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - MatPower mp; + SystemModelData mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_gencost_row.cpp b/Examples/MatPowerTesting/test_parse_gencost_row.cpp index aa94c3ea4..efc409d89 100644 --- a/Examples/MatPowerTesting/test_parse_gencost_row.cpp +++ b/Examples/MatPowerTesting/test_parse_gencost_row.cpp @@ -33,12 +33,12 @@ mpc.gencost = [ int main(int argc, char **argv) { int fail = 0; - std::vector> gencost_answer{ + std::vector> gencost_answer{ {2, 0, 0, 3, {0, 14, 0}}, {2, 0, 0, 3, {0, 15, 0}}, {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - MatPower mp; + SystemModelData mp; { std::istringstream iss(matpower_data); diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index 5729442c2..e4cec26fa 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -85,12 +85,12 @@ int main(int argc, char **argv) { int fail = 0; // All types will use the scalar types at the top of the file - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using MatPowerT = MatPower; - using LoadRowT = LoadRow; + using BusDataT = BusData; + using GenDataT = GenData; + using BranchDataT = BranchData; + using GenCostDataT = GenCostData; + using SystemModelDataT = SystemModelData; + using LoadDataT = LoadData; // Create the struct of expected values std::vector branch_answer{ @@ -101,7 +101,7 @@ int main(int argc, char **argv) { {3, 4, 0.00297, 0.0297, 0.00674, 0, 0, 0, 0, 0, 1, -360, 360}, {4, 5, 0.00297, 0.0297, 0.00674, 240, 240, 240, 0, 0, 1, -360, 360}, }; - std::vector bus_answer{ + std::vector bus_answer{ {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {3, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, @@ -122,7 +122,7 @@ int main(int argc, char **argv) { {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - std::vector> load_answer{ + std::vector> load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, diff --git a/PowerSystemData.hpp b/PowerSystemData.hpp index 67294db4f..5bba07992 100644 --- a/PowerSystemData.hpp +++ b/PowerSystemData.hpp @@ -24,7 +24,7 @@ namespace PowerSystemData struct BusData { IdxT bus_i; ///< Bus ID - IdxT type; ///< Bus type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + IdxT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) IdxT area; ///< Area number (>0) diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp index 0e47c5ee7..c32f4c030 100644 --- a/Utilities/FileIO.hpp +++ b/Utilities/FileIO.hpp @@ -156,7 +156,7 @@ void checkEndOfMatrixRow(std::istream& is) } template -void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow& lr) +void readMatPowerBusRow(const std::string& row, BusData& br, LoadData& lr) { logs() << "Parsing MATPOWER bus row\n"; std::stringstream is(row); @@ -177,12 +177,12 @@ void readMatPowerBusRow(const std::string& row, BusRow& br, LoadRow lr.bus_i = br.bus_i; // std::cout << br.str(); - // logs() << "Read BusRow with the following values:\n" << br.str(); + // logs() << "Read BusData with the following values:\n" << br.str(); // return br; } template -void readMatPowerGenRow(GenRow& gr, std::string& row) +void readMatPowerGenRow(GenData& gr, std::string& row) { logs() << "Parsing MATPOWER gen row\n"; std::stringstream is(row); @@ -194,7 +194,7 @@ void readMatPowerGenRow(GenRow& gr, std::string& row) } template -void readMatPowerBranchRow(BranchRow& br, std::string& row) +void readMatPowerBranchRow(BranchData& br, std::string& row) { logs() << "Parsing MATPOWER branch row\n"; std::stringstream is(row); @@ -205,7 +205,7 @@ void readMatPowerBranchRow(BranchRow& br, std::string& row) } template -void readMatPowerGenCostRow(GenCostRow& gcr, std::string& row) +void readMatPowerGenCostRow(GenCostData& gcr, std::string& row) { logs() << "Parsing MATPOWER gen cost row\n"; // Ensure last character is semicolon. @@ -222,7 +222,7 @@ void readMatPowerGenCostRow(GenCostRow& gcr, std::string& row) } template -void readMatPowerVersion(MatPower& mp, std::string& line) +void readMatPowerVersion(SystemModelData& mp, std::string& line) { logs() << "Parsing matpower version\n"; std::regex pat("mpc\\.version\\s*=\\s*'([0-9])';"); @@ -235,7 +235,7 @@ void readMatPowerVersion(MatPower& mp, std::string& line) } template -void readMatPowerBaseMVA(MatPower& mp, std::string& line) +void readMatPowerBaseMVA(SystemModelData& mp, std::string& line) { std::regex pat("mpc\\.baseMVA\\s*=\\s*([0-9]+);"); std::smatch matches; @@ -297,7 +297,7 @@ void printLookupTable(std::vector> const& table) } template -void readMatPowerFile(MatPower& mp, std::string& filename) +void readMatPowerFile(SystemModelData& mp, std::string& filename) { std::ifstream ifs{filename}; readMatPower(mp, ifs); @@ -306,13 +306,13 @@ void readMatPowerFile(MatPower& mp, std::string& filename) template -void readMatPower(MatPower& mp, std::istream& is) +void readMatPower(SystemModelData& mp, std::istream& is) { - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using LoadRowT = LoadRow; + using BusDataT = BusData; + using GenDataT = GenData; + using BranchDataT = BranchData; + using GenCostDataT = GenCostData; + using LoadDataT = LoadData; for (std::string line; std::getline(is, line);) { // Trim whitespace and remove comments @@ -335,8 +335,8 @@ void readMatPower(MatPower& mp, std::istream& is) if (component == "bus") { while (std::getline(is, line)) { if (line.find("];") != std::string::npos) break; - BusRowT br; - LoadRowT lr; + BusDataT br; + LoadDataT lr; readMatPowerBusRow(line, br, lr); mp.bus.push_back(std::move(br)); mp.load.push_back(std::move(lr)); diff --git a/Utilities/MatPowerUtils.hpp b/Utilities/MatPowerUtils.hpp deleted file mode 100644 index 618c0ca2e..000000000 --- a/Utilities/MatPowerUtils.hpp +++ /dev/null @@ -1,241 +0,0 @@ -#pragma once -#include -#include -#include -#include - -/** - * - * @file Utilities/MatPowerUtils.hpp - * @author Asher Mancinelli - * - * @remark `std::stringstream` is preferred over `operator+(std::string, ...)` - * due to stringstream's lack of reallocation on append. - * - */ - -namespace GridKit -{ - -namespace PowerSystemData -{ - - template - struct BusRow - { - IdxT bus_i; ///< Bus ID - IdxT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated - RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) - RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) - IdxT area; ///< Area number (>0) - RealT Vm; ///< Voltage magnitude (p.u.) - RealT Va; ///< Voltage phase (deg) - RealT baseKV; ///< Base voltage [kV] - IdxT zone; ///< Loss zone number (>0) - RealT Vmax; ///< Maximum voltage magnitude (p.u.) - RealT Vmin; ///< Minimum voltage magnitude (p.u.) - - inline std::string str() const - { - std::stringstream ss; - std::cerr << std::setw(10) << bus_i - << std::setw(10) << type - << std::setw(10) << Gs - << std::setw(10) << Bs - << std::setw(10) << area - << std::setw(10) << Vm - << std::setw(10) << Va - << std::setw(10) << baseKV - << std::setw(10) << zone - << std::setw(10) << Vmax - << std::setw(10) << Vmin; - ss << "\n"; - return ss.str(); - } - }; - - template - struct LoadRow - { - IdxT bus_i; ///< Bus ID - RealT Pd; ///< Active power demand [MW] - RealT Qd; ///< Reactive power demand [MVAr] - - inline std::string str() const - { - std::stringstream ss; - std::cerr << std::setw(10) << bus_i - << std::setw(10) << Pd - << std::setw(10) << Qd; - ss << "\n"; - return ss.str(); - } - }; - - template - struct GenRow - { - IdxT bus; ///< Bus ID - RealT Pg; ///< Active power output [MW] - RealT Qg; ///< Reactive power output [MVAr] - RealT Qmax; ///< Maximum reactive power output [MVAr] - RealT Qmin; ///< Minimum reactive power output [MVAr] - RealT Vg; ///< - RealT mBase; ///< Total MVA base of machine - IdxT status; ///< Service status (>0 in service, <=0 out of service) - RealT Pmax; ///< Maximum active power output [MVAr] - RealT Pmin; ///< Minimum active power output [MVAr] - RealT Pc1; ///< - RealT Pc2; ///< - RealT Qc1min; ///< - RealT Qc1max; ///< - RealT Qc2min; ///< - RealT Qc2max; ///< - RealT ramp_agc; ///< - RealT ramp_10; ///< - RealT ramp_30; ///< - RealT ramp_q; ///< - RealT apf; ///< - - inline std::string str() const - { - std::stringstream ss; - ss << std::setw(10) << bus - << std::setw(10) << Pg - << std::setw(10) << Qg - << std::setw(10) << Qmax - << std::setw(10) << Qmin - << std::setw(10) << Vg - << std::setw(10) << mBase - << std::setw(10) << status - << std::setw(10) << Pmax - << std::setw(10) << Pmin - << std::setw(10) << Pc1 - << std::setw(10) << Pc2 - << std::setw(10) << Qc1min - << std::setw(10) << Qc1max - << std::setw(10) << Qc2min - << std::setw(10) << Qc2max - << std::setw(10) << ramp_agc - << std::setw(10) << ramp_10 - << std::setw(10) << ramp_30 - << std::setw(10) << ramp_q - << std::setw(10) << apf; - ss << "\n"; - return ss.str(); - } - }; - - template - struct BranchRow - { - IdxT fbus; ///< "From" bus ID - IdxT tbus; ///< "To" bus ID - RealT r; ///< Resistance (p.u.) - RealT x; ///< Reactance (p.u.) - RealT b; ///< Total line charging susceptance (p.u.) - RealT rateA; ///< MVA rating A (long term rating), 0=unlimited - RealT rateB; ///< MVA rating B (short term rating), 0=unlimited - RealT rateC; ///< MVA rating C (emergency rating), 0=unlimited - RealT ratio; ///< Transformer off nominal turns ratio - RealT angle; ///< Transformer phase shift angle [deg], positive ⇒ delay - IdxT status; ///< Initial service status: 1=in-service, 0=out-of-service - RealT angmin; ///< Minimum anngle difference af - at [deg] - RealT angmax; ///< Maximum anngle difference af - at [deg] - - inline std::string str() const - { - std::stringstream ss; - ss << std::setw(10) << fbus - << std::setw(10) << tbus - << std::setw(10) << r - << std::setw(10) << x - << std::setw(10) << b - << std::setw(10) << rateA - << std::setw(10) << rateB - << std::setw(10) << rateC - << std::setw(10) << ratio - << std::setw(10) << angle - << std::setw(10) << status - << std::setw(10) << angmin - << std::setw(10) << angmax; - ss << "\n"; - return ss.str(); - } - }; - - template - struct GenCostRow - { - IdxT kind; - IdxT startup; - IdxT shutdown; - IdxT n; - std::vector rest; - - inline std::string str() const - { - std::stringstream ss; - ss << std::setw(10) << kind - << std::setw(10) << startup - << std::setw(10) << shutdown - << std::setw(10) << n; - for (const auto& val : rest) - ss << std::setw(10) << val; - ss << "\n"; - return ss.str(); - } - }; - - template - struct MatPower { - using BusRowT = BusRow; - using GenRowT = GenRow; - using BranchRowT = BranchRow; - using GenCostRowT = GenCostRow; - using LoadRowT = LoadRow; - - std::string version; - IdxT baseMVA; - std::vector bus; - std::vector gen; - std::vector branch; - std::vector gencost; - std::vector load; - - // Not sure if these should be in this struct... Not all matpower files - // I found contained them. - // - // std::string name; - // std::vector bus_name; - - inline std::string str() const - { - std::stringstream ss; - ss << "Version: " << version << "\n" - << "Base MVA: " << baseMVA << "\n"; - - ss << "Bus:\n"; - for (const auto& v : bus) - ss << bus.str() << "\n"; - - ss << "Gen:\n"; - for (const auto& v : gen) - ss << gen.str(); - - ss << "Branch:\n"; - for (const auto& v : branch) - ss << branch.str(); - - ss << "GenCost:\n"; - for (const auto& v : gencost) - ss << gencost.str(); - - ss << "\n"; - - return ss.str(); - } - }; - -} // namespace MatPower -} // namespace GridKit diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index 9b958ef14..216d42637 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -91,8 +91,8 @@ template bool isEqual(const T value, const T ref, const T tol) } template -inline bool isEqual(PowerSystemData::GenCostRow a, - PowerSystemData::GenCostRow b, +inline bool isEqual(PowerSystemData::GenCostData a, + PowerSystemData::GenCostData b, RealT tol = tol_) { int fail = 0; fail += a.kind != b.kind; @@ -106,8 +106,8 @@ inline bool isEqual(PowerSystemData::GenCostRow a, } template -inline bool isEqual(PowerSystemData::GenRow a, - PowerSystemData::GenRow b, RealT tol = tol_) { +inline bool isEqual(PowerSystemData::GenData a, + PowerSystemData::GenData b, RealT tol = tol_) { int fail = 0; fail += a.bus != b.bus; fail += !isEqual(a.Pg, b.Pg, tol); @@ -137,8 +137,8 @@ inline bool isEqual(PowerSystemData::GenRow a, } template -inline bool isEqual(PowerSystemData::BusRow a, - PowerSystemData::BusRow b, RealT tol = tol_) { +inline bool isEqual(PowerSystemData::BusData a, + PowerSystemData::BusData b, RealT tol = tol_) { int fail = 0; fail += a.bus_i != b.bus_i; fail += a.type != b.type; @@ -168,8 +168,8 @@ inline bool isEqual(PowerSystemData::BusRow a, } template -inline bool isEqual(PowerSystemData::LoadRow a, - PowerSystemData::LoadRow b, RealT tol = tol_) { +inline bool isEqual(PowerSystemData::LoadData a, + PowerSystemData::LoadData b, RealT tol = tol_) { int fail = 0; fail += a.bus_i != b.bus_i; fail += !isEqual(a.Pd, b.Pd, tol); @@ -183,8 +183,8 @@ inline bool isEqual(PowerSystemData::LoadRow a, } template -inline bool isEqual(PowerSystemData::BranchRow a, - PowerSystemData::BranchRow b, RealT tol = tol_) { +inline bool isEqual(PowerSystemData::BranchData a, + PowerSystemData::BranchData b, RealT tol = tol_) { int fail = 0; fail += a.fbus != b.fbus; fail += a.tbus != b.tbus; @@ -229,8 +229,8 @@ inline bool isEqual(std::vector a, std::vector b, double tol = tol_) } template -inline bool isEqual(PowerSystemData::MatPower a, - PowerSystemData::MatPower b) { +inline bool isEqual(PowerSystemData::SystemModelData a, + PowerSystemData::SystemModelData b) { int fail = 0; fail += a.version != b.version; fail += a.baseMVA != b.baseMVA; From f7733a62a32e938e229306b2af4db4ea988589bf Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Sun, 23 Oct 2022 22:18:40 -0400 Subject: [PATCH 33/52] Pass correct scalar and real types to derived bus classes. --- ComponentLib/Bus/BaseBus.hpp | 1 - ComponentLib/Bus/BusFactory.hpp | 15 ++++++++------- ComponentLib/Bus/BusPQ.hpp | 4 ++-- ComponentLib/Bus/BusPV.hpp | 4 ++-- ComponentLib/Bus/BusSlack.hpp | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ComponentLib/Bus/BaseBus.hpp b/ComponentLib/Bus/BaseBus.hpp index 2fcb9a629..4e7fc1b71 100644 --- a/ComponentLib/Bus/BaseBus.hpp +++ b/ComponentLib/Bus/BaseBus.hpp @@ -61,7 +61,6 @@ #define _BASE_BUS_HPP_ #include -// #include namespace ModelLib { diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp index f051aa0a2..c7b853b32 100644 --- a/ComponentLib/Bus/BusFactory.hpp +++ b/ComponentLib/Bus/BusFactory.hpp @@ -64,27 +64,28 @@ namespace ModelLib { - template + template class BusFactory { public: - using BusData = GridKit::PowerSystemData::BusData; + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; BusFactory() = delete; - static BaseBus* create(BusData& data) + static BaseBus* create(BusData& data) { - BaseBus* bus = nullptr; + BaseBus* bus = nullptr; switch(data.type) { case 1: - bus = new BusPQ(data); + bus = new BusPQ(data); break; case 2: - bus = new BusPV(data); + bus = new BusPV(data); break; case 3: - bus = new BusSlack(data); + bus = new BusSlack(data); break; default: // Throw exception diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp index 56798b6e2..9131dc21e 100644 --- a/ComponentLib/Bus/BusPQ.hpp +++ b/ComponentLib/Bus/BusPQ.hpp @@ -86,8 +86,8 @@ namespace ModelLib using BaseBus::tag_; public: - typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusData; + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; BusPQ(); BusPQ(ScalarT V, ScalarT theta); diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index 62f7773ae..16099a606 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -87,8 +87,8 @@ namespace ModelLib using BaseBus::tag_; public: - typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusData; + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; BusPV(); BusPV(ScalarT V, ScalarT theta0, ScalarT P); diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index 6ae58dce2..22b45f90a 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -86,8 +86,8 @@ namespace ModelLib using BaseBus::rtol_; public: - typedef typename ModelEvaluatorImpl::real_type real_type; - using BusData = GridKit::PowerSystemData::BusData; + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; BusSlack(); BusSlack(ScalarT V, ScalarT theta); From 5627c0aacef8ce4627febdf4e8333c2634a65b46 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Tue, 29 Nov 2022 22:13:52 -0500 Subject: [PATCH 34/52] Add generator base and slack classes. Classes compile correctly, not tested yet. --- ComponentLib/Generator/CMakeLists.txt | 2 -- ComponentLib/Generator/GeneratorBase.hpp | 11 ++++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ComponentLib/Generator/CMakeLists.txt b/ComponentLib/Generator/CMakeLists.txt index a09c5aed1..68ef63cf7 100644 --- a/ComponentLib/Generator/CMakeLists.txt +++ b/ComponentLib/Generator/CMakeLists.txt @@ -63,8 +63,6 @@ gridkit_add_library(generator SOURCES GeneratorSlack.cpp - GeneratorPV.cpp - GeneratorPQ.cpp OUTPUT_NAME gridkit_generator) diff --git a/ComponentLib/Generator/GeneratorBase.hpp b/ComponentLib/Generator/GeneratorBase.hpp index e1efa22bd..164e6eb2a 100644 --- a/ComponentLib/Generator/GeneratorBase.hpp +++ b/ComponentLib/Generator/GeneratorBase.hpp @@ -70,11 +70,9 @@ namespace ModelLib namespace ModelLib { - /** - * @brief Generator base class template - * - * @tparam ScalarT - Scalar type - * @tparam IdxT - Matrix and vector index type + /*! + * @brief Implementation of a power grid. + * */ template class GeneratorBase : public ModelEvaluatorImpl @@ -97,6 +95,9 @@ namespace ModelLib using bus_type = BaseBus; using real_type = typename ModelEvaluatorImpl::real_type; + // using BusData = GridKit::PowerSystemData::BusData; + // typedef typename ModelEvaluatorImpl::real_type real_type; + // typedef BaseBus bus_type; public: GeneratorBase(){} From c151339f7d619d562b81d3c840bd703d7e285af6 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Wed, 14 Dec 2022 13:59:31 -0500 Subject: [PATCH 35/52] Infrastructure for adding buses and generators to power flow models Add steady-state generator models and factory. Constructors now read directly from GenData and BusData structures. Updated Bus classes accordingly. Usage example provided in Grid3BusSys app. --- ComponentLib/Bus/BaseBus.hpp | 2 +- ComponentLib/Bus/BusFactory.hpp | 4 +- ComponentLib/Bus/BusPQ.hpp | 2 +- ComponentLib/Bus/BusPV.hpp | 2 +- ComponentLib/Bus/BusSlack.hpp | 2 +- ComponentLib/Generator/CMakeLists.txt | 2 + ComponentLib/Generator/GeneratorBase.hpp | 11 ++- ComponentLib/Generator/GeneratorPV.hpp | 8 +-- Examples/Grid3Bus/Grid3BusSys.cpp | 69 ++++--------------- .../MatPowerTesting/test_parse_matpower.cpp | 2 +- PowerSystemData.hpp | 2 +- Utilities/FileIO.hpp | 26 +++---- 12 files changed, 46 insertions(+), 86 deletions(-) diff --git a/ComponentLib/Bus/BaseBus.hpp b/ComponentLib/Bus/BaseBus.hpp index 4e7fc1b71..1d19d963f 100644 --- a/ComponentLib/Bus/BaseBus.hpp +++ b/ComponentLib/Bus/BaseBus.hpp @@ -104,7 +104,7 @@ namespace ModelLib enum BusType{PQ=1, PV, Slack, Isolated}; - BaseBus(IdxT id) : busID_(id) {} + BaseBus(){} virtual ~BaseBus(){} // Set defaults for ModelEvaluator methods diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp index c7b853b32..232171d49 100644 --- a/ComponentLib/Bus/BusFactory.hpp +++ b/ComponentLib/Bus/BusFactory.hpp @@ -60,7 +60,9 @@ #pragma once #include -#include +#include +#include +#include namespace ModelLib { diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp index 9131dc21e..45ed81a65 100644 --- a/ComponentLib/Bus/BusPQ.hpp +++ b/ComponentLib/Bus/BusPQ.hpp @@ -183,7 +183,7 @@ namespace ModelLib virtual const int BusType() const { - return 1; + return BaseBus::BusType::PQ; } private: diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index 16099a606..a629c0b00 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -193,7 +193,7 @@ namespace ModelLib virtual const int BusType() const { - return 2; + return BaseBus::BusType::PV; } private: diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index 22b45f90a..8bb973d1b 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -183,7 +183,7 @@ namespace ModelLib virtual const int BusType() const { - return 3; + return BaseBus::BusType::Slack; } private: diff --git a/ComponentLib/Generator/CMakeLists.txt b/ComponentLib/Generator/CMakeLists.txt index 68ef63cf7..a09c5aed1 100644 --- a/ComponentLib/Generator/CMakeLists.txt +++ b/ComponentLib/Generator/CMakeLists.txt @@ -63,6 +63,8 @@ gridkit_add_library(generator SOURCES GeneratorSlack.cpp + GeneratorPV.cpp + GeneratorPQ.cpp OUTPUT_NAME gridkit_generator) diff --git a/ComponentLib/Generator/GeneratorBase.hpp b/ComponentLib/Generator/GeneratorBase.hpp index 164e6eb2a..e1efa22bd 100644 --- a/ComponentLib/Generator/GeneratorBase.hpp +++ b/ComponentLib/Generator/GeneratorBase.hpp @@ -70,9 +70,11 @@ namespace ModelLib namespace ModelLib { - /*! - * @brief Implementation of a power grid. - * + /** + * @brief Generator base class template + * + * @tparam ScalarT - Scalar type + * @tparam IdxT - Matrix and vector index type */ template class GeneratorBase : public ModelEvaluatorImpl @@ -95,9 +97,6 @@ namespace ModelLib using bus_type = BaseBus; using real_type = typename ModelEvaluatorImpl::real_type; - // using BusData = GridKit::PowerSystemData::BusData; - // typedef typename ModelEvaluatorImpl::real_type real_type; - // typedef BaseBus bus_type; public: GeneratorBase(){} diff --git a/ComponentLib/Generator/GeneratorPV.hpp b/ComponentLib/Generator/GeneratorPV.hpp index c34df84ad..5e3be2041 100644 --- a/ComponentLib/Generator/GeneratorPV.hpp +++ b/ComponentLib/Generator/GeneratorPV.hpp @@ -124,18 +124,14 @@ namespace ModelLib return P_; } - /// @brief Reactive power excess on PV bus - /// @return reference to negative PV generator reactive power virtual ScalarT& Q() { - return (bus_->Q()); + return bus_->Q(); } - /// @brief Reactive power excess on PV bus - /// @return const reference to negative PV generator reactive power virtual const ScalarT& Q() const { - return (bus_->Q()); + return bus_->Q(); } private: diff --git a/Examples/Grid3Bus/Grid3BusSys.cpp b/Examples/Grid3Bus/Grid3BusSys.cpp index 02985ff1d..699b1b96e 100644 --- a/Examples/Grid3Bus/Grid3BusSys.cpp +++ b/Examples/Grid3Bus/Grid3BusSys.cpp @@ -89,49 +89,13 @@ static const std::string BUS3_DATA_STRING = R"( function mpc = case5 % Created by Reid Gomillion -% MATPOWER - -%% MATPOWER Case Format : Version 2 -mpc.version = '2'; - -%%----- Power Flow Data -----%% -%% system MVA base -mpc.baseMVA = 100; - -%% bus data -% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin -mpc.bus = [ - 1 3 2.0 0.0 0 0 0 1 0.0 0 0 0 0.0; - 2 1 2.5 -0.8 0 0 0 1 0.0 0 0 0 0.0; - 3 2 0 0 0 0 0 1.1 0.0 0 0 0 0.0; -]; - -%% generator data -% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf -mpc.gen = [ - 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; - 3 2.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; -]; - -%% branch data -% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax -mpc.branch = [ - 1 2 0 0.1 0 0 0 0 0 0 0 0 0; - 1 3 0 0.0666666 0 0 0 0 0 0 0 0 0; - 2 3 0 0.0833333 0 0 0 0 0 0 0 0 0; -]; - -%%----- OPF Data -----%% -%% generator cost data -% 1 startup shutdown n x1 y1 ... xn yn -% 2 startup shutdown n c(n-1) ... c0 -mpc.gencost = [ - 2 0 0 3 0 14 0; - 2 0 0 3 0 15 0; - 2 0 0 3 0 30 0; -]; - -)"; +int main() +{ + using namespace ModelLib; + using namespace AnalysisManager::Sundials; + using namespace AnalysisManager; + using namespace GridKit::Testing; + using namespace GridKit::PowerSystemData; using namespace ModelLib; @@ -273,35 +237,32 @@ int hardwired_case() SystemSteadyStateModel* sysmodel = new SystemSteadyStateModel(); // Next create and add buses ... - // Create a slack bus, fix V=1, theta=0, bus ID = 1 + // Create a slack bus, fix V=1, theta=0, bus ID = 1" << std::endl; BusData bd1; bd1.bus_i = 1; bd1.type = 3; bd1.Vm = 1.0; bd1.Va = 0.0; auto* bus1 = BusFactory::create(bd1); + // BaseBus* bus1 = new BusSlack(bd1); sysmodel->addBus(bus1); - //Create a PQ bus, initialize V=1, theta=0, bus ID = 2 + // Create a PQ bus, initialize V=1, theta=0, bus ID = 2" << std::endl; BusData bd2; bd2.bus_i = 2; bd2.type = 1; bd2.Vm = 1.0; bd2.Va = 0.0; auto* bus2 = BusFactory::create(bd2); + // BaseBus* bus2 = new BusPQ(bd2); sysmodel->addBus(bus2); - // Create a PV bus, fix V=1.1, initialize theta=0, and set power injection Pg=2 + std::cout << "// Create a PV bus, fix V=1.1, initialize theta=0, and set power injection Pg=2" << std::endl; BusData bd3; bd3.bus_i = 3; bd3.type = 2; bd3.Vm = 1.1; bd3.Va = 0.0; auto* bus3 = BusFactory::create(bd3); + // BaseBus* bus3 = new BusPV(1.1, 0.0, 2.0); sysmodel->addBus(bus3); // Create and add generators ... - // Create and add slack generator connected to bus1 - GenData gd1; - gd1.bus = 1; - auto* gen1 = GeneratorFactory::create(sysmodel->getBus(gd1.bus), gd1); - sysmodel->addComponent(gen1); - - // Create and add PV generator connected to bus3 + std::cout << "// Set power injection to 2.0 for bus3" << std::endl; GenData gd3; gd3.Pg = 2.0; gd3.bus = 3; - auto* gen3 = GeneratorFactory::create(sysmodel->getBus(gd3.bus), gd3); + auto* gen3 = GeneratorFactory::create(bus3, gd3); sysmodel->addComponent(gen3); // Create and add branches ... diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/Examples/MatPowerTesting/test_parse_matpower.cpp index e4cec26fa..fa926cad2 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/Examples/MatPowerTesting/test_parse_matpower.cpp @@ -122,7 +122,7 @@ int main(int argc, char **argv) { {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; - std::vector> load_answer{ + std::vector load_answer{ {1, 0, 0}, {2, 300, 98.61}, {3, 300, 98.61}, diff --git a/PowerSystemData.hpp b/PowerSystemData.hpp index 5bba07992..67294db4f 100644 --- a/PowerSystemData.hpp +++ b/PowerSystemData.hpp @@ -24,7 +24,7 @@ namespace PowerSystemData struct BusData { IdxT bus_i; ///< Bus ID - IdxT type; ///< Bust type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + IdxT type; ///< Bus type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) IdxT area; ///< Area number (>0) diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp index c32f4c030..825123c97 100644 --- a/Utilities/FileIO.hpp +++ b/Utilities/FileIO.hpp @@ -160,19 +160,19 @@ void readMatPowerBusRow(const std::string& row, BusData& br, LoadDa { logs() << "Parsing MATPOWER bus row\n"; std::stringstream is(row); - is >> br.bus_i - >> br.type - >> lr.Pd - >> lr.Qd - >> br.Gs - >> br.Bs - >> br.area - >> br.Vm - >> br.Va - >> br.baseKV - >> br.zone - >> br.Vmax - >> br.Vmin; + is >> br.bus_i // Bus ID + >> br.type // Bus type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + >> lr.Pd // Active power demand [MW] + >> lr.Qd // Reactive power demand [MVAr] + >> br.Gs // Shunt conductance (MW demanded at V = 1.0 p.u.) + >> br.Bs // Shunt susceptance (MVAr injected at V = 1.0 p.u.) + >> br.area // Area number (>0) + >> br.Vm // Voltage magnitude (p.u.) + >> br.Va // Voltage phase (deg) + >> br.baseKV // Base voltage [kV] + >> br.zone // Loss zone number (>0) + >> br.Vmax // Maximum voltage magnitude (p.u.) + >> br.Vmin; // Minimum voltage magnitude (p.u.) lr.bus_i = br.bus_i; From da342bda3c7df15a36e4150736683ec900096996 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 15 Dec 2022 00:22:26 -0500 Subject: [PATCH 36/52] Supporting infrastructure for Loads and Branches Expanded methods for adding components to the power system grid. Includes new constructors for loads and branches, as well as methods for accessing buses through their IDs. --- ComponentLib/Bus/BaseBus.hpp | 10 +++++++++- ComponentLib/Bus/BusPQ.cpp | 10 ---------- ComponentLib/Bus/BusPV.cpp | 18 ++++------------- ComponentLib/Bus/BusSlack.cpp | 9 --------- Examples/Grid3Bus/Grid3BusSys.cpp | 33 +++++++++++++++---------------- Utilities/Testing.hpp | 22 +++++++++++++++------ 6 files changed, 45 insertions(+), 57 deletions(-) diff --git a/ComponentLib/Bus/BaseBus.hpp b/ComponentLib/Bus/BaseBus.hpp index 1d19d963f..4e8cbd5f1 100644 --- a/ComponentLib/Bus/BaseBus.hpp +++ b/ComponentLib/Bus/BaseBus.hpp @@ -104,7 +104,7 @@ namespace ModelLib enum BusType{PQ=1, PV, Slack, Isolated}; - BaseBus(){} + BaseBus(IdxT id) : busID_(id) {} virtual ~BaseBus(){} // Set defaults for ModelEvaluator methods @@ -141,6 +141,14 @@ namespace ModelLib virtual const ScalarT& QB() const = 0; virtual const int BusType() const = 0; + + virtual const IdxT BusID() const + { + return busID_; + } + + protected: + const IdxT busID_; }; // class BaseBus } // namespace ModelLib diff --git a/ComponentLib/Bus/BusPQ.cpp b/ComponentLib/Bus/BusPQ.cpp index 5ef2711b8..18c6ec22c 100644 --- a/ComponentLib/Bus/BusPQ.cpp +++ b/ComponentLib/Bus/BusPQ.cpp @@ -113,16 +113,6 @@ BusPQ::BusPQ(BusData& data) size_ = 2; } -template -BusPQ::BusPQ(BusData& data) - : V0_(data.Vm), theta0_(data.Va) -{ - //std::cout << "Create BusPQ..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - - size_ = 2; -} - template BusPQ::~BusPQ() { diff --git a/ComponentLib/Bus/BusPV.cpp b/ComponentLib/Bus/BusPV.cpp index cdd377bdb..fd05b2ecb 100644 --- a/ComponentLib/Bus/BusPV.cpp +++ b/ComponentLib/Bus/BusPV.cpp @@ -74,7 +74,7 @@ namespace ModelLib { */ template BusPV::BusPV() - : BaseBus(0), V_(0.0), theta0_(0.0) + : BaseBus(0), V_(0.0), theta0_(0.0), Pg_(0.0) { //std::cout << "Create BusPV..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; @@ -92,18 +92,8 @@ BusPV::BusPV() * - Number of optimization parameters = 0 */ template -BusPV::BusPV(ScalarT V, ScalarT theta0) - : BaseBus(0), V_(V), theta0_(theta0) -{ - //std::cout << "Create BusPV..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - - size_ = 1; -} - -template -BusPV::BusPV(BusData& data) - : BaseBus(data.bus_i), V_(data.Vm), theta0_(data.Va) +BusPV::BusPV(ScalarT V, ScalarT theta0, ScalarT Pg) + : BaseBus(0), V_(V), theta0_(theta0), Pg_(Pg) { //std::cout << "Create BusPV ..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; @@ -113,7 +103,7 @@ BusPV::BusPV(BusData& data) template BusPV::BusPV(BusData& data) - : V_(data.Vm), theta0_(data.Va) //, Pg_(Pg) + : BaseBus(data.bus_i), V_(data.Vm), theta0_(data.Va) { //std::cout << "Create BusPV ..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; diff --git a/ComponentLib/Bus/BusSlack.cpp b/ComponentLib/Bus/BusSlack.cpp index 2a961e8f8..80a5ae091 100644 --- a/ComponentLib/Bus/BusSlack.cpp +++ b/ComponentLib/Bus/BusSlack.cpp @@ -109,15 +109,6 @@ BusSlack::BusSlack(BusData& data) size_ = 0; } -template -BusSlack::BusSlack(BusData& data) - : V_(data.Vm), theta_(data.Va) //, P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) -{ - //std::cout << "Create BusSlack..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - size_ = 0; -} - template BusSlack::~BusSlack() { diff --git a/Examples/Grid3Bus/Grid3BusSys.cpp b/Examples/Grid3Bus/Grid3BusSys.cpp index 699b1b96e..3d06d506e 100644 --- a/Examples/Grid3Bus/Grid3BusSys.cpp +++ b/Examples/Grid3Bus/Grid3BusSys.cpp @@ -145,12 +145,12 @@ int monolithic_case() kinsol->printFinalStats(); int retval1 = 0; - retval1 += !isEqual(th2, theta2_ref, 1e-4); - retval1 += !isEqual(V2, V2_ref , 1e-4); - retval1 += !isEqual(th3, theta3_ref, 1e-4); + retval1 += !isEqual(th2, -4.87979, 1e-4); + retval1 += !isEqual(V2, 1.08281, 1e-4); + retval1 += !isEqual(th3, 1.46241, 1e-4); if(retval1 == 0) - std::cout << "\nSuccess!\n\n\n"; + std::cout << "\nSucess!\n\n\n"; else std::cout << "\nFailed!\n\n\n"; @@ -241,28 +241,30 @@ int hardwired_case() BusData bd1; bd1.bus_i = 1; bd1.type = 3; bd1.Vm = 1.0; bd1.Va = 0.0; auto* bus1 = BusFactory::create(bd1); - // BaseBus* bus1 = new BusSlack(bd1); sysmodel->addBus(bus1); // Create a PQ bus, initialize V=1, theta=0, bus ID = 2" << std::endl; BusData bd2; bd2.bus_i = 2; bd2.type = 1; bd2.Vm = 1.0; bd2.Va = 0.0; auto* bus2 = BusFactory::create(bd2); - // BaseBus* bus2 = new BusPQ(bd2); sysmodel->addBus(bus2); - std::cout << "// Create a PV bus, fix V=1.1, initialize theta=0, and set power injection Pg=2" << std::endl; + // Create a PV bus, fix V=1.1, initialize theta=0, and set power injection Pg=2" << std::endl; BusData bd3; bd3.bus_i = 3; bd3.type = 2; bd3.Vm = 1.1; bd3.Va = 0.0; auto* bus3 = BusFactory::create(bd3); - // BaseBus* bus3 = new BusPV(1.1, 0.0, 2.0); sysmodel->addBus(bus3); // Create and add generators ... - std::cout << "// Set power injection to 2.0 for bus3" << std::endl; + // Create and add slack generator connected to bus1 + GenData gd1; + gd1.bus = 1; + auto* gen1 = GeneratorFactory::create(sysmodel->getBus(gd1.bus), gd1); + sysmodel->addComponent(gen1); + // Create and add PV generator connected to bus3 GenData gd3; gd3.Pg = 2.0; gd3.bus = 3; - auto* gen3 = GeneratorFactory::create(bus3, gd3); + auto* gen3 = GeneratorFactory::create(sysmodel->getBus(gd3.bus), gd3); sysmodel->addComponent(gen3); // Create and add branches ... @@ -271,13 +273,11 @@ int hardwired_case() brd12.fbus = 1; brd12.tbus = 2; brd12.x = 1.0/10.0; brd12.r = 0.0; brd12.b = 0.0; Branch* branch12 = new Branch(sysmodel->getBus(brd12.fbus), sysmodel->getBus(brd12.tbus), brd12); sysmodel->addComponent(branch12); - // Branch 1-3 BranchData brd13; brd13.fbus = 1; brd13.tbus = 3; brd13.x = 1.0/15.0; brd13.r = 0.0; brd13.b = 0.0; Branch* branch13 = new Branch(sysmodel->getBus(brd13.fbus), sysmodel->getBus(brd13.tbus), brd13); sysmodel->addComponent(branch13); - // Branch 2-3 BranchData brd23; brd23.fbus = 2; brd23.tbus = 3; brd23.x = 1.0/12.0; brd23.r = 0.0; brd23.b = 0.0; @@ -291,7 +291,6 @@ int hardwired_case() ld1.bus_i = 1; ld1.Pd = 2.0; ld1.Qd = 0.0; Load* load1 = new Load(sysmodel->getBus(ld1.bus_i), ld1); sysmodel->addComponent(load1); - // Load on bus2 LoadData ld2; ld2.bus_i = 2; ld2.Pd = 2.5; ld2.Qd = -0.8; @@ -327,12 +326,12 @@ int hardwired_case() kinsol->printFinalStats(); int retval2 = 0; - retval2 += !isEqual(th2, theta2_ref, 1e-4); - retval2 += !isEqual(V2, V2_ref , 1e-4); - retval2 += !isEqual(th3, theta3_ref, 1e-4); + retval2 += !isEqual(th2, -4.87979, 1e-4); + retval2 += !isEqual(V2, 1.08281, 1e-4); + retval2 += !isEqual(th3, 1.46241, 1e-4); if(retval2 == 0) - std::cout << "\nSuccess!\n\n\n"; + std::cout << "\nSucess!\n\n\n"; else std::cout << "\nFailed!\n\n\n"; diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp index 216d42637..f061cdbd1 100644 --- a/Utilities/Testing.hpp +++ b/Utilities/Testing.hpp @@ -93,7 +93,8 @@ template bool isEqual(const T value, const T ref, const T tol) template inline bool isEqual(PowerSystemData::GenCostData a, PowerSystemData::GenCostData b, - RealT tol = tol_) { + RealT tol = tol_) +{ int fail = 0; fail += a.kind != b.kind; fail += a.startup != b.startup; @@ -107,7 +108,9 @@ inline bool isEqual(PowerSystemData::GenCostData a, template inline bool isEqual(PowerSystemData::GenData a, - PowerSystemData::GenData b, RealT tol = tol_) { + PowerSystemData::GenData b, + RealT tol = tol_) +{ int fail = 0; fail += a.bus != b.bus; fail += !isEqual(a.Pg, b.Pg, tol); @@ -138,7 +141,9 @@ inline bool isEqual(PowerSystemData::GenData a, template inline bool isEqual(PowerSystemData::BusData a, - PowerSystemData::BusData b, RealT tol = tol_) { + PowerSystemData::BusData b, + RealT tol = tol_) +{ int fail = 0; fail += a.bus_i != b.bus_i; fail += a.type != b.type; @@ -169,7 +174,9 @@ inline bool isEqual(PowerSystemData::BusData a, template inline bool isEqual(PowerSystemData::LoadData a, - PowerSystemData::LoadData b, RealT tol = tol_) { + PowerSystemData::LoadData b, + RealT tol = tol_) +{ int fail = 0; fail += a.bus_i != b.bus_i; fail += !isEqual(a.Pd, b.Pd, tol); @@ -184,7 +191,9 @@ inline bool isEqual(PowerSystemData::LoadData a, template inline bool isEqual(PowerSystemData::BranchData a, - PowerSystemData::BranchData b, RealT tol = tol_) { + PowerSystemData::BranchData b, + RealT tol = tol_) +{ int fail = 0; fail += a.fbus != b.fbus; fail += a.tbus != b.tbus; @@ -230,7 +239,8 @@ inline bool isEqual(std::vector a, std::vector b, double tol = tol_) template inline bool isEqual(PowerSystemData::SystemModelData a, - PowerSystemData::SystemModelData b) { + PowerSystemData::SystemModelData b) +{ int fail = 0; fail += a.version != b.version; fail += a.baseMVA != b.baseMVA; From 0caf79b43a1cbed057eb2a8f60df4179ee79b311 Mon Sep 17 00:00:00 2001 From: "Gomillion, Reid" Date: Tue, 20 Jun 2023 18:17:21 +0000 Subject: [PATCH 37/52] Updated Parsing Example --- Examples/Grid3Bus/3bus.mat | 47 ++++++++++++++++++ Examples/Grid3Bus/Grid3BusSys.cpp | 79 ++++++++++++++++++++++++------- SystemSteadyStateModel.hpp | 37 +++++++++++++++ 3 files changed, 145 insertions(+), 18 deletions(-) create mode 100644 Examples/Grid3Bus/3bus.mat diff --git a/Examples/Grid3Bus/3bus.mat b/Examples/Grid3Bus/3bus.mat new file mode 100644 index 000000000..4663eb33c --- /dev/null +++ b/Examples/Grid3Bus/3bus.mat @@ -0,0 +1,47 @@ +( +function mpc = case5 +% Created by Reid Gomillion + +% MATPOWER + +%% MATPOWER Case Format : Version 2 +mpc.version = '2'; + +%%----- Power Flow Data -----%% +%% system MVA base +mpc.baseMVA = 100; + +%% bus data +% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin +mpc.bus = [ + 1 3 2.0 0.0 0 0 0 1 0.0 0 0 0 0.0; + 2 1 2.5 -0.8 0 0 0 1 0.0 0 0 0 0.0; + 3 2 0 0 0 0 0 1.1 0.0 0 0 0 0.0; +]; + +%% generator data +% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf +mpc.gen = [ + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 3 2.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; +]; + +%% branch data +% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax +mpc.branch = [ + 1 2 0 0.1 0 0 0 0 0 0 0 0 0; + 1 3 0 0.0666666 0 0 0 0 0 0 0 0 0; + 2 3 0 0.0833333 0 0 0 0 0 0 0 0 0; +]; + +%%----- OPF Data -----%% +%% generator cost data +% 1 startup shutdown n x1 y1 ... xn yn +% 2 startup shutdown n c(n-1) ... c0 +mpc.gencost = [ + 2 0 0 3 0 14 0; + 2 0 0 3 0 15 0; + 2 0 0 3 0 30 0; +]; + +) \ No newline at end of file diff --git a/Examples/Grid3Bus/Grid3BusSys.cpp b/Examples/Grid3Bus/Grid3BusSys.cpp index 3d06d506e..f14aa0d6e 100644 --- a/Examples/Grid3Bus/Grid3BusSys.cpp +++ b/Examples/Grid3Bus/Grid3BusSys.cpp @@ -89,13 +89,54 @@ static const std::string BUS3_DATA_STRING = R"( function mpc = case5 % Created by Reid Gomillion -int main() -{ - using namespace ModelLib; - using namespace AnalysisManager::Sundials; - using namespace AnalysisManager; - using namespace GridKit::Testing; - using namespace GridKit::PowerSystemData; +//Note: This was traced from the subsequent calls +static const std::string BUS3_DATA_STRING = R"( +function mpc = case5 +% Created by Reid Gomillion + +% MATPOWER + +%% MATPOWER Case Format : Version 2 +mpc.version = '2'; + +%%----- Power Flow Data -----%% +%% system MVA base +mpc.baseMVA = 100; + +%% bus data +% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin +mpc.bus = [ + 1 3 2.0 0.0 0 0 0 1 0.0 0 0 0 0.0; + 2 1 2.5 -0.8 0 0 0 1 0.0 0 0 0 0.0; + 3 2 0 0 0 0 0 1.1 0.0 0 0 0 0.0; +]; + +%% generator data +% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf +mpc.gen = [ + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 3 2.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; +]; + +%% branch data +% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax +mpc.branch = [ + 1 2 0 0.1 0 0 0 0 0 0 0 0 0; + 1 3 0 0.0666666 0 0 0 0 0 0 0 0 0; + 2 3 0 0.0833333 0 0 0 0 0 0 0 0 0; +]; + +%%----- OPF Data -----%% +%% generator cost data +% 1 startup shutdown n x1 y1 ... xn yn +% 2 startup shutdown n c(n-1) ... c0 +mpc.gencost = [ + 2 0 0 3 0 14 0; + 2 0 0 3 0 15 0; + 2 0 0 3 0 30 0; +]; + +)"; using namespace ModelLib; @@ -104,9 +145,6 @@ using namespace AnalysisManager; using namespace GridKit::Testing; using namespace GridKit::PowerSystemData; -constexpr double theta2_ref = -4.87979; // [deg] -constexpr double V2_ref = 1.08281; // [p.u.] -constexpr double theta3_ref = 1.46241; // [deg] /** * Testing the monlithic case via the class MiniGrid @@ -199,20 +237,20 @@ int parser_case() std::cout << "Solution:\n"; - std::cout << " theta2 = " << th2 << " deg, expected = " << theta2_ref << " deg\n"; - std::cout << " V2 = " << V2 << " p.u., expected = " << V2_ref << " p.u.\n"; - std::cout << " theta3 = " << th3 << " deg, expected = " << theta3_ref << " deg\n\n"; + std::cout << " theta2 = " << th2 << " deg, expected = " << " -4.87979 deg\n"; + std::cout << " V2 = " << V2 << " p.u., expected = " << " 1.08281 p.u.\n"; + std::cout << " theta3 = " << th3 << " deg, expected = " << " 1.46241 deg\n\n"; // Print solver performance statistics kinsol->printFinalStats(); int retval2 = 0; - retval2 += !isEqual(th2, theta2_ref, 1e-4); - retval2 += !isEqual(V2, V2_ref , 1e-4); - retval2 += !isEqual(th3, theta3_ref, 1e-4); + retval2 += !isEqual(th2, -4.87979, 1e-4); + retval2 += !isEqual(V2, 1.08281, 1e-4); + retval2 += !isEqual(th3, 1.46241, 1e-4); if(retval2 == 0) - std::cout << "\nSuccess!\n\n\n"; + std::cout << "\nSucess!\n\n\n"; else std::cout << "\nFailed!\n\n\n"; @@ -243,7 +281,7 @@ int hardwired_case() auto* bus1 = BusFactory::create(bd1); sysmodel->addBus(bus1); - // Create a PQ bus, initialize V=1, theta=0, bus ID = 2" << std::endl; + //Create a PQ bus, initialize V=1, theta=0, bus ID = 2" << std::endl; BusData bd2; bd2.bus_i = 2; bd2.type = 1; bd2.Vm = 1.0; bd2.Va = 0.0; auto* bus2 = BusFactory::create(bd2); @@ -261,6 +299,7 @@ int hardwired_case() gd1.bus = 1; auto* gen1 = GeneratorFactory::create(sysmodel->getBus(gd1.bus), gd1); sysmodel->addComponent(gen1); + // Create and add PV generator connected to bus3 GenData gd3; gd3.Pg = 2.0; gd3.bus = 3; @@ -273,11 +312,13 @@ int hardwired_case() brd12.fbus = 1; brd12.tbus = 2; brd12.x = 1.0/10.0; brd12.r = 0.0; brd12.b = 0.0; Branch* branch12 = new Branch(sysmodel->getBus(brd12.fbus), sysmodel->getBus(brd12.tbus), brd12); sysmodel->addComponent(branch12); + // Branch 1-3 BranchData brd13; brd13.fbus = 1; brd13.tbus = 3; brd13.x = 1.0/15.0; brd13.r = 0.0; brd13.b = 0.0; Branch* branch13 = new Branch(sysmodel->getBus(brd13.fbus), sysmodel->getBus(brd13.tbus), brd13); sysmodel->addComponent(branch13); + // Branch 2-3 BranchData brd23; brd23.fbus = 2; brd23.tbus = 3; brd23.x = 1.0/12.0; brd23.r = 0.0; brd23.b = 0.0; @@ -291,6 +332,7 @@ int hardwired_case() ld1.bus_i = 1; ld1.Pd = 2.0; ld1.Qd = 0.0; Load* load1 = new Load(sysmodel->getBus(ld1.bus_i), ld1); sysmodel->addComponent(load1); + // Load on bus2 LoadData ld2; ld2.bus_i = 2; ld2.Pd = 2.5; ld2.Qd = -0.8; @@ -346,6 +388,7 @@ int hardwired_case() int main() { //return the results of each case + //swapping orders of test causes memory error, specifically hardware <-> parser int resolve = 0; std::cout << std::string(32,'-') << std::endl; resolve += monolithic_case(); diff --git a/SystemSteadyStateModel.hpp b/SystemSteadyStateModel.hpp index c32dd5ec3..de2dc000e 100644 --- a/SystemSteadyStateModel.hpp +++ b/SystemSteadyStateModel.hpp @@ -127,6 +127,43 @@ class SystemSteadyStateModel : public ModelEvaluatorImpl atol_ = 1e-5; } + SystemSteadyStateModel(GridKit::PowerSystemData::SystemModelData mp) : ModelEvaluatorImpl(0,0,0) + { + rtol_ = 1e-5; + atol_ = 1e-5; + + //buses + for(auto busdata : mp.bus) + { + auto* bus = BusFactory::create(busdata); + this->addBus(bus); + } + + //generators + for (auto gendata : mp.gen) + { + auto* gen = GeneratorFactory::create(this->getBus(gendata.bus),gendata); + this->addComponent(gen); + } + + //branches + for (auto branchdata : mp.branch) + { + auto* branch = new Branch(this->getBus(branchdata.fbus),this->getBus(branchdata.tbus),branchdata); + this->addComponent(branch); + } + + //loads + for (auto loaddata : mp.load) + { + auto* loadm = new Load(this->getBus(loaddata.bus_i),loaddata); + this->addComponent(loadm); + } + + //There appears to not be a Generator Cost Object + //TODO: Implment for GenCost + } + /** * @brief Construct a new System Steady State Model object. Allows for simple allocation. * From d1c58bd1d85188ecab93d6bb8bd23bcb70dd138c Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Fri, 30 Jun 2023 15:42:21 -0400 Subject: [PATCH 38/52] Prototype Example of Creating a RL Circuit +Add hypergraph representation +Added Model form with appropiate indexing +Added Resistors, Capacitor, Inductor, and VoltageSource Component Models --- CircuitGraph.hpp | 119 ++++++++++ ComponentLib/CMakeLists.txt | 2 + .../PowerElectronicsComponents/CMakeLists.txt | 6 + .../Capacitor/CMakeLists.txt | 8 + .../Capacitor/Capacitor.cpp | 117 ++++++++++ .../Capacitor/Capacitor.hpp | 64 ++++++ .../CircuitComponent.hpp | 68 ++++++ .../Inductor/CMakeLists.txt | 8 + .../Inductor/Inductor.cpp | 117 ++++++++++ .../Inductor/Inductor.hpp | 66 ++++++ .../Resistor/CMakeLists.txt | 8 + .../Resistor/Resistor.cpp | 117 ++++++++++ .../Resistor/Resistor.hpp | 65 ++++++ .../VoltageSource/CMakeLists.txt | 8 + .../VoltageSource/VoltageSource.cpp | 119 ++++++++++ .../VoltageSource/VoltageSource.hpp | 63 +++++ Examples/CMakeLists.txt | 1 + Examples/RLCircuit/CMakeLists.txt | 12 + Examples/RLCircuit/RLCircuit.cpp | 114 +++++++++ ModelEvaluatorImpl.hpp | 8 + PowerElectronicsModel.hpp | 217 ++++++++++++++++++ 21 files changed, 1307 insertions(+) create mode 100644 CircuitGraph.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/Capacitor/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/Inductor/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/Resistor/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/VoltageSource/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp create mode 100644 Examples/RLCircuit/CMakeLists.txt create mode 100644 Examples/RLCircuit/RLCircuit.cpp create mode 100644 PowerElectronicsModel.hpp diff --git a/CircuitGraph.hpp b/CircuitGraph.hpp new file mode 100644 index 000000000..e54f5a150 --- /dev/null +++ b/CircuitGraph.hpp @@ -0,0 +1,119 @@ + + +#include +#include +#include +#include +#include + +/** + * @brief A very basic hypergraph setup for circuit representation. This forms the hypergraph as a bipartite graph. Doesn't allow removing. Can only grab sets of connections to nodes + * + * @todo should replace with something better and more efficent. Should replace with a libraries setup instead. This would allow fast and easy partitioning of circuits + * + * @todo should replace N and E with Node and Component classes respectively + * + * @tparam IdxT + * @tparam Label + */ +template +class CircuitGraph +{ +private: + std::set hypernodes; + std::set hyperedges; + std::map> edgestonodes; +public: + CircuitGraph(); + ~CircuitGraph(); + bool addHyperEdge(E he); + bool addHyperNode(N hn); + bool addConnection(N hn, E he); + std::set getHyperEdgeConnections(E he); + size_t amountHyperNodes(); + size_t amountHyperEdges(); + void printBiPartiteGraph(bool verbose = false); +}; + +template +CircuitGraph::CircuitGraph() +{ +} + +template +CircuitGraph::~CircuitGraph() +{ +} + +template +bool CircuitGraph::addHyperNode(N hn) +{ + return this->hypernodes.insert(hn).second; +} + +template +bool CircuitGraph::addHyperEdge(E he) +{ + return this->hyperedges.insert(he).second; +} + + +template +bool CircuitGraph::addConnection(N hn, E he) +{ + if(this->hyperedges.count(he) == 0 || this->hypernodes.count(hn) == 0) + { + return false; + } + return this->edgestonodes[he].insert(hn).second; +} + + +template +std::set CircuitGraph::getHyperEdgeConnections(E he) +{ + return this->edgestonodes[he]; +} + + +template +size_t CircuitGraph::amountHyperNodes() +{ + return this->hypernodes.size(); +} + + +template +size_t CircuitGraph::amountHyperEdges() +{ + return this->hyperedges.size(); +} + +/** + * @brief Printing + * + * @todo need to add verbose printing for connections display + * + * @tparam IdxT + * @param verbose + */ + +template +void CircuitGraph::printBiPartiteGraph(bool verbose) +{ + + std::cout << "Amount of HyperNodes: " << this->amountHyperNodes() << std::endl; + std::cout << "Amount of HyperEdges: " << this->amountHyperEdges() << std::endl; + std::cout << "Connections per Edge:" << std::endl; + for (auto i : this->edgestonodes) + { + std::cout << i.first << " : {"; + for (auto j : i.second){ + std::cout << j << ", "; + } + std::cout << "}\n"; + + } + + +} diff --git a/ComponentLib/CMakeLists.txt b/ComponentLib/CMakeLists.txt index 0c422d5b9..29a5a7988 100644 --- a/ComponentLib/CMakeLists.txt +++ b/ComponentLib/CMakeLists.txt @@ -69,3 +69,5 @@ add_subdirectory(Generator4Governor) add_subdirectory(Generator4Param) add_subdirectory(Load) add_subdirectory(MiniGrid) +add_subdirectory(PowerElectronicsComponents) + diff --git a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt new file mode 100644 index 000000000..c3e958300 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt @@ -0,0 +1,6 @@ + + +add_subdirectory(Capacitor) +add_subdirectory(Resistor) +add_subdirectory(VoltageSource) +add_subdirectory(Inductor) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/Capacitor/CMakeLists.txt new file mode 100644 index 000000000..62efc1795 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_capacitor + SOURCES + Capacitor.cpp + OUTPUT_NAME + gridkit_powerelec_capacitor) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp new file mode 100644 index 000000000..4fcda9d9f --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp @@ -0,0 +1,117 @@ + + + +#include +#include +#include +#include "Capacitor.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +Capacitor::Capacitor(IdxT id, ScalarT C) + : C_(C) +{ + this->size_ = 3; + this->n_intern = 1; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +Capacitor::~Capacitor() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int Capacitor::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int Capacitor::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int Capacitor::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int Capacitor::evaluateResidual() +{ + this->f_[0] = this->yp_[2]; + this->f_[1] = -this->yp_[2]; + this->f_[2] = this->y_[0] - this->y_[1] - this->y_[2] - this->C_ * this->yp_[2]; + return 0; +} + +template +int Capacitor::evaluateJacobian() +{ + + return 0; +} + +template +int Capacitor::evaluateIntegrand() +{ + return 0; +} + +template +int Capacitor::initializeAdjoint() +{ + return 0; +} + +template +int Capacitor::evaluateAdjointResidual() +{ + return 0; +} + +template +int Capacitor::evaluateAdjointIntegrand() +{ + return 0; +} + + + + +// Available template instantiations +template class Capacitor; +template class Capacitor; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp new file mode 100644 index 000000000..76cf94614 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp @@ -0,0 +1,64 @@ + + +#ifndef _CAP_HPP_ +#define _CAP_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive Capacitor class. + * + */ + template + class Capacitor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + Capacitor(IdxT id, ScalarT C); + virtual ~Capacitor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT C_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp new file mode 100644 index 000000000..7cfb5521a --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp @@ -0,0 +1,68 @@ + + +#ifndef _CIRCCOMP_HPP_ +#define _CIRCCOMP_HPP_ + +#include +#include +#include +#include + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive CircuitComponent class. + * + */ + template + class CircuitComponent : public ModelEvaluatorImpl + { + + public: + + + void updateTime(ScalarT t, ScalarT a) + { + this->time_ = t; + this->alpha_ = a; + } + + size_t getExternSize() + { + return this->n_extern; + } + + size_t getInternalSize() + { + return this->n_intern; + } + + std::set getExternIndices() + { + return this->extern_indices; + } + + bool setExternalConnectionNodes(size_t index, IdxT id) + { + this->connection_nodes[index] = id; + return true; + } + + IdxT getNodeConnection(size_t index) + { + return this->connection_nodes.at(index); + } + + protected: + size_t n_extern; + size_t n_intern; + std::set extern_indices; + std::map connection_nodes; + + }; + + +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/Inductor/CMakeLists.txt new file mode 100644 index 000000000..4c620030f --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Inductor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_inductor + SOURCES + Inductor.cpp + OUTPUT_NAME + gridkit_powerelec_inductor) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp new file mode 100644 index 000000000..278b0eebc --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -0,0 +1,117 @@ + + + +#include +#include +#include +#include "Inductor.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +Inductor::Inductor(IdxT id, ScalarT L) + : L_(L) +{ + this->size_ = 3; + this->n_intern = 1; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +Inductor::~Inductor() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int Inductor::allocate() +{ + + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int Inductor::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int Inductor::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int Inductor::evaluateResidual() +{ + this->f_[0] = this->y_[2]; + this->f_[1] = -this->y_[2]; + this->f_[2] = this->y_[0] - this->y_[1] - this->L_ * this->yp_[2]; + return 0; +} + +template +int Inductor::evaluateJacobian() +{ + return 0; +} + +template +int Inductor::evaluateIntegrand() +{ + return 0; +} + +template +int Inductor::initializeAdjoint() +{ + return 0; +} + +template +int Inductor::evaluateAdjointResidual() +{ + return 0; +} + +template +int Inductor::evaluateAdjointIntegrand() +{ + return 0; +} + + + + +// Available template instantiations +template class Inductor; +template class Inductor; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp new file mode 100644 index 000000000..e959aabf1 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp @@ -0,0 +1,66 @@ + + +#ifndef _IND_HPP_ +#define _IND_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive Inductor class. + * + */ + template + class Inductor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + + public: + Inductor(IdxT id, ScalarT L); + virtual ~Inductor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT L_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/Resistor/CMakeLists.txt new file mode 100644 index 000000000..9386bda83 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Resistor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_resistor + SOURCES + Resistor.cpp + OUTPUT_NAME + gridkit_powerelec_resistor) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp new file mode 100644 index 000000000..1aa06427a --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp @@ -0,0 +1,117 @@ + + + +#include +#include +#include +#include "Resistor.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant resistor model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +Resistor::Resistor(IdxT id, ScalarT R) + : R_(R) +{ + this->size_ = 2; + this->n_intern = 0; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +Resistor::~Resistor() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int Resistor::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int Resistor::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int Resistor::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int Resistor::evaluateResidual() +{ + + this->f_[0] = (this->y_[1] - this->y_[0])/this->R_ ; + this->f_[1] = (this->y_[0] - this->y_[1])/this->R_ ; + return 0; +} + +template +int Resistor::evaluateJacobian() +{ + return 0; +} + +template +int Resistor::evaluateIntegrand() +{ + return 0; +} + +template +int Resistor::initializeAdjoint() +{ + return 0; +} + +template +int Resistor::evaluateAdjointResidual() +{ + return 0; +} + +template +int Resistor::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class Resistor; +template class Resistor; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp new file mode 100644 index 000000000..0373e2c5c --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp @@ -0,0 +1,65 @@ + + +#ifndef _RES_HPP_ +#define _RES_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive Resistor class. + * + */ + template + class Resistor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + Resistor(IdxT id, ScalarT R); + virtual ~Resistor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT R_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/VoltageSource/CMakeLists.txt new file mode 100644 index 000000000..7196f4d43 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_voltagesource + SOURCES + VoltageSource.cpp + OUTPUT_NAME + gridkit_powerelec_voltagesource) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp new file mode 100644 index 000000000..c27c04bd2 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp @@ -0,0 +1,119 @@ + + + +#include +#include +#include +#include "VoltageSource.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant VoltageSource model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +VoltageSource::VoltageSource(IdxT id, ScalarT V) + : V_(V) +{ + this->size_ = 3; + this->n_intern = 1; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +VoltageSource::~VoltageSource() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int VoltageSource::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int VoltageSource::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int VoltageSource::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int VoltageSource::evaluateResidual() +{ + //Note this leaves induction lumped into y. Perhaps would be better to seperate volatge and induction into seperate vectors + // for easier development + this->f_[0] = this->y_[2]; + this->f_[1] = -this->y_[2]; + this->f_[2] = this->y_[0] - this->y_[1] - this->V_; + return 0; +} + +template +int VoltageSource::evaluateJacobian() +{ + return 0; +} + +template +int VoltageSource::evaluateIntegrand() +{ + return 0; +} + +template +int VoltageSource::initializeAdjoint() +{ + return 0; +} + +template +int VoltageSource::evaluateAdjointResidual() +{ + return 0; +} + +template +int VoltageSource::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class VoltageSource; +template class VoltageSource; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp new file mode 100644 index 000000000..dcbacf2f7 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp @@ -0,0 +1,63 @@ + + +#ifndef _VOSO_HPP_ +#define _VOSO_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive VoltageSource class. + * + */ + template + class VoltageSource : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + public: + VoltageSource(IdxT id, ScalarT V); + virtual ~VoltageSource(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT V_; + }; +} + +#endif diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index feec6623a..b42907fd3 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -56,6 +56,7 @@ # add_subdirectory(MatPowerTesting) +add_subdirectory(RLCircuit) if(TARGET SUNDIALS::kinsol) add_subdirectory(Grid3Bus) diff --git a/Examples/RLCircuit/CMakeLists.txt b/Examples/RLCircuit/CMakeLists.txt new file mode 100644 index 000000000..5069566bf --- /dev/null +++ b/Examples/RLCircuit/CMakeLists.txt @@ -0,0 +1,12 @@ + + + + +add_executable(rlcircuit RLCircuit.cpp) +target_link_libraries(rlcircuit GRIDKIT::powerelec_capacitor + GRIDKIT::powerelec_inductor + GRIDKIT::powerelec_resistor + GRIDKIT::powerelec_voltagesource) + +add_test(NAME RLCircuit COMMAND $) +install(TARGETS rlcircuit RUNTIME DESTINATION bin) diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp new file mode 100644 index 000000000..ba9333f40 --- /dev/null +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -0,0 +1,114 @@ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + + +int main(int argc, char const *argv[]) +{ + //Basic Circuit Setup + //@todo will want to eventually put components in the hyper graph instead of indicies + + std::unique_ptr> cirg(new CircuitGraph()); + for (size_t i = 0; i < 3; i++) + { + cirg->addHyperEdge(i); + } + for (size_t i = 0; i < 5; i++) + { + cirg->addHyperNode(i); + } + + //Create Connections of Nodes to edges sets + //External nodes + cirg->addConnection(0, 0); + cirg->addConnection(0, 2); + cirg->addConnection(2, 0); + cirg->addConnection(2, 1); + cirg->addConnection(3, 1); + cirg->addConnection(3, 2); + + //Internal nodes + cirg->addConnection(1,0); + cirg->addConnection(4,2); + + + cirg->printBiPartiteGraph(); + + + //Create circuit model + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(); + + size_t idoff = 0; + + //inductor + ModelLib::Inductor* induct = new ModelLib::Inductor(idoff,0.1); + //Form index to node uid realations + induct->setExternalConnectionNodes(0,2); + induct->setExternalConnectionNodes(2,1); + induct->setExternalConnectionNodes(1,0); + sysmodel->addComponent(induct); + + + //resistor + idoff++; + ModelLib::Resistor* resis = new ModelLib::Resistor(idoff, 1.0); + //Form index to node uid realations + resis->setExternalConnectionNodes(0,3); + resis->setExternalConnectionNodes(1,2); + sysmodel->addComponent(resis); + + //voltage source + idoff++; + ModelLib::VoltageSource* vsource = new ModelLib::VoltageSource(idoff, 0.1); + //Form index to node uid realations + vsource->setExternalConnectionNodes(0,0); + vsource->setExternalConnectionNodes(2,4); + vsource->setExternalConnectionNodes(1,3); + sysmodel->addComponent(vsource); + + + //Allocate with graph + sysmodel->allocate(*cirg); + + std::cout << sysmodel->y().size() << std::endl; + + //Create Intial points + sysmodel->y()[0] = 1.0; + sysmodel->y()[1] = 1.0; + sysmodel->y()[2] = 1.0; + sysmodel->y()[3] = 1.0; + sysmodel->y()[4] = 1.0; + + sysmodel->yp()[0] = 1.0; + sysmodel->yp()[1] = 1.0; + sysmodel->yp()[2] = 1.0; + sysmodel->yp()[3] = 1.0; + sysmodel->yp()[4] = 1.0; + + + sysmodel->initialize(); + + sysmodel->evaluateResidual(); + + std::cout << "Output: {"; + for (double i : sysmodel->getResidual()) + { + std::cout << i << ", "; + } + std::cout << "}\n"; + + + return 0; +} diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp index a4ef43a00..94cbeb5d3 100644 --- a/ModelEvaluatorImpl.hpp +++ b/ModelEvaluatorImpl.hpp @@ -252,6 +252,12 @@ namespace ModelLib return gB_; } + //@todo Fix ID naming + IdxT getIDcomponent() + { + return idc_; + } + protected: @@ -281,6 +287,8 @@ namespace ModelLib real_type rtol_; real_type atol_; + IdxT idc_; + }; diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp new file mode 100644 index 000000000..78350ee2f --- /dev/null +++ b/PowerElectronicsModel.hpp @@ -0,0 +1,217 @@ + + +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +namespace ModelLib +{ + +template +class PowerElectronicsModel : public ModelEvaluatorImpl +{ + typedef CircuitComponent component_type; + + using ModelEvaluatorImpl::size_; + // using ModelEvaluatorImpl::size_quad_; + // using ModelEvaluatorImpl::size_opt_; + using ModelEvaluatorImpl::nnz_; + // using ModelEvaluatorImpl::time_; + // using ModelEvaluatorImpl::alpha_; + using ModelEvaluatorImpl::y_; + using ModelEvaluatorImpl::yp_; + // using ModelEvaluatorImpl::yB_; + // using ModelEvaluatorImpl::ypB_; + // using ModelEvaluatorImpl::tag_; + using ModelEvaluatorImpl::f_; + // using ModelEvaluatorImpl::fB_; + // using ModelEvaluatorImpl::g_; + // using ModelEvaluatorImpl::gB_; + using ModelEvaluatorImpl::rtol_; + using ModelEvaluatorImpl::atol_; + // using ModelEvaluatorImpl::param_; + // using ModelEvaluatorImpl::param_up_; + // using ModelEvaluatorImpl::param_lo_; + +public: + /** + * @brief Constructor for the system model + */ + PowerElectronicsModel() : ModelEvaluatorImpl(0, 0, 0) + { + // Set system model tolerances + rtol_ = 1e-5; + atol_ = 1e-5; + } + + /** + * @brief Destructor for the system model + */ + virtual ~PowerElectronicsModel() + { + for (auto comp : this->components_) delete comp; + } + + /** + * @brief allocator default + * + * @todo this should throw an exception as no allocation without a graph is allowed. Or needs to be removed from the base class + * + * @return int + */ + int allocate() + { + + return 1; + } + + int allocate(CircuitGraph cir) + { + this->graph = cir; + + // Allocate all components + this->size_ = cir.amountHyperNodes(); + for(const auto& component : components_) + { + component->allocate(); + } + + // Allocate global vectors + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + int initialize() + { + + // Initialize components + for(const auto& component : components_) + { + component->initialize(); + } + + for(const auto& component : components_) + { + for(IdxT j=0; jsize(); ++j) + { + component->y()[j] = y_[component->getNodeConnection(j)]; + component->yp()[j] = yp_[component->getNodeConnection(j)]; + } + } + return 0; + } + + int tagDifferentiable() + { + return 0; + } + + int evaluateResidual() + { + for (IdxT i = 0; i < this->f_.size(); i++) + { + f_[i] = 0; + } + + // Update variables + for(const auto& component : components_) + { + for(IdxT j=0; jsize(); ++j) + { + component->y()[j] = y_[component->getNodeConnection(j)]; + component->yp()[j] = yp_[component->getNodeConnection(j)]; + } + component->evaluateResidual(); + } + + // Update system residual vector + + for(const auto& component : components_) + { + for(IdxT j=0; jsize(); ++j) + { + f_[component->getNodeConnection(j)] += component->getResidual()[j]; + } + } + + return 0; + } + + int evaluateJacobian() + { + return 0; + } + + /** + * @brief Evaluate integrands for the system quadratures. + */ + int evaluateIntegrand() + { + + return 0; + } + + /** + * @brief Initialize system adjoint. + * + * Updates variables and optimization parameters, then initializes + * adjoints locally and copies them to the system adjoint vector. + */ + int initializeAdjoint() + { + return 0; + } + + /** + * @brief Compute adjoint residual for the system model. + * + * + */ + int evaluateAdjointResidual() + { + return 0; + } + + + /** + * @brief Evaluate adjoint integrand for the system model. + * + * + */ + int evaluateAdjointIntegrand() + { + return 0; + } + + void updateTime(ScalarT t, ScalarT a) + { + } + + void addComponent(component_type* component) + { + this->components_.push_back(component); + } + + CircuitGraph getGraph() + { + return this->graph; + } + +private: + std::vector components_; + + CircuitGraph graph; + +}; // class PowerElectronicsModel + +} // namespace ModelLib From 426ab4cfd8baa40c3e2b93e8ad16e5bd62cc5139 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Thu, 27 Jul 2023 16:44:39 -0400 Subject: [PATCH 39/52] Add New Components and Changes to Composition +Added InductionMotor, Linear Transformer, and SynchronousMachine +Changes to PowerElectronicsModel --- .../PowerElectronicsComponents/CMakeLists.txt | 5 +- .../Capacitor/Capacitor.cpp | 2 + .../CircuitComponent.hpp | 69 ++++++++ .../InductionMotor/CMakeLists.txt | 8 + .../InductionMotor/InductionMotor.cpp | 135 ++++++++++++++++ .../InductionMotor/InductionMotor.hpp | 69 ++++++++ .../Inductor/Inductor.cpp | 2 + .../LinearTransformer/CMakeLists.txt | 8 + .../LinearTransformer/LinearTransformer.cpp | 124 ++++++++++++++ .../LinearTransformer/LinearTransformer.hpp | 67 ++++++++ .../Resistor/Resistor.cpp | 2 + .../SynchronousMachine/CMakeLists.txt | 8 + .../SynchronousMachine/SynchronousMachine.cpp | 151 ++++++++++++++++++ .../SynchronousMachine/SynchronousMachine.hpp | 76 +++++++++ .../VoltageSource/VoltageSource.cpp | 4 +- Examples/RLCircuit/RLCircuit.cpp | 31 +--- ModelEvaluatorImpl.hpp | 5 + PowerElectronicsModel.hpp | 19 ++- 18 files changed, 743 insertions(+), 42 deletions(-) create mode 100644 ComponentLib/PowerElectronicsComponents/InductionMotor/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/LinearTransformer/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/SynchronousMachine/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.hpp diff --git a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt index c3e958300..10f2c6fdc 100644 --- a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt +++ b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt @@ -3,4 +3,7 @@ add_subdirectory(Capacitor) add_subdirectory(Resistor) add_subdirectory(VoltageSource) -add_subdirectory(Inductor) \ No newline at end of file +add_subdirectory(Inductor) +add_subdirectory(LinearTransformer) +add_subdirectory(InductionMotor) +add_subdirectory(SynchronousMachine) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp index 4fcda9d9f..d905dda05 100644 --- a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp @@ -39,6 +39,8 @@ int Capacitor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); + this->J_.resize(this->size_^2); + this->M_.resize(this->size_^2); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp index 7cfb5521a..9e1052e43 100644 --- a/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp +++ b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp @@ -54,10 +54,79 @@ namespace ModelLib return this->connection_nodes.at(index); } + inline std::vector parkTransformMatrix(ScalarT angle) + { + std::vector result(9); + ScalarT anpim = angle - (2.0/3.0)*M_PI; + ScalarT anpip = angle + (2.0/3.0)*M_PI; + result[0] = (2.0/3.0)*cos(angle); + result[1] = (2.0/3.0)*cos(anpim); + result[2] = (2.0/3.0)*cos(anpip); + result[3] = (2.0/3.0)*sin(angle); + result[4] = (2.0/3.0)*sin(anpim); + result[5] = (2.0/3.0)*sin(anpip); + result[6] = 1.0/3.0; + result[7] = 1.0/3.0; + result[8] = 1.0/3.0; + return result; + } + + inline std::vector parkTransformMatrixDerivative(ScalarT angle) + { + std::vector result(9); + ScalarT anpim = angle - (2.0/3.0)*M_PI; + ScalarT anpip = angle + (2.0/3.0)*M_PI; + result[0] = (2.0/3.0)*sin(angle); + result[1] = (2.0/3.0)*sin(anpim); + result[2] = (2.0/3.0)*sin(anpip); + result[3] = (2.0/3.0)*-cos(angle); + result[4] = (2.0/3.0)*-cos(anpim); + result[5] = (2.0/3.0)*-cos(anpip); + result[6] = 0; + result[7] = 0; + result[8] = 0; + return result; + } + + inline std::vector inverseParkTransformMatrix(ScalarT angle) + { + std::vector result(9); + ScalarT anpim = angle - (2.0/3.0)*M_PI; + ScalarT anpip = angle + (2.0/3.0)*M_PI; + result[0] = cos(angle); + result[1] = sin(angle); + result[2] = 1.0; + result[3] = cos(anpim); + result[4] = sin(anpim); + result[5] = 1.0; + result[6] = cos(anpip); + result[7] = sin(anpip); + result[8] = 1.0; + return result; + } + + inline std::vector inverseParkTransformMatrixDerivative(ScalarT angle) + { + std::vector result(9); + ScalarT anpim = angle - (2.0/3.0)*M_PI; + ScalarT anpip = angle + (2.0/3.0)*M_PI; + result[0] = sin(angle); + result[1] = -cos(angle); + result[2] = 0.0; + result[3] = sin(anpim); + result[4] = -cos(anpim); + result[5] = 0.0; + result[6] = sin(anpip); + result[7] = -cos(anpip); + result[8] = 0.0; + return result; + } + protected: size_t n_extern; size_t n_intern; std::set extern_indices; + //@todo may want to replace the mapping of connection_nodes to Node objects instead of IdxT. Allows for container free setup std::map connection_nodes; }; diff --git a/ComponentLib/PowerElectronicsComponents/InductionMotor/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/InductionMotor/CMakeLists.txt new file mode 100644 index 000000000..95ef42436 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/InductionMotor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_inductionmotor + SOURCES + InductionMotor.cpp + OUTPUT_NAME + gridkit_powerelec_inductionmotor) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.cpp b/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.cpp new file mode 100644 index 000000000..75782b435 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.cpp @@ -0,0 +1,135 @@ + + + +#include +#include +#include +#include "InductionMotor.hpp" + + +namespace ModelLib { + + + +/*! + * @brief Constructor for a constant InductionMotor model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +InductionMotor::InductionMotor(IdxT id, ScalarT Lls, ScalarT Rs, ScalarT Llr, ScalarT Rr, ScalarT Lms, ScalarT J, ScalarT P) + : Lls_(Lls), + Rs_(Rs), + Llr_(Llr), + Rr_(Rr), + Lms_(Lms), + J_(J), + P_(P) +{ + this->size_ = 10; + this->n_intern = 5; + this->n_extern = 5; + this->extern_indices = {0,1,2,3,4}; + this->idc_ = id; +} + +template +InductionMotor::~InductionMotor() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int InductionMotor::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int InductionMotor::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int InductionMotor::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int InductionMotor::evaluateResidual() +{ + //Note this leaves induction lumped into y. Perhaps would be better to seperate volatge and induction into seperate vectors + // for easier development + this->f_[0] = y_[5] + y_[7]; + this->f_[1] = (-1.0/2.0) * y_[5] - (sqrt(3.0)/2.0)*y_[6] + y_[7]; + this->f_[2] = (-1.0/2.0) * y_[5] + (sqrt(3.0)/2.0)*y_[6] + y_[7]; + this->f_[3] = J_ * yp_[3] - (3.0/4.0)*P_*Lms_ * (y_[5]*y_[9] - y_[6]*y_[8]); + this->f_[4] = yp_[4] - y_[3]; + this->f_[5] = (1.0/3.0)*(2.0* y_[0] - y_[1] - y_[2]) - Rs_*y_[5] - (Lls_ + Lms_) * yp_[5] - Lms_ * yp_[6]; + this->f_[6] = (1.0/sqrt(3.0))*(-y_[1] + y_[2]) - Rs_*y_[6] - (Lls_ + Lms_) * yp_[6] - Lms_ * yp_[5]; + this->f_[7] = (y_[0] + y_[1] + y_[2])/3.0 - Rs_*y_[7] - Lls_ * yp_[7]; + this->f_[8] = Rr_*y_[8] + (Llr_ + Lms_)*yp_[8] + Lms_ * yp_[5] - (P_/2)*y_[3]*((Llr_+Lms_)*y_[9] + Lms_*y_[6]); + this->f_[9] = Rr_*y_[9] + (Llr_ + Lms_)*yp_[9] + Lms_ * yp_[6] + (P_/2)*y_[3]*((Llr_+Lms_)*y_[8] + Lms_*y_[5]); + return 0; +} + +template +int InductionMotor::evaluateJacobian() +{ + return 0; +} + +template +int InductionMotor::evaluateIntegrand() +{ + return 0; +} + +template +int InductionMotor::initializeAdjoint() +{ + return 0; +} + +template +int InductionMotor::evaluateAdjointResidual() +{ + return 0; +} + +template +int InductionMotor::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class InductionMotor; +template class InductionMotor; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.hpp b/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.hpp new file mode 100644 index 000000000..2547754e2 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/InductionMotor/InductionMotor.hpp @@ -0,0 +1,69 @@ + + +#ifndef _IMOTOR_HPP_ +#define _IMOTOR_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive InductionMotor class. + * + */ + template + class InductionMotor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + public: + InductionMotor(IdxT id, ScalarT Lls, ScalarT Rs, ScalarT Llr, ScalarT Rr, ScalarT Lms, ScalarT J, ScalarT P); + virtual ~InductionMotor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT Lls_; + ScalarT Rs_; + ScalarT Llr_; + ScalarT Rr_; + ScalarT Lms_; + ScalarT J_; + ScalarT P_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp index 278b0eebc..952a992d0 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -40,6 +40,8 @@ int Inductor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); + this->J_.resize(this->size_^2); + this->M_.resize(this->size_^2); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/LinearTransformer/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/LinearTransformer/CMakeLists.txt new file mode 100644 index 000000000..eaf95c043 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/LinearTransformer/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_lineartrasnformer + SOURCES + LinearTransformer.cpp + OUTPUT_NAME + gridkit_powerelec_lineartrasnformer) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.cpp b/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.cpp new file mode 100644 index 000000000..4caaeae66 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.cpp @@ -0,0 +1,124 @@ + + + +#include +#include +#include +#include "LinearTransformer.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant LinearTransformer model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +LinearTransformer::LinearTransformer(IdxT id, ScalarT L1, ScalarT L2, ScalarT R1, ScalarT R2, ScalarT M) + : L1_(L1), + L2_(L2), + R1_(R1), + R2_(R2), + M_(M) +{ + this->size_ = 4; + this->n_intern = 2; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +LinearTransformer::~LinearTransformer() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int LinearTransformer::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int LinearTransformer::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int LinearTransformer::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int LinearTransformer::evaluateResidual() +{ + //Note this leaves induction lumped into y. Perhaps would be better to seperate volatge and induction into seperate vectors + // for easier development + this->f_[0] = this->y_[2]; + this->f_[1] = this->y_[3]; + this->f_[2] = this->y_[0] - this->R1_ * this->y_[2] - this->L1_ * this->yp_[2] - this->M_ * this->yp_[3]; + this->f_[2] = this->y_[1] - this->R2_ * this->y_[3] - this->M_ * this->yp_[2] - this->L2_ * this->yp_[3]; + return 0; +} + +template +int LinearTransformer::evaluateJacobian() +{ + return 0; +} + +template +int LinearTransformer::evaluateIntegrand() +{ + return 0; +} + +template +int LinearTransformer::initializeAdjoint() +{ + return 0; +} + +template +int LinearTransformer::evaluateAdjointResidual() +{ + return 0; +} + +template +int LinearTransformer::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class LinearTransformer; +template class LinearTransformer; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.hpp b/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.hpp new file mode 100644 index 000000000..cf56adfa2 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/LinearTransformer/LinearTransformer.hpp @@ -0,0 +1,67 @@ + + +#ifndef _LTRANS_HPP_ +#define _LTRANS_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive LinearTransformer class. + * + */ + template + class LinearTransformer : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + public: + LinearTransformer(IdxT id, ScalarT L1, ScalarT L2, ScalarT R1, ScalarT R2, ScalarT M); + virtual ~LinearTransformer(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT L1_; + ScalarT L2_; + ScalarT R1_; + ScalarT R2_; + ScalarT M_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp index 1aa06427a..5faad23b4 100644 --- a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp @@ -39,6 +39,8 @@ int Resistor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); + this->J_.resize(this->size_^2); + this->M_.resize(this->size_^2); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/SynchronousMachine/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/CMakeLists.txt new file mode 100644 index 000000000..bfaeace4b --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_synmachine + SOURCES + SynchronousMachine.cpp + OUTPUT_NAME + gridkit_powerelec_synmachine) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.cpp b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.cpp new file mode 100644 index 000000000..05b1e59ac --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.cpp @@ -0,0 +1,151 @@ + + + +#include +#include +#include +#include "SynchronousMachine.hpp" + + +namespace ModelLib { + + + +/*! + * @brief Constructor for a constant SynchronousMachine model + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +SynchronousMachine::SynchronousMachine(IdxT id, ScalarT Lls, std::tuple Llkq, ScalarT Llfd, ScalarT Llkd, ScalarT Lmq, ScalarT Lmd, ScalarT Rs, std::tuple Rkq, ScalarT Rfd, ScalarT Rkd, ScalarT J, ScalarT P, ScalarT mub) + : Lls_(Lls), + Llkq_(Llkq), + Llfd_(Llfd), + Llkd_(Llkd), + Lmq_(Lmq), + Lmd_(Lmd), + Rs_(Rs), + Rkq_(Rkq), + Rfd_(Rfd), + Rkd_(Rkd), + J_(J), + P_(P), + mub_(mub) +{ + this->size_ = 13; + this->n_intern = 6; + this->n_extern = 7; + this->extern_indices = {0,1,2,3,4}; + this->idc_ = id; +} + +template +SynchronousMachine::~SynchronousMachine() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int SynchronousMachine::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + return 0; +} + +/** + * Initialization of the grid model + */ +template +int SynchronousMachine::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int SynchronousMachine::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int SynchronousMachine::evaluateResidual() +{ + ScalarT rkq1 = std::get<0>(Rkq_); + ScalarT rkq2 = std::get<1>(Rkq_); + ScalarT llkq1 = std::get<0>(Llkq_); + ScalarT llkq2 = std::get<1>(Llkq_); + + ScalarT cos1 = cos((P_/2.0)*y_[5]); + ScalarT sin1 = sin((P_/2.0)*y_[5]); + ScalarT cos23m = cos((P_/2.0)*y_[5] - (2.0/3.0)*M_PI); + ScalarT sin23m = sin((P_/2.0)*y_[5] - (2.0/3.0)*M_PI); + ScalarT cos23p = cos((P_/2.0)*y_[5] + (2.0/3.0)*M_PI); + ScalarT sin23p = sin((P_/2.0)*y_[5] + (2.0/3.0)*M_PI); + + this->f_[0] = y_[6]*cos1 + y_[7]*sin1 + y_[8]; + this->f_[1] = y_[6]*cos23m + y_[7]*sin23m + y_[8]; + this->f_[2] = y_[6]*cos23p + y_[7]*sin23p + y_[8]; + this->f_[3] = J_ * yp_[4] - (3.0/4.0)*P_*(Lmd_ *y_[6]* (y_[7] + y_[11] + y_[12]) - Lmq_*y_[7]*(y_[6] + y_[9] + y_[0])); + this->f_[4] = yp_[5] - y_[4]; + this->f_[5] = (-2.0/3.0)*(y_[0]*cos1 +y_[1]*cos23m + y_[2]*cos23p) + Rs_*y_[6] + (Lls_ + Lmq_)*yp_[6] + Lmq_*yp_[9] + Lmq_*yp_[10] + y_[4]*(P_/2.0)*((Lls_ + Lmd_)*y_[7] + Lmd_*y_[11] + Lmd_*y_[12]); + this->f_[6] = (-2.0/3.0)*(y_[0]*sin1 -y_[1]*sin23m - y_[2]*sin23p) + Rs_*y_[7] + (Lls_ + Lmd_)*yp_[7] + Lmd_*yp_[11] + Lmd_*yp_[12] - y_[4]*(P_/2.0)*((Lls_ + Lmq_)*y_[6] + Lmq_*y_[9] + Lmq_*y_[10]); + this->f_[7] = (-1.0/3.0)*(y_[0] + y_[1] + y_[2]) + Rs_*y_[8] + Lls_*yp_[8]; + this->f_[8] = rkq1*y_[9] + (llkq1 + Lmq_)*yp_[9] + Lmq_*yp_[6] + Lmq_*yp_[10]; + this->f_[9] = rkq1*y_[9] + (llkq1 + Lmq_)*yp_[9] + Lmq_*yp_[6] + Lmq_*yp_[10]; + return 0; +} + +template +int SynchronousMachine::evaluateJacobian() +{ + return 0; +} + +template +int SynchronousMachine::evaluateIntegrand() +{ + return 0; +} + +template +int SynchronousMachine::initializeAdjoint() +{ + return 0; +} + +template +int SynchronousMachine::evaluateAdjointResidual() +{ + return 0; +} + +template +int SynchronousMachine::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class SynchronousMachine; +template class SynchronousMachine; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.hpp b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.hpp new file mode 100644 index 000000000..a18eca9c9 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/SynchronousMachine/SynchronousMachine.hpp @@ -0,0 +1,76 @@ + + +#ifndef _SYNMACH_HPP_ +#define _SYNMACH_HPP_ + +#include +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive SynchronousMachine class. + * + */ + template + class SynchronousMachine : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + public: + SynchronousMachine(IdxT id, ScalarT Lls, std::tuple Llkq, ScalarT Llfd, ScalarT Llkd, ScalarT Lmq, ScalarT Lmd, ScalarT Rs, std::tuple Rkq, ScalarT Rfd, ScalarT Rkd, ScalarT J, ScalarT P, ScalarT mub); + virtual ~SynchronousMachine(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT Lls_; + std::tuple Llkq_; + ScalarT Llfd_; + ScalarT Llkd_; + ScalarT Lmq_; + ScalarT Lmd_; + ScalarT Rs_; + std::tuple Rkq_; + ScalarT Rfd_; + ScalarT Rkd_; + ScalarT J_; + ScalarT P_; + ScalarT mub_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp index c27c04bd2..e26841a6c 100644 --- a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp @@ -39,6 +39,8 @@ int VoltageSource::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); + this->J_.resize(this->size_^2); + this->M_.resize(this->size_^2); return 0; } @@ -72,7 +74,7 @@ int VoltageSource::evaluateResidual() // for easier development this->f_[0] = this->y_[2]; this->f_[1] = -this->y_[2]; - this->f_[2] = this->y_[0] - this->y_[1] - this->V_; + this->f_[2] = this->y_[1] - this->y_[0] - this->V_; return 0; } diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index ba9333f40..6d44d6b4f 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -12,39 +12,10 @@ #include #include -#include int main(int argc, char const *argv[]) { - //Basic Circuit Setup - //@todo will want to eventually put components in the hyper graph instead of indicies - - std::unique_ptr> cirg(new CircuitGraph()); - for (size_t i = 0; i < 3; i++) - { - cirg->addHyperEdge(i); - } - for (size_t i = 0; i < 5; i++) - { - cirg->addHyperNode(i); - } - - //Create Connections of Nodes to edges sets - //External nodes - cirg->addConnection(0, 0); - cirg->addConnection(0, 2); - cirg->addConnection(2, 0); - cirg->addConnection(2, 1); - cirg->addConnection(3, 1); - cirg->addConnection(3, 2); - - //Internal nodes - cirg->addConnection(1,0); - cirg->addConnection(4,2); - - - cirg->printBiPartiteGraph(); //Create circuit model @@ -80,7 +51,7 @@ int main(int argc, char const *argv[]) //Allocate with graph - sysmodel->allocate(*cirg); + sysmodel->allocate(5); std::cout << sysmodel->y().size() << std::endl; diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp index 94cbeb5d3..72abb858b 100644 --- a/ModelEvaluatorImpl.hpp +++ b/ModelEvaluatorImpl.hpp @@ -90,6 +90,8 @@ namespace ModelLib yp_(size_), f_(size_), g_(size_quad_), + J_(size_quad^2), + M_(size_quad^2), yB_(size_), ypB_(size_), fB_(size_), @@ -277,6 +279,9 @@ namespace ModelLib std::vector fB_; std::vector gB_; + std::vector J_; + std::vector M_; + std::vector param_; std::vector param_up_; std::vector param_lo_; diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp index 78350ee2f..7a9304716 100644 --- a/PowerElectronicsModel.hpp +++ b/PowerElectronicsModel.hpp @@ -72,12 +72,18 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 1; } - int allocate(CircuitGraph cir) + /** + * @brief Allocate the vector data with size amount + * @todo Add capability to go through component model connection to get the size of the actual vector + * + * @param s + * @return int + */ + int allocate(IdxT s) { - this->graph = cir; // Allocate all components - this->size_ = cir.amountHyperNodes(); + this->size_ = s; for(const auto& component : components_) { component->allocate(); @@ -202,16 +208,9 @@ class PowerElectronicsModel : public ModelEvaluatorImpl this->components_.push_back(component); } - CircuitGraph getGraph() - { - return this->graph; - } - private: std::vector components_; - CircuitGraph graph; - }; // class PowerElectronicsModel } // namespace ModelLib From b8f4106df45a6166f82e5fde3f1d9cdbe0b53866 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Wed, 15 Nov 2023 20:47:04 -0500 Subject: [PATCH 40/52] Added COO Sparse Matrices, Component Jacobians, and Discrete Generator + Basic COO Sparse Matrix Implmentation + Discrete Generator Component + Resistor Jacobian + Capacitor Jacobian + Voltage Source Jacobian + Inductor Jacobian + Testing for Sparse Jacobian and Discrete Generator --- CMakeLists.txt | 3 + .../PowerElectronicsComponents/CMakeLists.txt | 3 +- .../Capacitor/Capacitor.cpp | 19 +- .../Capacitor/Capacitor.hpp | 1 + .../DiscreteGenerator/CMakeLists.txt | 8 + .../DiscreteGenerator/DiscreteGenerator.cpp | 278 ++++++++++ .../DiscreteGenerator/DiscreteGenerator.hpp | 100 ++++ .../Inductor/Inductor.cpp | 21 +- .../Inductor/Inductor.hpp | 1 + .../Resistor/Resistor.cpp | 11 +- .../Resistor/Resistor.hpp | 1 + .../VoltageSource/VoltageSource.cpp | 10 +- .../VoltageSource/VoltageSource.hpp | 1 + Examples/CMakeLists.txt | 2 + Examples/DiscreteGeneratorTest/CMakeLists.txt | 9 + Examples/DiscreteGeneratorTest/DGTest.cpp | 56 ++ Examples/RLCircuit/RLCircuit.cpp | 4 + Examples/SparseTest/CMakeLists.txt | 7 + Examples/SparseTest/SparseTest.cpp | 55 ++ ModelEvaluatorImpl.hpp | 20 +- PowerElectronicsModel.hpp | 6 + SparseMatrix/CMakeLists.txt | 7 + SparseMatrix/COO_Matrix.hpp | 515 ++++++++++++++++++ 23 files changed, 1122 insertions(+), 16 deletions(-) create mode 100644 ComponentLib/PowerElectronicsComponents/DiscreteGenerator/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp create mode 100644 Examples/DiscreteGeneratorTest/CMakeLists.txt create mode 100644 Examples/DiscreteGeneratorTest/DGTest.cpp create mode 100644 Examples/SparseTest/CMakeLists.txt create mode 100644 Examples/SparseTest/SparseTest.cpp create mode 100644 SparseMatrix/CMakeLists.txt create mode 100644 SparseMatrix/COO_Matrix.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 19048d375..ef6cbcf57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,9 @@ add_subdirectory(ComponentLib) # General Utilities and File IO add_subdirectory(Utilities) +#Local Sparse matrix operations +add_subdirectory(SparseMatrix) + # Create solvers add_subdirectory(Solver) diff --git a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt index 10f2c6fdc..9d6ad8be1 100644 --- a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt +++ b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt @@ -6,4 +6,5 @@ add_subdirectory(VoltageSource) add_subdirectory(Inductor) add_subdirectory(LinearTransformer) add_subdirectory(InductionMotor) -add_subdirectory(SynchronousMachine) \ No newline at end of file +add_subdirectory(SynchronousMachine) +add_subdirectory(DiscreteGenerator) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp index d905dda05..ecbe9d51f 100644 --- a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp @@ -39,8 +39,7 @@ int Capacitor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); - this->J_.resize(this->size_^2); - this->M_.resize(this->size_^2); + return 0; } @@ -72,13 +71,27 @@ int Capacitor::evaluateResidual() { this->f_[0] = this->yp_[2]; this->f_[1] = -this->yp_[2]; - this->f_[2] = this->y_[0] - this->y_[1] - this->y_[2] - this->C_ * this->yp_[2]; + this->f_[2] = -this->C_ * this->yp_[2] + this->y_[0] - this->y_[1] - this->y_[2]; return 0; } template int Capacitor::evaluateJacobian() { + //Create dF/dy + std::vector rcord{2,2,2}; + std::vector ccord{0,1,2}; + std::vector vals{1.0, -1.0, -1.0}; + this->J_.setValues(rcord, ccord, vals); + + //Create -dF/dy' + std::vector rcordder{0,1,2}; + std::vector ccordder{2,2,2}; + std::vector valsder{1.0, -1.0, -this->C_}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); + + //Perform dF/dy + \alpha dF/dy' + this->J_.AXPY(this->alpha_, &Jacder); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp index 76cf94614..e1a9974c3 100644 --- a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.hpp @@ -36,6 +36,7 @@ namespace ModelLib using CircuitComponent::ypB_; using CircuitComponent::fB_; using CircuitComponent::gB_; + using CircuitComponent::J_; using CircuitComponent::param_; using CircuitComponent::idc_; diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/CMakeLists.txt new file mode 100644 index 000000000..c0ed2c7a9 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_disgen + SOURCES + DiscreteGenerator.cpp + OUTPUT_NAME + gridkit_powerelec_disgen) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp new file mode 100644 index 000000000..7770281d1 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp @@ -0,0 +1,278 @@ + + + +#include +#include +#include +#include "DiscreteGenerator.hpp" + +namespace ModelLib { + + +/*! + * @brief Constructor for a Discrete Generator + * @todo Maybe have parameters be templated in. Variables cannot be changed and are unlikely to. Allows for compile time optimizations + * + * Calls default ModelEvaluatorImpl constructor. + */ + +template +DiscreteGenerator::DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm) + : wb_(parm.wb), wc_(parm.wc), mp_(parm.mp), refmp_(parm.refmp), Vn_(parm.Vn), nq_(parm.nq), F_(parm.F), Kiv_(parm.Kiv), Kpv_(parm.Kpv), Kic_(parm.Kic), Kpc_(parm.Kpc), Cf_(parm.Cf), rLf_(parm.rLf), Lf_(parm.Lf), rLc_(parm.rLc), Lc_(parm.Lc) +{ + // internals [delta_i, Pi, Qi, phi_di, phi_qi, gamma_di, gamma_qi, il_di, il_qi, vo_di, vo_qi, io_di, io_qi] + // externals [Pref, Pbus, QBus] + this->size_ = 16; + this->n_intern = 13; + this->n_extern = 3; + this->extern_indices = {0,1,2}; + this->idc_ = id; +} + +template +DiscreteGenerator::~DiscreteGenerator() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int DiscreteGenerator::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + + return 0; +} + +/** + * Initialization of the grid model + */ +template +int DiscreteGenerator::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int DiscreteGenerator::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ +template +int DiscreteGenerator::evaluateResidual() +{ + // ### Externals Componenets ### + //Reference P + ScalarT wcom = this->wb_ - this->refmp_ * this->y_[0]; + + this->f_[0] = 0; + this->f_[1] = 0; + this->f_[2] = 0; + + // ### Internal Componenets ## + f_[3] = -yp_[3] + wb_ - mp_ * y_[4] - wcom; + + f_[4] = -yp_[4] + wc_ * (y_[12] * y_[14] + y_[13] * y_[15] - y_[4]); + f_[5] = -yp_[4] + wc_ * (-y_[12] * y_[15] + y_[13] * y_[14] - y_[5]); + + ScalarT vod_star = Vn_ - nq_ * y_[5]; + ScalarT voq_star = 0; + + f_[6] = -yp_[6] + vod_star - y_[12]; + f_[7] = -yp_[7] + voq_star - y_[13]; + + ScalarT ild_star = F_ * y_[14] - wb_ * Cf_ * y_[13] + Kpv_ * (vod_star - y_[12]) + Kiv_ * y_[6] ; + ScalarT ilq_star = F_ * y_[15] + wb_ * Cf_ * y_[12] + Kpv_ * (voq_star - y_[13]) + Kiv_ * y_[7]; + + f_[8] = -yp_[8] + ild_star - y_[10]; + f_[9] = -yp_[9] + ilq_star - y_[11]; + + ScalarT vid_star = -wb_ * Lf_ * y_[11] + Kpc_ * (ild_star - y_[10]) + Kic_ * y_[8]; + ScalarT viq_star = wb_ * Lf_ * y_[10] + Kpc_ * (ilq_star - y_[11]) + Kic_ * y_[9]; + + f_[10] = -yp_[10] - (rLf_ / Lf_) * y_[10] + wcom * y_[11] + (1/Lf_) * (vid_star - y_[12]); + f_[11] = -yp_[11] - (rLf_ / Lf_) * y_[11] - wcom * y_[10] + (1/Lf_) * (viq_star - y_[13]); + + f_[12] = -yp_[12] + wcom * y_[13] + (1/Cf_) * (y_[10] - y_[14]); + f_[13] = -yp_[13] - wcom * y_[12] + (1/Cf_) * (y_[11] - y_[15]); + + f_[14] = -yp_[14] - (rLc_ / Lc_) * y_[14] + wcom * y_[15] + (1/Lc_)*(y_[12] - y_[1]); + f_[15] = -yp_[15] - (rLc_ / Lc_) * y_[15] - wcom * y_[14] + (1/Lc_)*(y_[13] - y_[2]); + return 0; +} + +/** + * @brief Compute the jacobian of the DiscreteGenerator for iteration. dF/dy - \alpha dF/dy' + * + * The matrix dF/dy should be + * [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ mpref, 0, 0, 0, -mp, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, 0, wc*x15, wc*x16, wc*x13, wc*x14] +[ 0, 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, -wc*x16, wc*x15, wc*x14, -wc*x13] +[ 0, 0, 0, 0, 0, -nq, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0] +[ 0, 0, 0, 0, 0, -Kpv*nq, Kiv, 0, 0, 0, -1, 0, -Kpv, -Cf*wb, F, 0] +[ 0, 0, 0, 0, 0, 0, 0, Kiv, 0, 0, 0, -1, Cf*wb, -Kpv, 0, F] +[-mpref*x12, 0, 0, 0, 0, -(Kpc*Kpv*nq)/Lf, (Kiv*Kpc)/Lf, 0, Kic/Lf, 0, - Kpc/Lf - rLf/Lf, -mpref*x1, -(Kpc*Kpv + 1)/Lf, -(Cf*Kpc*wb)/Lf, (F*Kpc)/Lf, 0] +[ mpref*x11, 0, 0, 0, 0, 0, 0, (Kiv*Kpc)/Lf, 0, Kic/Lf, mpref*x1, - Kpc/Lf - rLf/Lf, (Cf*Kpc*wb)/Lf, -(Kpc*Kpv + 1)/Lf, 0, (F*Kpc)/Lf] +[-mpref*x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Cf, 0, 0, wb - mpref*x1, -1/Cf, 0] +[ mpref*x13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Cf, mpref*x1 - wb, 0, 0, -1/Cf] +[-mpref*x16, -1/Lc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, 0, -rLc/Lc, wb - mpref*x1] +[ mpref*x15, 0, -1/Lc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, mpref*x1 - wb, -rLc/Lc] + * 'Generated from MATLAB symbolic' + * Jacobian is mostly constant besides reference and rows 4 & 5 + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ +template +int DiscreteGenerator::evaluateJacobian() +{ + //Create dF/dy' + std::vector rcordder(13); + std::vector valsder(13,1.0); + for (int i = 0; i < 13; i++) + { + rcordder[i] = i + 3; + } + COO_Matrix Jacder = COO_Matrix(rcordder, rcordder, valsder,16,16); + + //Create dF/dy + //r = 3 + std::vector ctemp{0, 4}; + std::vector rtemp(ctemp.size(),3); + std::vector valtemp{this->refmp_, -this->mp_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 4 + ctemp = {4, 12, 13, 14, 15}; + std::fill(rtemp.begin(), rtemp.end(), 4); + valtemp = {-this->wc_, this->wc_*y_[14], this->wc_*y_[15], this->wc_*y_[12], this->wc_*y_[13]}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 5 + ctemp = {5, 12, 13, 14, 15}; + std::fill(rtemp.begin(), rtemp.end(), 5); + valtemp = {-this->wc_, -this->wc_*y_[15], this->wc_*y_[14], this->wc_*y_[13], -this->wc_*y_[12]}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 6 + ctemp = {5, 12}; + std::fill(rtemp.begin(), rtemp.end(), 6); + valtemp = {-this->nq_, -1.0}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 7 + ctemp = {13}; + std::fill(rtemp.begin(), rtemp.end(), 7); + valtemp = {-1.0}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 8 + ctemp = {5,6,10,12,13,14}; + std::fill(rtemp.begin(), rtemp.end(), 8); + valtemp = {-this->Kpv_*this->nq_, this->Kiv_, -1.0, -this->Kpv_, -this->Cf_*this->wb_, this->F_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 9 + ctemp = {7, 11, 12, 13, 15}; + std::fill(rtemp.begin(), rtemp.end(), 9); + valtemp = {this->Kiv_, -1.0, this->Cf_*this->wb_,-this->Kpv_,this->F_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 10 + ctemp = {0, 5, 6, 8, 10, 11, 12, 13, 14}; + std::fill(rtemp.begin(), rtemp.end(), 10); + valtemp = {-this->refmp_ * y_[11], -(this->Kpc_ * this->Kpv_ * this->nq_) / this->Lf_, (this->Kpc_ * this->Kiv_) / this->Lf_, this->Kic_ / this->Lf_, -(this->Kpc_ + this->rLf_) / this->Lf_, -this->refmp_ * y_[0], -(this->Kpc_ * this->Kpv_ + 1.0) / this->Lf_, -(this->Cf_ * this->Kpc_ * this->wb_) / this->Lf_, (this->F_ * this->Kpc_) / this->Lf_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 11 + ctemp = {0, 7, 9, 10, 11, 12, 13, 15}; + std::fill(rtemp.begin(), rtemp.end(), 11); + valtemp = {this->refmp_ * y_[10], (this->Kiv_ * this->Kpc_) / this->Lf_, this->Kic_ / this->Lf_, this->refmp_ * y_[0], -(this->Kpc_ + this->rLf_) / this->Lf_, (this->Cf_ * this->Kpc_ * this->wb_) / this->Lf_, -(this->Kpc_ * this->Kpv_ + 1.0) / this->Lf_, (this->F_ * this->Kpc_) / this->Lf_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 12 + ctemp = {0, 10, 13, 14}; + std::fill(rtemp.begin(), rtemp.end(), 12); + valtemp = {-this->refmp_ * y_[13], 1.0 / this->Cf_, this->wb_ - this->refmp_ * y_[0], -1.0 / this->Cf_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + + //r = 13 + ctemp = {0, 11, 12, 15}; + std::fill(rtemp.begin(), rtemp.end(), 13); + valtemp = {this->refmp_ * y_[12], 1.0 / this->Cf_, -this->wb_ + this->refmp_ * y_[0], -1.0 / this->Cf_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + + //r = 14 + ctemp = {0, 1, 12, 14, 15}; + std::fill(rtemp.begin(), rtemp.end(), 14); + valtemp = {-this->refmp_ * y_[15], -1.0 / this->Lc_, 1.0 / this->Lc_, -this->rLc_ / this->Lc_, this->wb_ - this->refmp_ * y_[0]}; + this->J_.setValues(rtemp, ctemp, valtemp); + + + //r = 15 + ctemp = {0, 2, 13, 14, 15}; + std::fill(rtemp.begin(), rtemp.end(), 15); + valtemp = {-this->refmp_ * y_[14], -1.0 / this->Lc_, 1.0 / this->Lc_, -this->wb_ + this->refmp_ * y_[0], -this->rLc_ / this->Lc_}; + this->J_.setValues(rtemp, ctemp, valtemp); + + + //Perform dF/dy + \alpha dF/dy' + + this->J_.AXPY(-this->alpha_, &Jacder); + + return 0; +} + +template +int DiscreteGenerator::evaluateIntegrand() +{ + return 0; +} + +template +int DiscreteGenerator::initializeAdjoint() +{ + return 0; +} + +template +int DiscreteGenerator::evaluateAdjointResidual() +{ + return 0; +} + +template +int DiscreteGenerator::evaluateAdjointIntegrand() +{ + return 0; +} + + + + +// Available template instantiations +template class DiscreteGenerator; +template class DiscreteGenerator; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp new file mode 100644 index 000000000..f5ce86899 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp @@ -0,0 +1,100 @@ + + +#ifndef _CAP_HPP_ +#define _CAP_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; + + template + struct DiscreteGeneratorParameters + { + ScalarT wb; + ScalarT wc; + ScalarT mp; + ScalarT refmp; + ScalarT Vn; + ScalarT nq; + ScalarT F; + ScalarT Kiv; + ScalarT Kpv; + ScalarT Kic; + ScalarT Kpc; + ScalarT Cf; + ScalarT rLf; + ScalarT Lf; + ScalarT rLc; + ScalarT Lc; + }; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive DiscreteGenerator class. + * + */ + template + class DiscreteGenerator : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::J_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm); + virtual ~DiscreteGenerator(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT wb_; + ScalarT wc_; + ScalarT mp_; + ScalarT refmp_; + ScalarT Vn_; + ScalarT nq_; + ScalarT F_; + ScalarT Kiv_; + ScalarT Kpv_; + ScalarT Kic_; + ScalarT Kpc_; + ScalarT Cf_; + ScalarT rLf_; + ScalarT Lf_; + ScalarT rLc_; + ScalarT Lc_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp index 952a992d0..89f903436 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -40,8 +40,7 @@ int Inductor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); - this->J_.resize(this->size_^2); - this->M_.resize(this->size_^2); + return 0; } @@ -73,13 +72,29 @@ int Inductor::evaluateResidual() { this->f_[0] = this->y_[2]; this->f_[1] = -this->y_[2]; - this->f_[2] = this->y_[0] - this->y_[1] - this->L_ * this->yp_[2]; + this->f_[2] = - this->L_ * this->yp_[2] + this->y_[0] - this->y_[1] ; return 0; } template int Inductor::evaluateJacobian() { + + //Create dF/dy + std::vector rcord{0,1,2,2}; + std::vector ccord{2,2,0,1}; + std::vector vals{1.0, -1.0, 1.0, -1.0}; + this->J_.setValues(rcord, ccord, vals); + + //Create -dF/dy' + std::vector rcordder{2}; + std::vector ccordder{2}; + std::vector valsder{-this->L_}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); + + //Perform dF/dy + \alpha dF/dy' + this->J_.AXPY(this->alpha_, &Jacder); + return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp index e959aabf1..2f2c1085b 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.hpp @@ -36,6 +36,7 @@ namespace ModelLib using CircuitComponent::ypB_; using CircuitComponent::fB_; using CircuitComponent::gB_; + using CircuitComponent::J_; using CircuitComponent::param_; using CircuitComponent::idc_; diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp index 5faad23b4..7536f2274 100644 --- a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp @@ -39,8 +39,7 @@ int Resistor::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); - this->J_.resize(this->size_^2); - this->M_.resize(this->size_^2); + return 0; } @@ -79,6 +78,14 @@ int Resistor::evaluateResidual() template int Resistor::evaluateJacobian() { + + //Create dF/dy + //does compiler make constant??? + std::vector rcord{0,0,1,1}; + std::vector ccord{0,1,0,1}; + std::vector vals{-1.0 / this->R_, 1.0 / this->R_, 1.0 / this->R_, -1.0 / this->R_}; + this->J_.setValues(rcord, ccord, vals); + return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp index 0373e2c5c..984d8304b 100644 --- a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.hpp @@ -36,6 +36,7 @@ namespace ModelLib using CircuitComponent::ypB_; using CircuitComponent::fB_; using CircuitComponent::gB_; + using CircuitComponent::J_; using CircuitComponent::param_; using CircuitComponent::idc_; diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp index e26841a6c..b7c18bd6f 100644 --- a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp @@ -39,8 +39,7 @@ int VoltageSource::allocate() this->y_.resize(this->size_); this->yp_.resize(this->size_); this->f_.resize(this->size_); - this->J_.resize(this->size_^2); - this->M_.resize(this->size_^2); + return 0; } @@ -81,6 +80,13 @@ int VoltageSource::evaluateResidual() template int VoltageSource::evaluateJacobian() { + + //Create dF/dy + std::vector rcord{0,1,2,2}; + std::vector ccord{2,2,0,1}; + std::vector vals{1.0, -1.0, -1.0, 1.0}; + this->J_.setValues(rcord, ccord, vals); + return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp index dcbacf2f7..3ac1c8699 100644 --- a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.hpp @@ -36,6 +36,7 @@ namespace ModelLib using CircuitComponent::ypB_; using CircuitComponent::fB_; using CircuitComponent::gB_; + using CircuitComponent::J_; using CircuitComponent::param_; using CircuitComponent::idc_; diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index b42907fd3..e15774642 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -57,6 +57,8 @@ add_subdirectory(MatPowerTesting) add_subdirectory(RLCircuit) +add_subdirectory(SparseTest) +add_subdirectory(DiscreteGeneratorTest) if(TARGET SUNDIALS::kinsol) add_subdirectory(Grid3Bus) diff --git a/Examples/DiscreteGeneratorTest/CMakeLists.txt b/Examples/DiscreteGeneratorTest/CMakeLists.txt new file mode 100644 index 000000000..b1100b91a --- /dev/null +++ b/Examples/DiscreteGeneratorTest/CMakeLists.txt @@ -0,0 +1,9 @@ + + + + +add_executable(dgtest DGTest.cpp) +target_link_libraries(dgtest GRIDKIT::powerelec_disgen) + +add_test(NAME DiscreteGeneratorTest COMMAND $) +install(TARGETS dgtest RUNTIME DESTINATION bin) diff --git a/Examples/DiscreteGeneratorTest/DGTest.cpp b/Examples/DiscreteGeneratorTest/DGTest.cpp new file mode 100644 index 000000000..7d4aeda6f --- /dev/null +++ b/Examples/DiscreteGeneratorTest/DGTest.cpp @@ -0,0 +1,56 @@ + + +#include +#include +#include +#include +#include +#include + +#include + + +int main(int argc, char const *argv[]) +{ + + ModelLib::DiscreteGeneratorParameters parms; + //Parameters from MATLAB Microgrid code for first DG + //refmp is need for reference input + parms.wb = 2.0*M_PI*50.0; + parms.wc = 31.41; + parms.mp = 9.4e-5; + parms.refmp = 9.4e-5; + parms.Vn = 380; + parms.nq = 1.3e-3; + parms.F = 0.75; + parms.Kiv = 420.0; + parms.Kpv = 0.1; + parms.Kic = 20.0 * 1.0e3; + parms.Kpc = 15.0; + parms.Cf = 50.0e-6; + parms.rLf = 0.1; + parms.Lf = 1.35e-3; + parms.rLc = 0.03; + parms.Lc = 0.35e-3; + + ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(0, parms); + + std::vector t1(16,0.0); + std::vector t2{0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.1,1.2,1.3,1.4,1.5}; + + dg->allocate(); + + dg->y() = t2; + dg->yp() = t1; + + dg->evaluateResidual(); + + std::cout << "Output: {"; + for (double i : dg->getResidual()) + { + std::cout << i << ", "; + } + std::cout << "}\n"; + + return 0; +} diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index 6d44d6b4f..4669d564e 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -80,6 +80,10 @@ int main(int argc, char const *argv[]) } std::cout << "}\n"; + induct->updateTime(0.0, 1.0); + induct->evaluateJacobian(); + induct->getJacobian().printMatrix(true); + return 0; } diff --git a/Examples/SparseTest/CMakeLists.txt b/Examples/SparseTest/CMakeLists.txt new file mode 100644 index 000000000..d0b6f5e05 --- /dev/null +++ b/Examples/SparseTest/CMakeLists.txt @@ -0,0 +1,7 @@ + + +add_executable(spmattest SparseTest.cpp) +target_link_libraries(spmattest GRIDKIT::SparseMatrix) + +add_test(NAME SparseMatrixTest COMMAND $) +install(TARGETS spmattest RUNTIME DESTINATION bin) diff --git a/Examples/SparseTest/SparseTest.cpp b/Examples/SparseTest/SparseTest.cpp new file mode 100644 index 000000000..976759533 --- /dev/null +++ b/Examples/SparseTest/SparseTest.cpp @@ -0,0 +1,55 @@ + + +#include +#include +#include +#include +#include +#include +#include + +#include + + + + +int main(int argc, char const *argv[]) +{ + std::vector val{0.1, 0.2, 0.3, 0.4}; + std::vector x{2,1,3,1}; + std::vector y{1,3,2,2}; + size_t n = 4; + size_t m = 4; + + COO_Matrix A = COO_Matrix(x,y,val,m,n); + + std::vector valn(4); + std::vector xn(4); + std::vector yn(4); + + std::tie(xn, yn, valn) = A.getEntries(); + + for (size_t i = 0; i < valn.size(); i++) + { + std::cout << valn[i] << "\n"; + } + + std::cout << "A:\n"; + A.printMatrix(true); + + std::vector val2{0.5, 0.6, 0.7, 0.8, 1.0}; + std::vector x2{0,2,0,2,1}; + std::vector y2{3,3,2,2,3}; + COO_Matrix B = COO_Matrix(x2,y2,val2,m,n); + + std::cout << "B:\n"; + B.printMatrix(true); + + A.AXPY(2.0, &B); + + std::cout << "A + 2B:\n"; + A.printMatrix(true); + + + return 0; +} diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp index 72abb858b..ade61feff 100644 --- a/ModelEvaluatorImpl.hpp +++ b/ModelEvaluatorImpl.hpp @@ -62,6 +62,7 @@ #include #include +#include namespace ModelLib { @@ -90,16 +91,16 @@ namespace ModelLib yp_(size_), f_(size_), g_(size_quad_), - J_(size_quad^2), - M_(size_quad^2), yB_(size_), ypB_(size_), fB_(size_), gB_(size_opt_), + J_(COO_Matrix()), param_(size_opt_), param_up_(size_opt_), param_lo_(size_opt_) - {} + { + } virtual IdxT size() { @@ -224,6 +225,16 @@ namespace ModelLib return f_; } + COO_Matrix& getJacobian() + { + return J_; + } + + const COO_Matrix& getJacobian() const + { + return J_; + } + std::vector& getIntegrand() { return g_; @@ -279,8 +290,7 @@ namespace ModelLib std::vector fB_; std::vector gB_; - std::vector J_; - std::vector M_; + COO_Matrix J_; std::vector param_; std::vector param_up_; diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp index 7a9304716..018ceaeaf 100644 --- a/PowerElectronicsModel.hpp +++ b/PowerElectronicsModel.hpp @@ -34,6 +34,7 @@ class PowerElectronicsModel : public ModelEvaluatorImpl // using ModelEvaluatorImpl::fB_; // using ModelEvaluatorImpl::g_; // using ModelEvaluatorImpl::gB_; + using ModelEvaluatorImpl::J_; using ModelEvaluatorImpl::rtol_; using ModelEvaluatorImpl::atol_; // using ModelEvaluatorImpl::param_; @@ -153,6 +154,11 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 0; } + /** + * @brief Creates the Sparse COO Jacobian representing \alpha dF/dy' + dF/dy + * + * @return int + */ int evaluateJacobian() { return 0; diff --git a/SparseMatrix/CMakeLists.txt b/SparseMatrix/CMakeLists.txt new file mode 100644 index 000000000..b51d669ec --- /dev/null +++ b/SparseMatrix/CMakeLists.txt @@ -0,0 +1,7 @@ + +add_library(SparseMatrix INTERFACE) +include_directories(SparseMatrix INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +add_library(GRIDKIT::SparseMatrix ALIAS SparseMatrix) + + diff --git a/SparseMatrix/COO_Matrix.hpp b/SparseMatrix/COO_Matrix.hpp new file mode 100644 index 000000000..e4b087386 --- /dev/null +++ b/SparseMatrix/COO_Matrix.hpp @@ -0,0 +1,515 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief Quick class to provide sparse matrices of COO type. Simplifies data movement + * @todo Add base class of sparse matrix for conversion to CSR + * @todo Switch Push back with buffer allocation for resizing + * @todo NonZero Values for preallocation + * @todo Fix warnings, mostly type casting of indexes. Should try to move to iterator somehow + * + * m x n sparse matrix + */ +template +class COO_Matrix +{ +private: + std::vector values; + std::vector row_indexes; + std::vector column_indexes; + Intdx rows_size; + Intdx columns_size; + bool sorted; +public: + COO_Matrix(std::vector r, std::vector c, std::vector v, Intdx m, Intdx n); + COO_Matrix(Intdx m, Intdx n); + COO_Matrix(); + ~COO_Matrix(); + + //could replace with binary operation for both + // --- Functions which donot sort --- + void setValues(std::vector r, std::vector c, std::vector val); + void addValues(std::vector r, std::vector c, std::vector val); + + // --- Functions which call sort --- + std::tuple, std::vector> getRowCopy(Intdx r); + std::tuple, std::vector, std::vector> getEntries(); + + // BLAS. Will sort before running + void AXPY(ScalarT alpha, COO_Matrix* a); + + // --- Permutation Operations --- + //No sorting is actually done. Only done when nesscary + void permutation(std::vector row_perm, std::vector col_perm); + void permutationSizeMap(std::vector row_perm, std::vector col_perm, Intdx m, Intdx n); + + //Resort values + void sortSparse(); + bool isSorted(); + + std::tuple getDimensions(); + + void printMatrix(bool sort); + +private: + std::vector indexEntries(std::vector r, std::vector c); + Intdx indexStartRow(Intdx r); +}; + +/** + * @brief Set values of sparse matrix. Increases size if outside bounds + * + * @todo should error return if outside bounds instead? + * + * @tparam ScalarT + * @tparam Intdx + * @param r + * @param c + * @param val + */ +template +inline void COO_Matrix::setValues(std::vector r, std::vector c, std::vector val) +{ + std::vector indexes = this->indexEntries(r,c); + + for (int i = 0; i < indexes.size(); i++) + { + if (indexes[i] == -1) + { + if (r[i] >= this->rows_size) + { + this->rows_size = r[i]; + } + if (c[i] >= this->columns_size) + { + this->columns_size = c[i]; + } + + this->row_indexes.push_back(r[i]); + this->column_indexes.push_back(c[i]); + this->values.push_back(val[i]); + this->sorted = false; + } + else + { + this->values[indexes[i]] = val[i]; + } + } + +} + +/** + * @brief Add new values to sparse matrix. Will increase size if outside bounds + * + * @todo should error return if outside bounds instead? + * + * @tparam ScalarT + * @tparam Intdx + * @param r + * @param c + * @param val + */ +template +inline void COO_Matrix::addValues(std::vector r, std::vector c, std::vector val) +{ + std::vector indexes = this->indexEntries(r,c); + + for (int i = 0; i < indexes.size(); i++) + { + if (indexes[i] == -1) + { + if (r[i] >= this->rows_size) + { + this->rows_size = r[i]; + } + if (c[i] >= this->columns_size) + { + this->columns_size = c[i]; + } + + this->row_indexes.push_back(r[i]); + this->column_indexes.push_back(c[i]); + this->values.push_back(val[i]); + this->sorted = false; + } + else + { + this->values[indexes[i]] += val[i]; + } + } + +} + +/** + * @brief Get copy of row values + * + * @tparam ScalarT + * @tparam Intdx + * @param r + * @return std::tuple, std::vector> + */ +template +inline std::tuple, std::vector> COO_Matrix::getRowCopy(Intdx r) +{ + if (!this->sorted) + { + this->sortSparse(); + } + Intdx rowindex = this->indexStartRow(r); + + + if (rowindex == -1) + { + return {std::vector(),std::vector()}; + } + + Intdx rsize = rowindex; + do + { + rsize++; + } while (rsize < this->values.size() && this->row_indexes[rsize] == r); + + return {{this->column_indexes.begin() + rowindex, this->column_indexes.begin() + rsize},{this->values.begin() + rowindex, this->values.begin() + rsize}}; +} + +/** + * @brief Get all Entries + * + * @tparam ScalarT + * @tparam Intdx + * @return std::tuple, std::vector, std::vector> + */ +template +inline std::tuple, std::vector, std::vector> COO_Matrix::getEntries() +{ + if (!this->sorted) + { + this->sortSparse(); + } + return {this->row_indexes, this->column_indexes, this->values}; +} + +template +inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrix *a) +{ + if (alpha == 0) return; + + if (!this->sorted) + { + this->sortSparse(); + } + if (!a->isSorted()) + { + a->sortSparse(); + } + std::vector val; + std::vector r; + std::vector c; + Intdx m = 0; + Intdx n = 0; + std::tie(r,c,val) = a->getEntries(); + std::tie(m,n) = a->getDimensions(); + + this->rows_size = this->rows_size > m ? this->rows_size : m; + this->columns_size = this->columns_size > n ? this->columns_size : n; + + Intdx aiter = 0; + //iterate for all current values in matrix + for (Intdx i = 0; i < static_cast(this->row_indexes.size()); i++) + { + //pushback values when they are not in current matrix + while(aiter < static_cast(r.size()) && (r[aiter] < this->row_indexes[i] || (r[aiter] == this->row_indexes[i] && c[aiter] < this->column_indexes[i]))) + { + this->row_indexes.push_back(r[aiter]); + this->column_indexes.push_back(c[aiter]); + this->values.push_back(alpha * val[aiter]); + aiter++; + } + if (aiter >= r.size()) break; + + + if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) + { + this->values[i] += alpha * val[aiter]; + aiter++; + } + } + //push back rest that was not found sorted + for (Intdx i = aiter; i < static_cast(r.size()); i++) + { + this->row_indexes.push_back(r[i]); + this->column_indexes.push_back(c[i]); + this->values.push_back(alpha * val[i]); + } + + this->sorted = false; +} + +/** + * @brief Permutate the matrix to a different one. Only changes the coordinates + * + * @tparam ScalarT + * @tparam Intdx + * @param row_perm + * @param col_perm + */ +template +inline void COO_Matrix::permutation(std::vector row_perm, std::vector col_perm) +{ + assert(row_perm.size() = this->rows_size); + assert(col_perm.size() = this->columns_size); + + for (int i = 0; i < this->values.size(); i++) + { + this->row_indexes[i] = row_perm[this->row_indexes[i]]; + this->column_indexes[i] = col_perm[this->column_indexes[i]]; + } + this->sorted = false; +} + +/** + * @brief Permutates the matrix and can change its size efficently + * if size is shrinking and value is to be removed the negative one + * + * @tparam ScalarT + * @tparam Intdx + * @param row_perm size of m + * @param col_perm size of n + * @param m + * @param n + */ +template +inline void COO_Matrix::permutationSizeMap(std::vector row_perm, std::vector col_perm, Intdx m, Intdx n) +{ + assert(row_perm.size() == this->rows_size); + assert(col_perm.size() == this->columns_size); + + this->rows_size = m; + this->columns_size = n; + + for (int i = 0; i < this->values.size(); i++) + { + if (row_perm[this->row_indexes[i]] == -1 || col_perm[this->column_indexes[i]] == -1) + { + this->values[i] = 0; + } + else + { + this->row_indexes[i] = row_perm[this->row_indexes[i]]; + this->column_indexes[i] = col_perm[this->column_indexes[i]]; + } + } + this->sorted = false; +} + +/** + * @brief Restructure the sparse matrix for faster accesses and modifications + * + * @tparam ScalarT + * @tparam Intdx + */ +template +inline void COO_Matrix::sortSparse() +{ + //index based sort code + // https://stackoverflow.com/questions/25921706/creating-a-vector-of-indices-of-a-sorted-vector + + + //cannot call sort since two arrays are used instead + std::vector ordervec(this->row_indexes.size()); + std::size_t n(0); + std::generate(std::begin(ordervec), std::end(ordervec), [&]{ return n++; }); + + std::sort( std::begin(ordervec), + std::end(ordervec), + [&](int i1, int i2) { return this->row_indexes[i1] < this->row_indexes[i2] || + (this->row_indexes[i1] == this->row_indexes[i2] && this->column_indexes[i1] < this->column_indexes[i2]); } ); + + + //reorder based of index-sorting. Only swap no extra memory + // https://stackoverflow.com/a/22183350 + for (size_t i = 0; i < ordervec.size(); i++) + { + //permutation swap + while (ordervec[i] != ordervec[ordervec[i]]) + { + std::swap(this->row_indexes[ordervec[i]], this->row_indexes[ordervec[ordervec[i]]]); + std::swap(this->column_indexes[ordervec[i]], this->column_indexes[ordervec[ordervec[i]]]); + std::swap(this->values[ordervec[i]], this->values[ordervec[ordervec[i]]]); + + //swap orderings + std::swap(ordervec[i], ordervec[ordervec[i]]); + } + + } + this->sorted = true; +} + +template +inline bool COO_Matrix::isSorted() +{ + return this->sorted; +} + +template +inline std::tuple COO_Matrix::getDimensions() +{ + return std::tuple(this->rows_size, this->columns_size); +} + +template +inline void COO_Matrix::printMatrix(bool sort) +{ + if (sort == true && this->sorted == false) + { + this->sortSparse(); + } + + std::cout << "Sparse COO Matrix\n"; + std::cout << "(x , y, value)\n"; + for (size_t i = 0; i < this->values.size(); i++) + { + std::cout << "(" << this->row_indexes[i] + << ", " << this->column_indexes[i] + << ", " << this->values[i] << ")\n"; + } +} + +/** + * @brief Given vector indexes return the entries + * + * @tparam ScalarT + * @tparam Intdx + * @param r + * @param c + * @return std::vector + */ +template +inline std::vector COO_Matrix::indexEntries(std::vector r, std::vector c) +{ + assert(r.size() == c.size()); + std::vector valsnew(r.size(), -1); + + //cannot assume input is sorted so linear + Intdx aiter = 0; + //should fix this + for (Intdx i = 0; i < this->row_indexes.size(); i++) + { + while(r[aiter] < this->row_indexes[i] || (r[aiter] == this->row_indexes[i] && c[aiter] < this->column_indexes[i])) + { + valsnew.push_back(-1); + aiter++; + } + + if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) + { + valsnew.push_back(i); + aiter++; + } + + } + return valsnew; + +} + +/** + * @brief Given row index get start. If no start returns -1 + * + * @tparam ScalarT + * @tparam Intdx + * @param r + * @return Intdx + */ +template +inline Intdx COO_Matrix::indexStartRow(Intdx r) +{ + if (this->sorted) + { + //basic binary search + Intdx i1 = 0; + Intdx i2 = this->row_indexes.size()-1; + Intdx m = 0; + while (i1 <= i2) + { + m = (i2 + i1) / 2; + //rows + if (this->row_indexes[m] < r) + { + i1 = m + 1; + } + else if (r < this->row_indexes[m]) + { + i2 = m - 1; + } + else + { + break; + } + } + //drop to first index + while (this->row_indexes[m] == r) + { + m--; + } + return m; + + } + else + { + for (int i = 0; i < this->row_indexes.size(); i++) + { + if (this->row_indexes[i] == r) + { + return i; + } + } + } + return -1; +} + +template +inline COO_Matrix::COO_Matrix(std::vector r, std::vector c, std::vector v, Intdx m, Intdx n) +{ + this->values = v; + this->row_indexes = r; + this->column_indexes = c; + this->rows_size = m; + this->columns_size = n; + this->sorted = false; +} + +template +inline COO_Matrix::COO_Matrix(Intdx m, Intdx n) +{ + this->rows_size = m; + this->columns_size = n; + this->values = std::vector(); + this->row_indexes = std::vector(); + this->column_indexes = std::vector(); + this->sorted = false; +} + +template +inline COO_Matrix::COO_Matrix() +{ + this->rows_size = 0; + this->columns_size = 0; + this->values = std::vector(); + this->row_indexes = std::vector(); + this->column_indexes = std::vector(); + this->sorted = false; +} + +template +COO_Matrix::~COO_Matrix() +{ + +} From d54de58805e0ec845dc421e6dd88be88ea4eb4a5 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 20 Nov 2023 17:21:22 -0500 Subject: [PATCH 41/52] Added Jacobian Assembly. Fixed and Added New Functionality to COO Matrices +Matrix Assembly +Refactored COO Matrix +COO can return CSR Data format --- .../Capacitor/Capacitor.cpp | 2 +- .../DiscreteGenerator/DiscreteGenerator.cpp | 2 +- .../Inductor/Inductor.cpp | 2 +- Examples/RLCircuit/RLCircuit.cpp | 9 +- Examples/SparseTest/SparseTest.cpp | 49 +- PowerElectronicsModel.hpp | 65 ++- SparseMatrix/COO_Matrix.hpp | 521 +++++++++++------- 7 files changed, 436 insertions(+), 214 deletions(-) diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp index ecbe9d51f..79faefe89 100644 --- a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp @@ -91,7 +91,7 @@ int Capacitor::evaluateJacobian() COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); //Perform dF/dy + \alpha dF/dy' - this->J_.AXPY(this->alpha_, &Jacder); + this->J_.AXPY(this->alpha_, Jacder); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp index 7770281d1..c66c5b0f9 100644 --- a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp @@ -237,7 +237,7 @@ int DiscreteGenerator::evaluateJacobian() //Perform dF/dy + \alpha dF/dy' - this->J_.AXPY(-this->alpha_, &Jacder); + this->J_.AXPY(-this->alpha_, Jacder); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp index 89f903436..b0b19e63b 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -93,7 +93,7 @@ int Inductor::evaluateJacobian() COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); //Perform dF/dy + \alpha dF/dy' - this->J_.AXPY(this->alpha_, &Jacder); + this->J_.AXPY(this->alpha_, Jacder); return 0; } diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index 4669d564e..124b50bc0 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -80,9 +80,12 @@ int main(int argc, char const *argv[]) } std::cout << "}\n"; - induct->updateTime(0.0, 1.0); - induct->evaluateJacobian(); - induct->getJacobian().printMatrix(true); + + sysmodel->updateTime(0.0, 1.0); + sysmodel->evaluateJacobian(); + sysmodel->getJacobian().printMatrix(); + + return 0; diff --git a/Examples/SparseTest/SparseTest.cpp b/Examples/SparseTest/SparseTest.cpp index 976759533..81e5ac7dd 100644 --- a/Examples/SparseTest/SparseTest.cpp +++ b/Examples/SparseTest/SparseTest.cpp @@ -10,9 +10,6 @@ #include - - - int main(int argc, char const *argv[]) { std::vector val{0.1, 0.2, 0.3, 0.4}; @@ -35,7 +32,7 @@ int main(int argc, char const *argv[]) } std::cout << "A:\n"; - A.printMatrix(true); + A.printMatrix(); std::vector val2{0.5, 0.6, 0.7, 0.8, 1.0}; std::vector x2{0,2,0,2,1}; @@ -43,13 +40,47 @@ int main(int argc, char const *argv[]) COO_Matrix B = COO_Matrix(x2,y2,val2,m,n); std::cout << "B:\n"; - B.printMatrix(true); + B.printMatrix(); - A.AXPY(2.0, &B); + A.AXPY(2.0, B); std::cout << "A + 2B:\n"; - A.printMatrix(true); - + A.printMatrix(); + + std::vector r; + std::vector c; + std::vector v; + std::tie(r,c,v) = A.getDataToCSR(); + + for (size_t i = 0; i < r.size() - 1; i++) + { + std::cout << r[i] << std::endl; + size_t rdiff = r[i+1] - r[i]; + for (size_t j = 0; j < rdiff; j++) + { + std::cout << c[j + r[i]] << ", " << v[j + r[i]] << std::endl; + } + } + std::cout << r[r.size()-1] << std::endl; + + //Basic Verification test + std::vector rtest = {0, 2, 4, 7, 8}; + std::vector ctest = {2,3,2,3,1,2,3,2}; + std::vector valtest = {1.4, 1.0, 0.4, 2.2, 0.1, 1.6, 1.2, 0.3}; + + assert(rtest.size() == r.size()); + assert(ctest.size() == c.size()); + assert(valtest.size() == v.size()); + + int failval = 0; + for (size_t i = 0; i < rtest.size(); i++) if (r[i] != rtest[i]) failval--; + for (size_t i = 0; i < ctest.size(); i++) + { + double vdiff = v[i] - valtest[i]; + if (c[i] != ctest[i] || -1e-14 > vdiff || vdiff > 1e-14) failval--; + } - return 0; + std::cout << failval << std::endl; + + return failval; } diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp index 018ceaeaf..bad48ecf0 100644 --- a/PowerElectronicsModel.hpp +++ b/PowerElectronicsModel.hpp @@ -23,8 +23,8 @@ class PowerElectronicsModel : public ModelEvaluatorImpl // using ModelEvaluatorImpl::size_quad_; // using ModelEvaluatorImpl::size_opt_; using ModelEvaluatorImpl::nnz_; - // using ModelEvaluatorImpl::time_; - // using ModelEvaluatorImpl::alpha_; + using ModelEvaluatorImpl::time_; + using ModelEvaluatorImpl::alpha_; using ModelEvaluatorImpl::y_; using ModelEvaluatorImpl::yp_; // using ModelEvaluatorImpl::yB_; @@ -98,6 +98,11 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 0; } + /** + * @brief Set intial y and y' of each component + * + * @return int + */ int initialize() { @@ -106,7 +111,18 @@ class PowerElectronicsModel : public ModelEvaluatorImpl { component->initialize(); } + this->distributeVectors(); + + return 0; + } + /** + * @brief Distribute y and y' to each component based of node connection graph + * + * @return int + */ + int distributeVectors() + { for(const auto& component : components_) { for(IdxT j=0; jsize(); ++j) @@ -123,6 +139,11 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 0; } + /** + * @brief Evaluate Residuals at each component then collect them + * + * @return int + */ int evaluateResidual() { for (IdxT i = 0; i < this->f_.size(); i++) @@ -130,16 +151,7 @@ class PowerElectronicsModel : public ModelEvaluatorImpl f_[i] = 0; } - // Update variables - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - component->y()[j] = y_[component->getNodeConnection(j)]; - component->yp()[j] = yp_[component->getNodeConnection(j)]; - } - component->evaluateResidual(); - } + this->distributeVectors(); // Update system residual vector @@ -161,6 +173,25 @@ class PowerElectronicsModel : public ModelEvaluatorImpl */ int evaluateJacobian() { + this->J_.zeroMatrix(); + this->distributeVectors(); + + //Evaluate component jacs + for(const auto& component : components_) + { + component->evaluateJacobian(); + std::vector r; + std::vector c; + std::vector v; + std::tie(r, c, v) = component->getJacobian().getEntrieCopies(); + for (IdxT i = 0; i < static_cast(r.size()); i++) + { + r[i] = component->getNodeConnection(r[i]); + c[i] = component->getNodeConnection(c[i]); + } + this->J_.AXPY(1.0, r, c, v); + } + return 0; } @@ -205,8 +236,18 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 0; } + /** + * @brief Distribute time and time scaling for each component + * + * @param t + * @param a + */ void updateTime(ScalarT t, ScalarT a) { + for(const auto& component : components_) + { + component->updateTime(t, a); + } } void addComponent(component_type* component) diff --git a/SparseMatrix/COO_Matrix.hpp b/SparseMatrix/COO_Matrix.hpp index e4b087386..5b0ece80c 100644 --- a/SparseMatrix/COO_Matrix.hpp +++ b/SparseMatrix/COO_Matrix.hpp @@ -11,10 +11,8 @@ /** * @brief Quick class to provide sparse matrices of COO type. Simplifies data movement - * @todo Add base class of sparse matrix for conversion to CSR - * @todo Switch Push back with buffer allocation for resizing - * @todo NonZero Values for preallocation - * @todo Fix warnings, mostly type casting of indexes. Should try to move to iterator somehow + * + * @todo add functionality to keep track of multiple sorted list. Faster adding of new entries and will have a threshold to sort completely. * * m x n sparse matrix */ @@ -29,176 +27,203 @@ class COO_Matrix Intdx columns_size; bool sorted; public: + //Constructors COO_Matrix(std::vector r, std::vector c, std::vector v, Intdx m, Intdx n); COO_Matrix(Intdx m, Intdx n); COO_Matrix(); ~COO_Matrix(); - //could replace with binary operation for both - // --- Functions which donot sort --- - void setValues(std::vector r, std::vector c, std::vector val); - void addValues(std::vector r, std::vector c, std::vector val); + + //Operations // --- Functions which call sort --- std::tuple, std::vector> getRowCopy(Intdx r); - std::tuple, std::vector, std::vector> getEntries(); + std::tuple&, std::vector&, std::vector&> getEntries(); + std::tuple, std::vector, std::vector> getEntrieCopies(); + + std::tuple, std::vector, std::vector> getDataToCSR(); // BLAS. Will sort before running - void AXPY(ScalarT alpha, COO_Matrix* a); + void setValues(std::vector r, std::vector c, std::vector v); + void AXPY(ScalarT alpha, COO_Matrix& a); + void AXPY(ScalarT alpha, std::vector r, std::vector c, std::vector v); + void SCAL(ScalarT alpha); // --- Permutation Operations --- //No sorting is actually done. Only done when nesscary void permutation(std::vector row_perm, std::vector col_perm); void permutationSizeMap(std::vector row_perm, std::vector col_perm, Intdx m, Intdx n); + void zeroMatrix(); + + void identityMatrix(Intdx n); + //Resort values void sortSparse(); bool isSorted(); std::tuple getDimensions(); - void printMatrix(bool sort); + void printMatrix(); private: - std::vector indexEntries(std::vector r, std::vector c); - Intdx indexStartRow(Intdx r); + Intdx indexStartRow(const std::vector &rows, Intdx r); + Intdx sparseCordBinarySearch(const std::vector &rows, const std::vector &columns, Intdx ri, Intdx ci); + void sortSparseCOO(std::vector &rows, std::vector &columns, std::vector &values); + }; /** - * @brief Set values of sparse matrix. Increases size if outside bounds - * - * @todo should error return if outside bounds instead? + * @brief Get copy of row values * * @tparam ScalarT * @tparam Intdx * @param r - * @param c - * @param val + * @return std::tuple, std::vector> */ template -inline void COO_Matrix::setValues(std::vector r, std::vector c, std::vector val) +inline std::tuple, std::vector> COO_Matrix::getRowCopy(Intdx r) { - std::vector indexes = this->indexEntries(r,c); + if (!this->sorted) + { + this->sortSparse(); + } + Intdx rowindex = this->indexStartRow(r); + - for (int i = 0; i < indexes.size(); i++) + if (rowindex == -1) { - if (indexes[i] == -1) - { - if (r[i] >= this->rows_size) - { - this->rows_size = r[i]; - } - if (c[i] >= this->columns_size) - { - this->columns_size = c[i]; - } - - this->row_indexes.push_back(r[i]); - this->column_indexes.push_back(c[i]); - this->values.push_back(val[i]); - this->sorted = false; - } - else - { - this->values[indexes[i]] = val[i]; - } + return {std::vector(),std::vector()}; } + + Intdx rsize = rowindex; + do + { + rsize++; + } while (rsize < this->values.size() && this->row_indexes[rsize] == r); + return {{this->column_indexes.begin() + rowindex, this->column_indexes.begin() + rsize},{this->values.begin() + rowindex, this->values.begin() + rsize}}; } /** - * @brief Add new values to sparse matrix. Will increase size if outside bounds - * - * @todo should error return if outside bounds instead? + * @brief Get all Entries pointers. Will sort before returnings * * @tparam ScalarT * @tparam Intdx - * @param r - * @param c - * @param val + * @return std::tuple, std::vector, std::vector> */ template -inline void COO_Matrix::addValues(std::vector r, std::vector c, std::vector val) +inline std::tuple&, std::vector&, std::vector&> COO_Matrix::getEntries() { - std::vector indexes = this->indexEntries(r,c); - - for (int i = 0; i < indexes.size(); i++) + if (!this->sorted) { - if (indexes[i] == -1) - { - if (r[i] >= this->rows_size) - { - this->rows_size = r[i]; - } - if (c[i] >= this->columns_size) - { - this->columns_size = c[i]; - } - - this->row_indexes.push_back(r[i]); - this->column_indexes.push_back(c[i]); - this->values.push_back(val[i]); - this->sorted = false; - } - else - { - this->values[indexes[i]] += val[i]; - } + this->sortSparse(); } - + return {this->row_indexes, this->column_indexes, this->values}; } /** - * @brief Get copy of row values + * @brief Get copies of the data. Sorted before returning * * @tparam ScalarT * @tparam Intdx - * @param r - * @return std::tuple, std::vector> + * @return std::tuple, std::vector, std::vector> */ template -inline std::tuple, std::vector> COO_Matrix::getRowCopy(Intdx r) +inline std::tuple, std::vector, std::vector> COO_Matrix::getEntrieCopies() { if (!this->sorted) { this->sortSparse(); } - Intdx rowindex = this->indexStartRow(r); - + return {this->row_indexes, this->column_indexes, this->values}; +} - if (rowindex == -1) +/** + * @brief Returns the data into CSR Format + * + * @tparam ScalarT + * @tparam Intdx + * @return std::tuple, std::vector, std::vector> + */ +template +inline std::tuple, std::vector, std::vector> COO_Matrix::getDataToCSR() +{ + if (!this->isSorted()) this->sortSparse(); + std::vector rowsizevec(this->rows_size + 1, 0); + Intdx counter = 0; + for (Intdx i = 0; i < static_cast(rowsizevec.size() - 1); i++) { - return {std::vector(),std::vector()}; + rowsizevec[i + 1] = rowsizevec[i]; + while (counter < static_cast(this->row_indexes.size()) && i == this->row_indexes[counter]) + { + rowsizevec[i+1]++; + counter++; + } } - - Intdx rsize = rowindex; - do - { - rsize++; - } while (rsize < this->values.size() && this->row_indexes[rsize] == r); - - return {{this->column_indexes.begin() + rowindex, this->column_indexes.begin() + rsize},{this->values.begin() + rowindex, this->values.begin() + rsize}}; + return {rowsizevec, this->column_indexes, this->values}; } /** - * @brief Get all Entries + * @brief Given set of vector data it will set the values into the matrix * * @tparam ScalarT * @tparam Intdx - * @return std::tuple, std::vector, std::vector> + * @param r + * @param c + * @param v */ template -inline std::tuple, std::vector, std::vector> COO_Matrix::getEntries() +inline void COO_Matrix::setValues(std::vector r, std::vector c, std::vector v) { - if (!this->sorted) + //sort input + this->sortSparseCOO(r, c, v); + + + //Duplicated with AXPY. Could replace with function depdent on lambda expression + Intdx aiter = 0; + //iterate for all current values in matrix + for (Intdx i = 0; i < static_cast(this->row_indexes.size()); i++) { - this->sortSparse(); + //pushback values when they are not in current matrix + while(aiter < static_cast(r.size()) && (r[aiter] < this->row_indexes[i] || (r[aiter] == this->row_indexes[i] && c[aiter] < this->column_indexes[i]))) + { + this->row_indexes.push_back(r[aiter]); + this->column_indexes.push_back(c[aiter]); + this->values.push_back(v[aiter]); + aiter++; + } + if (aiter >= static_cast(r.size())) break; + + + if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) + { + this->values[i] = v[aiter]; + aiter++; + } } - return {this->row_indexes, this->column_indexes, this->values}; + //push back rest that was not found sorted + for (Intdx i = aiter; i < static_cast(r.size()); i++) + { + this->row_indexes.push_back(r[i]); + this->column_indexes.push_back(c[i]); + this->values.push_back(v[i]); + } + + this->sorted = false; + } +/** + * @brief BLAS AXPY operation on another COO matrix. Will sort both matrices before acting + * + * @tparam ScalarT + * @tparam Intdx + * @param alpha + * @param a + */ template -inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrix *a) +inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrix& a) { if (alpha == 0) return; @@ -206,18 +231,17 @@ inline void COO_Matrix::AXPY(ScalarT alpha, COO_MatrixsortSparse(); } - if (!a->isSorted()) + if (!a.isSorted()) { - a->sortSparse(); + a.sortSparse(); } - std::vector val; - std::vector r; - std::vector c; Intdx m = 0; Intdx n = 0; - std::tie(r,c,val) = a->getEntries(); - std::tie(m,n) = a->getDimensions(); + std::tuple&, std::vector&, std::vector&> tpm = a.getEntries(); + const auto& [r, c, val] = tpm; + std::tie(m,n) = a.getDimensions(); + //Increase size as nesscary this->rows_size = this->rows_size > m ? this->rows_size : m; this->columns_size = this->columns_size > n ? this->columns_size : n; @@ -233,7 +257,7 @@ inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrixvalues.push_back(alpha * val[aiter]); aiter++; } - if (aiter >= r.size()) break; + if (aiter >= static_cast(r.size())) break; if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) @@ -253,6 +277,74 @@ inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrixsorted = false; } +/** + * @brief AXPY on 3list. + * + * @tparam ScalarT + * @tparam Intdx + * @param alpha + * @param r + * @param c + * @param v + */ +template +inline void COO_Matrix::AXPY(ScalarT alpha, std::vector r, std::vector c, std::vector v) +{ + if (alpha == 0) return; + + if (!this->sorted) + { + this->sortSparse(); + } + + //sort input + this->sortSparseCOO(r, c, v); + + Intdx aiter = 0; + //iterate for all current values in matrix + for (Intdx i = 0; i < static_cast(this->row_indexes.size()); i++) + { + //pushback values when they are not in current matrix + while(aiter < static_cast(r.size()) && (r[aiter] < this->row_indexes[i] || (r[aiter] == this->row_indexes[i] && c[aiter] < this->column_indexes[i]))) + { + this->row_indexes.push_back(r[aiter]); + this->column_indexes.push_back(c[aiter]); + this->values.push_back(alpha * v[aiter]); + aiter++; + } + if (aiter >= static_cast(r.size())) break; + + + if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) + { + this->values[i] += alpha * v[aiter]; + aiter++; + } + } + //push back rest that was not found sorted + for (Intdx i = aiter; i < static_cast(r.size()); i++) + { + this->row_indexes.push_back(r[i]); + this->column_indexes.push_back(c[i]); + this->values.push_back(alpha * v[i]); + } + + this->sorted = false; +} + +/** + * @brief Scale all values + * + * @tparam ScalarT + * @tparam Intdx + * @param alpha + */ +template +inline void COO_Matrix::SCAL(ScalarT alpha) +{ + for (auto i = this->values.begin(); i < this->values.end(); i++) *i *= alpha; +} + /** * @brief Permutate the matrix to a different one. Only changes the coordinates * @@ -273,6 +365,7 @@ inline void COO_Matrix::permutation(std::vector row_perm, this->column_indexes[i] = col_perm[this->column_indexes[i]]; } this->sorted = false; + //cycle sorting maybe useful since permutations are already known } /** @@ -311,48 +404,48 @@ inline void COO_Matrix::permutationSizeMap(std::vector ro } /** - * @brief Restructure the sparse matrix for faster accesses and modifications + * @brief Turn matrix into the zero matrix. Does not actual delete memory * * @tparam ScalarT * @tparam Intdx */ template -inline void COO_Matrix::sortSparse() +inline void COO_Matrix::zeroMatrix() { - //index based sort code - // https://stackoverflow.com/questions/25921706/creating-a-vector-of-indices-of-a-sorted-vector - - - //cannot call sort since two arrays are used instead - std::vector ordervec(this->row_indexes.size()); - std::size_t n(0); - std::generate(std::begin(ordervec), std::end(ordervec), [&]{ return n++; }); - - std::sort( std::begin(ordervec), - std::end(ordervec), - [&](int i1, int i2) { return this->row_indexes[i1] < this->row_indexes[i2] || - (this->row_indexes[i1] == this->row_indexes[i2] && this->column_indexes[i1] < this->column_indexes[i2]); } ); - + //resize doesn't effect capacity if smaller + this->column_indexes.resize(0); + this->row_indexes.resize(0); + this->values.resize(0); + this->sorted = true; +} - //reorder based of index-sorting. Only swap no extra memory - // https://stackoverflow.com/a/22183350 - for (size_t i = 0; i < ordervec.size(); i++) +template +inline void COO_Matrix::identityMatrix(Intdx n) +{ + //Reset Matrix + this->zeroMatrix(); + for (Intdx i = 0; i < n; i++) { - //permutation swap - while (ordervec[i] != ordervec[ordervec[i]]) - { - std::swap(this->row_indexes[ordervec[i]], this->row_indexes[ordervec[ordervec[i]]]); - std::swap(this->column_indexes[ordervec[i]], this->column_indexes[ordervec[ordervec[i]]]); - std::swap(this->values[ordervec[i]], this->values[ordervec[ordervec[i]]]); - - //swap orderings - std::swap(ordervec[i], ordervec[ordervec[i]]); - } - + this->column_indexes[i] = i; + this->row_indexes[i] = i; + this->values[i] = 1.0; } this->sorted = true; } +/** + * @brief Restructure the sparse matrix for faster accesses and modifications + * + * @tparam ScalarT + * @tparam Intdx + */ +template +inline void COO_Matrix::sortSparse() +{ + this->sortSparseCOO(this->row_indexes, this->column_indexes, this->values); + this->sorted = true; +} + template inline bool COO_Matrix::isSorted() { @@ -365,10 +458,16 @@ inline std::tuple COO_Matrix::getDimensions() return std::tuple(this->rows_size, this->columns_size); } +/** + * @brief Print matrix that is sorted + * + * @tparam ScalarT + * @tparam Intdx + */ template -inline void COO_Matrix::printMatrix(bool sort) +inline void COO_Matrix::printMatrix() { - if (sort == true && this->sorted == false) + if (this->sorted == false) { this->sortSparse(); } @@ -384,95 +483,143 @@ inline void COO_Matrix::printMatrix(bool sort) } /** - * @brief Given vector indexes return the entries + * @brief Find the lowest row cordinate from set of provided cordinates * + * Assumes rows and columns are sorted * @tparam ScalarT * @tparam Intdx * @param r - * @param c - * @return std::vector + * @return Intdx */ template -inline std::vector COO_Matrix::indexEntries(std::vector r, std::vector c) +inline Intdx COO_Matrix::indexStartRow(const std::vector &rows, Intdx r) { - assert(r.size() == c.size()); - std::vector valsnew(r.size(), -1); - - //cannot assume input is sorted so linear - Intdx aiter = 0; - //should fix this - for (Intdx i = 0; i < this->row_indexes.size(); i++) + //Specialized Binary Search for Lowest Row + Intdx i1 = 0; + Intdx i2 = rows->size()-1; + Intdx m_smallest = -1; + Intdx m = -1; + while (i1 <= i2) { - while(r[aiter] < this->row_indexes[i] || (r[aiter] == this->row_indexes[i] && c[aiter] < this->column_indexes[i])) + m = (i2 + i1) / 2; + //rows + if (rows[m] < r) { - valsnew.push_back(-1); - aiter++; + i1 = m + 1; } - - if (r[aiter] == this->row_indexes[i] && c[aiter] == this->column_indexes[i]) + else if (r < rows[m]) { - valsnew.push_back(i); - aiter++; + i2 = m - 1; + } + else + { + if (i1 == i2) + { + return m_smallest; + } + + //Keep track of smallest cordinate + m_smallest = m; + i2 = m - 1; } - } - return valsnew; - + return m_smallest; } /** - * @brief Given row index get start. If no start returns -1 + * @brief Basic binary search * * @tparam ScalarT * @tparam Intdx - * @param r + * @param rows + * @param columns + * @param ri + * @param ci * @return Intdx */ template -inline Intdx COO_Matrix::indexStartRow(Intdx r) +inline Intdx COO_Matrix::sparseCordBinarySearch(const std::vector &rows, const std::vector &columns, Intdx ri, Intdx ci) { - if (this->sorted) + assert(rows.size() == columns.size()); + //basic binary search + Intdx i1 = 0; + Intdx i2 = rows.size()-1; + Intdx m = 0; + while (i1 <= i2) { - //basic binary search - Intdx i1 = 0; - Intdx i2 = this->row_indexes.size()-1; - Intdx m = 0; - while (i1 <= i2) + m = (i2 + i1) / 2; + //rows + if (rows[m] < ri) + { + i1 = m + 1; + } + else if (ri < rows[m]) + { + i2 = m - 1; + } + else { - m = (i2 + i1) / 2; - //rows - if (this->row_indexes[m] < r) + if (columns[m] < ci) { i1 = m + 1; } - else if (r < this->row_indexes[m]) + else if (ci < columns[m]) { i2 = m - 1; } - else - { - break; - } + break; } - //drop to first index - while (this->row_indexes[m] == r) - { - m--; - } - return m; - } - else + + return m; +} + +/** + * @brief Sort a disoreded set of values. Assume nothing on order. + * + * @todo simple setup. Should add better sorting since list are pre-sorted + * + * @tparam ScalarT + * @tparam Intdx + * @param rows + * @param columns + * @param values + */ +template +inline void COO_Matrix::sortSparseCOO(std::vector &rows, std::vector &columns, std::vector &values) +{ + + //index based sort code + // https://stackoverflow.com/questions/25921706/creating-a-vector-of-indices-of-a-sorted-vector + //cannot call sort since two arrays are used instead + std::vector ordervec(rows.size()); + std::size_t n(0); + std::generate(std::begin(ordervec), std::end(ordervec), [&]{ return n++; }); + + //Sort by row first then column. + std::sort( std::begin(ordervec), + std::end(ordervec), + [&](int i1, int i2) { return (rows[i1] < rows[i2]) || + (rows[i1] == rows[i2] && columns[i1] < columns[i2]); } ); + + + //reorder based of index-sorting. Only swap cost no extra memory. + // @todo see if extra memory creation is fine + // https://stackoverflow.com/a/22183350 + for (size_t i = 0; i < ordervec.size(); i++) { - for (int i = 0; i < this->row_indexes.size(); i++) + //permutation swap + while (ordervec[i] != ordervec[ordervec[i]]) { - if (this->row_indexes[i] == r) - { - return i; - } + std::swap(rows[ordervec[i]], rows[ordervec[ordervec[i]]]); + std::swap(columns[ordervec[i]], columns[ordervec[ordervec[i]]]); + std::swap(values[ordervec[i]], values[ordervec[ordervec[i]]]); + + //swap orderings + std::swap(ordervec[i], ordervec[ordervec[i]]); } + } - return -1; } template From 928452ffc83d2df8b62cb7138e237cd742a36999 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Sun, 10 Dec 2023 22:28:24 -0500 Subject: [PATCH 42/52] Jacobian Assembly, IDA + KLU Cmake, RL Circuit + Cmake configurations for Sundials and SuiteSparse + Jacobian Assembly for components + Working RL Circuit example utilizing assembly techniques --- CMake/FindSuiteSparse.cmake | 5 +- CMakeLists.txt | 4 +- .../CircuitComponent.hpp | 2 + .../Inductor/Inductor.cpp | 12 +- .../Resistor/Resistor.cpp | 9 +- .../VoltageSource/VoltageSource.cpp | 8 +- Examples/RLCircuit/CMakeLists.txt | 3 +- Examples/RLCircuit/RLCircuit.cpp | 113 +++++++++++++----- ModelEvaluator.hpp | 16 ++- ModelEvaluatorImpl.hpp | 6 +- PowerElectronicsModel.hpp | 95 ++++++++++++--- Solver/Dynamic/CMakeLists.txt | 5 + Solver/Dynamic/Ida.cpp | 90 +++++++++++--- Solver/Dynamic/Ida.hpp | 7 +- SparseMatrix/COO_Matrix.hpp | 74 +++++++++++- SystemModel.hpp | 11 ++ 16 files changed, 378 insertions(+), 82 deletions(-) diff --git a/CMake/FindSuiteSparse.cmake b/CMake/FindSuiteSparse.cmake index 2d73feb76..5a1026935 100644 --- a/CMake/FindSuiteSparse.cmake +++ b/CMake/FindSuiteSparse.cmake @@ -69,11 +69,11 @@ Author(s): set(SUITESPARSE_MODULES amd colamd - klu) + klu + suitesparseconfig) find_library(SUITESPARSE_LIBRARY NAMES - suitesparseconfig ${SUITESPARSE_MODULES} PATHS ${SUITESPARSE_DIR} $ENV{SUITESPARSE_DIR} ${SUITESPARSE_ROOT_DIR} @@ -97,6 +97,7 @@ find_path(SUITESPARSE_INCLUDE_DIR amd.h colamd.h klu.h + SuiteSparse_config.h PATHS ${SUITESPARSE_DIR} $ENV{SUITESPARSE_DIR} ${SUITESPARSE_ROOT_DIR} ${SUITESPARSE_LIBRARY_DIR}/.. PATH_SUFFIXES diff --git a/CMakeLists.txt b/CMakeLists.txt index ef6cbcf57..badea53a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ option(GRIDKIT_ENABLE_IPOPT "Enable Ipopt support" ON) option(GRIDKIT_ENABLE_SUNDIALS "Enable SUNDIALS support" ON) # Enable KLU -option(GRIDKIT_ENABLE_SUNDIALS_SPARSE "Enable SUNDIALS sparse linear solvers" OFF) +option(GRIDKIT_ENABLE_SUNDIALS_SPARSE "Enable SUNDIALS sparse linear solvers" ON) set(CMAKE_MACOSX_RPATH 1) @@ -110,7 +110,7 @@ endif("${isSystemDir}" STREQUAL "-1") # TODO: Probably beter to set a debug interface target -set(CMAKE_CXX_FLAGS_DEBUG "-Wall -O0 -g") +set(CMAKE_CXX_FLAGS_DEBUG "-Wall -O0 -g -DDEBUG") set(CMAKE_CXX_STANDARD 17) diff --git a/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp index 9e1052e43..fe2efdf96 100644 --- a/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp +++ b/ComponentLib/PowerElectronicsComponents/CircuitComponent.hpp @@ -27,6 +27,8 @@ namespace ModelLib this->time_ = t; this->alpha_ = a; } + + bool hasJacobian() { return true;} size_t getExternSize() { diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp index b0b19e63b..a24b7a8e9 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -70,26 +70,30 @@ int Inductor::tagDifferentiable() template int Inductor::evaluateResidual() { + //input this->f_[0] = this->y_[2]; + //output this->f_[1] = -this->y_[2]; - this->f_[2] = - this->L_ * this->yp_[2] + this->y_[0] - this->y_[1] ; + //internal + this->f_[2] = this->L_ * this->yp_[2] + this->y_[0] - this->y_[1] ; return 0; } template int Inductor::evaluateJacobian() { - + this->J_.zeroMatrix(); + //Create dF/dy std::vector rcord{0,1,2,2}; std::vector ccord{2,2,0,1}; std::vector vals{1.0, -1.0, 1.0, -1.0}; this->J_.setValues(rcord, ccord, vals); - //Create -dF/dy' + //Create dF/dy' std::vector rcordder{2}; std::vector ccordder{2}; - std::vector valsder{-this->L_}; + std::vector valsder{this->L_}; COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); //Perform dF/dy + \alpha dF/dy' diff --git a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp index 7536f2274..45d9a34f3 100644 --- a/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Resistor/Resistor.cpp @@ -69,9 +69,10 @@ int Resistor::tagDifferentiable() template int Resistor::evaluateResidual() { - - this->f_[0] = (this->y_[1] - this->y_[0])/this->R_ ; - this->f_[1] = (this->y_[0] - this->y_[1])/this->R_ ; + //input + this->f_[0] = (this->y_[0] - this->y_[1])/this->R_ ; + //ouput + this->f_[1] = (this->y_[1] - this->y_[0])/this->R_ ; return 0; } @@ -83,7 +84,7 @@ int Resistor::evaluateJacobian() //does compiler make constant??? std::vector rcord{0,0,1,1}; std::vector ccord{0,1,0,1}; - std::vector vals{-1.0 / this->R_, 1.0 / this->R_, 1.0 / this->R_, -1.0 / this->R_}; + std::vector vals{1.0 / this->R_, -1.0 / this->R_, -1.0 / this->R_, 1.0 / this->R_}; this->J_.setValues(rcord, ccord, vals); return 0; diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp index b7c18bd6f..c7cb09798 100644 --- a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp @@ -71,20 +71,22 @@ int VoltageSource::evaluateResidual() { //Note this leaves induction lumped into y. Perhaps would be better to seperate volatge and induction into seperate vectors // for easier development + //input this->f_[0] = this->y_[2]; + //ouput this->f_[1] = -this->y_[2]; - this->f_[2] = this->y_[1] - this->y_[0] - this->V_; + //internal + this->f_[2] = -this->y_[1] + this->y_[0] + this->V_; return 0; } template int VoltageSource::evaluateJacobian() { - //Create dF/dy std::vector rcord{0,1,2,2}; std::vector ccord{2,2,0,1}; - std::vector vals{1.0, -1.0, -1.0, 1.0}; + std::vector vals{1.0, -1.0, 1.0, -1.0}; this->J_.setValues(rcord, ccord, vals); return 0; diff --git a/Examples/RLCircuit/CMakeLists.txt b/Examples/RLCircuit/CMakeLists.txt index 5069566bf..476eb5e95 100644 --- a/Examples/RLCircuit/CMakeLists.txt +++ b/Examples/RLCircuit/CMakeLists.txt @@ -6,7 +6,8 @@ add_executable(rlcircuit RLCircuit.cpp) target_link_libraries(rlcircuit GRIDKIT::powerelec_capacitor GRIDKIT::powerelec_inductor GRIDKIT::powerelec_resistor - GRIDKIT::powerelec_voltagesource) + GRIDKIT::powerelec_voltagesource + GRIDKIT::solvers_dyn) add_test(NAME RLCircuit COMMAND $) install(TARGETS rlcircuit RUNTIME DESTINATION bin) diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index 124b50bc0..c71eef06d 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -12,68 +12,89 @@ #include #include +#include +#include int main(int argc, char const *argv[]) { - + double abstol = 1e-8; + double reltol = 1e-8; + bool usejac = true; + //TODO:setup as named parameters //Create circuit model - ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(); + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac); size_t idoff = 0; + //RL circuit parameters + double rinit = 1.0; + double linit = 1.0; + double vinit = 1.0; + + //inductor - ModelLib::Inductor* induct = new ModelLib::Inductor(idoff,0.1); + ModelLib::Inductor* induct = new ModelLib::Inductor(idoff,linit); //Form index to node uid realations - induct->setExternalConnectionNodes(0,2); - induct->setExternalConnectionNodes(2,1); - induct->setExternalConnectionNodes(1,0); + // input + induct->setExternalConnectionNodes(0,1); + //output + induct->setExternalConnectionNodes(1,-1); + //internal + induct->setExternalConnectionNodes(2,2); + //add component sysmodel->addComponent(induct); //resistor idoff++; - ModelLib::Resistor* resis = new ModelLib::Resistor(idoff, 1.0); + ModelLib::Resistor* resis = new ModelLib::Resistor(idoff, rinit); //Form index to node uid realations - resis->setExternalConnectionNodes(0,3); - resis->setExternalConnectionNodes(1,2); + //input + resis->setExternalConnectionNodes(0,0); + //output + resis->setExternalConnectionNodes(1,1); + //add sysmodel->addComponent(resis); //voltage source idoff++; - ModelLib::VoltageSource* vsource = new ModelLib::VoltageSource(idoff, 0.1); + ModelLib::VoltageSource* vsource = new ModelLib::VoltageSource(idoff, vinit); //Form index to node uid realations - vsource->setExternalConnectionNodes(0,0); - vsource->setExternalConnectionNodes(2,4); - vsource->setExternalConnectionNodes(1,3); + //input + vsource->setExternalConnectionNodes(0,-1); + //output + vsource->setExternalConnectionNodes(1,0); + //internal + vsource->setExternalConnectionNodes(2,3); + + sysmodel->addComponent(vsource); - - //Allocate with graph - sysmodel->allocate(5); + sysmodel->allocate(4); std::cout << sysmodel->y().size() << std::endl; + //Grounding for IDA. If no grounding then circuit is \mu > 1 + //v_0 (grounded) //Create Intial points - sysmodel->y()[0] = 1.0; - sysmodel->y()[1] = 1.0; - sysmodel->y()[2] = 1.0; - sysmodel->y()[3] = 1.0; - sysmodel->y()[4] = 1.0; - - sysmodel->yp()[0] = 1.0; - sysmodel->yp()[1] = 1.0; - sysmodel->yp()[2] = 1.0; - sysmodel->yp()[3] = 1.0; - sysmodel->yp()[4] = 1.0; + sysmodel->y()[0] = vinit; //v_1 + sysmodel->y()[1] = vinit; // v_2 + sysmodel->y()[2] = 0.0; // i_L + sysmodel->y()[3] = 0.0; // i_s + + sysmodel->yp()[0] = 0.0; // v'_1 + sysmodel->yp()[1] = 0.0; // v'_2 + sysmodel->yp()[2] = -vinit / linit; // i'_s + sysmodel->yp()[3] = -vinit / linit; // i'_L + sysmodel->initialize(); - sysmodel->evaluateResidual(); - std::cout << "Output: {"; + std::cout << "Verify Intial Resisdual is Zero: {"; for (double i : sysmodel->getResidual()) { std::cout << i << ", "; @@ -83,10 +104,44 @@ int main(int argc, char const *argv[]) sysmodel->updateTime(0.0, 1.0); sysmodel->evaluateJacobian(); + std::cout << "Intial Jacobian with alpha = 1:\n"; sysmodel->getJacobian().printMatrix(); + // Create numerical integrator and configure it for the generator model + AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + double t_init = 0.0; + double t_final = 1.0; + + // setup simulation + idas->configureSimulation(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + idas->runSimulation(t_final); + + std::vector& yfinial = sysmodel->y(); + + std::cout << "Final Vector y\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << yfinial[i] << "\n"; + } + + std::vector yexact(4); + + //analytical solution to the circuit + yexact[0] = vinit; + yexact[2] = (-vinit / rinit) * (exp((rinit / linit) * t_final) - 1.0); + yexact[3] = yexact[2]; + yexact[1] = vinit - rinit * yexact[2]; + + std::cout << "Element-wise Relative error at t=" << t_final << "\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << abs((yfinial[i] - yexact[i]) / yexact[i]) << "\n"; + } return 0; } diff --git a/ModelEvaluator.hpp b/ModelEvaluator.hpp index 5eda481de..50c5e8b77 100644 --- a/ModelEvaluator.hpp +++ b/ModelEvaluator.hpp @@ -62,6 +62,7 @@ #include #include +#include namespace ModelLib { @@ -88,11 +89,20 @@ namespace ModelLib virtual int initializeAdjoint() = 0; virtual int evaluateAdjointResidual() = 0; - //virtual int evaluateAdjointJacobian() = 0; + // virtual int evaluateAdjointJacobian() = 0; virtual int evaluateAdjointIntegrand() = 0; virtual IdxT size() = 0; virtual IdxT nnz() = 0; + + /** + * @brief Is the Jacobian defined. Used in IDA to determine wether DQ is used or not + * + * @return true + * @return false + */ + virtual bool hasJacobian() = 0; + virtual IdxT size_quad() = 0; virtual IdxT size_opt() = 0; virtual void updateTime(real_type t, real_type a) = 0; @@ -125,6 +135,10 @@ namespace ModelLib virtual std::vector& getResidual() = 0; virtual const std::vector& getResidual() const = 0; + + virtual COO_Matrix& getJacobian() = 0; + virtual const COO_Matrix& getJacobian() const = 0; + virtual std::vector& getIntegrand() = 0; virtual const std::vector& getIntegrand() const = 0; diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp index ade61feff..928d26f30 100644 --- a/ModelEvaluatorImpl.hpp +++ b/ModelEvaluatorImpl.hpp @@ -62,7 +62,6 @@ #include #include -#include namespace ModelLib { @@ -112,6 +111,11 @@ namespace ModelLib return nnz_; } + virtual bool hasJacobian() + { + return false; + } + virtual IdxT size_quad() { return size_quad_; diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp index bad48ecf0..47efcc7f7 100644 --- a/PowerElectronicsModel.hpp +++ b/PowerElectronicsModel.hpp @@ -43,13 +43,27 @@ class PowerElectronicsModel : public ModelEvaluatorImpl public: /** - * @brief Constructor for the system model + * @brief Default constructor for the system model */ PowerElectronicsModel() : ModelEvaluatorImpl(0, 0, 0) { - // Set system model tolerances - rtol_ = 1e-5; - atol_ = 1e-5; + // Set system model tolerances as default + rtol_ = 1e-4; + atol_ = 1e-4; + // By default use jacobian + usejac_ = true; + } + + /** + * @brief Constructor for the system model + */ + PowerElectronicsModel(double rt, double at, bool ju) : ModelEvaluatorImpl(0, 0, 0) + { + // Set system model tolerances from input + rtol_ = rt; + atol_ = at; + // Can choose not to use jacobain + usejac_ = ju; } /** @@ -73,6 +87,28 @@ class PowerElectronicsModel : public ModelEvaluatorImpl return 1; } + /** + * @brief Will check if each component has jacobian avalible. If one doesn't then jacobain is false. + * + * + * @return true + * @return false + */ + bool hasJacobian() + { + if (!this->usejac_) return false; + + for(const auto& component : components_) + { + if (!component->hasJacobian()) + { + return false; + } + + } + return true; + } + /** * @brief Allocate the vector data with size amount * @todo Add capability to go through component model connection to get the size of the actual vector @@ -127,8 +163,16 @@ class PowerElectronicsModel : public ModelEvaluatorImpl { for(IdxT j=0; jsize(); ++j) { - component->y()[j] = y_[component->getNodeConnection(j)]; - component->yp()[j] = yp_[component->getNodeConnection(j)]; + if(component->getNodeConnection(j) != -1) + { + component->y()[j] = y_[component->getNodeConnection(j)]; + component->yp()[j] = yp_[component->getNodeConnection(j)]; + } + else + { + component->y()[j] = 0.0; + component->yp()[j] = 0.0; + } } } return 0; @@ -148,7 +192,7 @@ class PowerElectronicsModel : public ModelEvaluatorImpl { for (IdxT i = 0; i < this->f_.size(); i++) { - f_[i] = 0; + f_[i] = 0.0; } this->distributeVectors(); @@ -157,9 +201,16 @@ class PowerElectronicsModel : public ModelEvaluatorImpl for(const auto& component : components_) { + //TODO:check return type + component->evaluateResidual(); for(IdxT j=0; jsize(); ++j) { - f_[component->getNodeConnection(j)] += component->getResidual()[j]; + //@todo should do a different grounding check + if (component->getNodeConnection(j) != -1) + { + f_[component->getNodeConnection(j)] += component->getResidual()[j]; + } + } } @@ -180,16 +231,27 @@ class PowerElectronicsModel : public ModelEvaluatorImpl for(const auto& component : components_) { component->evaluateJacobian(); - std::vector r; - std::vector c; - std::vector v; - std::tie(r, c, v) = component->getJacobian().getEntrieCopies(); + + //get references to local jacobain + std::tuple&, std::vector&, std::vector&> tpm = component->getJacobian().getEntries(); + const auto& [r, c, v] = tpm; + + //Create copies of data to handle groundings + std::vector rgr; + std::vector cgr; + std::vector vgr; for (IdxT i = 0; i < static_cast(r.size()); i++) { - r[i] = component->getNodeConnection(r[i]); - c[i] = component->getNodeConnection(c[i]); + if (component->getNodeConnection(r[i]) != -1 && component->getNodeConnection(c[i]) != -1) + { + rgr.push_back(component->getNodeConnection(r[i])); + cgr.push_back(component->getNodeConnection(c[i])); + vgr.push_back(v[i]); + } } - this->J_.AXPY(1.0, r, c, v); + + //AXPY to Global Jacobian + this->J_.AXPY(1.0, rgr, cgr, vgr); } return 0; @@ -248,6 +310,8 @@ class PowerElectronicsModel : public ModelEvaluatorImpl { component->updateTime(t, a); } + this->time_ = t; + this->alpha_ = a; } void addComponent(component_type* component) @@ -257,6 +321,7 @@ class PowerElectronicsModel : public ModelEvaluatorImpl private: std::vector components_; + bool usejac_; }; // class PowerElectronicsModel diff --git a/Solver/Dynamic/CMakeLists.txt b/Solver/Dynamic/CMakeLists.txt index 759829967..85c7ea920 100644 --- a/Solver/Dynamic/CMakeLists.txt +++ b/Solver/Dynamic/CMakeLists.txt @@ -66,6 +66,11 @@ gridkit_add_library(solvers_dyn LINK_LIBRARIES PUBLIC SUNDIALS::nvecserial PUBLIC SUNDIALS::idas + PUBLIC SUNDIALS::sunlinsolklu + PUBLIC suitesparseconfig + PUBLIC klu + PUBLIC amd + PUBLIC colamd OUTPUT_NAME gridkit_solvers_dyn) diff --git a/Solver/Dynamic/Ida.cpp b/Solver/Dynamic/Ida.cpp index c71a8fd07..5137119f1 100644 --- a/Solver/Dynamic/Ida.cpp +++ b/Solver/Dynamic/Ida.cpp @@ -61,10 +61,13 @@ #include #include -// #include #include /* access to IDADls interface */ #include +//Sundials Sparse KLU +#include +#include + #include "ModelEvaluator.hpp" #include "Ida.hpp" @@ -103,6 +106,9 @@ namespace Sundials yp_ = N_VClone(yy_); checkAllocation((void*) yp_, "N_VClone"); + //get intial conditions + this->getDefaultInitialCondition(); + // Create vectors to store restart initial condition yy0_ = N_VClone(yy_); checkAllocation((void*) yy0_, "N_VClone"); @@ -144,14 +150,7 @@ namespace Sundials } // Set up linear solver - JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); - checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); - - linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); - checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); - - retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); - checkOutput(retval, "IDASetLinearSolver"); + this->configureLinearSolver(); return retval; } @@ -160,16 +159,32 @@ namespace Sundials int Ida::configureLinearSolver() { int retval = 0; + if (model_->hasJacobian()) + { + JacobianMat_ = SUNSparseMatrix(model_->size(), model_->size(), model_->size() * model_->size(), CSR_MAT, context_); + checkAllocation((void*) JacobianMat_, "SUNSparseMatrix"); - // Set up linear solver - JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); - checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); + linearSolver_ = SUNLinSol_KLU(yy_, JacobianMat_, context_); + checkAllocation((void*) linearSolver_, "SUNLinSol_KLU"); - linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); - checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); + retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); + checkOutput(retval, "IDASetLinearSolver"); - retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); - checkOutput(retval, "IDASetLinearSolver"); + retval = IDASetJacFn(solver_, this->Jac); + checkOutput(retval, "IDASetJacFn"); + } + else + { + JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); + checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); + + linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); + checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); + + retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); + checkOutput(retval, "IDASetLinearSolver"); + + } return retval; } @@ -525,8 +540,49 @@ namespace Sundials return 0; } + template + int Ida::Jac(realtype t, realtype cj, N_Vector yy, N_Vector yp, N_Vector resvec, SUNMatrix J, void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) + { - template + ModelLib::ModelEvaluator* model = static_cast*>(user_data); + + + model->updateTime(t, cj); + copyVec(yy, model->y()); + copyVec(yp, model->yp()); + + model->evaluateJacobian(); + COO_Matrix Jac = model->getJacobian(); + + //Get reference to the jacobian entries + std::tuple&, std::vector&, std::vector&> tpm = Jac.getEntries(); + const auto [r, c, val] = tpm; + + //get the CSR row pointers from COO matrix + std::vector csrrowdata = Jac.getCSRRowData(); + + SUNMatZero(J); + + //Set row pointers + sunindextype *rowptrs = SUNSparseMatrix_IndexPointers(J); + for (unsigned int i = 0; i < csrrowdata.size() ; i++) + { + rowptrs[i] = csrrowdata[i]; + } + + sunindextype *colvals = SUNSparseMatrix_IndexValues(J); + realtype *data = SUNSparseMatrix_Data(J); + //Copy data from model jac to sundials + for (unsigned int i = 0; i < c.size(); i++ ) + { + colvals[i] = c[i]; + data[i] = val[i]; + } + + return 0; + } + + template int Ida::Integrand(realtype tt, N_Vector yy, N_Vector yp, N_Vector rhsQ, void *user_data) { ModelLib::ModelEvaluator* model = static_cast*>(user_data); diff --git a/Solver/Dynamic/Ida.hpp b/Solver/Dynamic/Ida.hpp index 3fa3368c9..a4cea9561 100644 --- a/Solver/Dynamic/Ida.hpp +++ b/Solver/Dynamic/Ida.hpp @@ -65,7 +65,7 @@ #include #include #include /* access to sparse SUNMatrix */ -// #include /* access to KLU linear solver */ +#include /* access to KLU linear solver */ #include /* access to dense linear solver */ #include "ModelEvaluator.hpp" @@ -165,6 +165,11 @@ namespace AnalysisManager static int Residual(realtype t, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data); + + static int Jac(realtype t, realtype cj, + N_Vector yy, N_Vector yp, N_Vector resvec, + SUNMatrix J, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); static int Integrand(realtype t, N_Vector yy, N_Vector yp, diff --git a/SparseMatrix/COO_Matrix.hpp b/SparseMatrix/COO_Matrix.hpp index 5b0ece80c..c256e015c 100644 --- a/SparseMatrix/COO_Matrix.hpp +++ b/SparseMatrix/COO_Matrix.hpp @@ -40,8 +40,10 @@ class COO_Matrix std::tuple, std::vector> getRowCopy(Intdx r); std::tuple&, std::vector&, std::vector&> getEntries(); std::tuple, std::vector, std::vector> getEntrieCopies(); + std::tuple, std::vector, std::vector> getEntrieCopiesSubMatrix(std::vector submap); std::tuple, std::vector, std::vector> getDataToCSR(); + std::vector getCSRRowData(); // BLAS. Will sort before running void setValues(std::vector r, std::vector c, std::vector v); @@ -61,15 +63,19 @@ class COO_Matrix //Resort values void sortSparse(); bool isSorted(); + Intdx nnz(); std::tuple getDimensions(); void printMatrix(); + + static void sortSparseCOO(std::vector &rows, std::vector &columns, std::vector &values); + private: Intdx indexStartRow(const std::vector &rows, Intdx r); Intdx sparseCordBinarySearch(const std::vector &rows, const std::vector &columns, Intdx ri, Intdx ci); - void sortSparseCOO(std::vector &rows, std::vector &columns, std::vector &values); + bool checkIncreaseSize(Intdx r, Intdx c); }; @@ -164,6 +170,35 @@ inline std::tuple, std::vector, std::vector> return {rowsizevec, this->column_indexes, this->values}; } +/** + * @brief Only creates the row data + * + * @todo swap this with having the matrix store the data and updates. This can then be passed by reference + * + * @todo fails, fix + * + * @tparam ScalarT + * @tparam Intdx + * @return std::vector + */ +template +inline std::vector COO_Matrix::getCSRRowData() +{ + if (!this->isSorted()) this->sortSparse(); + std::vector rowsizevec(this->rows_size + 1, 0); + Intdx counter = 0; + for (Intdx i = 0; i < static_cast(rowsizevec.size() - 1); i++) + { + rowsizevec[i + 1] = rowsizevec[i]; + while (counter < static_cast(this->row_indexes.size()) && i == this->row_indexes[counter]) + { + rowsizevec[i+1]++; + counter++; + } + } + return rowsizevec; +} + /** * @brief Given set of vector data it will set the values into the matrix * @@ -191,6 +226,7 @@ inline void COO_Matrix::setValues(std::vector r, std::vec this->row_indexes.push_back(r[aiter]); this->column_indexes.push_back(c[aiter]); this->values.push_back(v[aiter]); + this->checkIncreaseSize(r[aiter], c[aiter]); aiter++; } if (aiter >= static_cast(r.size())) break; @@ -208,6 +244,8 @@ inline void COO_Matrix::setValues(std::vector r, std::vec this->row_indexes.push_back(r[i]); this->column_indexes.push_back(c[i]); this->values.push_back(v[i]); + + this->checkIncreaseSize(r[i], c[i]); } this->sorted = false; @@ -256,6 +294,8 @@ inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrixcolumn_indexes.push_back(c[aiter]); this->values.push_back(alpha * val[aiter]); aiter++; + + this->checkIncreaseSize(r[aiter], c[aiter]); } if (aiter >= static_cast(r.size())) break; @@ -272,6 +312,8 @@ inline void COO_Matrix::AXPY(ScalarT alpha, COO_Matrixrow_indexes.push_back(r[i]); this->column_indexes.push_back(c[i]); this->values.push_back(alpha * val[i]); + + this->checkIncreaseSize(r[i], c[i]); } this->sorted = false; @@ -310,6 +352,8 @@ inline void COO_Matrix::AXPY(ScalarT alpha, std::vector r this->row_indexes.push_back(r[aiter]); this->column_indexes.push_back(c[aiter]); this->values.push_back(alpha * v[aiter]); + + this->checkIncreaseSize(r[aiter], c[aiter]); aiter++; } if (aiter >= static_cast(r.size())) break; @@ -327,6 +371,8 @@ inline void COO_Matrix::AXPY(ScalarT alpha, std::vector r this->row_indexes.push_back(r[i]); this->column_indexes.push_back(c[i]); this->values.push_back(alpha * v[i]); + + this->checkIncreaseSize(r[i], c[i]); } this->sorted = false; @@ -452,6 +498,12 @@ inline bool COO_Matrix::isSorted() return this->sorted; } +template +inline Intdx COO_Matrix::nnz() +{ + return static_cast(this->values.size); +} + template inline std::tuple COO_Matrix::getDimensions() { @@ -574,10 +626,28 @@ inline Intdx COO_Matrix::sparseCordBinarySearch(const std::vecto return m; } +template +inline bool COO_Matrix::checkIncreaseSize(Intdx r, Intdx c) +{ + bool changed = false; + if (r + 1 > this->rows_size) + { + this->rows_size = r + 1; + changed = true; + } + if (c + 1 > this->columns_size) + { + this->columns_size = c + 1; + changed = true; + } + + return changed; +} + /** * @brief Sort a disoreded set of values. Assume nothing on order. * - * @todo simple setup. Should add better sorting since list are pre-sorted + * @todo simple setup. Should add stable sorting since list are pre-sorted * * @tparam ScalarT * @tparam Intdx diff --git a/SystemModel.hpp b/SystemModel.hpp index 34c7ff120..77bbdd20b 100644 --- a/SystemModel.hpp +++ b/SystemModel.hpp @@ -183,6 +183,17 @@ class SystemModel : public ModelEvaluatorImpl return 0; } + /** + * @brief Assume that jacobian is not avalible + * + * @return true + * @return false + */ + bool hasJacobian() + { + return false; + } + /** * @brief Initialize buses first, then all the other components. * From 86e23a01e3aa8638a9b435efe22a560e05598042 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Tue, 30 Jan 2024 16:19:33 -0500 Subject: [PATCH 43/52] Added the Transmission Line Component --- .../PowerElectronicsComponents/CMakeLists.txt | 3 +- .../TransmissionLine/CMakeLists.txt | 8 + .../TransmissionLine/TransmissionLine.cpp | 201 ++++++++++++++++++ .../TransmissionLine/TransmissionLine.hpp | 71 +++++++ Examples/RLCircuit/RLCircuit.cpp | 1 - 5 files changed, 282 insertions(+), 2 deletions(-) create mode 100644 ComponentLib/PowerElectronicsComponents/TransmissionLine/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.hpp diff --git a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt index 9d6ad8be1..8b96aaa66 100644 --- a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt +++ b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt @@ -7,4 +7,5 @@ add_subdirectory(Inductor) add_subdirectory(LinearTransformer) add_subdirectory(InductionMotor) add_subdirectory(SynchronousMachine) -add_subdirectory(DiscreteGenerator) \ No newline at end of file +add_subdirectory(DiscreteGenerator) +add_subdirectory(TransmissionLine) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/TransmissionLine/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/TransmissionLine/CMakeLists.txt new file mode 100644 index 000000000..6e2cea4f4 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/TransmissionLine/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_tranline + SOURCES + TransmissionLine.cpp + OUTPUT_NAME + gridkit_powerelec_tranline) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.cpp b/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.cpp new file mode 100644 index 000000000..62965c68e --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.cpp @@ -0,0 +1,201 @@ + +#include +#include +#include +#include "TransmissionLine.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant TransmissionLine model + * + * Calls default ModelEvaluatorImpl constructor. + * + * This is the Medium distance form with the use of the admittance matrix. + * Since the line is of medium length then there is no real part for shunt admittance + */ + +template +TransmissionLine::TransmissionLine(IdxT id, ScalarT R,ScalarT X, ScalarT B) + : R_(R), X_(X), B_(B) +{ + // internals [Iret1, Iimt1, Iret2, Iimt2] + // externals [Vre11, Vim11, Vre12, Vim12, Vre21, Vim21, Vre22, Vim22] + this->size_ = 12; + this->n_intern = 4; + this->n_extern = 8; + this->extern_indices = {0,1,2,3,4,5,6,7}; + this->idc_ = id; + + ScalarT magImpendence = 1 / (R_*R_ + X_*X_); + YReMat_ = magImpendence * R_; + YImMatOff_ = magImpendence * X_; + YImMatDi_ = B_ / (2.0) - YImMatOff_; +} + +template +TransmissionLine::~TransmissionLine() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int TransmissionLine::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + + return 0; +} + +/** + * Initialization of the grid model + */ +template +int TransmissionLine::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int TransmissionLine::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Evaluate residual of transmission line + * + * The complex admittance matrix is: + * [[ Y/2 + 1/Z, -1/Z]; + * [ -1/Z, Y/2 + 1/Z]] = + * [[R/|Z|, -R/|Z|]; + * [-R/|Z|, R/|Z|]] + + * i [[B/2 - X/|Z|, X/|Z|]; + * [X/|Z|, B/2 - X/|Z|]] + * = Dre + i Dim + * + * Then + * Ire = Dre Vre - Dim Vim + * Iim = Dre Vim + Dim Vre + * + * To express this for Modified Nodal Analysis the Voltages of the admittance matrix are put into voltage drops + */ +template +int TransmissionLine::evaluateResidual() +{ + //input + this->f_[0] = y_[8] ; + this->f_[1] = y_[9] ; + + this->f_[2] = y_[10] ; + this->f_[3] = y_[11] ; + //ouput + this->f_[4] = -y_[8] ; + this->f_[5] = -y_[9] ; + + this->f_[6] = -y_[10] ; + this->f_[7] = -y_[11] ; + + //Voltage drop accross terminals + ScalarT V1re = y_[0] - y_[4]; + ScalarT V1im = y_[1] - y_[5]; + ScalarT V2re = y_[2] - y_[6]; + ScalarT V2im = y_[3] - y_[7]; + + //Internal variables + //row 1 + this->f_[8] = YReMat_ * (V1re - V2re) - (YImMatDi_ * V1im + YImMatOff_ * V2im) - y_[8] ; + this->f_[9] = YReMat_ * (V1im - V2im) + (YImMatDi_ * V1re + YImMatOff_ * V2re) - y_[9] ; + + //row2 + this->f_[10] = YReMat_ * (V2re - V1re) - (YImMatOff_ * V1im + YImMatDi_ * V2im) - y_[10]; + this->f_[11] = YReMat_ * (V2im - V1im) + (YImMatOff_ * V1re + YImMatDi_ * V2re) - y_[11]; + + + return 0; +} + +/** + * @brief Generate Jacobian for Transmission Line + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ +template +int TransmissionLine::evaluateJacobian() +{ + + //Create dF/dy + std::vector rtemp{0,1,2,3,4,5,6,7,8,9,10,11}; + std::vector ctemp{8,9,10,11,8,9,10,11,8,9,10,11}; + std::vector vals{1.0,1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::vector ccord{0,1,2,3,4,5,6,7}; + + std::vector rcord(ccord.size(),8); + vals = {YReMat_, -YImMatDi_ ,-YReMat_, -YImMatOff_,-YReMat_, YImMatDi_ ,YReMat_, YImMatOff_}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::fill(rcord.begin(), rcord.end(), 9); + vals = {YImMatDi_ ,YReMat_, YImMatOff_, -YReMat_,-YImMatDi_ ,-YReMat_, -YImMatOff_, YReMat_}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::fill(rcord.begin(), rcord.end(), 10); + vals = {-YReMat_, -YImMatDi_ ,YReMat_, -YImMatOff_,YReMat_, YImMatDi_ ,-YReMat_, YImMatOff_}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::fill(rcord.begin(), rcord.end(), 11); + vals = {YImMatDi_ ,-YReMat_, YImMatOff_, YReMat_,-YImMatDi_ ,YReMat_, -YImMatOff_, -YReMat_}; + this->J_.setValues(rtemp, ctemp, vals); + + return 0; +} + +template +int TransmissionLine::evaluateIntegrand() +{ + return 0; +} + +template +int TransmissionLine::initializeAdjoint() +{ + return 0; +} + +template +int TransmissionLine::evaluateAdjointResidual() +{ + return 0; +} + +template +int TransmissionLine::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class TransmissionLine; +template class TransmissionLine; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.hpp b/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.hpp new file mode 100644 index 000000000..0f729d449 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/TransmissionLine/TransmissionLine.hpp @@ -0,0 +1,71 @@ + + +#ifndef _TRANLINE_HPP_ +#define _TRANLINE_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive TransmissionLine class. + * + */ + template + class TransmissionLine : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::J_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + TransmissionLine(IdxT id, ScalarT R, ScalarT X, ScalarT B); + virtual ~TransmissionLine(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT R_; + ScalarT X_; + ScalarT B_; + ScalarT YReMat_; + ScalarT YImMatDi_; + ScalarT YImMatOff_; + }; +} + +#endif diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index c71eef06d..e902b1242 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -89,7 +89,6 @@ int main(int argc, char const *argv[]) sysmodel->yp()[2] = -vinit / linit; // i'_s sysmodel->yp()[3] = -vinit / linit; // i'_L - sysmodel->initialize(); sysmodel->evaluateResidual(); From 5b8993616e500bc329ffcc542c0b935079da46c8 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 19 Feb 2024 13:31:19 -0500 Subject: [PATCH 44/52] Added Microgrid Example - Added MicrogridBusDQ - Added MicrogridLine - Added MicrogridLoad - Updated DiscreteGenerator - Added Output Testing for DG - Added Microgrid Assmebly Example - Updated Capacitor, Inductor, and Voltage residuals - Updated RLCircuit Example --- .../PowerElectronicsComponents/CMakeLists.txt | 5 +- .../Capacitor/Capacitor.cpp | 13 +- .../DiscreteGenerator/DiscreteGenerator.cpp | 211 ++++++---- .../DiscreteGenerator/DiscreteGenerator.hpp | 5 +- .../Inductor/Inductor.cpp | 10 +- .../MicrogridBusDQ/CMakeLists.txt | 8 + .../MicrogridBusDQ/MicrogridBusDQ.cpp | 132 +++++++ .../MicrogridBusDQ/MicrogridBusDQ.hpp | 66 ++++ .../MicrogridLine/CMakeLists.txt | 8 + .../MicrogridLine/MicrogridLine.cpp | 172 +++++++++ .../MicrogridLine/MicrogridLine.hpp | 67 ++++ .../MicrogridLoad/CMakeLists.txt | 8 + .../MicrogridLoad/MicrogridLoad.cpp | 169 ++++++++ .../MicrogridLoad/MicrogridLoad.hpp | 67 ++++ .../VoltageSource/VoltageSource.cpp | 8 +- Examples/CMakeLists.txt | 1 + Examples/DiscreteGeneratorTest/CMakeLists.txt | 5 +- Examples/DiscreteGeneratorTest/DGTest.cpp | 30 +- Examples/Microgrid/CMakeLists.txt | 13 + Examples/Microgrid/Microgrid.cpp | 361 ++++++++++++++++++ Examples/RLCircuit/RLCircuit.cpp | 8 +- SparseMatrix/COO_Matrix.hpp | 9 + 22 files changed, 1279 insertions(+), 97 deletions(-) create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLine/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.hpp create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLoad/CMakeLists.txt create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.cpp create mode 100644 ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.hpp create mode 100644 Examples/Microgrid/CMakeLists.txt create mode 100644 Examples/Microgrid/Microgrid.cpp diff --git a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt index 8b96aaa66..3fba4be7f 100644 --- a/ComponentLib/PowerElectronicsComponents/CMakeLists.txt +++ b/ComponentLib/PowerElectronicsComponents/CMakeLists.txt @@ -8,4 +8,7 @@ add_subdirectory(LinearTransformer) add_subdirectory(InductionMotor) add_subdirectory(SynchronousMachine) add_subdirectory(DiscreteGenerator) -add_subdirectory(TransmissionLine) \ No newline at end of file +add_subdirectory(TransmissionLine) +add_subdirectory(MicrogridLoad) +add_subdirectory(MicrogridLine) +add_subdirectory(MicrogridBusDQ) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp index 79faefe89..b6287b359 100644 --- a/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Capacitor/Capacitor.cpp @@ -69,15 +69,20 @@ int Capacitor::tagDifferentiable() template int Capacitor::evaluateResidual() { - this->f_[0] = this->yp_[2]; - this->f_[1] = -this->yp_[2]; - this->f_[2] = -this->C_ * this->yp_[2] + this->y_[0] - this->y_[1] - this->y_[2]; + //input + this->f_[0] = C_ * this->yp_[2]; + //output + this->f_[1] = -C_ * this->yp_[2]; + + //internal + this->f_[2] = -C_ * this->yp_[2] + this->y_[0] - this->y_[1] - this->y_[2]; return 0; } template int Capacitor::evaluateJacobian() { + this->J_.zeroMatrix(); //Create dF/dy std::vector rcord{2,2,2}; std::vector ccord{0,1,2}; @@ -87,7 +92,7 @@ int Capacitor::evaluateJacobian() //Create -dF/dy' std::vector rcordder{0,1,2}; std::vector ccordder{2,2,2}; - std::vector valsder{1.0, -1.0, -this->C_}; + std::vector valsder{C_, -C_, -this->C_}; COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); //Perform dF/dy + \alpha dF/dy' diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp index c66c5b0f9..607ec5312 100644 --- a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp @@ -17,11 +17,11 @@ namespace ModelLib { */ template -DiscreteGenerator::DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm) - : wb_(parm.wb), wc_(parm.wc), mp_(parm.mp), refmp_(parm.refmp), Vn_(parm.Vn), nq_(parm.nq), F_(parm.F), Kiv_(parm.Kiv), Kpv_(parm.Kpv), Kic_(parm.Kic), Kpc_(parm.Kpc), Cf_(parm.Cf), rLf_(parm.rLf), Lf_(parm.Lf), rLc_(parm.rLc), Lc_(parm.Lc) +DiscreteGenerator::DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm, bool reference_frame) + : wb_(parm.wb), wc_(parm.wc), mp_(parm.mp), Vn_(parm.Vn), nq_(parm.nq), F_(parm.F), Kiv_(parm.Kiv), Kpv_(parm.Kpv), Kic_(parm.Kic), Kpc_(parm.Kpc), Cf_(parm.Cf), rLf_(parm.rLf), Lf_(parm.Lf), rLc_(parm.rLc), Lc_(parm.Lc), refframe_(reference_frame) { - // internals [delta_i, Pi, Qi, phi_di, phi_qi, gamma_di, gamma_qi, il_di, il_qi, vo_di, vo_qi, io_di, io_qi] - // externals [Pref, Pbus, QBus] + // internals [\delta_i, Pi, Qi, phi_di, phi_qi, gamma_di, gamma_qi, il_di, il_qi, vo_di, vo_qi, io_di, io_qi] + // externals [\omega_ref, vba_out, vbb_out] this->size_ = 16; this->n_intern = 13; this->n_extern = 3; @@ -74,42 +74,64 @@ template int DiscreteGenerator::evaluateResidual() { // ### Externals Componenets ### - //Reference P - ScalarT wcom = this->wb_ - this->refmp_ * this->y_[0]; - this->f_[0] = 0; - this->f_[1] = 0; - this->f_[2] = 0; + ScalarT omega = wb_ - mp_ * y_[4]; + //ref common ref motor angle + if (refframe_) + { + f_[0] = omega - y_[0]; + } + else + { + f_[0] = 0.0; + } + + + //output + //current transformed to common frame + f_[1] = cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15]; + f_[2] = sin(y_[3]) * y_[14] + cos(y_[3]) * y_[15]; - // ### Internal Componenets ## - f_[3] = -yp_[3] + wb_ - mp_ * y_[4] - wcom; + //Take incoming voltages to current rotator reference frame + ScalarT vbd_in = cos(y_[3]) * y_[1] + sin(y_[3]) * y_[2]; + ScalarT vbq_in = -sin(y_[3]) * y_[1] + cos(y_[3]) * y_[2]; + // ### Internal Componenets ## + // Rotator difference angle + f_[3] = -yp_[3] + omega - y_[0]; + + // P and Q equations f_[4] = -yp_[4] + wc_ * (y_[12] * y_[14] + y_[13] * y_[15] - y_[4]); - f_[5] = -yp_[4] + wc_ * (-y_[12] * y_[15] + y_[13] * y_[14] - y_[5]); + f_[5] = -yp_[5] + wc_ * (-y_[12] * y_[15] + y_[13] * y_[14] - y_[5]); + //Voltage control ScalarT vod_star = Vn_ - nq_ * y_[5]; - ScalarT voq_star = 0; + ScalarT voq_star = 0.0; f_[6] = -yp_[6] + vod_star - y_[12]; f_[7] = -yp_[7] + voq_star - y_[13]; - ScalarT ild_star = F_ * y_[14] - wb_ * Cf_ * y_[13] + Kpv_ * (vod_star - y_[12]) + Kiv_ * y_[6] ; + + ScalarT ild_star = F_ * y_[14] - wb_ * Cf_ * y_[13] + Kpv_ * (vod_star - y_[12]) + Kiv_ * y_[6]; ScalarT ilq_star = F_ * y_[15] + wb_ * Cf_ * y_[12] + Kpv_ * (voq_star - y_[13]) + Kiv_ * y_[7]; + //Current control f_[8] = -yp_[8] + ild_star - y_[10]; f_[9] = -yp_[9] + ilq_star - y_[11]; ScalarT vid_star = -wb_ * Lf_ * y_[11] + Kpc_ * (ild_star - y_[10]) + Kic_ * y_[8]; ScalarT viq_star = wb_ * Lf_ * y_[10] + Kpc_ * (ilq_star - y_[11]) + Kic_ * y_[9]; - f_[10] = -yp_[10] - (rLf_ / Lf_) * y_[10] + wcom * y_[11] + (1/Lf_) * (vid_star - y_[12]); - f_[11] = -yp_[11] - (rLf_ / Lf_) * y_[11] - wcom * y_[10] + (1/Lf_) * (viq_star - y_[13]); + //Output LC Filter + f_[10] = -yp_[10] - (rLf_ / Lf_) * y_[10] + omega * y_[11] + (vid_star - y_[12]) / Lf_; + f_[11] = -yp_[11] - (rLf_ / Lf_) * y_[11] - omega * y_[10] + (viq_star - y_[13]) / Lf_; - f_[12] = -yp_[12] + wcom * y_[13] + (1/Cf_) * (y_[10] - y_[14]); - f_[13] = -yp_[13] - wcom * y_[12] + (1/Cf_) * (y_[11] - y_[15]); + f_[12] = -yp_[12] + omega * y_[13] + (y_[10] - y_[14]) / Cf_; + f_[13] = -yp_[13] - omega * y_[12] + (y_[11] - y_[15]) / Cf_; - f_[14] = -yp_[14] - (rLc_ / Lc_) * y_[14] + wcom * y_[15] + (1/Lc_)*(y_[12] - y_[1]); - f_[15] = -yp_[15] - (rLc_ / Lc_) * y_[15] - wcom * y_[14] + (1/Lc_)*(y_[13] - y_[2]); + //Output Connector + f_[14] = -yp_[14] - (rLc_ / Lc_) * y_[14] + omega * y_[15] + (y_[12] - vbd_in) / Lc_; + f_[15] = -yp_[15] - (rLc_ / Lc_) * y_[15] - omega * y_[14] + (y_[13] - vbq_in) / Lc_; return 0; } @@ -117,24 +139,24 @@ int DiscreteGenerator::evaluateResidual() * @brief Compute the jacobian of the DiscreteGenerator for iteration. dF/dy - \alpha dF/dy' * * The matrix dF/dy should be - * [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -[ mpref, 0, 0, 0, -mp, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -[ 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, 0, wc*x15, wc*x16, wc*x13, wc*x14] -[ 0, 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, -wc*x16, wc*x15, wc*x14, -wc*x13] -[ 0, 0, 0, 0, 0, -nq, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0] -[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0] -[ 0, 0, 0, 0, 0, -Kpv*nq, Kiv, 0, 0, 0, -1, 0, -Kpv, -Cf*wb, F, 0] -[ 0, 0, 0, 0, 0, 0, 0, Kiv, 0, 0, 0, -1, Cf*wb, -Kpv, 0, F] -[-mpref*x12, 0, 0, 0, 0, -(Kpc*Kpv*nq)/Lf, (Kiv*Kpc)/Lf, 0, Kic/Lf, 0, - Kpc/Lf - rLf/Lf, -mpref*x1, -(Kpc*Kpv + 1)/Lf, -(Cf*Kpc*wb)/Lf, (F*Kpc)/Lf, 0] -[ mpref*x11, 0, 0, 0, 0, 0, 0, (Kiv*Kpc)/Lf, 0, Kic/Lf, mpref*x1, - Kpc/Lf - rLf/Lf, (Cf*Kpc*wb)/Lf, -(Kpc*Kpv + 1)/Lf, 0, (F*Kpc)/Lf] -[-mpref*x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Cf, 0, 0, wb - mpref*x1, -1/Cf, 0] -[ mpref*x13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Cf, mpref*x1 - wb, 0, 0, -1/Cf] -[-mpref*x16, -1/Lc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, 0, -rLc/Lc, wb - mpref*x1] -[ mpref*x15, 0, -1/Lc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, mpref*x1 - wb, -rLc/Lc] + * +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[-1, 0, 0, 0, -mp, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +[ 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, 0, wc*x15, wc*x16, wc*x13, wc*x14] +[ 0, 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, -wc*x16, wc*x15, wc*x14, -wc*x13] +[ 0, 0, 0, 0, 0, -nq, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0] +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0] +[ 0, 0, 0, 0, 0, -Kpv*nq, Kiv, 0, 0, 0, -1, 0, -Kpv, -Cf*wb, F, 0] +[ 0, 0, 0, 0, 0, 0, 0, Kiv, 0, 0, 0, -1, Cf*wb, -Kpv, 0, F] +[ 0, 0, 0, 0, -mp*x12, -(Kpc*Kpv*nq)/Lf, (Kiv*Kpc)/Lf, 0, Kic/Lf, 0, - Kpc/Lf - rLf/Lf, -mp*x5, -(Kpc*Kpv + 1)/Lf, -(Cf*Kpc*wb)/Lf, (F*Kpc)/Lf, 0] +[ 0, 0, 0, 0, mp*x11, 0, 0, (Kiv*Kpc)/Lf, 0, Kic/Lf, mp*x5, - Kpc/Lf - rLf/Lf, (Cf*Kpc*wb)/Lf, -(Kpc*Kpv + 1)/Lf, 0, (F*Kpc)/Lf] +[ 0, 0, 0, 0, -mp*x14, 0, 0, 0, 0, 0, 1/Cf, 0, 0, wb - mp*x5, -1/Cf, 0] +[ 0, 0, 0, 0, mp*x13, 0, 0, 0, 0, 0, 0, 1/Cf, mp*x5 - wb, 0, 0, -1/Cf] +[ 0, -cos(x4)/Lc, -sin(x4)/Lc, -(x3*cos(x4) - x2*sin(x4))/Lc, -mp*x16, 0, 0, 0, 0, 0, 0, 0, 1/Lc, 0, -rLc/Lc, wb - mp*x5] +[ 0, sin(x4)/Lc, -cos(x4)/Lc, (x2*cos(x4) + x3*sin(x4))/Lc, mp*x15, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, mp*x5 - wb, -rLc/Lc] * 'Generated from MATLAB symbolic' - * Jacobian is mostly constant besides reference and rows 4 & 5 * * @tparam ScalarT * @tparam IdxT @@ -145,99 +167,146 @@ int DiscreteGenerator::evaluateJacobian() { //Create dF/dy' std::vector rcordder(13); - std::vector valsder(13,1.0); + std::vector valsder(13, -1.0); for (int i = 0; i < 13; i++) { rcordder[i] = i + 3; } COO_Matrix Jacder = COO_Matrix(rcordder, rcordder, valsder,16,16); + std::vector ctemp{}; + std::vector rtemp{}; + std::vector valtemp{}; + + + //Create dF/dy + //r = 1 + + ctemp = {3, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(1); + valtemp = { - sin(y_[3]) * y_[14] - cos(y_[3]) * y_[15], cos(y_[3]),sin(y_[3])}; + this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 2 + + ctemp = {3, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(2); + valtemp = { - cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15], -sin(y_[3]),cos(y_[3])}; + this->J_.setValues(rtemp, ctemp, valtemp); + //r = 3 - std::vector ctemp{0, 4}; - std::vector rtemp(ctemp.size(),3); - std::vector valtemp{this->refmp_, -this->mp_}; + + ctemp = {0, 4}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(3); + valtemp = {-1.0, -mp_}; this->J_.setValues(rtemp, ctemp, valtemp); + + //r = 0 + if (refframe_) + { + ctemp = {0, 4}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(0); + valtemp = {-1.0, -mp_}; + this->J_.setValues(rtemp, ctemp, valtemp); + } + //r = 4 ctemp = {4, 12, 13, 14, 15}; - std::fill(rtemp.begin(), rtemp.end(), 4); - valtemp = {-this->wc_, this->wc_*y_[14], this->wc_*y_[15], this->wc_*y_[12], this->wc_*y_[13]}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(4); + valtemp = {-wc_, wc_*y_[14], wc_*y_[15], wc_*y_[12], wc_*y_[13]}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 5 ctemp = {5, 12, 13, 14, 15}; - std::fill(rtemp.begin(), rtemp.end(), 5); - valtemp = {-this->wc_, -this->wc_*y_[15], this->wc_*y_[14], this->wc_*y_[13], -this->wc_*y_[12]}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(5); + valtemp = {-wc_, -wc_*y_[15], wc_*y_[14], wc_*y_[13], -wc_*y_[12]}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 6 ctemp = {5, 12}; - std::fill(rtemp.begin(), rtemp.end(), 6); - valtemp = {-this->nq_, -1.0}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(6); + valtemp = {-nq_, -1.0}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 7 ctemp = {13}; - std::fill(rtemp.begin(), rtemp.end(), 7); + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(7); valtemp = {-1.0}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 8 ctemp = {5,6,10,12,13,14}; - std::fill(rtemp.begin(), rtemp.end(), 8); - valtemp = {-this->Kpv_*this->nq_, this->Kiv_, -1.0, -this->Kpv_, -this->Cf_*this->wb_, this->F_}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(8); + valtemp = {-Kpv_*nq_, Kiv_, -1.0, -Kpv_, -Cf_*wb_, F_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 9 ctemp = {7, 11, 12, 13, 15}; - std::fill(rtemp.begin(), rtemp.end(), 9); - valtemp = {this->Kiv_, -1.0, this->Cf_*this->wb_,-this->Kpv_,this->F_}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(9); + valtemp = {Kiv_, -1.0, Cf_*wb_,-Kpv_,F_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 10 - ctemp = {0, 5, 6, 8, 10, 11, 12, 13, 14}; - std::fill(rtemp.begin(), rtemp.end(), 10); - valtemp = {-this->refmp_ * y_[11], -(this->Kpc_ * this->Kpv_ * this->nq_) / this->Lf_, (this->Kpc_ * this->Kiv_) / this->Lf_, this->Kic_ / this->Lf_, -(this->Kpc_ + this->rLf_) / this->Lf_, -this->refmp_ * y_[0], -(this->Kpc_ * this->Kpv_ + 1.0) / this->Lf_, -(this->Cf_ * this->Kpc_ * this->wb_) / this->Lf_, (this->F_ * this->Kpc_) / this->Lf_}; + ctemp = {4, 5, 6, 8, 10, 11, 12, 13, 14}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(10); + valtemp = {-mp_ * y_[11], -(Kpc_ * Kpv_ * nq_) / Lf_, (Kpc_ * Kiv_) / Lf_, Kic_ / Lf_, -(Kpc_ + rLf_) / Lf_, -mp_ * y_[4], -(Kpc_ * Kpv_ + 1.0) / Lf_, -(Cf_ * Kpc_ * wb_) / Lf_, (F_ * Kpc_) / Lf_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 11 - ctemp = {0, 7, 9, 10, 11, 12, 13, 15}; - std::fill(rtemp.begin(), rtemp.end(), 11); - valtemp = {this->refmp_ * y_[10], (this->Kiv_ * this->Kpc_) / this->Lf_, this->Kic_ / this->Lf_, this->refmp_ * y_[0], -(this->Kpc_ + this->rLf_) / this->Lf_, (this->Cf_ * this->Kpc_ * this->wb_) / this->Lf_, -(this->Kpc_ * this->Kpv_ + 1.0) / this->Lf_, (this->F_ * this->Kpc_) / this->Lf_}; + ctemp = {4, 7, 9, 10, 11, 12, 13, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(11); + valtemp = {mp_ * y_[10], (Kiv_ * Kpc_) / Lf_, Kic_ / Lf_, mp_ * y_[4], -(Kpc_ + rLf_) / Lf_, (Cf_ * Kpc_ * wb_) / Lf_, -(Kpc_ * Kpv_ + 1.0) / Lf_, (F_ * Kpc_) / Lf_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 12 - ctemp = {0, 10, 13, 14}; - std::fill(rtemp.begin(), rtemp.end(), 12); - valtemp = {-this->refmp_ * y_[13], 1.0 / this->Cf_, this->wb_ - this->refmp_ * y_[0], -1.0 / this->Cf_}; + ctemp = {4, 10, 13, 14}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(12); + valtemp = {-mp_ * y_[13], 1.0 / Cf_, wb_ - mp_ * y_[4], -1.0 / Cf_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 13 - ctemp = {0, 11, 12, 15}; - std::fill(rtemp.begin(), rtemp.end(), 13); - valtemp = {this->refmp_ * y_[12], 1.0 / this->Cf_, -this->wb_ + this->refmp_ * y_[0], -1.0 / this->Cf_}; + ctemp = {4, 11, 12, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(13); + valtemp = {mp_ * y_[12], 1.0 / Cf_, -wb_ + mp_ * y_[4], -1.0 / Cf_}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 14 - ctemp = {0, 1, 12, 14, 15}; - std::fill(rtemp.begin(), rtemp.end(), 14); - valtemp = {-this->refmp_ * y_[15], -1.0 / this->Lc_, 1.0 / this->Lc_, -this->rLc_ / this->Lc_, this->wb_ - this->refmp_ * y_[0]}; + ctemp = {1, 2, 3, 4, 12, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(14); + valtemp = {(1.0/Lc_) * -cos(y_[3]) , (1.0/Lc_) * -sin(y_[3]) , (1.0/Lc_) * (sin(y_[3]) * y_[1] - cos(y_[3]) * y_[2]), -mp_ * y_[15], 1.0 / Lc_, -rLc_ / Lc_, wb_ - mp_ * y_[4]}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 15 - ctemp = {0, 2, 13, 14, 15}; - std::fill(rtemp.begin(), rtemp.end(), 15); - valtemp = {-this->refmp_ * y_[14], -1.0 / this->Lc_, 1.0 / this->Lc_, -this->wb_ + this->refmp_ * y_[0], -this->rLc_ / this->Lc_}; + ctemp = {1, 2, 3, 4, 13, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(15); + valtemp = {(1.0/Lc_) * sin(y_[3]) , (1.0/Lc_) * -cos(y_[3]), (1.0/Lc_) * (cos(y_[3]) * y_[1] + sin(y_[3]) * y_[2]), mp_ * y_[14], 1.0 / Lc_, -wb_ + mp_ * y_[4], -rLc_ / Lc_}; this->J_.setValues(rtemp, ctemp, valtemp); //Perform dF/dy + \alpha dF/dy' - this->J_.AXPY(-this->alpha_, Jacder); + this->J_.AXPY(this->alpha_, Jacder); return 0; } diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp index f5ce86899..bca984460 100644 --- a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.hpp @@ -18,7 +18,6 @@ namespace ModelLib ScalarT wb; ScalarT wc; ScalarT mp; - ScalarT refmp; ScalarT Vn; ScalarT nq; ScalarT F; @@ -63,7 +62,7 @@ namespace ModelLib public: - DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm); + DiscreteGenerator(IdxT id, DiscreteGeneratorParameters parm, bool reference_frame); virtual ~DiscreteGenerator(); int allocate(); @@ -81,7 +80,6 @@ namespace ModelLib ScalarT wb_; ScalarT wc_; ScalarT mp_; - ScalarT refmp_; ScalarT Vn_; ScalarT nq_; ScalarT F_; @@ -94,6 +92,7 @@ namespace ModelLib ScalarT Lf_; ScalarT rLc_; ScalarT Lc_; + bool refframe_; }; } diff --git a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp index a24b7a8e9..885153d41 100644 --- a/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp +++ b/ComponentLib/PowerElectronicsComponents/Inductor/Inductor.cpp @@ -71,11 +71,11 @@ template int Inductor::evaluateResidual() { //input - this->f_[0] = this->y_[2]; + this->f_[0] = -this->y_[2]; //output - this->f_[1] = -this->y_[2]; + this->f_[1] = this->y_[2]; //internal - this->f_[2] = this->L_ * this->yp_[2] + this->y_[0] - this->y_[1] ; + this->f_[2] = -this->L_ * this->yp_[2] + this->y_[1] - this->y_[0] ; return 0; } @@ -87,13 +87,13 @@ int Inductor::evaluateJacobian() //Create dF/dy std::vector rcord{0,1,2,2}; std::vector ccord{2,2,0,1}; - std::vector vals{1.0, -1.0, 1.0, -1.0}; + std::vector vals{-1.0, 1.0, -1.0, 1.0}; this->J_.setValues(rcord, ccord, vals); //Create dF/dy' std::vector rcordder{2}; std::vector ccordder{2}; - std::vector valsder{this->L_}; + std::vector valsder{-this->L_}; COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,3,3); //Perform dF/dy + \alpha dF/dy' diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/CMakeLists.txt new file mode 100644 index 000000000..1bfb8dc3d --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_mircobusdq + SOURCES + MicrogridBusDQ.cpp + OUTPUT_NAME + gridkit_powerelec_mircobusdq) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.cpp b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.cpp new file mode 100644 index 000000000..206108221 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.cpp @@ -0,0 +1,132 @@ + +#include +#include +#include +#include "MicrogridBusDQ.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant MicrogridBusDQ model + * + * Calls default ModelEvaluatorImpl constructor. + * + * Each microgrid line has a virtual resistance RN + */ + +template +MicrogridBusDQ::MicrogridBusDQ(IdxT id, ScalarT RN) + : RN_(RN) +{ + // externals [vbus_d, vbus_q] + this->size_ = 2; + this->n_intern = 0; + this->n_extern = 2; + this->extern_indices = {0,1}; + this->idc_ = id; +} + +template +MicrogridBusDQ::~MicrogridBusDQ() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int MicrogridBusDQ::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + + return 0; +} + +/** + * Initialization of the grid model + */ +template +int MicrogridBusDQ::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int MicrogridBusDQ::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Evaluate residual of microgrid line + * This model has "Virtual resistors" on both ends with parameters RN1 and RN2 + * + */ +template +int MicrogridBusDQ::evaluateResidual() +{ + //bus voltage + f_[0] = -y_[0] / RN_; + f_[1] = -y_[1] / RN_; + + return 0; +} + +/** + * @brief Generate Jacobian for Transmission Line + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ +template +int MicrogridBusDQ::evaluateJacobian() +{ + this->J_.zeroMatrix(); + + //Create dF/dy + std::vector rtemp{0,1}; + std::vector ctemp{0,1}; + std::vector vals{-1.0 / RN_,-1.0 / RN_}; + this->J_.setValues(rtemp, ctemp, vals); + + return 0; +} + +template +int MicrogridBusDQ::evaluateIntegrand() +{ + return 0; +} + +template +int MicrogridBusDQ::initializeAdjoint() +{ + return 0; +} + +template +int MicrogridBusDQ::evaluateAdjointResidual() +{ + return 0; +} + +template +int MicrogridBusDQ::evaluateAdjointIntegrand() +{ + return 0; +} + + +// Available template instantiations +template class MicrogridBusDQ; +template class MicrogridBusDQ; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.hpp b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.hpp new file mode 100644 index 000000000..44154da38 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridBusDQ/MicrogridBusDQ.hpp @@ -0,0 +1,66 @@ + + +#ifndef _VIRBUSDQ_HPP_ +#define _VIRBUSDQ_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive MicrogridBusDQ class. + * + */ + template + class MicrogridBusDQ : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::J_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + MicrogridBusDQ(IdxT id, ScalarT RN); + virtual ~MicrogridBusDQ(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT RN_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLine/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/MicrogridLine/CMakeLists.txt new file mode 100644 index 000000000..d59cebb9c --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLine/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_mircoline + SOURCES + MicrogridLine.cpp + OUTPUT_NAME + gridkit_powerelec_mircoline) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.cpp b/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.cpp new file mode 100644 index 000000000..e040ceb70 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.cpp @@ -0,0 +1,172 @@ + +#include +#include +#include +#include "MicrogridLine.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant MicrogridLine model + * + * Calls default ModelEvaluatorImpl constructor. + * + * Each microgrid line has a virtual resistance RN + */ + +template +MicrogridLine::MicrogridLine(IdxT id, ScalarT R,ScalarT L) + : R_(R), L_(L) +{ + // internals [id, iq] + // externals [\omegaref, vbd_in, vbq_in, vbd_out, vbq_out] + this->size_ = 7; + this->n_intern = 2; + this->n_extern = 5; + this->extern_indices = {0,1,2,3,4}; + this->idc_ = id; +} + +template +MicrogridLine::~MicrogridLine() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int MicrogridLine::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + + return 0; +} + +/** + * Initialization of the grid model + */ +template +int MicrogridLine::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int MicrogridLine::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Evaluate residual of microgrid line + * This model has "Virtual resistors" on both ends with parameters RN1 and RN2 + * + */ +template +int MicrogridLine::evaluateResidual() +{ + //ref motor + this->f_[0] = 0.0; + + //input + this->f_[1] = -y_[5] ; + this->f_[2] = -y_[6] ; + + //output + this->f_[3] = y_[5] ; + this->f_[4] = y_[6] ; + + //Internal variables + this->f_[5] = -yp_[5] - (R_ / L_) * y_[5] + y_[0]*y_[6] + (y_[1] - y_[3])/L_; + this->f_[6] = -yp_[6] - (R_ / L_) * y_[6] - y_[0]*y_[5] + (y_[2] - y_[4])/L_; + + + return 0; +} + +/** + * @brief Generate Jacobian for Transmission Line + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ +template +int MicrogridLine::evaluateJacobian() +{ + this->J_.zeroMatrix(); + + //Create dF/dy + std::vector rtemp{1,2,3,4}; + std::vector ctemp{5,6,5,6}; + std::vector vals{-1.0,-1.0,1.0,1.0}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::vector ccord{0, 1, 3, 5, 6}; + + std::vector rcord(ccord.size(),5); + vals = {y_[6], (1.0 / L_) , -(1.0 / L_), - (R_ / L_) , y_[0]}; + this->J_.setValues(rcord, ccord, vals); + + + std::vector ccor2{0, 2, 4, 5, 6}; + std::fill(rcord.begin(), rcord.end(), 6); + vals = {-y_[5], (1.0 / L_) , -(1.0 / L_), -y_[0], - (R_ / L_)}; + this->J_.setValues(rcord, ccor2, vals); + + + //Create -dF/dy' + std::vector rcordder{5,6}; + std::vector ccordder{5,6}; + std::vector valsder{-1.0, -1.0}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,7,7); + + //Perform dF/dy + \alpha dF/dy' + this->J_.AXPY(this->alpha_, Jacder); + + + return 0; +} + +template +int MicrogridLine::evaluateIntegrand() +{ + return 0; +} + +template +int MicrogridLine::initializeAdjoint() +{ + return 0; +} + +template +int MicrogridLine::evaluateAdjointResidual() +{ + return 0; +} + +template +int MicrogridLine::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class MicrogridLine; +template class MicrogridLine; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.hpp b/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.hpp new file mode 100644 index 000000000..11ef78617 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLine/MicrogridLine.hpp @@ -0,0 +1,67 @@ + + +#ifndef _TRANLINE_HPP_ +#define _TRANLINE_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive MicrogridLine class. + * + */ + template + class MicrogridLine : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::J_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + MicrogridLine(IdxT id, ScalarT R, ScalarT L); + virtual ~MicrogridLine(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT R_; + ScalarT L_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLoad/CMakeLists.txt b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/CMakeLists.txt new file mode 100644 index 000000000..313d47688 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(powerelec_microload + SOURCES + MicrogridLoad.cpp + OUTPUT_NAME + gridkit_powerelec_microload) \ No newline at end of file diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.cpp b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.cpp new file mode 100644 index 000000000..c39f53388 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.cpp @@ -0,0 +1,169 @@ + +#include +#include +#include +#include "MicrogridLoad.hpp" + +namespace ModelLib { + +/*! + * @brief Constructor for a constant MicrogridLoad model + * + * Calls default ModelEvaluatorImpl constructor. + * + * This is the Medium distance form with the use of the admittance matrix. + * Since the line is of medium length then there is no real part for shunt admittance + */ + +template +MicrogridLoad::MicrogridLoad(IdxT id, ScalarT R,ScalarT L) + : R_(R), L_(L) +{ + // internals [id, iq] + // externals [\omegaref, vbd_out, vbq_out] + this->size_ = 5; + this->n_intern = 2; + this->n_extern = 3; + this->extern_indices = {0,1,2}; + this->idc_ = id; + +} + +template +MicrogridLoad::~MicrogridLoad() +{ +} + +/*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ +template +int MicrogridLoad::allocate() +{ + this->y_.resize(this->size_); + this->yp_.resize(this->size_); + this->f_.resize(this->size_); + + return 0; +} + +/** + * Initialization of the grid model + */ +template +int MicrogridLoad::initialize() +{ + return 0; +} + +/* + * \brief Identify differential variables + */ +template +int MicrogridLoad::tagDifferentiable() +{ + return 0; +} + +/** + * @brief Eval Micro Load + */ +template +int MicrogridLoad::evaluateResidual() +{ + //ref motor + this->f_[0] = 0.0; + + //only input for loads + + //input + this->f_[1] = -y_[3] ; + this->f_[2] = -y_[4] ; + + //Internal variables + this->f_[3] = -yp_[3] - (R_ / L_) * y_[3] + y_[0]*y_[4] + y_[1] / L_; + this->f_[4] = -yp_[4] - (R_ / L_) * y_[4] - y_[0]*y_[3] + y_[2] / L_; + + + return 0; +} + +/** + * @brief Generate Jacobian for Micro Load + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ +template +int MicrogridLoad::evaluateJacobian() +{ + this->J_.zeroMatrix(); + + //Create dF/dy + std::vector rtemp{1,2}; + std::vector ctemp{3,4}; + std::vector vals{-1.0,-1.0}; + this->J_.setValues(rtemp, ctemp, vals); + + + std::vector ccord{0, 1, 3, 4}; + + std::vector rcord(ccord.size(),3); + vals = {y_[4], (1.0 / L_) , - (R_ / L_) , y_[0]}; + this->J_.setValues(rcord, ccord, vals); + + + std::vector ccor2{0, 2, 3, 4}; + std::fill(rcord.begin(), rcord.end(), 4); + vals = {-y_[3], (1.0 / L_) , -y_[0], - (R_ / L_)}; + this->J_.setValues(rcord, ccor2, vals); + + + //Create -dF/dy' + std::vector rcordder{3,4}; + std::vector ccordder{3,4}; + std::vector valsder{-1.0, -1.0}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder,5,5); + + //Perform dF/dy + \alpha dF/dy' + this->J_.AXPY(this->alpha_, Jacder); + + return 0; +} + +template +int MicrogridLoad::evaluateIntegrand() +{ + return 0; +} + +template +int MicrogridLoad::initializeAdjoint() +{ + return 0; +} + +template +int MicrogridLoad::evaluateAdjointResidual() +{ + return 0; +} + +template +int MicrogridLoad::evaluateAdjointIntegrand() +{ + return 0; +} + + + + + +// Available template instantiations +template class MicrogridLoad; +template class MicrogridLoad; + + +} //namespace ModelLib + diff --git a/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.hpp b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.hpp new file mode 100644 index 000000000..22694f614 --- /dev/null +++ b/ComponentLib/PowerElectronicsComponents/MicrogridLoad/MicrogridLoad.hpp @@ -0,0 +1,67 @@ + + +#ifndef _TRANLOAD_HPP_ +#define _TRANLOAD_HPP_ + +#include +#include +#include + + +namespace ModelLib +{ + template class BaseBus; +} + + +namespace ModelLib +{ + /*! + * @brief Declaration of a passive MicrogridLoad class. + * + */ + template + class MicrogridLoad : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::J_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + + public: + MicrogridLoad(IdxT id, ScalarT R, ScalarT L); + virtual ~MicrogridLoad(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + //int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + + private: + ScalarT R_; + ScalarT L_; + }; +} + +#endif diff --git a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp index c7cb09798..e58e50556 100644 --- a/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp +++ b/ComponentLib/PowerElectronicsComponents/VoltageSource/VoltageSource.cpp @@ -72,11 +72,11 @@ int VoltageSource::evaluateResidual() //Note this leaves induction lumped into y. Perhaps would be better to seperate volatge and induction into seperate vectors // for easier development //input - this->f_[0] = this->y_[2]; + this->f_[0] = -this->y_[2]; //ouput - this->f_[1] = -this->y_[2]; + this->f_[1] = this->y_[2]; //internal - this->f_[2] = -this->y_[1] + this->y_[0] + this->V_; + this->f_[2] = this->y_[1] - this->y_[0] - this->V_; return 0; } @@ -86,7 +86,7 @@ int VoltageSource::evaluateJacobian() //Create dF/dy std::vector rcord{0,1,2,2}; std::vector ccord{2,2,0,1}; - std::vector vals{1.0, -1.0, 1.0, -1.0}; + std::vector vals{-1.0, 1.0, -1.0, 1.0}; this->J_.setValues(rcord, ccord, vals); return 0; diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index e15774642..2c53fcc25 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -57,6 +57,7 @@ add_subdirectory(MatPowerTesting) add_subdirectory(RLCircuit) +add_subdirectory(Microgrid) add_subdirectory(SparseTest) add_subdirectory(DiscreteGeneratorTest) diff --git a/Examples/DiscreteGeneratorTest/CMakeLists.txt b/Examples/DiscreteGeneratorTest/CMakeLists.txt index b1100b91a..9238fb346 100644 --- a/Examples/DiscreteGeneratorTest/CMakeLists.txt +++ b/Examples/DiscreteGeneratorTest/CMakeLists.txt @@ -3,7 +3,10 @@ add_executable(dgtest DGTest.cpp) -target_link_libraries(dgtest GRIDKIT::powerelec_disgen) +target_link_libraries(dgtest GRIDKIT::powerelec_disgen + GRIDKIT::powerelec_mircoline + GRIDKIT::powerelec_microload + GRIDKIT::solvers_dyn) add_test(NAME DiscreteGeneratorTest COMMAND $) install(TARGETS dgtest RUNTIME DESTINATION bin) diff --git a/Examples/DiscreteGeneratorTest/DGTest.cpp b/Examples/DiscreteGeneratorTest/DGTest.cpp index 7d4aeda6f..d3dd2c68b 100644 --- a/Examples/DiscreteGeneratorTest/DGTest.cpp +++ b/Examples/DiscreteGeneratorTest/DGTest.cpp @@ -15,11 +15,9 @@ int main(int argc, char const *argv[]) ModelLib::DiscreteGeneratorParameters parms; //Parameters from MATLAB Microgrid code for first DG - //refmp is need for reference input parms.wb = 2.0*M_PI*50.0; parms.wc = 31.41; parms.mp = 9.4e-5; - parms.refmp = 9.4e-5; parms.Vn = 380; parms.nq = 1.3e-3; parms.F = 0.75; @@ -33,7 +31,7 @@ int main(int argc, char const *argv[]) parms.rLc = 0.03; parms.Lc = 0.35e-3; - ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(0, parms); + ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(0, parms, true); std::vector t1(16,0.0); std::vector t2{0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.1,1.2,1.3,1.4,1.5}; @@ -48,9 +46,33 @@ int main(int argc, char const *argv[]) std::cout << "Output: {"; for (double i : dg->getResidual()) { - std::cout << i << ", "; + printf("%e ,", i); } std::cout << "}\n"; + //Generated from matlab code with same parameters and inputs + std::vector true_vec{3.141592277589793e+02, + 8.941907747838389e-01, + 1.846733023014284e+00, + 3.141592277589793e+02, + 1.014543000000000e+02, + -1.507680000000000e+01, + 3.787993500000000e+02, + -1.300000000000000e+00, + 2.899095146477517e+02, + 2.939138495559215e+02, + 1.507210571826699e+07, + 1.659799832843673e+07, + -7.591593003913325e+03, + -8.376991073310774e+03, + 3.337988298081817e+03, + 2.684419146397466e+03}; + + std::cout << "Test the Relative Error\n"; + for (size_t i = 0; i < true_vec.size(); i++) + { + printf("%e ,\n", (true_vec[i] - dg->getResidual()[i]) / true_vec[i]); + } + return 0; } diff --git a/Examples/Microgrid/CMakeLists.txt b/Examples/Microgrid/CMakeLists.txt new file mode 100644 index 000000000..0958144c4 --- /dev/null +++ b/Examples/Microgrid/CMakeLists.txt @@ -0,0 +1,13 @@ + + + + +add_executable(microgrid Microgrid.cpp) +target_link_libraries(microgrid GRIDKIT::powerelec_disgen + GRIDKIT::powerelec_mircoline + GRIDKIT::powerelec_microload + GRIDKIT::solvers_dyn + GRIDKIT::powerelec_mircobusdq) + +add_test(NAME Microgrid COMMAND $) +install(TARGETS microgrid RUNTIME DESTINATION bin) diff --git a/Examples/Microgrid/Microgrid.cpp b/Examples/Microgrid/Microgrid.cpp new file mode 100644 index 000000000..a0cf8dc9b --- /dev/null +++ b/Examples/Microgrid/Microgrid.cpp @@ -0,0 +1,361 @@ + + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include +#include +#include + + +int main(int argc, char const *argv[]) +{ + double abstol = 1.0e-4; + double reltol = 1.0e-4; + bool usejac = true; + + //TODO:setup as named parameters + //Create circuit model + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac); + + //Modeled after the problem in the paper + double RN = 1.0e4; + + //DG Params + + ModelLib::DiscreteGeneratorParameters parms1; + parms1.wb = 2.0*M_PI*50.0; + parms1.wc = 31.41; + parms1.mp = 9.4e-5; + parms1.Vn = 380; + parms1.nq = 1.3e-3; + parms1.F = 0.75; + parms1.Kiv = 420.0; + parms1.Kpv = 0.1; + parms1.Kic = 20.0 * 1.0e3; + parms1.Kpc = 15.0; + parms1.Cf = 50.0e-6; + parms1.rLf = 0.1; + parms1.Lf = 1.35e-3; + parms1.rLc = 0.03; + parms1.Lc = 0.35e-3; + + ModelLib::DiscreteGeneratorParameters parms2; + //Parameters from MATLAB Microgrid code for first DG + parms2.wb = 2.0*M_PI*50.0; + parms2.wc = 31.41; + parms2.mp = 12.5e-5; + parms2.Vn = 380; + parms2.nq = 1.5e-3; + parms2.F = 0.75; + parms2.Kiv = 390.0; + parms2.Kpv = 0.05; + parms2.Kic = 16.0 * 1.0e3; + parms2.Kpc = 10.5; + parms2.Cf = 50.0e-6; + parms2.rLf = 0.1; + parms2.Lf = 1.35e-3; + parms2.rLc = 0.03; + parms2.Lc = 0.35e-3; + + //Line params + double rline1 = 0.23; + double Lline1 = 0.1 / (2.0 * M_PI * 50.0); + + double rline2 = 0.35; + double Lline2 = 0.58 / (2.0 * M_PI * 50.0); + + double rline3 = 0.23; + double Lline3 = 0.1 / (2.0 * M_PI * 50.0); + + //load parms + double rload1 = 3.0; + double Lload1 = 2.0 / (2.0 * M_PI * 50.0); + + double rload2 = 2.0; + double Lload2 = 1.0 / (2.0 * M_PI * 50.0); + + + //indexing sets + size_t Nsize = 2; + // DGs + Lines + Loads + size_t vec_size_internals = 13*(2*Nsize) + (2 + 4*(Nsize - 1)) + 2*Nsize; + // \omegaref + BusDQ + size_t vec_size_externals = 1 + 2*(2*Nsize); + size_t dqbus1 = vec_size_externals + 1; + size_t dqbus2 = vec_size_externals + 3; + size_t dqbus3 = vec_size_externals + 5; + size_t dqbus4 = vec_size_externals + 7; + + size_t vec_size_total = vec_size_internals + vec_size_externals; + + + size_t indexv = 0; + + //dg 1 + ModelLib::DiscreteGenerator *dg1 = new ModelLib::DiscreteGenerator(0, parms1, true); + //ref motor + dg1->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg1->setExternalConnectionNodes(1,dqbus1); + dg1->setExternalConnectionNodes(2,dqbus1 + 1); + //internal connections + for (size_t i = 0; i < 13; i++) + { + + dg1->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg1); + + //dg 2 + ModelLib::DiscreteGenerator *dg2 = new ModelLib::DiscreteGenerator(1, parms1, false); + //ref motor + dg2->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg2->setExternalConnectionNodes(1,dqbus2); + dg2->setExternalConnectionNodes(2,dqbus2 + 1); + //internal connections + for (size_t i = 0; i < 13; i++) + { + + dg2->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg2); + + + //dg 3 + ModelLib::DiscreteGenerator *dg3 = new ModelLib::DiscreteGenerator(2, parms2, false); + //ref motor + dg3->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg3->setExternalConnectionNodes(1,dqbus3); + dg3->setExternalConnectionNodes(2,dqbus3 + 1); + //internal connections + for (size_t i = 0; i < 13; i++) + { + + dg3->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg3); + + + //dg 4 + ModelLib::DiscreteGenerator *dg4 = new ModelLib::DiscreteGenerator(3, parms2, false); + //ref motor + dg4->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg4->setExternalConnectionNodes(1,dqbus4); + dg4->setExternalConnectionNodes(2,dqbus4 + 1); + + //internal connections + for (size_t i = 0; i < 13; i++) + { + + dg4->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg4); + + // Lines + + //line 1 + ModelLib::MicrogridLine *l1 = new ModelLib::MicrogridLine(4, rline1, Lline1); + //ref motor + l1->setExternalConnectionNodes(0,vec_size_internals); + //input connections + l1->setExternalConnectionNodes(1,dqbus1); + l1->setExternalConnectionNodes(2,dqbus1 + 1); + //output connections + l1->setExternalConnectionNodes(3,dqbus2); + l1->setExternalConnectionNodes(4,dqbus2 + 1); + //internal connections + for (size_t i = 0; i < 2; i++) + { + + l1->setExternalConnectionNodes(5 + i,indexv + i); + } + indexv += 2; + sysmodel->addComponent(l1); + + + //line 2 + ModelLib::MicrogridLine *l2 = new ModelLib::MicrogridLine(5, rline2, Lline2); + //ref motor + l2->setExternalConnectionNodes(0,vec_size_internals); + //input connections + l2->setExternalConnectionNodes(1,dqbus2); + l2->setExternalConnectionNodes(2,dqbus2 + 1); + //output connections + l2->setExternalConnectionNodes(3,dqbus3); + l2->setExternalConnectionNodes(4,dqbus3 + 1); + //internal connections + for (size_t i = 0; i < 2; i++) + { + + l2->setExternalConnectionNodes(5 + i,indexv + i); + } + indexv += 2; + sysmodel->addComponent(l2); + + //line 3 + ModelLib::MicrogridLine *l3 = new ModelLib::MicrogridLine(6, rline3, Lline3); + //ref motor + l3->setExternalConnectionNodes(0,vec_size_internals); + //input connections + l3->setExternalConnectionNodes(1,dqbus3); + l3->setExternalConnectionNodes(2,dqbus3 + 1); + //output connections + l3->setExternalConnectionNodes(3,dqbus4); + l3->setExternalConnectionNodes(4,dqbus4 + 1); + //internal connections + for (size_t i = 0; i < 2; i++) + { + + l3->setExternalConnectionNodes(5 + i,indexv + i); + } + indexv += 2; + sysmodel->addComponent(l3); + + // loads + + //load 1 + ModelLib::MicrogridLoad *load1 = new ModelLib::MicrogridLoad(7, rload1, Lload1); + //ref motor + load1->setExternalConnectionNodes(0,vec_size_internals); + //input connections + load1->setExternalConnectionNodes(1,dqbus1); + load1->setExternalConnectionNodes(2,dqbus1 + 1); + //internal connections + for (size_t i = 0; i < 2; i++) + { + + load1->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 2; + sysmodel->addComponent(load1); + + //load 2 + ModelLib::MicrogridLoad *load2 = new ModelLib::MicrogridLoad(8, rload2, Lload2); + //ref motor + load2->setExternalConnectionNodes(0,vec_size_internals); + //input connections + load2->setExternalConnectionNodes(1,dqbus3); + load2->setExternalConnectionNodes(2,dqbus3 + 1); + //internal connections + for (size_t i = 0; i < 2; i++) + { + + load2->setExternalConnectionNodes(3 + i,indexv + i); + } + indexv += 2; + sysmodel->addComponent(load2); + + //Virtual PQ Buses + ModelLib::MicrogridBusDQ *bus1 = new ModelLib::MicrogridBusDQ(9, RN); + + bus1->setExternalConnectionNodes(0,dqbus1); + bus1->setExternalConnectionNodes(1,dqbus1 + 1); + sysmodel->addComponent(bus1); + + ModelLib::MicrogridBusDQ *bus2 = new ModelLib::MicrogridBusDQ(10, RN); + + bus2->setExternalConnectionNodes(0,dqbus2); + bus2->setExternalConnectionNodes(1,dqbus2 + 1); + sysmodel->addComponent(bus2); + + ModelLib::MicrogridBusDQ *bus3 = new ModelLib::MicrogridBusDQ(11, RN); + + bus3->setExternalConnectionNodes(0,dqbus3); + bus3->setExternalConnectionNodes(1,dqbus3 + 1); + sysmodel->addComponent(bus3); + + ModelLib::MicrogridBusDQ *bus4 = new ModelLib::MicrogridBusDQ(12, RN); + + bus4->setExternalConnectionNodes(0,dqbus4); + bus4->setExternalConnectionNodes(1,dqbus4 + 1); + sysmodel->addComponent(bus4); + + sysmodel->allocate(vec_size_total); + + std::cout << sysmodel->y().size() << std::endl; + std::cout << vec_size_internals << ", " << vec_size_externals << "\n"; + + //Create Intial points for states + for (size_t i = 0; i < vec_size_total; i++) + { + sysmodel->y()[i] = 0.0; + sysmodel->yp()[i] = 0.0; + } + + // Create Intial derivatives specifics generated in MATLAB + //DGs + for (size_t i = 0; i < 2; i++) + { + sysmodel->yp()[13*i + 3] = parms1.Vn; + sysmodel->yp()[13*i + 5] = parms1.Kpv * parms1.Vn; + sysmodel->yp()[13*i + 7] = (parms1.Kpc * parms1.Kpv * parms1.Vn) / parms1.Lf; + } + for (size_t i = 2; i < 4; i++) + { + sysmodel->yp()[13*i + 3] = parms2.Vn; + sysmodel->yp()[13*i + 5] = parms2.Kpv * parms2.Vn; + sysmodel->yp()[13*i + 7] = (parms2.Kpc * parms2.Kpv * parms2.Vn) / parms2.Lf; + } + + //since the intial P_com = 0 + sysmodel->y()[62] = parms1.wb; + + + + sysmodel->initialize(); + sysmodel->evaluateResidual(); + + std::vector& fres = sysmodel->getResidual(); + std::cout << "Verify Intial Resisdual is Zero: {\n"; + for (size_t i = 0; i < fres.size(); i++) + { + printf("%u : %e \n", i, fres[i]); + } + std::cout << "}\n"; + + sysmodel->updateTime(0.0, 1.0e-8); + sysmodel->evaluateJacobian(); + std::cout << "Intial Jacobian with alpha:\n"; + // std::cout << sysmodel->getJacobian().frobnorm() << "\n"; + + + // //Create numerical integrator and configure it for the generator model + // AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + // double t_init = 0.0; + // double t_final = 1.0; + + // // setup simulation + // idas->configureSimulation(); + // idas->getDefaultInitialCondition(); + // idas->initializeSimulation(t_init); + + // idas->runSimulation(t_final); + + // std::vector& yfinial = sysmodel->y(); + + // std::cout << "Final Vector y\n"; + // for (size_t i = 0; i < yfinial.size(); i++) + // { + // std::cout << yfinial[i] << "\n"; + // } + + return 0; +} diff --git a/Examples/RLCircuit/RLCircuit.cpp b/Examples/RLCircuit/RLCircuit.cpp index e902b1242..55fe476b9 100644 --- a/Examples/RLCircuit/RLCircuit.cpp +++ b/Examples/RLCircuit/RLCircuit.cpp @@ -18,8 +18,8 @@ int main(int argc, char const *argv[]) { - double abstol = 1e-8; - double reltol = 1e-8; + double abstol = 1.0e-8; + double reltol = 1.0e-8; bool usejac = true; //TODO:setup as named parameters @@ -132,9 +132,9 @@ int main(int argc, char const *argv[]) //analytical solution to the circuit yexact[0] = vinit; - yexact[2] = (-vinit / rinit) * (exp((rinit / linit) * t_final) - 1.0); + yexact[2] = (vinit / rinit) * (exp(-(rinit / linit) * t_final) - 1.0); yexact[3] = yexact[2]; - yexact[1] = vinit - rinit * yexact[2]; + yexact[1] = vinit + rinit * yexact[2]; std::cout << "Element-wise Relative error at t=" << t_final << "\n"; for (size_t i = 0; i < yfinial.size(); i++) diff --git a/SparseMatrix/COO_Matrix.hpp b/SparseMatrix/COO_Matrix.hpp index c256e015c..716748fa8 100644 --- a/SparseMatrix/COO_Matrix.hpp +++ b/SparseMatrix/COO_Matrix.hpp @@ -50,6 +50,7 @@ class COO_Matrix void AXPY(ScalarT alpha, COO_Matrix& a); void AXPY(ScalarT alpha, std::vector r, std::vector c, std::vector v); void SCAL(ScalarT alpha); + ScalarT frobnorm(); // --- Permutation Operations --- //No sorting is actually done. Only done when nesscary @@ -391,6 +392,14 @@ inline void COO_Matrix::SCAL(ScalarT alpha) for (auto i = this->values.begin(); i < this->values.end(); i++) *i *= alpha; } +template +inline ScalarT COO_Matrix::frobnorm() +{ + ScalarT totsum = 0.0; + for (auto i = this->values.begin(); i < this->values.end(); i++) totsum += abs(*i)^2; + return totsum; +} + /** * @brief Permutate the matrix to a different one. Only changes the coordinates * From 662520527ad3863fa88df877efb429e244b7f9e5 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 19 Feb 2024 18:53:44 -0500 Subject: [PATCH 45/52] Working Microgrid (Finite Difference) - "grounded" the rotor difference in reference - Comparing agianst reference from MATLAB --- Examples/Microgrid/Microgrid.cpp | 168 +++++++++++++++++++++++-------- Solver/Dynamic/Ida.cpp | 6 +- 2 files changed, 130 insertions(+), 44 deletions(-) diff --git a/Examples/Microgrid/Microgrid.cpp b/Examples/Microgrid/Microgrid.cpp index a0cf8dc9b..5f788080a 100644 --- a/Examples/Microgrid/Microgrid.cpp +++ b/Examples/Microgrid/Microgrid.cpp @@ -19,9 +19,9 @@ int main(int argc, char const *argv[]) { - double abstol = 1.0e-4; - double reltol = 1.0e-4; - bool usejac = true; + double abstol = 1.0e-8; + double reltol = 1.0e-8; + bool usejac = false; //TODO:setup as named parameters //Create circuit model @@ -36,14 +36,14 @@ int main(int argc, char const *argv[]) parms1.wb = 2.0*M_PI*50.0; parms1.wc = 31.41; parms1.mp = 9.4e-5; - parms1.Vn = 380; + parms1.Vn = 380.0; parms1.nq = 1.3e-3; parms1.F = 0.75; parms1.Kiv = 420.0; parms1.Kpv = 0.1; - parms1.Kic = 20.0 * 1.0e3; + parms1.Kic = 2.0e4; parms1.Kpc = 15.0; - parms1.Cf = 50.0e-6; + parms1.Cf = 5.0e-5; parms1.rLf = 0.1; parms1.Lf = 1.35e-3; parms1.rLc = 0.03; @@ -54,12 +54,12 @@ int main(int argc, char const *argv[]) parms2.wb = 2.0*M_PI*50.0; parms2.wc = 31.41; parms2.mp = 12.5e-5; - parms2.Vn = 380; + parms2.Vn = 380.0; parms2.nq = 1.5e-3; parms2.F = 0.75; parms2.Kiv = 390.0; parms2.Kpv = 0.05; - parms2.Kic = 16.0 * 1.0e3; + parms2.Kic = 16.0e3; parms2.Kpc = 10.5; parms2.Cf = 50.0e-6; parms2.rLf = 0.1; @@ -87,14 +87,14 @@ int main(int argc, char const *argv[]) //indexing sets size_t Nsize = 2; - // DGs + Lines + Loads - size_t vec_size_internals = 13*(2*Nsize) + (2 + 4*(Nsize - 1)) + 2*Nsize; + // DGs + - refframe Lines + Loads + size_t vec_size_internals = 13*(2*Nsize) - 1 + (2 + 4*(Nsize - 1)) + 2*Nsize; // \omegaref + BusDQ size_t vec_size_externals = 1 + 2*(2*Nsize); - size_t dqbus1 = vec_size_externals + 1; - size_t dqbus2 = vec_size_externals + 3; - size_t dqbus3 = vec_size_externals + 5; - size_t dqbus4 = vec_size_externals + 7; + size_t dqbus1 = vec_size_internals + 1; + size_t dqbus2 = vec_size_internals + 3; + size_t dqbus3 = vec_size_internals + 5; + size_t dqbus4 = vec_size_internals + 7; size_t vec_size_total = vec_size_internals + vec_size_externals; @@ -108,13 +108,15 @@ int main(int argc, char const *argv[]) //outputs dg1->setExternalConnectionNodes(1,dqbus1); dg1->setExternalConnectionNodes(2,dqbus1 + 1); + //"grounding" of the difference + dg1->setExternalConnectionNodes(3,-1); //internal connections - for (size_t i = 0; i < 13; i++) + for (size_t i = 0; i < 12; i++) { - dg1->setExternalConnectionNodes(3 + i,indexv + i); + dg1->setExternalConnectionNodes(4 + i,indexv + i); } - indexv += 13; + indexv += 12; sysmodel->addComponent(dg1); //dg 2 @@ -300,22 +302,22 @@ int main(int argc, char const *argv[]) } // Create Intial derivatives specifics generated in MATLAB - //DGs - for (size_t i = 0; i < 2; i++) - { - sysmodel->yp()[13*i + 3] = parms1.Vn; - sysmodel->yp()[13*i + 5] = parms1.Kpv * parms1.Vn; - sysmodel->yp()[13*i + 7] = (parms1.Kpc * parms1.Kpv * parms1.Vn) / parms1.Lf; - } + //DGs 1 + sysmodel->yp()[2] = parms1.Vn; + sysmodel->yp()[4] = parms1.Kpv * parms1.Vn; + sysmodel->yp()[6] = (parms1.Kpc * parms1.Kpv * parms1.Vn) / parms1.Lf; + sysmodel->yp()[12 + 3] = parms1.Vn; + sysmodel->yp()[12 + 5] = parms1.Kpv * parms1.Vn; + sysmodel->yp()[12 + 7] = (parms1.Kpc * parms1.Kpv * parms1.Vn) / parms1.Lf; for (size_t i = 2; i < 4; i++) { - sysmodel->yp()[13*i + 3] = parms2.Vn; - sysmodel->yp()[13*i + 5] = parms2.Kpv * parms2.Vn; - sysmodel->yp()[13*i + 7] = (parms2.Kpc * parms2.Kpv * parms2.Vn) / parms2.Lf; + sysmodel->yp()[13*i - 1 + 3] = parms2.Vn; + sysmodel->yp()[13*i - 1 + 5] = parms2.Kpv * parms2.Vn; + sysmodel->yp()[13*i - 1 + 7] = (parms2.Kpc * parms2.Kpv * parms2.Vn) / parms2.Lf; } //since the intial P_com = 0 - sysmodel->y()[62] = parms1.wb; + sysmodel->y()[vec_size_internals] = parms1.wb; @@ -336,26 +338,106 @@ int main(int argc, char const *argv[]) // std::cout << sysmodel->getJacobian().frobnorm() << "\n"; - // //Create numerical integrator and configure it for the generator model - // AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + //Create numerical integrator and configure it for the generator model + AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + double t_init = 0.0; + double t_final = 1.0; - // double t_init = 0.0; - // double t_final = 1.0; + // setup simulation + idas->configureSimulation(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); - // // setup simulation - // idas->configureSimulation(); - // idas->getDefaultInitialCondition(); - // idas->initializeSimulation(t_init); + idas->runSimulation(t_final); - // idas->runSimulation(t_final); + std::vector& yfinial = sysmodel->y(); - // std::vector& yfinial = sysmodel->y(); + std::cout << "Final Vector y\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << yfinial[i] << "\n"; + } - // std::cout << "Final Vector y\n"; - // for (size_t i = 0; i < yfinial.size(); i++) - // { - // std::cout << yfinial[i] << "\n"; - // } + //Generate from MATLAB code ODE form with tolerances of 1e-12 + std::vectortrue_vec{ + 2.297543153595780e+04, + 1.275311524125022e+04, + 3.763060183116022e-02, + -2.098153459325261e-02, + 1.848285659119097e-02, + -1.563291404944864e-04, + 6.321941907011718e+01, + -2.942264300846256e+01, + 3.634209302905854e+02, + -2.668928293656362e-06, + 6.321941919221522e+01, + -3.509200178595996e+01, + -7.555954467454730e-03, + 2.297580486511343e+04, + 8.742028429066131e+03, + 3.710079564796484e-02, + -1.421122598056797e-02, + 1.874079517807597e-02, + -9.891304812687215e-05, + 6.232933298360234e+01, + -1.796494061423331e+01, + 3.686353885026506e+02, + 3.465673854181523e-05, + 6.232933406188410e+01, + -2.371564475187742e+01, + -8.273939686941580e-02, + 1.727775042678524e+04, + 1.649365247247288e+04, + 3.116555157570849e-02, + -2.985990066758010e-02, + 2.250012115906506e-02, + -2.643873146501096e-04, + 4.861823510250247e+01, + -4.088592755441309e+01, + 3.552597163751238e+02, + -1.496407194199739e-04, + 4.861823504694532e+01, + -4.642797132602495e+01, + -8.445727984408551e-02, + 1.727723725566433e+04, + 9.182386962936238e+03, + 3.024959333190777e-02, + -1.617250828202081e-02, + 2.318056864131751e-02, + -1.295918667730514e-04, + 4.718938244522050e+01, + -1.935782085675469e+01, + 3.662262287803608e+02, + 1.076423957830039e-04, + 4.718938116520511e+01, + -2.507094256286497e+01, + -1.881248349415025e+01, + 2.114714832305742e+01, + 4.329946674909793e+01, + -3.037887936225145e+00, + -4.487023117352992e+01, + 2.895883729832657e+01, + 8.199613345691378e+01, + -5.623856502948122e+01, + 1.327498499660322e+02, + -8.228065162347022e+01, + 3.119995747945993e+02, + 3.576922945168803e+02, + -5.850795361581618e+00, + 3.641193316268954e+02, + -8.846325267612976e+00, + 3.472146752739036e+02, + -3.272400970143252e+01, + 3.604108939430972e+02, + -3.492842627398574e+01 + }; + + std::cout << "Test the Relative Error\n"; + for (size_t i = 0; i < true_vec.size(); i++) + { + printf("%u : %e ,\n", i, abs(true_vec[i] - yfinial[i]) / abs(true_vec[i])); + } return 0; } diff --git a/Solver/Dynamic/Ida.cpp b/Solver/Dynamic/Ida.cpp index 5137119f1..1bae455f1 100644 --- a/Solver/Dynamic/Ida.cpp +++ b/Solver/Dynamic/Ida.cpp @@ -134,6 +134,10 @@ namespace Sundials retval = IDASStolerances(solver_, rtol, atol); checkOutput(retval, "IDASStolerances"); + /// \todo Need to set max number of steps based on user input! + retval = IDASetMaxNumSteps(solver_, 5000); + checkOutput(retval, "IDASetMaxNumSteps"); + // Tag differential variables std::vector& tag = model_->tag(); if (static_cast(tag.size()) == model_->size()) @@ -415,7 +419,7 @@ namespace Sundials checkOutput(retval, "IDASetUserDataB"); /// \todo Need to set max number of steps based on user input! - retval = IDASetMaxNumStepsB(solver_, backwardID_, 2000); + retval = IDASetMaxNumStepsB(solver_, backwardID_, 200); checkOutput(retval, "IDASetMaxNumSteps"); // Set up linear solver From ae8a8bdeaea2d0a1cfcec0a141ad69b046279e84 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Thu, 22 Feb 2024 14:11:25 -0500 Subject: [PATCH 46/52] Fixed the Jacobian in Microgrid Example --- .../DiscreteGenerator/DiscreteGenerator.cpp | 5 +++-- Examples/Microgrid/Microgrid.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp index 607ec5312..038a24ea2 100644 --- a/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp +++ b/ComponentLib/PowerElectronicsComponents/DiscreteGenerator/DiscreteGenerator.cpp @@ -165,6 +165,7 @@ int DiscreteGenerator::evaluateResidual() template int DiscreteGenerator::evaluateJacobian() { + this->J_.zeroMatrix(); //Create dF/dy' std::vector rcordder(13); std::vector valsder(13, -1.0); @@ -186,7 +187,7 @@ int DiscreteGenerator::evaluateJacobian() ctemp = {3, 14, 15}; rtemp.clear(); for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(1); - valtemp = { - sin(y_[3]) * y_[14] - cos(y_[3]) * y_[15], cos(y_[3]),sin(y_[3])}; + valtemp = { - sin(y_[3]) * y_[14] - cos(y_[3]) * y_[15], cos(y_[3]),-sin(y_[3])}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 2 @@ -194,7 +195,7 @@ int DiscreteGenerator::evaluateJacobian() ctemp = {3, 14, 15}; rtemp.clear(); for (size_t i = 0; i < ctemp.size(); i++) rtemp.push_back(2); - valtemp = { - cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15], -sin(y_[3]),cos(y_[3])}; + valtemp = { cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15], sin(y_[3]),cos(y_[3])}; this->J_.setValues(rtemp, ctemp, valtemp); //r = 3 diff --git a/Examples/Microgrid/Microgrid.cpp b/Examples/Microgrid/Microgrid.cpp index 5f788080a..dddd4f291 100644 --- a/Examples/Microgrid/Microgrid.cpp +++ b/Examples/Microgrid/Microgrid.cpp @@ -21,7 +21,7 @@ int main(int argc, char const *argv[]) { double abstol = 1.0e-8; double reltol = 1.0e-8; - bool usejac = false; + bool usejac = true; //TODO:setup as named parameters //Create circuit model From 742dc0dd4ae438c69a9e8a6e622d63c53c74e631 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Thu, 22 Feb 2024 14:26:46 -0500 Subject: [PATCH 47/52] Added a max step size control for model objects --- Examples/Microgrid/Microgrid.cpp | 3 ++- ModelEvaluator.hpp | 1 + ModelEvaluatorImpl.hpp | 7 +++++++ PowerElectronicsModel.hpp | 7 +++++-- Solver/Dynamic/Ida.cpp | 5 ++++- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Examples/Microgrid/Microgrid.cpp b/Examples/Microgrid/Microgrid.cpp index dddd4f291..acc8be386 100644 --- a/Examples/Microgrid/Microgrid.cpp +++ b/Examples/Microgrid/Microgrid.cpp @@ -21,11 +21,12 @@ int main(int argc, char const *argv[]) { double abstol = 1.0e-8; double reltol = 1.0e-8; + size_t max_step_amount = 3000; bool usejac = true; //TODO:setup as named parameters //Create circuit model - ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac); + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac, max_step_amount); //Modeled after the problem in the paper double RN = 1.0e4; diff --git a/ModelEvaluator.hpp b/ModelEvaluator.hpp index 50c5e8b77..ad56fbd48 100644 --- a/ModelEvaluator.hpp +++ b/ModelEvaluator.hpp @@ -107,6 +107,7 @@ namespace ModelLib virtual IdxT size_opt() = 0; virtual void updateTime(real_type t, real_type a) = 0; virtual void setTolerances(real_type& rtol, real_type& atol) const = 0; + virtual void setMaxSteps(IdxT& msa) const = 0; virtual std::vector& y() = 0; virtual const std::vector& y() const = 0; diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp index 928d26f30..0f8969f0b 100644 --- a/ModelEvaluatorImpl.hpp +++ b/ModelEvaluatorImpl.hpp @@ -139,6 +139,11 @@ namespace ModelLib atol = atol_; } + virtual void setMaxSteps(IdxT& msa) const + { + msa = max_steps_; + } + std::vector& y() { return y_; @@ -306,6 +311,8 @@ namespace ModelLib real_type rtol_; real_type atol_; + IdxT max_steps_; + IdxT idc_; }; diff --git a/PowerElectronicsModel.hpp b/PowerElectronicsModel.hpp index 47efcc7f7..04508607f 100644 --- a/PowerElectronicsModel.hpp +++ b/PowerElectronicsModel.hpp @@ -50,18 +50,21 @@ class PowerElectronicsModel : public ModelEvaluatorImpl // Set system model tolerances as default rtol_ = 1e-4; atol_ = 1e-4; + this->max_steps_ = 2000; // By default use jacobian - usejac_ = true; + usejac_ = false; + } /** * @brief Constructor for the system model */ - PowerElectronicsModel(double rt, double at, bool ju) : ModelEvaluatorImpl(0, 0, 0) + PowerElectronicsModel(double rt=1e-4, double at=1e-4, bool ju=false, IdxT msa=2000) : ModelEvaluatorImpl(0, 0, 0) { // Set system model tolerances from input rtol_ = rt; atol_ = at; + this->max_steps_ = msa; // Can choose not to use jacobain usejac_ = ju; } diff --git a/Solver/Dynamic/Ida.cpp b/Solver/Dynamic/Ida.cpp index 1bae455f1..2be2913a9 100644 --- a/Solver/Dynamic/Ida.cpp +++ b/Solver/Dynamic/Ida.cpp @@ -133,9 +133,12 @@ namespace Sundials model_->setTolerances(rtol, atol); ///< \todo Function name should be "getTolerances"! retval = IDASStolerances(solver_, rtol, atol); checkOutput(retval, "IDASStolerances"); + + IdxT msa; + model_->setMaxSteps(msa); /// \todo Need to set max number of steps based on user input! - retval = IDASetMaxNumSteps(solver_, 5000); + retval = IDASetMaxNumSteps(solver_, msa); checkOutput(retval, "IDASetMaxNumSteps"); // Tag differential variables From a010111171c30f1ab1cfe313c659e2be76fd5073 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 26 Feb 2024 17:51:38 -0500 Subject: [PATCH 48/52] Working example with the scalable microgrid - not correct residuals --- Examples/CMakeLists.txt | 1 + Examples/Microgrid/Microgrid.cpp | 2 +- Examples/Scale_Microgrid/CMakeLists.txt | 13 + Examples/Scale_Microgrid/Scale_Microgrid.cpp | 366 +++++++++++++++++++ 4 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 Examples/Scale_Microgrid/CMakeLists.txt create mode 100644 Examples/Scale_Microgrid/Scale_Microgrid.cpp diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 2c53fcc25..3df418ba2 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -58,6 +58,7 @@ add_subdirectory(MatPowerTesting) add_subdirectory(RLCircuit) add_subdirectory(Microgrid) +add_subdirectory(Scale_Microgrid) add_subdirectory(SparseTest) add_subdirectory(DiscreteGeneratorTest) diff --git a/Examples/Microgrid/Microgrid.cpp b/Examples/Microgrid/Microgrid.cpp index acc8be386..275974b19 100644 --- a/Examples/Microgrid/Microgrid.cpp +++ b/Examples/Microgrid/Microgrid.cpp @@ -360,7 +360,7 @@ int main(int argc, char const *argv[]) std::cout << yfinial[i] << "\n"; } - //Generate from MATLAB code ODE form with tolerances of 1e-12 + //Generate from MATLAB code ODE form with tolerances of 1e-14 std::vectortrue_vec{ 2.297543153595780e+04, 1.275311524125022e+04, diff --git a/Examples/Scale_Microgrid/CMakeLists.txt b/Examples/Scale_Microgrid/CMakeLists.txt new file mode 100644 index 000000000..8ffc91d81 --- /dev/null +++ b/Examples/Scale_Microgrid/CMakeLists.txt @@ -0,0 +1,13 @@ + + + + +add_executable(scalemicrogrid Scale_Microgrid.cpp) +target_link_libraries(scalemicrogrid GRIDKIT::powerelec_disgen + GRIDKIT::powerelec_mircoline + GRIDKIT::powerelec_microload + GRIDKIT::solvers_dyn + GRIDKIT::powerelec_mircobusdq) + +add_test(NAME ScaleMicrogrid COMMAND $) +install(TARGETS scalemicrogrid RUNTIME DESTINATION bin) diff --git a/Examples/Scale_Microgrid/Scale_Microgrid.cpp b/Examples/Scale_Microgrid/Scale_Microgrid.cpp new file mode 100644 index 000000000..de5174e5e --- /dev/null +++ b/Examples/Scale_Microgrid/Scale_Microgrid.cpp @@ -0,0 +1,366 @@ + + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include +#include +#include + +int main(int argc, char const *argv[]) +{ + double abstol = 1.0e-8; + double reltol = 1.0e-8; + size_t max_step_amount = 3000; + bool usejac = true; + + //TODO:setup as named parameters + //Create circuit model + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac, max_step_amount); + + + //The amount of DG line load cobinations to generate for scale + size_t Nsize = 2; + + //Modeled after the problem in the paper + // Every Bus has the same virtual resistance. This is due to the numerical stability as mentioned in the paper. + double RN = 1.0e4; + + //DG Params Vector + //All DGs have the same set of parameters except for the first two. + ModelLib::DiscreteGeneratorParameters DG_parms1; + DG_parms1.wb = 2.0*M_PI*50.0; + DG_parms1.wc = 31.41; + DG_parms1.mp = 9.4e-5; + DG_parms1.Vn = 380.0; + DG_parms1.nq = 1.3e-3; + DG_parms1.F = 0.75; + DG_parms1.Kiv = 420.0; + DG_parms1.Kpv = 0.1; + DG_parms1.Kic = 2.0e4; + DG_parms1.Kpc = 15.0; + DG_parms1.Cf = 5.0e-5; + DG_parms1.rLf = 0.1; + DG_parms1.Lf = 1.35e-3; + DG_parms1.rLc = 0.03; + DG_parms1.Lc = 0.35e-3; + + ModelLib::DiscreteGeneratorParameters DG_parms2; + DG_parms2.wb = 2.0*M_PI*50.0; + DG_parms2.wc = 31.41; + DG_parms2.mp = 12.5e-5; + DG_parms2.Vn = 380.0; + DG_parms2.nq = 1.5e-3; + DG_parms2.F = 0.75; + DG_parms2.Kiv = 390.0; + DG_parms2.Kpv = 0.05; + DG_parms2.Kic = 16.0e3; + DG_parms2.Kpc = 10.5; + DG_parms2.Cf = 50.0e-6; + DG_parms2.rLf = 0.1; + DG_parms2.Lf = 1.35e-3; + DG_parms2.rLc = 0.03; + DG_parms2.Lc = 0.35e-3; + + std::vector> DGParams_list(2*Nsize, DG_parms2); + + DGParams_list[0] = DG_parms1; + DGParams_list[1] = DG_parms1; + + //line vector params + //Every odd line has the same parameters and every even line has the same parameters + double rline1 = 0.23; + double Lline1 = 0.1 / (2.0 * M_PI * 50.0); + double rline2 = 0.35; + double Lline2 = 0.58 / (2.0 * M_PI * 50.0); + std::vector rline_list(2*Nsize-1, 0.0); + std::vector Lline_list(2*Nsize-1, 0.0); + for (size_t i = 0; i < rline_list.size(); i++) + { + rline_list[i] = (i % 2) ? rline1 : rline2; + Lline_list[i] = (i % 2) ? Lline1 : Lline2; + } + + + //load parms + //Only the first load has the same paramaters. + double rload1 = 3.0; + double Lload1 = 2.0 / (2.0 * M_PI * 50.0); + double rload2 = 2.0; + double Lload2 = 1.0 / (2.0 * M_PI * 50.0); + + std::vector rload_list(Nsize, rload2); + std::vector Lload_list(Nsize, Lload2); + rload_list[0] = rload1; + Lload_list[0] = Lload1; + + // DGs + - refframe Lines + Loads + size_t vec_size_internals = 13*(2*Nsize) - 1 + (2 + 4*(Nsize - 1)) + 2*Nsize; + // \omegaref + BusDQ + size_t vec_size_externals = 1 + 2*(2*Nsize); + + std::vector vdqbus_index(2*Nsize,0); + vdqbus_index[0] = vec_size_internals + 1; + for (size_t i = 1; i < vdqbus_index.size(); i++) + { + vdqbus_index[i] = vdqbus_index[i-1] + 2; + } + + //Total size of the vector setup + size_t vec_size_total = vec_size_internals + vec_size_externals; + + + //Create the reference DG + ModelLib::DiscreteGenerator *dg_ref = new ModelLib::DiscreteGenerator(0, DGParams_list[0], true); + //ref motor + dg_ref->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg_ref->setExternalConnectionNodes(1,vdqbus_index[0]); + dg_ref->setExternalConnectionNodes(2,vdqbus_index[0] + 1); + //"grounding" of the difference + dg_ref->setExternalConnectionNodes(3,-1); + //internal connections + for (size_t i = 0; i < 12; i++) + { + + dg_ref->setExternalConnectionNodes(4 + i,i); + } + sysmodel->addComponent(dg_ref); + + //Keep track of models and index location + size_t indexv = 12; + size_t model_id = 1; + //Add all other DGs + for (size_t i = 1; i < 2*Nsize; i++) + { + + //current DG to add + ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(model_id, DGParams_list[i], false); + //ref motor + dg->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg->setExternalConnectionNodes(1,vdqbus_index[i]); + dg->setExternalConnectionNodes(2,vdqbus_index[i] + 1); + //internal connections + for (size_t j = 0; j < 13; j++) + { + + dg->setExternalConnectionNodes(3 + j,indexv + j); + } + indexv += 13; + sysmodel->addComponent(dg); + model_id++; + } + + // Load all the Line compoenents + for (size_t i = 0; i < 2*Nsize - 1; i++) + { + //line + ModelLib::MicrogridLine *line_model = new ModelLib::MicrogridLine(model_id, rline_list[i], Lline_list[i]); + //ref motor + line_model->setExternalConnectionNodes(0,vec_size_internals); + //input connections + line_model->setExternalConnectionNodes(1,vdqbus_index[i]); + line_model->setExternalConnectionNodes(2,vdqbus_index[i] + 1); + //output connections + line_model->setExternalConnectionNodes(3,vdqbus_index[i+1]); + line_model->setExternalConnectionNodes(4,vdqbus_index[i+1] + 1); + //internal connections + for (size_t j = 0; j < 2; j++) + { + line_model->setExternalConnectionNodes(5 + j,indexv + j); + } + indexv += 2; + sysmodel->addComponent(line_model); + model_id++; + } + + // Load all the Load components + for (size_t i = 0; i < Nsize; i++) + { + ModelLib::MicrogridLoad *load_model = new ModelLib::MicrogridLoad(model_id, rload_list[i], Lload_list[i]); + //ref motor + load_model->setExternalConnectionNodes(0,vec_size_internals); + //input connections + load_model->setExternalConnectionNodes(1,vdqbus_index[2*i]); + load_model->setExternalConnectionNodes(2,vdqbus_index[2*i] + 1); + //internal connections + for (size_t j = 0; j < 2; j++) + { + + load_model->setExternalConnectionNodes(3 + j,indexv + j); + } + indexv += 2; + sysmodel->addComponent(load_model); + model_id++; + } + + //Add all the microgrid Virtual DQ Buses + for (size_t i = 0; i < 2*Nsize; i++) + { + ModelLib::MicrogridBusDQ *virDQbus_model = new ModelLib::MicrogridBusDQ( + model_id, RN); + + virDQbus_model->setExternalConnectionNodes(0, vdqbus_index[i]); + virDQbus_model->setExternalConnectionNodes(1, vdqbus_index[i] + 1); + sysmodel->addComponent(virDQbus_model); + + model_id++; + } + + //allocate all the intial conditions + sysmodel->allocate(vec_size_total); + + std::cout << sysmodel->y().size() << std::endl; + std::cout << vec_size_internals << ", " << vec_size_externals << "\n"; + + //Create Intial points for states. Every state is to specified to the zero intially + for (size_t i = 0; i < vec_size_total; i++) + { + sysmodel->y()[i] = 0.0; + sysmodel->yp()[i] = 0.0; + } + + // Create Intial derivatives specifics generated in MATLAB + for (size_t i = 0; i < 2*Nsize; i++) + { + sysmodel->yp()[13*i - 1 + 3] = DGParams_list[i].Vn; + sysmodel->yp()[13*i - 1 + 5] = DGParams_list[i].Kpv * DGParams_list[i].Vn; + sysmodel->yp()[13*i - 1 + 7] = (DGParams_list[i].Kpc * DGParams_list[i].Kpv * DGParams_list[i].Vn) / DGParams_list[i].Lf; + } + + //since the intial P_com = 0, the set the intial vector to the reference frame + sysmodel->y()[vec_size_internals] = DG_parms1.wb; + + sysmodel->initialize(); + sysmodel->evaluateResidual(); + + std::vector& fres = sysmodel->getResidual(); + std::cout << "Verify Intial Resisdual is Zero: {\n"; + for (size_t i = 0; i < fres.size(); i++) + { + printf("%u : %e \n", i, fres[i]); + } + std::cout << "}\n"; + + sysmodel->updateTime(0.0, 1.0e-8); + sysmodel->evaluateJacobian(); + std::cout << "Intial Jacobian with alpha:\n"; + // std::cout << sysmodel->getJacobian().frobnorm() << "\n"; + + + //Create numerical integrator and configure it for the generator model + AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + double t_init = 0.0; + double t_final = 1.0; + + // setup simulation + idas->configureSimulation(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + + idas->runSimulation(t_final); + + std::vector& yfinial = sysmodel->y(); + + std::cout << "Final Vector y\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << yfinial[i] << "\n"; + } + + if(Nsize == 2) + { + //Generate from MATLAB code ODE form with tolerances of 1e-14 + std::vectortrue_vec{ + 2.297543153595780e+04, + 1.275311524125022e+04, + 3.763060183116022e-02, + -2.098153459325261e-02, + 1.848285659119097e-02, + -1.563291404944864e-04, + 6.321941907011718e+01, + -2.942264300846256e+01, + 3.634209302905854e+02, + -2.668928293656362e-06, + 6.321941919221522e+01, + -3.509200178595996e+01, + -7.555954467454730e-03, + 2.297580486511343e+04, + 8.742028429066131e+03, + 3.710079564796484e-02, + -1.421122598056797e-02, + 1.874079517807597e-02, + -9.891304812687215e-05, + 6.232933298360234e+01, + -1.796494061423331e+01, + 3.686353885026506e+02, + 3.465673854181523e-05, + 6.232933406188410e+01, + -2.371564475187742e+01, + -8.273939686941580e-02, + 1.727775042678524e+04, + 1.649365247247288e+04, + 3.116555157570849e-02, + -2.985990066758010e-02, + 2.250012115906506e-02, + -2.643873146501096e-04, + 4.861823510250247e+01, + -4.088592755441309e+01, + 3.552597163751238e+02, + -1.496407194199739e-04, + 4.861823504694532e+01, + -4.642797132602495e+01, + -8.445727984408551e-02, + 1.727723725566433e+04, + 9.182386962936238e+03, + 3.024959333190777e-02, + -1.617250828202081e-02, + 2.318056864131751e-02, + -1.295918667730514e-04, + 4.718938244522050e+01, + -1.935782085675469e+01, + 3.662262287803608e+02, + 1.076423957830039e-04, + 4.718938116520511e+01, + -2.507094256286497e+01, + -1.881248349415025e+01, + 2.114714832305742e+01, + 4.329946674909793e+01, + -3.037887936225145e+00, + -4.487023117352992e+01, + 2.895883729832657e+01, + 8.199613345691378e+01, + -5.623856502948122e+01, + 1.327498499660322e+02, + -8.228065162347022e+01, + 3.119995747945993e+02, + 3.576922945168803e+02, + -5.850795361581618e+00, + 3.641193316268954e+02, + -8.846325267612976e+00, + 3.472146752739036e+02, + -3.272400970143252e+01, + 3.604108939430972e+02, + -3.492842627398574e+01 + }; + + std::cout << "Test the Relative Error\n"; + for (size_t i = 0; i < true_vec.size(); i++) + { + printf("%u : %e ,\n", i, abs(true_vec[i] - yfinial[i]) / abs(true_vec[i])); + } + } + + return 0; +} From a2c22d4640bcabe0930c931539699df561a72082 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 26 Feb 2024 18:01:35 -0500 Subject: [PATCH 49/52] Fixed N=2 case --- Examples/Scale_Microgrid/Scale_Microgrid.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Examples/Scale_Microgrid/Scale_Microgrid.cpp b/Examples/Scale_Microgrid/Scale_Microgrid.cpp index de5174e5e..c4be8df86 100644 --- a/Examples/Scale_Microgrid/Scale_Microgrid.cpp +++ b/Examples/Scale_Microgrid/Scale_Microgrid.cpp @@ -86,8 +86,8 @@ int main(int argc, char const *argv[]) std::vector Lline_list(2*Nsize-1, 0.0); for (size_t i = 0; i < rline_list.size(); i++) { - rline_list[i] = (i % 2) ? rline1 : rline2; - Lline_list[i] = (i % 2) ? Lline1 : Lline2; + rline_list[i] = (i % 2) ? rline2 : rline1; + Lline_list[i] = (i % 2) ? Lline2 : Lline1; } @@ -144,7 +144,7 @@ int main(int argc, char const *argv[]) { //current DG to add - ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(model_id, DGParams_list[i], false); + ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(model_id++, DGParams_list[i], false); //ref motor dg->setExternalConnectionNodes(0,vec_size_internals); //outputs @@ -158,14 +158,13 @@ int main(int argc, char const *argv[]) } indexv += 13; sysmodel->addComponent(dg); - model_id++; } // Load all the Line compoenents for (size_t i = 0; i < 2*Nsize - 1; i++) { //line - ModelLib::MicrogridLine *line_model = new ModelLib::MicrogridLine(model_id, rline_list[i], Lline_list[i]); + ModelLib::MicrogridLine *line_model = new ModelLib::MicrogridLine(model_id++, rline_list[i], Lline_list[i]); //ref motor line_model->setExternalConnectionNodes(0,vec_size_internals); //input connections @@ -181,13 +180,12 @@ int main(int argc, char const *argv[]) } indexv += 2; sysmodel->addComponent(line_model); - model_id++; } // Load all the Load components for (size_t i = 0; i < Nsize; i++) { - ModelLib::MicrogridLoad *load_model = new ModelLib::MicrogridLoad(model_id, rload_list[i], Lload_list[i]); + ModelLib::MicrogridLoad *load_model = new ModelLib::MicrogridLoad(model_id++, rload_list[i], Lload_list[i]); //ref motor load_model->setExternalConnectionNodes(0,vec_size_internals); //input connections @@ -201,20 +199,17 @@ int main(int argc, char const *argv[]) } indexv += 2; sysmodel->addComponent(load_model); - model_id++; } //Add all the microgrid Virtual DQ Buses for (size_t i = 0; i < 2*Nsize; i++) { ModelLib::MicrogridBusDQ *virDQbus_model = new ModelLib::MicrogridBusDQ( - model_id, RN); + model_id++, RN); virDQbus_model->setExternalConnectionNodes(0, vdqbus_index[i]); virDQbus_model->setExternalConnectionNodes(1, vdqbus_index[i] + 1); sysmodel->addComponent(virDQbus_model); - - model_id++; } //allocate all the intial conditions From 9e92e6669206b1479cf5935ba8ebea3a031c4177 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Mon, 26 Feb 2024 19:04:44 -0500 Subject: [PATCH 50/52] Multiple Scaled Problems with References - Added N = 2,4,8 reference solutions from MATLAB - Microgrid Matches results for given sizes --- Examples/Scale_Microgrid/Scale_Microgrid.cpp | 123 ++++---- Examples/Scale_Microgrid/microgrid_N2.txt | 70 +++++ Examples/Scale_Microgrid/microgrid_N4.txt | 142 +++++++++ Examples/Scale_Microgrid/microgrid_N8.txt | 286 +++++++++++++++++++ 4 files changed, 546 insertions(+), 75 deletions(-) create mode 100644 Examples/Scale_Microgrid/microgrid_N2.txt create mode 100644 Examples/Scale_Microgrid/microgrid_N4.txt create mode 100644 Examples/Scale_Microgrid/microgrid_N8.txt diff --git a/Examples/Scale_Microgrid/Scale_Microgrid.cpp b/Examples/Scale_Microgrid/Scale_Microgrid.cpp index c4be8df86..15b54abff 100644 --- a/Examples/Scale_Microgrid/Scale_Microgrid.cpp +++ b/Examples/Scale_Microgrid/Scale_Microgrid.cpp @@ -29,7 +29,10 @@ int main(int argc, char const *argv[]) //The amount of DG line load cobinations to generate for scale - size_t Nsize = 2; + size_t Nsize = 8; + + //Set to false if the parameters choosen are not used to generate data files + bool orgparams = true; //Modeled after the problem in the paper // Every Bus has the same virtual resistance. This is due to the numerical stability as mentioned in the paper. @@ -274,88 +277,58 @@ int main(int argc, char const *argv[]) std::cout << yfinial[i] << "\n"; } - if(Nsize == 2) + //if proper MATLAB results are avalible and model is using origional parameters + //All data generated with abstol=1e-12 and reltol=1e-12 with ode23tb + if (orgparams && (Nsize == 2 || Nsize == 4 || Nsize == 8)) { - //Generate from MATLAB code ODE form with tolerances of 1e-14 - std::vectortrue_vec{ - 2.297543153595780e+04, - 1.275311524125022e+04, - 3.763060183116022e-02, - -2.098153459325261e-02, - 1.848285659119097e-02, - -1.563291404944864e-04, - 6.321941907011718e+01, - -2.942264300846256e+01, - 3.634209302905854e+02, - -2.668928293656362e-06, - 6.321941919221522e+01, - -3.509200178595996e+01, - -7.555954467454730e-03, - 2.297580486511343e+04, - 8.742028429066131e+03, - 3.710079564796484e-02, - -1.421122598056797e-02, - 1.874079517807597e-02, - -9.891304812687215e-05, - 6.232933298360234e+01, - -1.796494061423331e+01, - 3.686353885026506e+02, - 3.465673854181523e-05, - 6.232933406188410e+01, - -2.371564475187742e+01, - -8.273939686941580e-02, - 1.727775042678524e+04, - 1.649365247247288e+04, - 3.116555157570849e-02, - -2.985990066758010e-02, - 2.250012115906506e-02, - -2.643873146501096e-04, - 4.861823510250247e+01, - -4.088592755441309e+01, - 3.552597163751238e+02, - -1.496407194199739e-04, - 4.861823504694532e+01, - -4.642797132602495e+01, - -8.445727984408551e-02, - 1.727723725566433e+04, - 9.182386962936238e+03, - 3.024959333190777e-02, - -1.617250828202081e-02, - 2.318056864131751e-02, - -1.295918667730514e-04, - 4.718938244522050e+01, - -1.935782085675469e+01, - 3.662262287803608e+02, - 1.076423957830039e-04, - 4.718938116520511e+01, - -2.507094256286497e+01, - -1.881248349415025e+01, - 2.114714832305742e+01, - 4.329946674909793e+01, - -3.037887936225145e+00, - -4.487023117352992e+01, - 2.895883729832657e+01, - 8.199613345691378e+01, - -5.623856502948122e+01, - 1.327498499660322e+02, - -8.228065162347022e+01, - 3.119995747945993e+02, - 3.576922945168803e+02, - -5.850795361581618e+00, - 3.641193316268954e+02, - -8.846325267612976e+00, - 3.472146752739036e+02, - -3.272400970143252e+01, - 3.604108939430972e+02, - -3.492842627398574e+01 - }; + + //get relative path + std::string rel_path = std::filesystem::current_path(); + + const std::regex base_regex("(.+)\\/build.*"); + std::smatch base_match; + std::regex_match(rel_path, base_match, base_regex); + std::string base_path = base_match[1].str(); + + base_path += "/Examples/Scale_Microgrid"; + + switch (Nsize) + { + case 2: + base_path += "/microgrid_N2.txt"; + break; + case 4: + base_path += "/microgrid_N4.txt"; + break; + case 8: + base_path += "/microgrid_N8.txt"; + break; + default: + //shouldn't end up here bust just incase + assert(0==1); + break; + } + std::cout << base_path << std::endl; + + //load vector from data file + std::vector true_vec(vec_size_total, 0.0); + double val_cur = 0.0; + std::ifstream data_file(base_path); + size_t i = 0; + while (data_file >> val_cur && i < true_vec.size()) + { + true_vec[i++] = val_cur; + } + data_file.close(); + //check relative error std::cout << "Test the Relative Error\n"; for (size_t i = 0; i < true_vec.size(); i++) { printf("%u : %e ,\n", i, abs(true_vec[i] - yfinial[i]) / abs(true_vec[i])); } } + return 0; } diff --git a/Examples/Scale_Microgrid/microgrid_N2.txt b/Examples/Scale_Microgrid/microgrid_N2.txt new file mode 100644 index 000000000..d0edf2a51 --- /dev/null +++ b/Examples/Scale_Microgrid/microgrid_N2.txt @@ -0,0 +1,70 @@ +22975.4182636905 +12753.1173017451 +0.0376305671131306 +-0.0209815421114537 +0.0184828563235406 +-0.00015632917065729 +63.2193617412383 +-29.4226556659582 +363.420924977355 +-3.01001804456668e-06 +63.2193618667302 +-35.0920143829141 +-0.00755583999797958 +22975.8457840701 +8742.0172166684 +0.0371009878165673 +-0.0142112776774797 +0.0187407972932474 +-9.8913852531819e-05 +62.3296548917654 +-17.9650261562766 +368.635407345931 +3.79041261513032e-05 +62.3296560841534 +-23.7157298601546 +-0.0827401584095097 +17277.712521392 +16493.7578328327 +0.0311645357391787 +-0.0298601153771274 +0.0225001003469904 +-0.000264388302121386 +48.6166482764357 +-40.8862612232969 +355.25957014696 +-0.000167008045114112 +48.6166481095298 +-46.4283022775928 +-0.0844566209033113 +17277.2493364959 +9182.29479881977 +0.0302503981389185 +-0.0161722538457184 +0.023180586071601 +-0.000129590157483103 +47.1906392248137 +-19.3574255862892 +366.226354188735 +0.000121054462396047 +47.19063792117 +-25.0705499054599 +-18.8125403122072 +21.1471334522508 +43.2997340692497 +-3.03798323340816 +-44.8715356440453 +28.9585224749495 +81.99613295014 +-56.2385627562355 +132.749774614687 +-82.280664729262 +311.999576042192 +357.692287974629 +-5.85078929333349 +364.119335219897 +-8.84631033126304 +347.214535767435 +-32.7241067379802 +360.411028950125 +-34.9283280833745 diff --git a/Examples/Scale_Microgrid/microgrid_N4.txt b/Examples/Scale_Microgrid/microgrid_N4.txt new file mode 100644 index 000000000..29a0b71b8 --- /dev/null +++ b/Examples/Scale_Microgrid/microgrid_N4.txt @@ -0,0 +1,142 @@ +27828.3291148094 +10602.3611530864 +0.0452452394028709 +-0.0173410584955486 +0.018686818367312 +-0.000129595027000909 +76.0120809944985 +-23.2367034227098 +366.216582730654 +-0.000167782960864797 +76.0120710728117 +-28.9413214479885 +-0.0154989336357971 +27832.0772154743 +7838.80352597054 +0.0448129806183038 +-0.0127296381144373 +0.0188642014642206 +-9.04502393904097e-05 +75.2859236720964 +-15.4316980534341 +369.809174828127 +-5.17440472732025e-05 +75.285919083362 +-21.1922719962368 +-0.142596248886844 +20950.1519748442 +16334.3924580166 +0.0377787488551238 +-0.0295717781600636 +0.0225780601074885 +-0.000265567743682681 +58.9348270364006 +-40.4081583028089 +355.498460539903 +-8.66167274613643e-05 +58.9348242715342 +-45.9457664944992 +-0.164628885385433 +20956.2846481359 +12345.7855779785 +0.0371673110634281 +-0.0220171188824754 +0.0229486760225139 +-0.000191111142238558 +57.9810673844105 +-28.5265491599081 +361.481100853144 +8.24481547667206e-05 +57.9810719040216 +-34.1573355283559 +-0.245126576498858 +20978.9206932923 +17875.6825958711 +0.0380785081131898 +-0.0325621468970297 +0.0224354615928625 +-0.000295085318936756 +59.4025243779293 +-45.1101946009202 +353.186117339098 +5.52721744209165e-05 +59.4025238741703 +-50.6117204294148 +-0.253672269778405 +20990.6142554844 +11779.5685373245 +0.0371243965775962 +-0.0209716906203726 +0.0230016494389548 +-0.000180846578022512 +57.9140614794815 +-26.8817831662193 +362.331254349606 +0.000209247259473183 +57.9140782926947 +-32.5257339504705 +-0.288747285297145 +21004.5418902462 +16686.981801999 +0.0379131316203435 +-0.0302602142538338 +0.0225460339603269 +-0.000272422675391038 +59.1444740212228 +-41.4902940591195 +354.969993387113 +8.14114753778542e-05 +59.1444846638236 +-47.0195494892644 +-0.285876486857154 +21005.895228757 +8274.13913126834 +0.0366267978764156 +-0.0145584209340773 +0.0233276948336748 +-0.000117627382397687 +57.1378568500881 +-16.7923279871216 +367.58883605301 +0.000263351556352378 +57.1378679159653 +-22.518140603782 +-6.57009481597077 +28.1053117219546 +68.341829672125 +5.75010361666728 +-7.27398138223966 +42.3413009908014 +44.2901915856089 +-0.850144510998897 +-26.9214526328474 +37.7939474726438 +20.9421230166698 +-8.2155394685309 +-48.4341275019927 +37.706248875936 +82.5460878639016 +-57.0458911301263 +127.388509162578 +-90.4406093871607 +116.522583626035 +-102.149734009655 +112.650118587972 +-107.825883544914 +311.543402422187 +360.780248808368 +-7.42039816792328 +365.078323407317 +-13.2331839185884 +344.46378568747 +-54.5546252592288 +350.335287885457 +-63.572021962256 +334.342198258035 +-88.749585714325 +344.281369936645 +-94.7726681838823 +332.2248206198 +-103.942854393111 +347.103721199815 +-107.812479611979 diff --git a/Examples/Scale_Microgrid/microgrid_N8.txt b/Examples/Scale_Microgrid/microgrid_N8.txt new file mode 100644 index 000000000..3e1ba779b --- /dev/null +++ b/Examples/Scale_Microgrid/microgrid_N8.txt @@ -0,0 +1,286 @@ +29266.6517718661 +9842.93617289812 +0.0475360674334622 +-0.0160323945316821 +0.0187557247105805 +-0.000119821248231538 +79.8612117213119 +-21.0144010498971 +367.201497494684 +-0.00135963018489767 +79.8611351716573 +-26.7318789917162 +-0.018074876389402 +29296.9645459408 +7415.51099954903 +0.0471789367393934 +-0.0120180219897291 +0.0189117902285582 +-8.57914733703415e-05 +79.2614266664798 +-14.2194852461262 +370.357116139458 +-0.00065261697325357 +79.261388452934 +-19.9860446882469 +-0.161178046356866 +22178.7337755581 +15750.48869542 +0.0399575496599213 +-0.028431003000158 +0.0226540351215628 +-0.000255811047442045 +62.3338080750298 +-38.6061338491152 +356.372404460464 +-0.000888421043595241 +62.3337589017493 +-44.1546192236143 +-0.191206982234175 +22245.3587939821 +12476.0312983393 +0.0395296431152022 +-0.0222832972915751 +0.0229591349358969 +-0.000195357283522886 +61.6667253463805 +-28.9363062720176 +361.284131747149 +0.000606091049765824 +61.6667589580497 +-34.5611135316627 +-0.300475535038271 +22471.354929649 +17410.9400696732 +0.0407475331761201 +-0.0316496339533813 +0.0225047347006168 +-0.000287941144857336 +63.5662158978541 +-43.6654709736205 +353.882194971394 +-0.00050508442766251 +63.5661867600733 +-49.1745383652835 +-0.321406735230742 +22562.1063953332 +12532.040739496 +0.0400730650460856 +-0.0224103188019356 +0.0229590093469276 +-0.000197040279593967 +62.5145400797163 +-29.1337602252211 +361.200953962968 +0.00123813270414561 +62.5146115608051 +-34.7565572443792 +-0.398765881347133 +22822.9625175864 +17526.9123376124 +0.0413769691613727 +-0.0318846988884131 +0.0224996948233429 +-0.000290724959665147 +64.5480523645119 +-44.0326735095454 +353.709220392926 +-0.000255137918253834 +64.548036917491 +-49.5382706457328 +-0.409294621792759 +22917.4640781459 +11700.1980576741 +0.0405370737861658 +-0.0208717910251266 +0.0230419643488667 +-0.000182321342412399 +63.2383663569188 +-26.7111380754575 +362.449323338104 +0.00143605100750772 +63.2384503029344 +-32.3525635247183 +-0.460038982115987 +23175.0870418607 +17429.0372806116 +0.0419717095772374 +-0.0317010913432995 +0.0225145433123769 +-0.000289381352876061 +65.4757968347883 +-43.7415548084125 +353.856643943042 +-0.000116590766441278 +65.4757901489451 +-49.2486679790579 +-0.461848591689221 +23264.6732405303 +10919.0360806903 +0.0409947737541995 +-0.0194331296392293 +0.0231200668519233 +-0.000168575863901554 +63.9522672718067 +-24.4455560147541 +363.621937642842 +0.00154556746783549 +63.9523565934322 +-30.1044436917781 +-0.491529580804623 +23488.6137650364 +17313.8654584652 +0.0424952351974662 +-0.0314883547842804 +0.0225303364455447 +-0.000287714847080755 +66.2924442955506 +-43.4048501801219 +354.030311475628 +0.000169934086992562 +66.2924545883603 +-48.9139721676174 +-0.486548093474613 +23557.6136117665 +10241.0790360359 +0.0413774884672506 +-0.0181860120867723 +0.0231877453638413 +-0.000156639599075328 +64.5492156984859 +-22.4816084883194 +364.639179755733 +0.00142420279185394 +64.5492984953198 +-28.1556597465189 +-0.499726325044563 +23722.4168131373 +16958.7765974266 +0.0428487548646152 +-0.0308090857078185 +0.0225672437721518 +-0.000281355782039133 +66.8440182379463 +-42.3350991467661 +354.562942832682 +0.000573219240561573 +66.844044569212 +-47.8519918014414 +-0.490219448053285 +23769.8747006891 +9267.5206785042 +0.0415639300026818 +-0.0164109903099032 +0.0232814268213158 +-0.000139385907988285 +64.8399200066663 +-19.6874999818575 +366.100410278813 +0.00128332197988872 +64.8400012051758 +-25.3838027935624 +-0.491586583798841 +23854.0240861864 +15160.7060140903 +0.0427385845553072 +-0.0273659210853948 +0.0227360281885303 +-0.00024756822257102 +66.6722121992594 +-36.9193366680176 +357.260483774461 +0.000734666517031364 +66.6722602990682 +-42.4779079553274 +-0.482907936930927 +23870.5548740189 +6166.60742794455 +0.0412253604361869 +-0.0108406830677542 +0.0235710268609798 +-8.45378382385454e-05 +64.3117067426907 +-10.9219886629635 +370.751596332923 +0.00130490570318174 +64.3117765573399 +-16.6904284244068 +-2.9267653635869 +30.5878043390112 +75.9238910016987 +9.17392754248112 +4.3701560041079 +48.7765765968327 +58.3101300775815 +3.13323809951331 +-6.37573932293514 +46.1701408549949 +41.9244199648313 +-6.5432868117422 +-17.3691293511209 +41.8611610718482 +27.7383173553277 +-12.9709065074016 +-27.5322418670623 +38.9032728624808 +16.2733736528389 +-16.5280348065045 +-36.4800564569504 +37.0627808819117 +7.38198504755967 +-17.9899033675727 +-44.0731708800056 +36.9539474625741 +1.14781892918688 +-15.9507601441003 +-49.1751072411967 +44.6278268007059 +82.7517114852138 +-57.3188928805757 +125.959171148664 +-93.1822145893453 +110.816672146529 +-108.811406393296 +99.5107131550674 +-119.104827911048 +92.0427992280762 +-125.056967118294 +88.0811872722293 +-127.985464658329 +87.1649116220972 +-128.957730829954 +89.0189233593932 +-129.480383815729 +311.408200092424 +361.890500304156 +-7.90450151715305 +365.594288034004 +-14.6504114199963 +344.278948204657 +-61.517809887448 +348.104769580715 +-73.1715704285651 +329.472137794467 +-107.797643650827 +335.509251816504 +-117.787067889008 +317.044841017058 +-139.602945170765 +325.182412285621 +-147.51178633583 +307.989533967543 +-158.91998673915 +318.171184823086 +-165.141414351062 +302.951769665185 +-168.712626964975 +315.009688292198 +-173.624287308414 +302.070219389208 +-171.572667424371 +315.86470341008 +-175.706947618597 +306.288884765777 +-170.785573848562 +322.018589824395 +-176.179397251772 From 6616ce5d9d13a31bbd9fe0e9f5fac39b45efe369 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Tue, 7 May 2024 17:32:16 -0400 Subject: [PATCH 51/52] Rebase Fixes of develop --- ComponentLib/Bus/BusPV.cpp | 6 ++--- ComponentLib/Bus/BusPV.hpp | 2 +- ComponentLib/Bus/BusSlack.hpp | 1 - Examples/Grid3Bus/Grid3BusSys.cpp | 4 ++++ Solver/Dynamic/Ida.cpp | 2 +- SystemSteadyStateModel.hpp | 37 ------------------------------- 6 files changed, 9 insertions(+), 43 deletions(-) diff --git a/ComponentLib/Bus/BusPV.cpp b/ComponentLib/Bus/BusPV.cpp index fd05b2ecb..13ff37512 100644 --- a/ComponentLib/Bus/BusPV.cpp +++ b/ComponentLib/Bus/BusPV.cpp @@ -74,7 +74,7 @@ namespace ModelLib { */ template BusPV::BusPV() - : BaseBus(0), V_(0.0), theta0_(0.0), Pg_(0.0) + : BaseBus(0), V_(0.0), theta0_(0.0) { //std::cout << "Create BusPV..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; @@ -92,8 +92,8 @@ BusPV::BusPV() * - Number of optimization parameters = 0 */ template -BusPV::BusPV(ScalarT V, ScalarT theta0, ScalarT Pg) - : BaseBus(0), V_(V), theta0_(theta0), Pg_(Pg) +BusPV::BusPV(ScalarT V, ScalarT theta0) + : BaseBus(0), V_(V), theta0_(theta0) { //std::cout << "Create BusPV ..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp index a629c0b00..cf645d591 100644 --- a/ComponentLib/Bus/BusPV.hpp +++ b/ComponentLib/Bus/BusPV.hpp @@ -91,7 +91,7 @@ namespace ModelLib using BusData = GridKit::PowerSystemData::BusData; BusPV(); - BusPV(ScalarT V, ScalarT theta0, ScalarT P); + BusPV(ScalarT V, ScalarT theta0); BusPV(BusData& data); virtual ~BusPV(); diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp index 8bb973d1b..19c27d96a 100644 --- a/ComponentLib/Bus/BusSlack.hpp +++ b/ComponentLib/Bus/BusSlack.hpp @@ -92,7 +92,6 @@ namespace ModelLib BusSlack(); BusSlack(ScalarT V, ScalarT theta); BusSlack(BusData& data); - BusSlack(BusData& data); virtual ~BusSlack(); virtual int evaluateResidual(); virtual int evaluateAdjointResidual(); diff --git a/Examples/Grid3Bus/Grid3BusSys.cpp b/Examples/Grid3Bus/Grid3BusSys.cpp index f14aa0d6e..654b7eb7e 100644 --- a/Examples/Grid3Bus/Grid3BusSys.cpp +++ b/Examples/Grid3Bus/Grid3BusSys.cpp @@ -145,6 +145,10 @@ using namespace AnalysisManager; using namespace GridKit::Testing; using namespace GridKit::PowerSystemData; +constexpr double theta2_ref = -4.87979; // [deg] +constexpr double V2_ref = 1.08281; // [p.u.] +constexpr double theta3_ref = 1.46241; // [deg] + /** * Testing the monlithic case via the class MiniGrid diff --git a/Solver/Dynamic/Ida.cpp b/Solver/Dynamic/Ida.cpp index 2be2913a9..a9beca964 100644 --- a/Solver/Dynamic/Ida.cpp +++ b/Solver/Dynamic/Ida.cpp @@ -422,7 +422,7 @@ namespace Sundials checkOutput(retval, "IDASetUserDataB"); /// \todo Need to set max number of steps based on user input! - retval = IDASetMaxNumStepsB(solver_, backwardID_, 200); + retval = IDASetMaxNumStepsB(solver_, backwardID_, 2000); checkOutput(retval, "IDASetMaxNumSteps"); // Set up linear solver diff --git a/SystemSteadyStateModel.hpp b/SystemSteadyStateModel.hpp index de2dc000e..c32dd5ec3 100644 --- a/SystemSteadyStateModel.hpp +++ b/SystemSteadyStateModel.hpp @@ -127,43 +127,6 @@ class SystemSteadyStateModel : public ModelEvaluatorImpl atol_ = 1e-5; } - SystemSteadyStateModel(GridKit::PowerSystemData::SystemModelData mp) : ModelEvaluatorImpl(0,0,0) - { - rtol_ = 1e-5; - atol_ = 1e-5; - - //buses - for(auto busdata : mp.bus) - { - auto* bus = BusFactory::create(busdata); - this->addBus(bus); - } - - //generators - for (auto gendata : mp.gen) - { - auto* gen = GeneratorFactory::create(this->getBus(gendata.bus),gendata); - this->addComponent(gen); - } - - //branches - for (auto branchdata : mp.branch) - { - auto* branch = new Branch(this->getBus(branchdata.fbus),this->getBus(branchdata.tbus),branchdata); - this->addComponent(branch); - } - - //loads - for (auto loaddata : mp.load) - { - auto* loadm = new Load(this->getBus(loaddata.bus_i),loaddata); - this->addComponent(loadm); - } - - //There appears to not be a Generator Cost Object - //TODO: Implment for GenCost - } - /** * @brief Construct a new System Steady State Model object. Allows for simple allocation. * From 749f8d1591e519dce7aaeb6bce0e87ecb6e29d52 Mon Sep 17 00:00:00 2001 From: Reid Gomillion Date: Tue, 7 May 2024 23:05:06 -0400 Subject: [PATCH 52/52] Updated Scale Microgrid for CMake Source --- CMakeLists.txt | 3 + Examples/Scale_Microgrid/Scale_Microgrid.cpp | 587 +++++++++---------- 2 files changed, 288 insertions(+), 302 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index badea53a8..7a6e651e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,9 @@ option(GRIDKIT_ENABLE_SUNDIALS_SPARSE "Enable SUNDIALS sparse linear solvers" ON set(CMAKE_MACOSX_RPATH 1) +#Provide string to source +add_compile_definitions("SOURCE_ROOT=${CMAKE_SOURCE_DIR}") + list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake) # https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling#always-full-rpath diff --git a/Examples/Scale_Microgrid/Scale_Microgrid.cpp b/Examples/Scale_Microgrid/Scale_Microgrid.cpp index 15b54abff..9f1baef64 100644 --- a/Examples/Scale_Microgrid/Scale_Microgrid.cpp +++ b/Examples/Scale_Microgrid/Scale_Microgrid.cpp @@ -16,248 +16,251 @@ #include #include +//macro to get macro +#define STRING(x) #x +#define XSTRING(x) STRING(x) + int main(int argc, char const *argv[]) { - double abstol = 1.0e-8; - double reltol = 1.0e-8; - size_t max_step_amount = 3000; - bool usejac = true; - - //TODO:setup as named parameters - //Create circuit model - ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac, max_step_amount); - - - //The amount of DG line load cobinations to generate for scale - size_t Nsize = 8; - - //Set to false if the parameters choosen are not used to generate data files - bool orgparams = true; - - //Modeled after the problem in the paper - // Every Bus has the same virtual resistance. This is due to the numerical stability as mentioned in the paper. - double RN = 1.0e4; - - //DG Params Vector - //All DGs have the same set of parameters except for the first two. - ModelLib::DiscreteGeneratorParameters DG_parms1; - DG_parms1.wb = 2.0*M_PI*50.0; - DG_parms1.wc = 31.41; - DG_parms1.mp = 9.4e-5; - DG_parms1.Vn = 380.0; - DG_parms1.nq = 1.3e-3; - DG_parms1.F = 0.75; - DG_parms1.Kiv = 420.0; - DG_parms1.Kpv = 0.1; - DG_parms1.Kic = 2.0e4; - DG_parms1.Kpc = 15.0; - DG_parms1.Cf = 5.0e-5; - DG_parms1.rLf = 0.1; - DG_parms1.Lf = 1.35e-3; - DG_parms1.rLc = 0.03; - DG_parms1.Lc = 0.35e-3; - - ModelLib::DiscreteGeneratorParameters DG_parms2; - DG_parms2.wb = 2.0*M_PI*50.0; - DG_parms2.wc = 31.41; - DG_parms2.mp = 12.5e-5; - DG_parms2.Vn = 380.0; - DG_parms2.nq = 1.5e-3; - DG_parms2.F = 0.75; - DG_parms2.Kiv = 390.0; - DG_parms2.Kpv = 0.05; - DG_parms2.Kic = 16.0e3; - DG_parms2.Kpc = 10.5; - DG_parms2.Cf = 50.0e-6; - DG_parms2.rLf = 0.1; - DG_parms2.Lf = 1.35e-3; - DG_parms2.rLc = 0.03; - DG_parms2.Lc = 0.35e-3; - - std::vector> DGParams_list(2*Nsize, DG_parms2); - - DGParams_list[0] = DG_parms1; - DGParams_list[1] = DG_parms1; - - //line vector params - //Every odd line has the same parameters and every even line has the same parameters - double rline1 = 0.23; - double Lline1 = 0.1 / (2.0 * M_PI * 50.0); - double rline2 = 0.35; - double Lline2 = 0.58 / (2.0 * M_PI * 50.0); - std::vector rline_list(2*Nsize-1, 0.0); - std::vector Lline_list(2*Nsize-1, 0.0); - for (size_t i = 0; i < rline_list.size(); i++) - { - rline_list[i] = (i % 2) ? rline2 : rline1; - Lline_list[i] = (i % 2) ? Lline2 : Lline1; - } - - - //load parms - //Only the first load has the same paramaters. - double rload1 = 3.0; - double Lload1 = 2.0 / (2.0 * M_PI * 50.0); - double rload2 = 2.0; - double Lload2 = 1.0 / (2.0 * M_PI * 50.0); - - std::vector rload_list(Nsize, rload2); - std::vector Lload_list(Nsize, Lload2); - rload_list[0] = rload1; - Lload_list[0] = Lload1; - - // DGs + - refframe Lines + Loads - size_t vec_size_internals = 13*(2*Nsize) - 1 + (2 + 4*(Nsize - 1)) + 2*Nsize; - // \omegaref + BusDQ - size_t vec_size_externals = 1 + 2*(2*Nsize); - - std::vector vdqbus_index(2*Nsize,0); - vdqbus_index[0] = vec_size_internals + 1; - for (size_t i = 1; i < vdqbus_index.size(); i++) - { - vdqbus_index[i] = vdqbus_index[i-1] + 2; - } - - //Total size of the vector setup - size_t vec_size_total = vec_size_internals + vec_size_externals; - - - //Create the reference DG - ModelLib::DiscreteGenerator *dg_ref = new ModelLib::DiscreteGenerator(0, DGParams_list[0], true); - //ref motor - dg_ref->setExternalConnectionNodes(0,vec_size_internals); - //outputs - dg_ref->setExternalConnectionNodes(1,vdqbus_index[0]); - dg_ref->setExternalConnectionNodes(2,vdqbus_index[0] + 1); - //"grounding" of the difference - dg_ref->setExternalConnectionNodes(3,-1); - //internal connections - for (size_t i = 0; i < 12; i++) - { - - dg_ref->setExternalConnectionNodes(4 + i,i); - } - sysmodel->addComponent(dg_ref); - - //Keep track of models and index location - size_t indexv = 12; - size_t model_id = 1; - //Add all other DGs - for (size_t i = 1; i < 2*Nsize; i++) - { - - //current DG to add - ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(model_id++, DGParams_list[i], false); - //ref motor - dg->setExternalConnectionNodes(0,vec_size_internals); - //outputs - dg->setExternalConnectionNodes(1,vdqbus_index[i]); - dg->setExternalConnectionNodes(2,vdqbus_index[i] + 1); - //internal connections - for (size_t j = 0; j < 13; j++) - { - - dg->setExternalConnectionNodes(3 + j,indexv + j); - } - indexv += 13; - sysmodel->addComponent(dg); - } - - // Load all the Line compoenents - for (size_t i = 0; i < 2*Nsize - 1; i++) - { - //line - ModelLib::MicrogridLine *line_model = new ModelLib::MicrogridLine(model_id++, rline_list[i], Lline_list[i]); - //ref motor - line_model->setExternalConnectionNodes(0,vec_size_internals); - //input connections - line_model->setExternalConnectionNodes(1,vdqbus_index[i]); - line_model->setExternalConnectionNodes(2,vdqbus_index[i] + 1); - //output connections - line_model->setExternalConnectionNodes(3,vdqbus_index[i+1]); - line_model->setExternalConnectionNodes(4,vdqbus_index[i+1] + 1); - //internal connections - for (size_t j = 0; j < 2; j++) - { - line_model->setExternalConnectionNodes(5 + j,indexv + j); - } - indexv += 2; - sysmodel->addComponent(line_model); - } - - // Load all the Load components - for (size_t i = 0; i < Nsize; i++) - { - ModelLib::MicrogridLoad *load_model = new ModelLib::MicrogridLoad(model_id++, rload_list[i], Lload_list[i]); - //ref motor - load_model->setExternalConnectionNodes(0,vec_size_internals); - //input connections - load_model->setExternalConnectionNodes(1,vdqbus_index[2*i]); - load_model->setExternalConnectionNodes(2,vdqbus_index[2*i] + 1); - //internal connections - for (size_t j = 0; j < 2; j++) - { - - load_model->setExternalConnectionNodes(3 + j,indexv + j); - } - indexv += 2; - sysmodel->addComponent(load_model); - } - - //Add all the microgrid Virtual DQ Buses - for (size_t i = 0; i < 2*Nsize; i++) - { - ModelLib::MicrogridBusDQ *virDQbus_model = new ModelLib::MicrogridBusDQ( - model_id++, RN); - - virDQbus_model->setExternalConnectionNodes(0, vdqbus_index[i]); - virDQbus_model->setExternalConnectionNodes(1, vdqbus_index[i] + 1); - sysmodel->addComponent(virDQbus_model); - } - - //allocate all the intial conditions - sysmodel->allocate(vec_size_total); - - std::cout << sysmodel->y().size() << std::endl; - std::cout << vec_size_internals << ", " << vec_size_externals << "\n"; - - //Create Intial points for states. Every state is to specified to the zero intially - for (size_t i = 0; i < vec_size_total; i++) - { - sysmodel->y()[i] = 0.0; - sysmodel->yp()[i] = 0.0; - } - - // Create Intial derivatives specifics generated in MATLAB - for (size_t i = 0; i < 2*Nsize; i++) - { - sysmodel->yp()[13*i - 1 + 3] = DGParams_list[i].Vn; - sysmodel->yp()[13*i - 1 + 5] = DGParams_list[i].Kpv * DGParams_list[i].Vn; - sysmodel->yp()[13*i - 1 + 7] = (DGParams_list[i].Kpc * DGParams_list[i].Kpv * DGParams_list[i].Vn) / DGParams_list[i].Lf; - } - - //since the intial P_com = 0, the set the intial vector to the reference frame - sysmodel->y()[vec_size_internals] = DG_parms1.wb; - - sysmodel->initialize(); - sysmodel->evaluateResidual(); - - std::vector& fres = sysmodel->getResidual(); - std::cout << "Verify Intial Resisdual is Zero: {\n"; - for (size_t i = 0; i < fres.size(); i++) - { - printf("%u : %e \n", i, fres[i]); - } - std::cout << "}\n"; - - sysmodel->updateTime(0.0, 1.0e-8); - sysmodel->evaluateJacobian(); - std::cout << "Intial Jacobian with alpha:\n"; - // std::cout << sysmodel->getJacobian().frobnorm() << "\n"; - - - //Create numerical integrator and configure it for the generator model - AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + double abstol = 1.0e-8; + double reltol = 1.0e-8; + size_t max_step_amount = 3000; + bool usejac = true; + + //TODO:setup as named parameters + //Create circuit model + ModelLib::PowerElectronicsModel* sysmodel = new ModelLib::PowerElectronicsModel(reltol, abstol, usejac, max_step_amount); + + + //The amount of DG line load cobinations to generate for scale + size_t Nsize = 8; + + //Set to false if the parameters choosen are not used to generate data files + bool orgparams = true; + + //Modeled after the problem in the paper + // Every Bus has the same virtual resistance. This is due to the numerical stability as mentioned in the paper. + double RN = 1.0e4; + + //DG Params Vector + //All DGs have the same set of parameters except for the first two. + ModelLib::DiscreteGeneratorParameters DG_parms1; + DG_parms1.wb = 2.0*M_PI*50.0; + DG_parms1.wc = 31.41; + DG_parms1.mp = 9.4e-5; + DG_parms1.Vn = 380.0; + DG_parms1.nq = 1.3e-3; + DG_parms1.F = 0.75; + DG_parms1.Kiv = 420.0; + DG_parms1.Kpv = 0.1; + DG_parms1.Kic = 2.0e4; + DG_parms1.Kpc = 15.0; + DG_parms1.Cf = 5.0e-5; + DG_parms1.rLf = 0.1; + DG_parms1.Lf = 1.35e-3; + DG_parms1.rLc = 0.03; + DG_parms1.Lc = 0.35e-3; + + ModelLib::DiscreteGeneratorParameters DG_parms2; + DG_parms2.wb = 2.0*M_PI*50.0; + DG_parms2.wc = 31.41; + DG_parms2.mp = 12.5e-5; + DG_parms2.Vn = 380.0; + DG_parms2.nq = 1.5e-3; + DG_parms2.F = 0.75; + DG_parms2.Kiv = 390.0; + DG_parms2.Kpv = 0.05; + DG_parms2.Kic = 16.0e3; + DG_parms2.Kpc = 10.5; + DG_parms2.Cf = 50.0e-6; + DG_parms2.rLf = 0.1; + DG_parms2.Lf = 1.35e-3; + DG_parms2.rLc = 0.03; + DG_parms2.Lc = 0.35e-3; + + std::vector> DGParams_list(2*Nsize, DG_parms2); + + DGParams_list[0] = DG_parms1; + DGParams_list[1] = DG_parms1; + + //line vector params + //Every odd line has the same parameters and every even line has the same parameters + double rline1 = 0.23; + double Lline1 = 0.1 / (2.0 * M_PI * 50.0); + double rline2 = 0.35; + double Lline2 = 0.58 / (2.0 * M_PI * 50.0); + std::vector rline_list(2*Nsize-1, 0.0); + std::vector Lline_list(2*Nsize-1, 0.0); + for (size_t i = 0; i < rline_list.size(); i++) + { + rline_list[i] = (i % 2) ? rline2 : rline1; + Lline_list[i] = (i % 2) ? Lline2 : Lline1; + } + + + //load parms + //Only the first load has the same paramaters. + double rload1 = 3.0; + double Lload1 = 2.0 / (2.0 * M_PI * 50.0); + double rload2 = 2.0; + double Lload2 = 1.0 / (2.0 * M_PI * 50.0); + + std::vector rload_list(Nsize, rload2); + std::vector Lload_list(Nsize, Lload2); + rload_list[0] = rload1; + Lload_list[0] = Lload1; + + // DGs + - refframe Lines + Loads + size_t vec_size_internals = 13*(2*Nsize) - 1 + (2 + 4*(Nsize - 1)) + 2*Nsize; + // \omegaref + BusDQ + size_t vec_size_externals = 1 + 2*(2*Nsize); + + std::vector vdqbus_index(2*Nsize,0); + vdqbus_index[0] = vec_size_internals + 1; + for (size_t i = 1; i < vdqbus_index.size(); i++) + { + vdqbus_index[i] = vdqbus_index[i-1] + 2; + } + + //Total size of the vector setup + size_t vec_size_total = vec_size_internals + vec_size_externals; + + + //Create the reference DG + ModelLib::DiscreteGenerator *dg_ref = new ModelLib::DiscreteGenerator(0, DGParams_list[0], true); + //ref motor + dg_ref->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg_ref->setExternalConnectionNodes(1,vdqbus_index[0]); + dg_ref->setExternalConnectionNodes(2,vdqbus_index[0] + 1); + //"grounding" of the difference + dg_ref->setExternalConnectionNodes(3,-1); + //internal connections + for (size_t i = 0; i < 12; i++) + { + + dg_ref->setExternalConnectionNodes(4 + i,i); + } + sysmodel->addComponent(dg_ref); + + //Keep track of models and index location + size_t indexv = 12; + size_t model_id = 1; + //Add all other DGs + for (size_t i = 1; i < 2*Nsize; i++) + { + + //current DG to add + ModelLib::DiscreteGenerator *dg = new ModelLib::DiscreteGenerator(model_id++, DGParams_list[i], false); + //ref motor + dg->setExternalConnectionNodes(0,vec_size_internals); + //outputs + dg->setExternalConnectionNodes(1,vdqbus_index[i]); + dg->setExternalConnectionNodes(2,vdqbus_index[i] + 1); + //internal connections + for (size_t j = 0; j < 13; j++) + { + + dg->setExternalConnectionNodes(3 + j,indexv + j); + } + indexv += 13; + sysmodel->addComponent(dg); + } + + // Load all the Line compoenents + for (size_t i = 0; i < 2*Nsize - 1; i++) + { + //line + ModelLib::MicrogridLine *line_model = new ModelLib::MicrogridLine(model_id++, rline_list[i], Lline_list[i]); + //ref motor + line_model->setExternalConnectionNodes(0,vec_size_internals); + //input connections + line_model->setExternalConnectionNodes(1,vdqbus_index[i]); + line_model->setExternalConnectionNodes(2,vdqbus_index[i] + 1); + //output connections + line_model->setExternalConnectionNodes(3,vdqbus_index[i+1]); + line_model->setExternalConnectionNodes(4,vdqbus_index[i+1] + 1); + //internal connections + for (size_t j = 0; j < 2; j++) + { + line_model->setExternalConnectionNodes(5 + j,indexv + j); + } + indexv += 2; + sysmodel->addComponent(line_model); + } + + // Load all the Load components + for (size_t i = 0; i < Nsize; i++) + { + ModelLib::MicrogridLoad *load_model = new ModelLib::MicrogridLoad(model_id++, rload_list[i], Lload_list[i]); + //ref motor + load_model->setExternalConnectionNodes(0,vec_size_internals); + //input connections + load_model->setExternalConnectionNodes(1,vdqbus_index[2*i]); + load_model->setExternalConnectionNodes(2,vdqbus_index[2*i] + 1); + //internal connections + for (size_t j = 0; j < 2; j++) + { + + load_model->setExternalConnectionNodes(3 + j,indexv + j); + } + indexv += 2; + sysmodel->addComponent(load_model); + } + + //Add all the microgrid Virtual DQ Buses + for (size_t i = 0; i < 2*Nsize; i++) + { + ModelLib::MicrogridBusDQ *virDQbus_model = new ModelLib::MicrogridBusDQ( + model_id++, RN); + + virDQbus_model->setExternalConnectionNodes(0, vdqbus_index[i]); + virDQbus_model->setExternalConnectionNodes(1, vdqbus_index[i] + 1); + sysmodel->addComponent(virDQbus_model); + } + + //allocate all the intial conditions + sysmodel->allocate(vec_size_total); + + std::cout << sysmodel->y().size() << std::endl; + std::cout << vec_size_internals << ", " << vec_size_externals << "\n"; + + //Create Intial points for states. Every state is to specified to the zero intially + for (size_t i = 0; i < vec_size_total; i++) + { + sysmodel->y()[i] = 0.0; + sysmodel->yp()[i] = 0.0; + } + + // Create Intial derivatives specifics generated in MATLAB + for (size_t i = 0; i < 2*Nsize; i++) + { + sysmodel->yp()[13*i - 1 + 3] = DGParams_list[i].Vn; + sysmodel->yp()[13*i - 1 + 5] = DGParams_list[i].Kpv * DGParams_list[i].Vn; + sysmodel->yp()[13*i - 1 + 7] = (DGParams_list[i].Kpc * DGParams_list[i].Kpv * DGParams_list[i].Vn) / DGParams_list[i].Lf; + } + + //since the intial P_com = 0, the set the intial vector to the reference frame + sysmodel->y()[vec_size_internals] = DG_parms1.wb; + + sysmodel->initialize(); + sysmodel->evaluateResidual(); + + std::vector& fres = sysmodel->getResidual(); + std::cout << "Verify Intial Resisdual is Zero: {\n"; + for (size_t i = 0; i < fres.size(); i++) + { + printf("%u : %.16e \n", i, fres[i]); + } + std::cout << "}\n"; + + sysmodel->updateTime(0.0, 1.0e-8); + sysmodel->evaluateJacobian(); + std::cout << "Intial Jacobian with alpha:\n"; + + + //Create numerical integrator and configure it for the generator model + AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); double t_init = 0.0; double t_final = 1.0; @@ -269,66 +272,46 @@ int main(int argc, char const *argv[]) idas->runSimulation(t_final); - std::vector& yfinial = sysmodel->y(); - - std::cout << "Final Vector y\n"; - for (size_t i = 0; i < yfinial.size(); i++) - { - std::cout << yfinial[i] << "\n"; - } - - //if proper MATLAB results are avalible and model is using origional parameters - //All data generated with abstol=1e-12 and reltol=1e-12 with ode23tb - if (orgparams && (Nsize == 2 || Nsize == 4 || Nsize == 8)) - { - - //get relative path - std::string rel_path = std::filesystem::current_path(); - - const std::regex base_regex("(.+)\\/build.*"); - std::smatch base_match; - std::regex_match(rel_path, base_match, base_regex); - std::string base_path = base_match[1].str(); - - base_path += "/Examples/Scale_Microgrid"; - - switch (Nsize) - { - case 2: - base_path += "/microgrid_N2.txt"; - break; - case 4: - base_path += "/microgrid_N4.txt"; - break; - case 8: - base_path += "/microgrid_N8.txt"; - break; - default: - //shouldn't end up here bust just incase - assert(0==1); - break; - } - std::cout << base_path << std::endl; - - //load vector from data file - std::vector true_vec(vec_size_total, 0.0); - double val_cur = 0.0; - std::ifstream data_file(base_path); - size_t i = 0; - while (data_file >> val_cur && i < true_vec.size()) - { - true_vec[i++] = val_cur; - } - data_file.close(); - - //check relative error - std::cout << "Test the Relative Error\n"; - for (size_t i = 0; i < true_vec.size(); i++) - { - printf("%u : %e ,\n", i, abs(true_vec[i] - yfinial[i]) / abs(true_vec[i])); - } - } - - - return 0; + std::vector& yfinial = sysmodel->y(); + + std::cout << "Final Vector y\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + printf("%u: % 2.16e\n", i, yfinial[i]); + } + + //if proper MATLAB results are avalible and model is using origional parameters + std::vector compDataSizes = {2,4,8}; + //All data generated with abstol=1e-12 and reltol=1e-12 with ode23tb + if (orgparams && compDataSizes.end() != std::find(compDataSizes.begin(), compDataSizes.end(), Nsize)) + { + //get the cmake source dir from the cmake configuration + std::string base_path = XSTRING(SOURCE_ROOT); + + base_path += "/Examples/Scale_Microgrid/microgrid_N"; + base_path += std::to_string(Nsize); + base_path += ".txt"; + std::cout << base_path << std::endl; + + //load vector from data file + std::vector true_vec(vec_size_total, 0.0); + double val_cur = 0.0; + std::ifstream data_file(base_path); + size_t i = 0; + while (data_file >> val_cur && i < true_vec.size()) + { + true_vec[i++] = val_cur; + } + data_file.close(); + + //check relative error + std::cout << "Test the Relative Error\n"; + for (size_t i = 0; i < true_vec.size(); i++) + { + printf("%u: % 2.16e\n", i, abs(true_vec[i] - yfinial[i]) / abs(true_vec[i])); + } + } + + + return 0; }