diff --git a/examples/PowerFlow/Grid3Bus/Grid3BusSys.cpp b/examples/PowerFlow/Grid3Bus/Grid3BusSys.cpp index 28ba4430..b5d83076 100644 --- a/examples/PowerFlow/Grid3Bus/Grid3BusSys.cpp +++ b/examples/PowerFlow/Grid3Bus/Grid3BusSys.cpp @@ -20,11 +20,11 @@ #include #include #include +#include #include +#include #include -#include #include -#include #include static const std::string BUS3_DATA_STRING = R"( diff --git a/examples/PowerFlow/MatPowerTesting/MatPowerTesting.hpp b/examples/PowerFlow/MatPowerTesting/MatPowerTesting.hpp index 1da0e95c..648296a4 100644 --- a/examples/PowerFlow/MatPowerTesting/MatPowerTesting.hpp +++ b/examples/PowerFlow/MatPowerTesting/MatPowerTesting.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include namespace diff --git a/examples/PowerFlow/MatPowerTesting/test_parse_branch_row.cpp b/examples/PowerFlow/MatPowerTesting/test_parse_branch_row.cpp index e5ff203f..442dda53 100644 --- a/examples/PowerFlow/MatPowerTesting/test_parse_branch_row.cpp +++ b/examples/PowerFlow/MatPowerTesting/test_parse_branch_row.cpp @@ -1,8 +1,8 @@ #include #include "MatPowerTesting.hpp" -#include -#include +#include +#include using namespace GridKit; using namespace GridKit::Testing; diff --git a/examples/PowerFlow/MatPowerTesting/test_parse_bus_row.cpp b/examples/PowerFlow/MatPowerTesting/test_parse_bus_row.cpp index 60a7c914..ff874dcf 100644 --- a/examples/PowerFlow/MatPowerTesting/test_parse_bus_row.cpp +++ b/examples/PowerFlow/MatPowerTesting/test_parse_bus_row.cpp @@ -1,8 +1,8 @@ #include #include "MatPowerTesting.hpp" -#include -#include +#include +#include using namespace GridKit; using namespace GridKit::Testing; diff --git a/examples/PowerFlow/MatPowerTesting/test_parse_gen_row.cpp b/examples/PowerFlow/MatPowerTesting/test_parse_gen_row.cpp index 45ce4a18..437f0af7 100644 --- a/examples/PowerFlow/MatPowerTesting/test_parse_gen_row.cpp +++ b/examples/PowerFlow/MatPowerTesting/test_parse_gen_row.cpp @@ -1,8 +1,8 @@ #include #include "MatPowerTesting.hpp" -#include -#include +#include +#include using namespace GridKit; using namespace GridKit::Testing; diff --git a/examples/PowerFlow/MatPowerTesting/test_parse_gencost_row.cpp b/examples/PowerFlow/MatPowerTesting/test_parse_gencost_row.cpp index e1b9e061..68dad345 100644 --- a/examples/PowerFlow/MatPowerTesting/test_parse_gencost_row.cpp +++ b/examples/PowerFlow/MatPowerTesting/test_parse_gencost_row.cpp @@ -1,8 +1,8 @@ #include #include "MatPowerTesting.hpp" -#include -#include +#include +#include using namespace GridKit; using namespace GridKit::Testing; diff --git a/examples/PowerFlow/MatPowerTesting/test_parse_matpower.cpp b/examples/PowerFlow/MatPowerTesting/test_parse_matpower.cpp index fb5bd196..c384743f 100644 --- a/examples/PowerFlow/MatPowerTesting/test_parse_matpower.cpp +++ b/examples/PowerFlow/MatPowerTesting/test_parse_matpower.cpp @@ -1,8 +1,8 @@ #include #include "MatPowerTesting.hpp" -#include -#include +#include +#include using namespace GridKit; using namespace GridKit::Testing; diff --git a/src/Model/PhasorDynamics/Branch/Branch.cpp b/src/Model/PhasorDynamics/Branch/Branch.cpp index 0ccbe1a1..c65b3367 100644 --- a/src/Model/PhasorDynamics/Branch/Branch.cpp +++ b/src/Model/PhasorDynamics/Branch/Branch.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include namespace GridKit { diff --git a/src/Model/PhasorDynamics/Bus/Bus.cpp b/src/Model/PhasorDynamics/Bus/Bus.cpp index 7253ee66..3dfaad6e 100644 --- a/src/Model/PhasorDynamics/Bus/Bus.cpp +++ b/src/Model/PhasorDynamics/Bus/Bus.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include namespace GridKit { diff --git a/src/Model/PhasorDynamics/Bus/BusInfinite.cpp b/src/Model/PhasorDynamics/Bus/BusInfinite.cpp index f4f18b83..61fa5d20 100644 --- a/src/Model/PhasorDynamics/Bus/BusInfinite.cpp +++ b/src/Model/PhasorDynamics/Bus/BusInfinite.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include namespace GridKit { diff --git a/src/Model/PhasorDynamics/BusFault/BusFault.cpp b/src/Model/PhasorDynamics/BusFault/BusFault.cpp index d2f519ee..7b12af30 100644 --- a/src/Model/PhasorDynamics/BusFault/BusFault.cpp +++ b/src/Model/PhasorDynamics/BusFault/BusFault.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include namespace GridKit { diff --git a/src/Model/PhasorDynamics/Load/Load.cpp b/src/Model/PhasorDynamics/Load/Load.cpp index b7c51505..e1ccb26c 100644 --- a/src/Model/PhasorDynamics/Load/Load.cpp +++ b/src/Model/PhasorDynamics/Load/Load.cpp @@ -5,7 +5,6 @@ #include #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/Capacitor/Capacitor.hpp b/src/Model/PowerElectronics/Capacitor/Capacitor.hpp index b86ed913..1357150e 100644 --- a/src/Model/PowerElectronics/Capacitor/Capacitor.hpp +++ b/src/Model/PowerElectronics/Capacitor/Capacitor.hpp @@ -4,7 +4,6 @@ #define _CAP_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/CircuitComponent.hpp b/src/Model/PowerElectronics/CircuitComponent.hpp index 56e0d4c5..f3efe363 100644 --- a/src/Model/PowerElectronics/CircuitComponent.hpp +++ b/src/Model/PowerElectronics/CircuitComponent.hpp @@ -6,7 +6,6 @@ #include #include -#include namespace GridKit { diff --git a/src/CircuitGraph.hpp b/src/Model/PowerElectronics/CircuitGraph.hpp similarity index 100% rename from src/CircuitGraph.hpp rename to src/Model/PowerElectronics/CircuitGraph.hpp diff --git a/src/Model/PowerElectronics/DistributedGenerator/DistributedGenerator.hpp b/src/Model/PowerElectronics/DistributedGenerator/DistributedGenerator.hpp index 96654cf6..a7540646 100644 --- a/src/Model/PowerElectronics/DistributedGenerator/DistributedGenerator.hpp +++ b/src/Model/PowerElectronics/DistributedGenerator/DistributedGenerator.hpp @@ -4,7 +4,6 @@ #define _CAP_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/InductionMotor/InductionMotor.hpp b/src/Model/PowerElectronics/InductionMotor/InductionMotor.hpp index 007e7fd5..1e02ef0c 100644 --- a/src/Model/PowerElectronics/InductionMotor/InductionMotor.hpp +++ b/src/Model/PowerElectronics/InductionMotor/InductionMotor.hpp @@ -4,7 +4,6 @@ #define _IMOTOR_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/Inductor/Inductor.hpp b/src/Model/PowerElectronics/Inductor/Inductor.hpp index c40920b0..685e69bb 100644 --- a/src/Model/PowerElectronics/Inductor/Inductor.hpp +++ b/src/Model/PowerElectronics/Inductor/Inductor.hpp @@ -4,7 +4,6 @@ #define _IND_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/LinearTransformer/LinearTransformer.hpp b/src/Model/PowerElectronics/LinearTransformer/LinearTransformer.hpp index b1e9c57c..7be8bd59 100644 --- a/src/Model/PowerElectronics/LinearTransformer/LinearTransformer.hpp +++ b/src/Model/PowerElectronics/LinearTransformer/LinearTransformer.hpp @@ -4,7 +4,6 @@ #define _LTRANS_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/MicrogridBusDQ/MicrogridBusDQ.hpp b/src/Model/PowerElectronics/MicrogridBusDQ/MicrogridBusDQ.hpp index 46173c5a..150618c2 100644 --- a/src/Model/PowerElectronics/MicrogridBusDQ/MicrogridBusDQ.hpp +++ b/src/Model/PowerElectronics/MicrogridBusDQ/MicrogridBusDQ.hpp @@ -4,7 +4,6 @@ #define _VIRBUSDQ_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/MicrogridLine/MicrogridLine.hpp b/src/Model/PowerElectronics/MicrogridLine/MicrogridLine.hpp index 14d29b85..66304c59 100644 --- a/src/Model/PowerElectronics/MicrogridLine/MicrogridLine.hpp +++ b/src/Model/PowerElectronics/MicrogridLine/MicrogridLine.hpp @@ -4,7 +4,6 @@ #define _TRANLINE_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/MicrogridLoad/MicrogridLoad.hpp b/src/Model/PowerElectronics/MicrogridLoad/MicrogridLoad.hpp index 685a0504..e05764d5 100644 --- a/src/Model/PowerElectronics/MicrogridLoad/MicrogridLoad.hpp +++ b/src/Model/PowerElectronics/MicrogridLoad/MicrogridLoad.hpp @@ -4,7 +4,6 @@ #define _TRANLOAD_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/Resistor/Resistor.hpp b/src/Model/PowerElectronics/Resistor/Resistor.hpp index 0821b992..06186351 100644 --- a/src/Model/PowerElectronics/Resistor/Resistor.hpp +++ b/src/Model/PowerElectronics/Resistor/Resistor.hpp @@ -4,7 +4,6 @@ #define _RES_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/SynchronousMachine/SynchronousMachine.hpp b/src/Model/PowerElectronics/SynchronousMachine/SynchronousMachine.hpp index 74766d15..2c98384b 100644 --- a/src/Model/PowerElectronics/SynchronousMachine/SynchronousMachine.hpp +++ b/src/Model/PowerElectronics/SynchronousMachine/SynchronousMachine.hpp @@ -6,7 +6,6 @@ #include #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/SystemModelPowerElectronics.hpp b/src/Model/PowerElectronics/SystemModelPowerElectronics.hpp index 10548309..7c82ec70 100644 --- a/src/Model/PowerElectronics/SystemModelPowerElectronics.hpp +++ b/src/Model/PowerElectronics/SystemModelPowerElectronics.hpp @@ -6,8 +6,8 @@ #include #include -#include #include +#include #include namespace GridKit diff --git a/src/Model/PowerElectronics/TransmissionLine/TransmissionLine.hpp b/src/Model/PowerElectronics/TransmissionLine/TransmissionLine.hpp index badd0cf9..18610692 100644 --- a/src/Model/PowerElectronics/TransmissionLine/TransmissionLine.hpp +++ b/src/Model/PowerElectronics/TransmissionLine/TransmissionLine.hpp @@ -4,7 +4,6 @@ #define _TRANLINE_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerElectronics/VoltageSource/VoltageSource.hpp b/src/Model/PowerElectronics/VoltageSource/VoltageSource.hpp index d3b630a0..03d7a1e0 100644 --- a/src/Model/PowerElectronics/VoltageSource/VoltageSource.hpp +++ b/src/Model/PowerElectronics/VoltageSource/VoltageSource.hpp @@ -4,7 +4,6 @@ #define _VOSO_HPP_ #include -#include namespace GridKit { diff --git a/src/Model/PowerFlow/Branch/Branch.cpp b/src/Model/PowerFlow/Branch/Branch.cpp index 08b94326..ecbc1b6d 100644 --- a/src/Model/PowerFlow/Branch/Branch.cpp +++ b/src/Model/PowerFlow/Branch/Branch.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include namespace GridKit { diff --git a/src/Model/PowerFlow/Bus/BusFactory.hpp b/src/Model/PowerFlow/Bus/BusFactory.hpp index 5a1c6e95..dc91c38b 100644 --- a/src/Model/PowerFlow/Bus/BusFactory.hpp +++ b/src/Model/PowerFlow/Bus/BusFactory.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace GridKit { diff --git a/src/Model/PowerFlow/Bus/BusPQ.hpp b/src/Model/PowerFlow/Bus/BusPQ.hpp index fd96ca39..e0b76b16 100644 --- a/src/Model/PowerFlow/Bus/BusPQ.hpp +++ b/src/Model/PowerFlow/Bus/BusPQ.hpp @@ -3,7 +3,7 @@ #define _BUS_PQ_HPP_ #include "BaseBus.hpp" -#include +#include namespace GridKit { diff --git a/src/Model/PowerFlow/Bus/BusPV.hpp b/src/Model/PowerFlow/Bus/BusPV.hpp index ac180e92..b4ea8fd8 100644 --- a/src/Model/PowerFlow/Bus/BusPV.hpp +++ b/src/Model/PowerFlow/Bus/BusPV.hpp @@ -5,7 +5,7 @@ #include #include "BaseBus.hpp" -#include +#include namespace GridKit { diff --git a/src/Model/PowerFlow/Bus/BusSlack.hpp b/src/Model/PowerFlow/Bus/BusSlack.hpp index 96d2ba66..4a693e43 100644 --- a/src/Model/PowerFlow/Bus/BusSlack.hpp +++ b/src/Model/PowerFlow/Bus/BusSlack.hpp @@ -3,7 +3,7 @@ #define _BUS_SLACK_HPP_ #include "BaseBus.hpp" -#include +#include namespace GridKit { diff --git a/src/Model/PowerFlow/Generator/GeneratorFactory.hpp b/src/Model/PowerFlow/Generator/GeneratorFactory.hpp index 07d1ac4c..daedd23b 100644 --- a/src/Model/PowerFlow/Generator/GeneratorFactory.hpp +++ b/src/Model/PowerFlow/Generator/GeneratorFactory.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include namespace GridKit { diff --git a/src/Model/PowerFlow/Generator/GeneratorPQ.hpp b/src/Model/PowerFlow/Generator/GeneratorPQ.hpp index 1561c61b..0628257e 100644 --- a/src/Model/PowerFlow/Generator/GeneratorPQ.hpp +++ b/src/Model/PowerFlow/Generator/GeneratorPQ.hpp @@ -5,7 +5,7 @@ #include "GeneratorBase.hpp" #include -#include +#include namespace GridKit { diff --git a/src/Model/PowerFlow/Generator/GeneratorPV.hpp b/src/Model/PowerFlow/Generator/GeneratorPV.hpp index 7882114e..efe629f1 100644 --- a/src/Model/PowerFlow/Generator/GeneratorPV.hpp +++ b/src/Model/PowerFlow/Generator/GeneratorPV.hpp @@ -5,7 +5,7 @@ #include "GeneratorBase.hpp" #include -#include +#include namespace GridKit { diff --git a/src/Model/PowerFlow/Generator/GeneratorSlack.hpp b/src/Model/PowerFlow/Generator/GeneratorSlack.hpp index fa5b1bef..43a7c321 100644 --- a/src/Model/PowerFlow/Generator/GeneratorSlack.hpp +++ b/src/Model/PowerFlow/Generator/GeneratorSlack.hpp @@ -1,11 +1,10 @@ #pragma once -// #include #include #include "GeneratorBase.hpp" -#include +#include namespace GridKit { diff --git a/src/Model/PowerFlow/Load/Load.hpp b/src/Model/PowerFlow/Load/Load.hpp index a9c17eb0..5091761c 100644 --- a/src/Model/PowerFlow/Load/Load.hpp +++ b/src/Model/PowerFlow/Load/Load.hpp @@ -3,7 +3,7 @@ #define _LOAD_HPP_ #include -#include +#include namespace GridKit { diff --git a/src/Model/PowerFlow/MatpowerParser.hpp b/src/Model/PowerFlow/MatpowerParser.hpp new file mode 100644 index 00000000..dcf926ef --- /dev/null +++ b/src/Model/PowerFlow/MatpowerParser.hpp @@ -0,0 +1,299 @@ + +/** + * @file FileIO.hpp + * @author Slaven Peles + * + * Contains definition of a utility for reading lookup tables. + * + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace GridKit +{ + using namespace GridKit::PowerSystemData; + + static const std::string matlab_syntax_error{ + "Only a subset of Matlab syntax is supported." + "\n\t'=' for assignment must be on the same line as the field, eg " + "`mpc.version = '2'`." + "\n\tOpen brace ('[') must be on the same line as the field for matrix " + "initialization." + "\n\tEach row of a matrix must be terminated by a semicolon."}; + + std::ostream& logs() + { +#ifndef NDEBUG + std::cerr << "[FileIO.hpp]: "; + return std::cerr; +#else + static std::ofstream ofs; + ofs.setstate(std::ios_base::badbit); + return ofs; +#endif + } + + void ltrim(std::string& s) + { + const std::string nothing = ""; + s = std::regex_replace(s, std::regex("^\\s+"), nothing); + } + + void rtrim(std::string& s) + { + const std::string nothing = ""; + s = std::regex_replace(s, std::regex("\\s+$"), nothing); + } + + void trim_matlab_comments(std::string& s) + { + const std::string nothing = ""; + s = std::regex_replace(s, std::regex("%.+"), nothing); + } + + // Retrive MATPOWER component from assignment line. + // + // For example, the string " mpc.bus = [ ... ] % Some comment" will + // return the value "bus". + std::string getMatPowerComponent(const std::string& line) + { + logs() << "Getting matpower component from line\n"; + std::regex pat("mpc.([a-zA-Z]+)\\s*=.+"); + std::smatch matches; + std::string component; + if (std::regex_match(line, matches, pat)) + { + component = matches[1].str(); + } + else + { + throw std::runtime_error(matlab_syntax_error + "\nGot line " + line); + } + ltrim(component); + rtrim(component); + return component; + } + + // Ensure that all of the given line has been consumed, and that the only + // remaining non-whitespace character left in the line is a semicolon. + void checkEndOfMatrixRow(std::istream& is) + { + std::string rest; + is >> rest; + ltrim(rest); + rtrim(rest); + if (rest != ";") + throw std::runtime_error(matlab_syntax_error); + } + + template + void readMatPowerBusRow(const std::string& row, BusData& br, LoadData& 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.) + + lr.bus_i = br.bus_i; + + // std::cout << br.str(); + // logs() << "Read BusData with the following values:\n" << br.str(); + // return br; + } + + template + void readMatPowerGenRow(GenData& 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; + checkEndOfMatrixRow(is); + } + + template + void readMatPowerBranchRow(BranchData& 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; + checkEndOfMatrixRow(is); + } + + template + void readMatPowerGenCostRow(GenCostData& gcr, std::string& row) + { + logs() << "Parsing MATPOWER gen cost row\n"; + // Ensure last character is semicolon. + rtrim(row); + if (row[row.size() - 1] != ';') + throw std::runtime_error(matlab_syntax_error + "\nGot line " + row); + + std::stringstream is(row); + is >> gcr.kind >> gcr.startup >> gcr.shutdown >> gcr.n; + + for (RealT r; is >> r;) + { + gcr.rest.push_back(r); + } + } + + template + void readMatPowerVersion(SystemModelData& mp, std::string& line) + { + logs() << "Parsing matpower version\n"; + std::regex pat("mpc\\.version\\s*=\\s*'([0-9])';"); + std::smatch matches; + if (std::regex_match(line, matches, pat)) + { + mp.version = matches[1].str(); + } + else + { + throw std::runtime_error(matlab_syntax_error + "\nGot line '" + line + "'"); + } + } + + template + void readMatPowerBaseMVA(SystemModelData& mp, std::string& line) + { + std::regex pat("mpc\\.baseMVA\\s*=\\s*([0-9]+);"); + std::smatch matches; + if (std::regex_match(line, matches, pat)) + { + std::string s = matches[1]; + mp.baseMVA = std::atof(s.c_str()); + } + else + { + throw std::runtime_error(matlab_syntax_error + "\nGot line '" + line + "'"); + } + } + + template + void readMatPowerFile(SystemModelData& mp, std::string& filename) + { + std::ifstream ifs{filename}; + readMatPower(mp, ifs); + } + + template + void readMatPower(SystemModelData& mp, std::istream& is) + { + 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 + ltrim(line); + rtrim(line); + logs() << line << "\n"; + trim_matlab_comments(line); + + // Skip empty lines and comment-only lines + if (line.size() == 0) + continue; + + // Skip the matlab function declaration + if (line.find("function") != std::string::npos) + continue; + + // Check for MATPOWER component definitions + if (line.find("mpc") != std::string::npos) + { + const std::string component = getMatPowerComponent(line); + logs() << "Got component: '" << component << "'\n"; + // First, parse matrix components + if (component == "bus") + { + while (std::getline(is, line)) + { + if (line.find("];") != std::string::npos) + break; + BusDataT br; + LoadDataT 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)) + { + if (line.find("];") != std::string::npos) + break; + 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; + 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; + GenCostDataT gcr; + readMatPowerGenCostRow(gcr, line); + mp.gencost.push_back(gcr); + } + } + + // Next, parse scalar components + else if (component == "version") + { + readMatPowerVersion(mp, line); + } + else if (component == "baseMVA") + { + readMatPowerBaseMVA(mp, line); + } + } + } + } + + // } // namespace PowerSystemsData +} // namespace GridKit diff --git a/src/PowerSystemData.hpp b/src/Model/PowerFlow/PowerSystemData.hpp similarity index 100% rename from src/PowerSystemData.hpp rename to src/Model/PowerFlow/PowerSystemData.hpp diff --git a/src/Utilities/FileIO.hpp b/src/Utilities/FileIO.hpp index 130b79c1..1e4c2b3d 100644 --- a/src/Utilities/FileIO.hpp +++ b/src/Utilities/FileIO.hpp @@ -8,200 +8,14 @@ */ #pragma once -#include #include #include -#include #include -#include #include #include -#include - -namespace -{ - - using namespace GridKit; - using namespace GridKit::PowerSystemData; - - static const std::string matlab_syntax_error{ - "Only a subset of Matlab syntax is supported." - "\n\t'=' for assignment must be on the same line as the field, eg " - "`mpc.version = '2'`." - "\n\tOpen brace ('[') must be on the same line as the field for matrix " - "initialization." - "\n\tEach row of a matrix must be terminated by a semicolon."}; - - std::ostream& logs() - { -#ifndef NDEBUG - std::cerr << "[FileIO.hpp]: "; - return std::cerr; -#else - static std::ofstream ofs; - ofs.setstate(std::ios_base::badbit); - return ofs; -#endif - } - - void ltrim(std::string& s) - { - const std::string nothing = ""; - s = std::regex_replace(s, std::regex("^\\s+"), nothing); - } - - void rtrim(std::string& s) - { - const std::string nothing = ""; - s = std::regex_replace(s, std::regex("\\s+$"), nothing); - } - - void trim_matlab_comments(std::string& s) - { - const std::string nothing = ""; - s = std::regex_replace(s, std::regex("%.+"), nothing); - } - - // Retrive MATPOWER component from assignment line. - // - // For example, the string " mpc.bus = [ ... ] % Some comment" will - // return the value "bus". - std::string getMatPowerComponent(const std::string& line) - { - logs() << "Getting matpower component from line\n"; - std::regex pat("mpc.([a-zA-Z]+)\\s*=.+"); - std::smatch matches; - std::string component; - if (std::regex_match(line, matches, pat)) - { - component = matches[1].str(); - } - else - { - throw std::runtime_error(matlab_syntax_error + "\nGot line " + line); - } - ltrim(component); - rtrim(component); - return component; - } - - // Ensure that all of the given line has been consumed, and that the only - // remaining non-whitespace character left in the line is a semicolon. - void checkEndOfMatrixRow(std::istream& is) - { - std::string rest; - is >> rest; - ltrim(rest); - rtrim(rest); - if (rest != ";") - throw std::runtime_error(matlab_syntax_error); - } - - template - void readMatPowerBusRow(const std::string& row, BusData& br, LoadData& 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.) - - lr.bus_i = br.bus_i; - - // std::cout << br.str(); - // logs() << "Read BusData with the following values:\n" << br.str(); - // return br; - } - - template - void readMatPowerGenRow(GenData& 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; - checkEndOfMatrixRow(is); - } - - template - void readMatPowerBranchRow(BranchData& 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; - checkEndOfMatrixRow(is); - } - - template - void readMatPowerGenCostRow(GenCostData& gcr, std::string& row) - { - logs() << "Parsing MATPOWER gen cost row\n"; - // Ensure last character is semicolon. - rtrim(row); - if (row[row.size() - 1] != ';') - throw std::runtime_error(matlab_syntax_error + "\nGot line " + row); - - std::stringstream is(row); - is >> gcr.kind >> gcr.startup >> gcr.shutdown >> gcr.n; - - for (RealT r; is >> r;) - { - gcr.rest.push_back(r); - } - } - - template - void readMatPowerVersion(SystemModelData& mp, std::string& line) - { - logs() << "Parsing matpower version\n"; - std::regex pat("mpc\\.version\\s*=\\s*'([0-9])';"); - std::smatch matches; - if (std::regex_match(line, matches, pat)) - { - mp.version = matches[1].str(); - } - else - { - throw std::runtime_error(matlab_syntax_error + "\nGot line '" + line + "'"); - } - } - - template - void readMatPowerBaseMVA(SystemModelData& mp, std::string& line) - { - std::regex pat("mpc\\.baseMVA\\s*=\\s*([0-9]+);"); - std::smatch matches; - if (std::regex_match(line, matches, pat)) - { - std::string s = matches[1]; - mp.baseMVA = std::atof(s.c_str()); - } - else - { - throw std::runtime_error(matlab_syntax_error + "\nGot line '" + line + "'"); - } - } - -} // namespace - namespace GridKit { - /** * @brief Reads in an input stream of tabulated data * @@ -281,105 +95,4 @@ namespace GridKit std::cout << "\n"; } } - - template - void readMatPowerFile(SystemModelData& mp, std::string& filename) - { - std::ifstream ifs{filename}; - readMatPower(mp, ifs); - } - - template - void readMatPower(SystemModelData& mp, std::istream& is) - { - 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 - ltrim(line); - rtrim(line); - logs() << line << "\n"; - trim_matlab_comments(line); - - // Skip empty lines and comment-only lines - if (line.size() == 0) - continue; - - // Skip the matlab function declaration - if (line.find("function") != std::string::npos) - continue; - - // Check for MATPOWER component definitions - if (line.find("mpc") != std::string::npos) - { - const std::string component = getMatPowerComponent(line); - logs() << "Got component: '" << component << "'\n"; - // First, parse matrix components - if (component == "bus") - { - while (std::getline(is, line)) - { - if (line.find("];") != std::string::npos) - break; - BusDataT br; - LoadDataT 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)) - { - if (line.find("];") != std::string::npos) - break; - 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; - 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; - GenCostDataT gcr; - readMatPowerGenCostRow(gcr, line); - mp.gencost.push_back(gcr); - } - } - - // Next, parse scalar components - else if (component == "version") - { - readMatPowerVersion(mp, line); - } - else if (component == "baseMVA") - { - readMatPowerBaseMVA(mp, line); - } - } - } - } - } // namespace GridKit