diff --git a/dpsim-models/include/dpsim-models/Components.h b/dpsim-models/include/dpsim-models/Components.h index 46d2858473..3ea5bf957c 100644 --- a/dpsim-models/include/dpsim-models/Components.h +++ b/dpsim-models/include/dpsim-models/Components.h @@ -123,6 +123,7 @@ #include #include #include +#include #include #include #include diff --git a/dpsim-models/include/dpsim-models/Signal/PMUSignalDevice.h b/dpsim-models/include/dpsim-models/Signal/PMUSignalDevice.h new file mode 100644 index 0000000000..2e15063fa8 --- /dev/null +++ b/dpsim-models/include/dpsim-models/Signal/PMUSignalDevice.h @@ -0,0 +1,51 @@ + +#pragma once + +#include + +#include +#include +#include + + +namespace CPS { +namespace Signal { + + class PMUSignalDevice: + public SimSignalComp, + public SharedFactory + { + protected: + public: + ///FIXME: This is never explicitely set to reference anything, so the outside code is responsible for setting up the reference. + + //***PMUSignalDevice has two attributes:Input and Output***// + const Attribute::Ptr mInput; + const Attribute::Ptr mOutput; + + //Constructor + PMUSignalDevice(String name, Logger::Level logLevel = Logger::Level::off); + + //Operation for adding measurement error + void MeasurementError(Real time); + + //***Get task list for the solver***// + Task::List getTasks(); + + //***The process of the solve is recognized as a PostStep.***// + class PostStep : public Task { + public: + PostStep(PMUSignalDevice& PMU) : + Task(**PMU.mName + ".Poststep"), mPMU(PMU) { + mAttributeDependencies.push_back(PMU.mInput); + mModifiedAttributes.push_back(PMU.mOutput); + } + + void execute(Real time, Int timeStepCount); + + private: + PMUSignalDevice& mPMU; + }; + }; + } +} \ No newline at end of file diff --git a/dpsim-models/src/CMakeLists.txt b/dpsim-models/src/CMakeLists.txt index bf7c6240b3..ea2f4adbc8 100644 --- a/dpsim-models/src/CMakeLists.txt +++ b/dpsim-models/src/CMakeLists.txt @@ -131,6 +131,7 @@ list(APPEND MODELS_SOURCES Signal/TurbineGovernor.cpp Signal/PLL.cpp Signal/Integrator.cpp + Signal/PMUSignalDevice.cpp Signal/PowerControllerVSI.cpp Signal/SineWaveGenerator.cpp Signal/SignalGenerator.cpp diff --git a/dpsim-models/src/Signal/PMUSignalDevice.cpp b/dpsim-models/src/Signal/PMUSignalDevice.cpp new file mode 100644 index 0000000000..40a6c8a347 --- /dev/null +++ b/dpsim-models/src/Signal/PMUSignalDevice.cpp @@ -0,0 +1,37 @@ +#include + +using namespace CPS; +using namespace CPS::Signal; + +PMUSignalDevice::PMUSignalDevice(String name, Logger::Level logLevel) : + SimSignalComp(name, name, logLevel), + /// CHECK: Which of these really need to be attributes? + mInput(Attribute::createDynamic("input", mAttributes)), + + //*** Important: the output attribute is a matrix component, which should be initialized as Zero(1,1) + mOutput(Attribute::create("output", mAttributes, MatrixComp::Zero(1,1))){ } + + +// } + + +void PMUSignalDevice::MeasurementError(Real time){ + + + mSLog->info("Input values: input = {}", **mInput); + + + /// adding the measurement error + // noise is considered as a 10% error + **mOutput =**mInput*1.1; + + mSLog->info("Output values: output = {}:", **mOutput); +} + +void PMUSignalDevice::PostStep::execute(Real time, Int timeStepCount) { + mPMU.MeasurementError(time); +} + +Task::List PMUSignalDevice::getTasks() { + return Task::List({std::make_shared(*this)}); +} \ No newline at end of file diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index 27367365a4..375c493c5a 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -85,6 +85,8 @@ set(CIRCUIT_SOURCES Circuits/DP_SynGenTrStab_3Bus_SteadyState.cpp Circuits/DP_SynGenTrStab_3Bus_Fault.cpp Circuits/SP_SynGenTrStab_3Bus_Fault.cpp + + Circuits/Three_bus_sim.cpp ) diff --git a/dpsim/examples/cxx/Circuits/Three_bus_sim.cpp b/dpsim/examples/cxx/Circuits/Three_bus_sim.cpp new file mode 100644 index 0000000000..70a31c59d5 --- /dev/null +++ b/dpsim/examples/cxx/Circuits/Three_bus_sim.cpp @@ -0,0 +1,143 @@ +#include +#include "../Examples.h" + +using namespace DPsim; +using namespace CPS; +using namespace CIM::Examples::Grids::Three_bus_cfg; + +ScenarioConfig Three_bus_cfg; + +void Three_bus_sim(String simName, Real timeStep, Real finalTime, Real cmdInertia_G1, Real cmdInertia_G2, Real cmdDamping_G1, Real cmdDamping_G2) +{ + // ----- POWERFLOW FOR INITIALIZATION ----- + Real timeStepPF = finalTime; + Real finalTimePF = finalTime + timeStepPF; + String simNamePF = simName + "_PF"; + Logger::setLogDir("logs/" + simNamePF); + + // Components + // nodes + auto n1_PF = SimNode::make("n1", PhaseType::Single); + auto n2_PF = SimNode::make("n2", PhaseType::Single); + auto n3_PF = SimNode::make("n3", PhaseType::Single); + + //***Applying the new signal model: PMUSignalDevice + //***Tonstruction a PMU + auto pmu_1 = Signal::PMUSignalDevice::make("PMU_1", Logger::Level::debug); + // //***The attribute mInput of PMU is set by the mVoltage of the SimNode + pmu_1->mInput->setReference(n1_PF->mVoltage); + + auto pmu_2 = Signal::PMUSignalDevice::make("PMU_2", Logger::Level::debug); + pmu_2->mInput->setReference(n2_PF->mVoltage); + + auto pmu_3 = Signal::PMUSignalDevice::make("PMU_3", Logger::Level::debug); + pmu_3->mInput->setReference(n3_PF->mVoltage); + + // injection + // configuration(Synchronous generator 1) + auto gen1_PF = SP::Ph1::SynchronGenerator::make("Generator_1", Logger::Level::debug); + // setPointVoltage is defined as the voltage at the transfomer primary side and should be transformed to network side + gen1_PF->setParameters(Three_bus_cfg.nomPower_G1, Three_bus_cfg.nomPhPhVoltRMS_G1, Three_bus_cfg.initActivePower_G1, Three_bus_cfg.setPointVoltage_G1 * Three_bus_cfg.t1_ratio, PowerflowBusType::VD, Three_bus_cfg.initReactivePower_G1); + gen1_PF->setBaseVoltage(Three_bus_cfg.Vnom); + + // Synchronous generator 2 + auto gen2_PF = SP::Ph1::SynchronGenerator::make("Generator_2", Logger::Level::debug); + // setPointVoltage is defined as the voltage at the transfomer primary side and should be transformed to network side + gen2_PF->setParameters(Three_bus_cfg.nomPower_G2, Three_bus_cfg.nomPhPhVoltRMS_G2, Three_bus_cfg.initActivePower_G2, Three_bus_cfg.setPointVoltage_G2 * Three_bus_cfg.t2_ratio, PowerflowBusType::PV, Three_bus_cfg.initReactivePower_G2); + gen2_PF->setBaseVoltage(Three_bus_cfg.Vnom); + + // use Shunt as Load for powerflow + auto load_PF = SP::Ph1::Shunt::make("Load", Logger::Level::debug); + load_PF->setParameters(Three_bus_cfg.activePower_L / std::pow(Three_bus_cfg.Vnom, 2), -Three_bus_cfg.reactivePower_L / std::pow(Three_bus_cfg.Vnom, 2)); + load_PF->setBaseVoltage(Three_bus_cfg.Vnom); + + // Line12 + auto line_pf_1 = SP::Ph1::PiLine::make("PiLine_13", Logger::Level::debug); + line_pf_1->setParameters(Three_bus_cfg.lineResistance, Three_bus_cfg.lineInductance, Three_bus_cfg.lineCapacitance); + line_pf_1->setBaseVoltage(Three_bus_cfg.Vnom); + // Line13 + auto line_pf_2 = SP::Ph1::PiLine::make("PiLine_31", Logger::Level::debug); + line_pf_2->setParameters(Three_bus_cfg.lineResistance, Three_bus_cfg.lineInductance, Three_bus_cfg.lineCapacitance); + line_pf_2->setBaseVoltage(Three_bus_cfg.Vnom); + // Line23 + auto line_pf_3 = SP::Ph1::PiLine::make("PiLine_23", Logger::Level::debug); + line_pf_3->setParameters(Three_bus_cfg.lineResistance, 2 * Three_bus_cfg.lineInductance, 2 * Three_bus_cfg.lineCapacitance); + line_pf_3->setBaseVoltage(Three_bus_cfg.Vnom); + + // Topology + gen1_PF->connect({n1_PF}); + gen2_PF->connect({n2_PF}); + load_PF->connect({n3_PF}); + line_pf_1->connect({n1_PF, n2_PF}); + line_pf_2->connect({n1_PF, n3_PF}); + line_pf_3->connect({n2_PF, n3_PF}); + + auto systemPF = SystemTopology(50, + SystemNodeList{n1_PF, n2_PF, n3_PF}, + SystemComponentList{gen1_PF, gen2_PF, line_pf_1, line_pf_2, line_pf_3, load_PF}); + + //***Adding the PMU into the system topology + systemPF.mComponents.push_back(pmu_1); + systemPF.mComponents.push_back(pmu_2); + systemPF.mComponents.push_back(pmu_3); + + // Logging + auto loggerPF = DataLogger::make(simNamePF); + loggerPF->logAttribute("v_bus1", n1_PF->attribute("v")); + loggerPF->logAttribute("v_bus2", n2_PF->attribute("v")); + loggerPF->logAttribute("v_bus3", n3_PF->attribute("v")); + + //***Logging the data from PMU + loggerPF->logAttribute("pmu_input_1", pmu_1->attribute("input")); + loggerPF->logAttribute("pmu_output_1", pmu_1->attribute("output")); + + loggerPF->logAttribute("pmu_input_2", pmu_2->attribute("input")); + loggerPF->logAttribute("pmu_output_2", pmu_2->attribute("output")); + loggerPF->logAttribute("pmu_input_3", pmu_3->attribute("input")); + loggerPF->logAttribute("pmu_output_3", pmu_3->attribute("output")); + + // Simulation + Simulation simPF(simNamePF, Logger::Level::debug); + simPF.setSystem(systemPF); + simPF.setTimeStep(timeStepPF); + simPF.setFinalTime(finalTimePF); + simPF.setDomain(Domain::SP); + simPF.setSolverType(Solver::Type::NRP); + simPF.setSolverAndComponentBehaviour(Solver::Behaviour::Initialization); + simPF.doInitFromNodesAndTerminals(false); + simPF.addLogger(loggerPF); + + simPF.run(); +} + +int main(int argc, char *argv[]) +{ + + // Simultion parameters + String simName = "Three_bus_sim"; + Real finalTime = 50; + Real timeStep = 0.001; + Real cmdInertia_G1 = 1.0; + Real cmdInertia_G2 = 1.0; + Real cmdDamping_G1 = 1.0; + Real cmdDamping_G2 = 1.0; + + CommandLineArgs args(argc, argv); + if (argc > 1) + { + timeStep = args.timeStep; + finalTime = args.duration; + if (args.name != "dpsim") + simName = args.name; + if (args.options.find("SCALEINERTIA_G1") != args.options.end()) + cmdInertia_G1 = args.getOptionReal("SCALEINERTIA_G1"); + if (args.options.find("SCALEINERTIA_G2") != args.options.end()) + cmdInertia_G2 = args.getOptionReal("SCALEINERTIA_G2"); + if (args.options.find("SCALEDAMPING_G1") != args.options.end()) + cmdDamping_G1 = args.getOptionReal("SCALEDAMPING_G1"); + if (args.options.find("SCALEDAMPING_G2") != args.options.end()) + cmdDamping_G2 = args.getOptionReal("SCALEDAMPING_G2"); + } + + Three_bus_sim(simName, timeStep, finalTime, cmdInertia_G1, cmdInertia_G2, cmdDamping_G1, cmdDamping_G2); +} \ No newline at end of file diff --git a/dpsim/examples/cxx/Examples.h b/dpsim/examples/cxx/Examples.h index 4e8a00c71b..ec4bd59d85 100644 --- a/dpsim/examples/cxx/Examples.h +++ b/dpsim/examples/cxx/Examples.h @@ -419,6 +419,51 @@ namespace ThreeBus { }; } +namespace Three_bus_cfg{ + struct ScenarioConfig { + + //-----------Network-----------// + Real Vnom = 6.9e3; + Real nomFreq = 50; + Real nomOmega= nomFreq* 2*PI; + + //-----------Generator 1 (bus1)-----------// + Real nomPower_G1 = 100e6; + Real nomPhPhVoltRMS_G1 = 6.9e3; + Real nomFreq_G1 = 50; + + // Initialization parameters + Real initActivePower_G1 = 0.3386e6; + Real initReactivePower_G1= 0.3222e6; + Real setPointVoltage_G1=nomPhPhVoltRMS_G1; + + //-----------Generator 2 (bus2)-----------// + Real nomPower_G2 = 100e6; + Real nomPhPhVoltRMS_G2 = 6.9e3; + Real nomFreq_G2 = 50; + + // Initialization parameters + Real initActivePower_G2 = 0.2222e6; + Real initReactivePower_G2=(-1)*0.0285e6; + Real setPointVoltage_G2=nomPhPhVoltRMS_G2; + + //-----------Transformers-----------// + Real t1_ratio=1; + Real t2_ratio=1; + + //-----------Load (bus3)----------- + Real activePower_L= 0.5556e6; + Real reactivePower_L= 0.2778e6; + + // -----------Transmission Lines-----------// + + Real lineResistance = 0.025; + Real lineInductance = 0.075/(2*PI*50); + Real lineCapacitance = 0; + + }; + +} namespace SGIB { struct ScenarioConfig { diff --git a/dpsim/src/PFSolver.cpp b/dpsim/src/PFSolver.cpp index 10d5fa037f..1ce1feb146 100644 --- a/dpsim/src/PFSolver.cpp +++ b/dpsim/src/PFSolver.cpp @@ -66,7 +66,10 @@ void PFSolver::assignMatrixNodeIndices() { void PFSolver::initializeComponents(){ for (auto comp : mSystem.mComponents) { - std::dynamic_pointer_cast>(comp)->updateMatrixNodeIndices(); + auto sComp = std::dynamic_pointer_cast(comp); + if (!sComp) { + std::dynamic_pointer_cast>(comp)->updateMatrixNodeIndices(); + } } mSLog->info("-- Initialize components from terminals or nodes of topology"); @@ -404,5 +407,19 @@ void PFSolver::SolveTask::execute(Real time, Int timeStepCount) { } Task::List PFSolver::getTasks() { - return Task::List{std::make_shared(*this)}; + + Task::List l; + + for (auto comp : mSystem.mComponents) { + auto sComp = std::dynamic_pointer_cast(comp); + if (sComp) { + for (auto task : sComp->getTasks()) { + l.push_back(task); + } + } + } + + l.push_back(std::make_shared(*this)); + + return l; } diff --git a/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb b/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb index 7727043782..25f81b2791 100644 --- a/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb +++ b/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb @@ -269,7 +269,8 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", + "language": "python", "name": "python3" }, "language_info": { @@ -282,10 +283,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.7" - }, - "orig_nbformat": 3 + "version": "3.9.10" + } }, "nbformat": 4, "nbformat_minor": 4 -} \ No newline at end of file +} diff --git a/examples/Notebooks/Circuits/CS_R2CL.ipynb b/examples/Notebooks/Circuits/CS_R2CL.ipynb index 70ee8ec8ee..757083957f 100644 --- a/examples/Notebooks/Circuits/CS_R2CL.ipynb +++ b/examples/Notebooks/Circuits/CS_R2CL.ipynb @@ -369,7 +369,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -383,7 +383,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.9" + "version": "3.9.10" }, "tests": { "skip": false diff --git a/examples/Notebooks/Circuits/DP_SP_SynGenTrStab_3Bus_SteadyState.ipynb b/examples/Notebooks/Circuits/DP_SP_SynGenTrStab_3Bus_SteadyState.ipynb index 7083c9a790..cbc1118033 100644 --- a/examples/Notebooks/Circuits/DP_SP_SynGenTrStab_3Bus_SteadyState.ipynb +++ b/examples/Notebooks/Circuits/DP_SP_SynGenTrStab_3Bus_SteadyState.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "markdown", + "metadata": {}, "source": [ "# 3 Bus (2 Generators, 1 Load) Steady state SP vs DP" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "import villas.dataprocessing.readtools as rt\n", "from villas.dataprocessing.timeseries import TimeSeries as ts\n", @@ -20,27 +22,27 @@ "import dpsimpy\n", "\n", "#%matplotlib widget" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## DP Simulation" - ], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "### Parameters" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "#-----------Power system-----------\n", "#Voltage level as Base Voltage\n", @@ -109,20 +111,20 @@ "final_time = 10\n", "time_step = 0.001\n", "scale_inertia= 1.0" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "### Powerflow for Initialization" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "time_step_pf = final_time\n", "final_time_pf = final_time + time_step_pf\n", @@ -194,20 +196,20 @@ "sim_pf.do_init_from_nodes_and_terminals(False)\n", "sim_pf.add_logger(logger_pf)\n", "sim_pf.run()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "### Dynamic Simulation" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "sim_name_dp = sim_name + \"_DP\"\n", "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_dp)\n", @@ -300,27 +302,27 @@ "sim_dp.add_logger(logger_dp)\n", "\n", "sim_dp.run()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## SP Simulation" - ], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "### Parameters" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "#-----------Power system-----------\n", "#Voltage level as Base Voltage\n", @@ -389,20 +391,20 @@ "final_time = 10\n", "time_step = 0.001\n", "scale_inertia= 1.0" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "### Powerflow for Initialization" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "time_step_pf = final_time\n", "final_time_pf = final_time + time_step_pf\n", @@ -473,20 +475,20 @@ "sim_pf.do_init_from_nodes_and_terminals(False)\n", "sim_pf.add_logger(logger_pf)\n", "sim_pf.run()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "### Dynamic Simulation" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "sim_name_sp = sim_name + \"_SP\"\n", "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_sp)\n", @@ -579,58 +581,58 @@ "sim_sp.add_logger(logger_sp)\n", "\n", "sim_sp.run()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## SP Results" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "work_dir = 'logs/SP_SynGenTrStab_3Bus_SteadyState_SP/'\n", "log_name = 'SP_SynGenTrStab_3Bus_SteadyState_SP'\n", "print(work_dir + log_name + '.csv')\n", "ts_sp1ph_TrStab_dl= rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## DP Results" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "work_dir = 'logs/DP_SynGenTrStab_3Bus_SteadyState_DP/'\n", "log_name = 'DP_SynGenTrStab_3Bus_SteadyState_DP'\n", "print(work_dir + log_name + '.csv')\n", "ts_dp1ph_TrStab_dl = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## Generator 1&2 terminal voltage" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "timestep=50e-6;\n", "t_begin=0\n", @@ -658,20 +660,20 @@ "plt.legend()\n", "\n", "f.show()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## Generator 1&2 terminal Current" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "f= plt.figure(figsize=(16,8))\n", "\n", @@ -692,20 +694,20 @@ "plt.legend()\n", "\n", "f.show()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## Generator 1&2 Rotor frequency" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "f= plt.figure(figsize=(16,8))\n", "\n", @@ -734,20 +736,20 @@ "plt.legend()\n", "\n", "f.show()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## Generator 1&2 Rotor angular velocity $\\omega _r$" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "f= plt.figure(figsize=(16,8))\n", "\n", @@ -776,20 +778,20 @@ "plt.legend()\n", "\n", "f.show()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## Generator 1&2 Rotor angle $\\delta _r$" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "f= plt.figure(figsize=(16,8))\n", "\n", @@ -818,21 +820,20 @@ "plt.legend()\n", "\n", "f.show()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", + "language": "python", "name": "python3" }, "language_info": { @@ -845,9 +846,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.7" + "version": "3.9.10" }, - "orig_nbformat": 3, "tests": { "skip": false } diff --git a/examples/Notebooks/Circuits/EMT_Slack_PiLine_PQLoad_with_PF_Init.ipynb b/examples/Notebooks/Circuits/EMT_Slack_PiLine_PQLoad_with_PF_Init.ipynb index 013d44e0f3..34cb16d842 100644 --- a/examples/Notebooks/Circuits/EMT_Slack_PiLine_PQLoad_with_PF_Init.ipynb +++ b/examples/Notebooks/Circuits/EMT_Slack_PiLine_PQLoad_with_PF_Init.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "markdown", + "metadata": {}, "source": [ "# EMT Simulation of topology with slack, line and PQ load" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "from villas.dataprocessing.readtools import *\n", "from villas.dataprocessing.timeseries import *\n", @@ -18,20 +20,20 @@ "import re\n", "\n", "# %matplotlib widget" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## Simulation" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# Parameters\n", "V_nom = 20e3\n", @@ -152,53 +154,53 @@ "sim_emt.add_logger(logger_emt)\n", "sim_emt.add_event(load_step_event)\n", "sim_emt.run()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## PF results" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "modelName = 'EMT_Slack_PiLine_PQLoad_with_PF_Init_PF'\n", "path = 'logs/' + modelName + '/'\n", "dpsim_result_file = path + modelName + '.csv'\n", "\n", "ts_dpsim_pf = read_timeseries_csv(dpsim_result_file)" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "## EMT results" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "modelName = 'EMT_Slack_PiLine_PQLoad_with_PF_Init_EMT'\n", "path = 'logs/' + modelName + '/'\n", "dpsim_result_file = path + modelName + '.csv'\n", "PEAK1PH_TO_RMS3PH = np.sqrt(3.0/2.0)\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "plt.figure(figsize=(12,6))\n", "for ts_name, ts_obj in ts_dpsim.items():\n", @@ -210,13 +212,13 @@ "plt.xlim(4.9,5.5)\n", "plt.legend()\n", "plt.show()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "plt.figure(figsize=(12,6))\n", "for ts_name, ts_obj in ts_dpsim.items():\n", @@ -228,13 +230,13 @@ "plt.xlim(4.9, 5.5)\n", "plt.legend()\n", "plt.show()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "Fs = int(1 / (ts_dpsim['i12_0'].time[1] - ts_dpsim['i12_0'].time[0]))\n", "plt.figure(figsize=(12,6))\n", @@ -243,21 +245,19 @@ "plt.xlim(44,55)\n", "plt.legend()\n", "plt.show()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -271,9 +271,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.9" + "version": "3.9.10" } }, "nbformat": 4, "nbformat_minor": 4 -} \ No newline at end of file +} diff --git a/examples/Notebooks/Circuits/Three_bus.ipynb b/examples/Notebooks/Circuits/Three_bus.ipynb new file mode 100644 index 0000000000..7ad3dd0873 --- /dev/null +++ b/examples/Notebooks/Circuits/Three_bus.ipynb @@ -0,0 +1,342 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f1a00965-0cf7-478b-82dc-58e34f62fe23", + "metadata": {}, + "source": [ + "# Three bus system" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "443114a8", + "metadata": {}, + "outputs": [], + "source": [ + "from villas.dataprocessing.readtools import *\n", + "from villas.dataprocessing.timeseries import *\n", + "import matplotlib.pyplot as plt\n", + "import dpsimpy\n", + "import re\n", + "import math \n", + "\n", + "# %matplotlib widget" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2921b17d-2a11-49f0-8311-47afed27cfb8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Attribute list for object with name Generator_1:\n", + "name type size value \n", + "-----------------------------------------------------------------------------------------------\n", + "P_set Real 338600.000000 \n", + "P_set_pu Real 0.000000 \n", + "Q_set Real 322200.000000 \n", + "Q_set_pu Real 0.000000 \n", + "V_set Real 6900.000000 \n", + "V_set_pu Real 0.000000 \n", + "base_Voltage Real 6900.000000 \n", + "i_intf MatrixComplex 1x1 [...] \n", + "name String \"Generator_1\" \n", + "uid String \"Generator_1\" \n", + "v_intf MatrixComplex 1x1 [...] \n", + "\n", + "Attribute list for object with name Generator_2:\n", + "name type size value \n", + "-----------------------------------------------------------------------------------------------\n", + "P_set Real 222200.000000 \n", + "P_set_pu Real 0.000000 \n", + "Q_set Real -28500.000000 \n", + "Q_set_pu Real 0.000000 \n", + "V_set Real 6900.000000 \n", + "V_set_pu Real 0.000000 \n", + "base_Voltage Real 6900.000000 \n", + "i_intf MatrixComplex 1x1 [...] \n", + "name String \"Generator_2\" \n", + "uid String \"Generator_2\" \n", + "v_intf MatrixComplex 1x1 [...] \n", + "\n", + "Attribute list for object with name PiLine_13:\n", + "name type size value \n", + "-----------------------------------------------------------------------------------------------\n", + "C_parallel Real 0.000000 \n", + "G_parallel Real 0.000001 \n", + "L_series Real 0.000239 \n", + "R_series Real 0.025000 \n", + "base_Voltage Real 6900.000000 \n", + "current Complex 0.000000<0.000000 \n", + "current_1 Complex 0.000000<0.000000 \n", + "current_vector MatrixComplex 2x1 [...] \n", + "i_intf MatrixComplex 1x1 [...] \n", + "name String \"PiLine_13\" \n", + "nodal_injection_stored Unknown Unknown Unknown \n", + "p_branch Real 0.000000 \n", + "p_branch_1 Real 0.000000 \n", + "p_branch_vector MatrixReal 2x1 [...] \n", + "p_inj Real 0.000000 \n", + "q_branch Real 0.000000 \n", + "q_branch_1 Real 0.000000 \n", + "q_branch_vector MatrixReal 2x1 [...] \n", + "q_inj Real 0.000000 \n", + "right_vector MatrixReal 0x0 [...] \n", + "uid String \"PiLine_13\" \n", + "v_intf MatrixComplex 1x1 [...] \n", + "\n", + "Attribute list for object with name PiLine_31:\n", + "name type size value \n", + "-----------------------------------------------------------------------------------------------\n", + "C_parallel Real 0.000000 \n", + "G_parallel Real 0.000001 \n", + "L_series Real 0.000239 \n", + "R_series Real 0.025000 \n", + "base_Voltage Real 6900.000000 \n", + "current Complex 0.000000<0.000000 \n", + "current_1 Complex 0.000000<0.000000 \n", + "current_vector MatrixComplex 2x1 [...] \n", + "i_intf MatrixComplex 1x1 [...] \n", + "name String \"PiLine_31\" \n", + "nodal_injection_stored Unknown Unknown Unknown \n", + "p_branch Real 0.000000 \n", + "p_branch_1 Real 0.000000 \n", + "p_branch_vector MatrixReal 2x1 [...] \n", + "p_inj Real 0.000000 \n", + "q_branch Real 0.000000 \n", + "q_branch_1 Real 0.000000 \n", + "q_branch_vector MatrixReal 2x1 [...] \n", + "q_inj Real 0.000000 \n", + "right_vector MatrixReal 0x0 [...] \n", + "uid String \"PiLine_31\" \n", + "v_intf MatrixComplex 1x1 [...] \n", + "\n", + "Attribute list for object with name PiLine_23:\n", + "name type size value \n", + "-----------------------------------------------------------------------------------------------\n", + "C_parallel Real 0.000000 \n", + "G_parallel Real 0.000001 \n", + "L_series Real 0.000477 \n", + "R_series Real 0.050000 \n", + "base_Voltage Real 6900.000000 \n", + "current Complex 0.000000<0.000000 \n", + "current_1 Complex 0.000000<0.000000 \n", + "current_vector MatrixComplex 2x1 [...] \n", + "i_intf MatrixComplex 1x1 [...] \n", + "name String \"PiLine_23\" \n", + "nodal_injection_stored Unknown Unknown Unknown \n", + "p_branch Real 0.000000 \n", + "p_branch_1 Real 0.000000 \n", + "p_branch_vector MatrixReal 2x1 [...] \n", + "p_inj Real 0.000000 \n", + "q_branch Real 0.000000 \n", + "q_branch_1 Real 0.000000 \n", + "q_branch_vector MatrixReal 2x1 [...] \n", + "q_inj Real 0.000000 \n", + "right_vector MatrixReal 0x0 [...] \n", + "uid String \"PiLine_23\" \n", + "v_intf MatrixComplex 1x1 [...] \n", + "\n", + "Attribute list for object with name Load:\n", + "name type size value \n", + "-----------------------------------------------------------------------------------------------\n", + "B Real -0.005835 \n", + "G Real 0.011670 \n", + "i_intf MatrixComplex 1x1 [...] \n", + "name String \"Load\" \n", + "uid String \"Load\" \n", + "v_intf MatrixComplex 1x1 [...] \n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[15:48:47.535015 PiLine_13 warning] Zero value for Capacitance, setting default value of C=1e-12 [F]\n", + "[15:48:47.535030 PiLine_13 warning] Zero value for Conductance, setting default value of G=1e-06 [S]\n", + "[15:48:47.535441 PiLine_31 warning] Zero value for Capacitance, setting default value of C=1e-12 [F]\n", + "[15:48:47.535447 PiLine_31 warning] Zero value for Conductance, setting default value of G=1e-06 [S]\n", + "[15:48:47.535890 PiLine_23 warning] Zero value for Capacitance, setting default value of C=1e-12 [F]\n", + "[15:48:47.535895 PiLine_23 warning] Zero value for Conductance, setting default value of G=1e-06 [S]\n", + "[15:48:47.540426 Three_bus_system info] Initialize simulation: Three_bus_system\n", + "[15:48:47.540983 Three_bus_system info] Scheduling tasks.\n", + "[15:48:47.541283 Three_bus_system info] Scheduling done.\n", + "[15:48:47.541286 Three_bus_system info] Opening interfaces.\n", + "[15:48:47.541290 Three_bus_system info] Start synchronization with remotes on 0 interfaces\n", + "[15:48:47.541292 Three_bus_system info] Synchronized simulation start with remotes\n", + "[15:48:47.541294 Three_bus_system info] Start simulation: Three_bus_system\n", + "[15:48:47.541301 Three_bus_system info] Time step: 1.000000e+00\n", + "[15:48:47.541303 Three_bus_system info] Final time: 2.000000e+00\n", + "[15:48:47.542472 Three_bus_system info] Simulation calculation time: 0.001164\n", + "[15:48:47.542509 Three_bus_system info] Simulation finished.\n" + ] + } + ], + "source": [ + "### nominal power\n", + "V_nom = 6.9e3\n", + "\n", + "\n", + "# Simulation parameters\n", + "time_step = 0.001\n", + "final_time = 1.0\n", + "\n", + "# POWERFLOW FOR INITIALIZATION\n", + "time_step_pf = final_time\n", + "final_time_pf = final_time + time_step_pf\n", + "sim_name_pf = 'Three_bus_system'\n", + "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", + "\n", + "# Components\n", + "# nodes\n", + "n1_pf = dpsimpy.sp.SimNode('n1', dpsimpy.PhaseType.Single)\n", + "n2_pf = dpsimpy.sp.SimNode('n2', dpsimpy.PhaseType.Single)\n", + "n3_pf = dpsimpy.sp.SimNode('n3', dpsimpy.PhaseType.Single)\n", + "\n", + "#injection\n", + "\n", + "# configuration(Synchronous generator 1)\n", + "nom_power_G1=100e6\n", + "nom_ph_ph_volt_RMS_G1=6.9e3\n", + "init_active_power_G1=0.3386e6\n", + "init_reactive_power_G1=0.3222e6\n", + "set_point_voltage_G1=nom_ph_ph_volt_RMS_G1\n", + "t1_ratio=1\n", + "\n", + "#setup\n", + "gen1_pf = dpsimpy.sp.ph1.SynchronGenerator(\"Generator_1\", dpsimpy.LogLevel.debug)\n", + "#setPointVoltage is defined as the voltage at the transfomer primary side and should be transformed to network side\n", + "# VD means slack bus\n", + "gen1_pf.set_parameters(nom_power_G1, nom_ph_ph_volt_RMS_G1, init_active_power_G1,\n", + " set_point_voltage_G1 * t1_ratio, dpsimpy.PowerflowBusType.VD,init_reactive_power_G1)\n", + "gen1_pf.set_base_voltage(V_nom)\n", + "\n", + "\n", + "# configuration(Synchronous generator 2)\n", + "nom_power_G2=100e6\n", + "nom_ph_ph_volt_RMS_G2=6.9e3\n", + "init_active_power_G2=0.2222e6\n", + "init_reactive_power_G2=-0.0285e6\n", + "set_point_voltage_G2=nom_ph_ph_volt_RMS_G2\n", + "t2_ratio=1\n", + "\n", + "gen2_pf = dpsimpy.sp.ph1.SynchronGenerator(\"Generator_2\", dpsimpy.LogLevel.debug)\n", + "#setPointVoltage is defined as the voltage at the transfomer primary side and should be transformed to network side\n", + "gen2_pf.set_parameters(nom_power_G2, nom_ph_ph_volt_RMS_G2, init_active_power_G2,\n", + " set_point_voltage_G2 * t2_ratio, dpsimpy.PowerflowBusType.PV,init_reactive_power_G2)\n", + "gen2_pf.set_base_voltage(V_nom)\n", + "\n", + "#line power flow\n", + "line_resistance=0.025\n", + "pi= math.pi\n", + "line_inductance=0.075/(2*pi*50)\n", + "\n", + "line_pf_1 = dpsimpy.sp.ph1.PiLine('PiLine_13', dpsimpy.LogLevel.debug)\n", + "line_pf_1.set_parameters(R=line_resistance, L=line_inductance, C=0)\n", + "line_pf_1.set_base_voltage(V_nom)\n", + "\n", + "line_pf_2 = dpsimpy.sp.ph1.PiLine('PiLine_31', dpsimpy.LogLevel.debug)\n", + "line_pf_2.set_parameters(R=line_resistance, L=line_inductance, C=0)\n", + "line_pf_2.set_base_voltage(V_nom)\n", + "\n", + "line_pf_3 = dpsimpy.sp.ph1.PiLine('PiLine_23', dpsimpy.LogLevel.debug)\n", + "line_pf_3.set_parameters(R=2*line_resistance, L=2*line_inductance, C=0)\n", + "line_pf_3.set_base_voltage(V_nom)\n", + "\n", + "\n", + "# load power flow on node 3\n", + "p_demand=0.5556e6\n", + "q_demand=0.2778e6\n", + "active_power_L=p_demand\n", + "reactive_power_L=q_demand\n", + "load_pf = dpsimpy.sp.ph1.Shunt('Load', dpsimpy.LogLevel.debug)\n", + "load_pf.set_parameters(active_power_L / V_nom**2, - reactive_power_L / V_nom**2)\n", + "load_pf.set_base_voltage(V_nom)\n", + "\n", + "'''\n", + "# Load on node 3\n", + "p_demand=0.5556e6\n", + "q_demand=0.2778e6\n", + "active_power_L=p_demand\n", + "reactive_power_L=q_demand\n", + "load_pf = dpsimpy.dp.ph1.RXLoad(\"Load\", dpsimpy.LogLevel.debug)\n", + "load_pf.set_parameters(active_power_L, reactive_power_L, V_nom)\n", + "'''\n", + "\n", + "# Topology\n", + "gen1_pf.connect([n1_pf])\n", + "gen2_pf.connect([n2_pf])\n", + "line_pf_1.connect([n1_pf, n3_pf])\n", + "line_pf_2.connect([n1_pf, n3_pf])\n", + "line_pf_3.connect([n2_pf, n3_pf])\n", + "load_pf.connect([n3_pf])\n", + "system_pf = dpsimpy.SystemTopology(50, [n1_pf, n2_pf,n3_pf], [gen1_pf,gen2_pf, line_pf_1,line_pf_2,line_pf_3, load_pf])\n", + "\n", + "# Logging\n", + "logger_pf = dpsimpy.Logger(sim_name_pf)\n", + "logger_pf.log_attribute('v1', 'v', n1_pf)\n", + "logger_pf.log_attribute('v2', 'v', n2_pf)\n", + "logger_pf.log_attribute('v3', 'v', n3_pf)\n", + "logger_pf.log_attribute('i13', 'i_intf', line_pf_1)\n", + "logger_pf.log_attribute('i23', 'i_intf', line_pf_3)\n", + "\n", + "\n", + "# print\n", + "gen1_pf.print_attribute_list()\n", + "gen2_pf.print_attribute_list()\n", + "line_pf_1.print_attribute_list()\n", + "line_pf_2.print_attribute_list()\n", + "line_pf_3.print_attribute_list()\n", + "load_pf.print_attribute_list()\n", + "\n", + "\n", + "# Simulation\n", + "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", + "sim_pf.set_domain(dpsimpy.Domain.SP)\n", + "sim_pf.set_system(system_pf)\n", + "sim_pf.set_time_step(time_step_pf)\n", + "sim_pf.set_final_time(final_time_pf)\n", + "sim_pf.set_solver(dpsimpy.Solver.NRP)\n", + "sim_pf.do_init_from_nodes_and_terminals(False)\n", + "sim_pf.add_logger(logger_pf)\n", + "sim_pf.run()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a728916c-e239-40d3-8656-0498872266bf", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/Notebooks/Circuits/VS_CS_R4.ipynb b/examples/Notebooks/Circuits/VS_CS_R4.ipynb index c4435ffc17..f5aa6adab8 100644 --- a/examples/Notebooks/Circuits/VS_CS_R4.ipynb +++ b/examples/Notebooks/Circuits/VS_CS_R4.ipynb @@ -345,7 +345,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -359,7 +359,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.9" + "version": "3.9.10" }, "widgets": { "application/vnd.jupyter.widget-state+json": { diff --git a/examples/Notebooks/Circuits/VS_R2L3.ipynb b/examples/Notebooks/Circuits/VS_R2L3.ipynb index 8653ad07f8..45dda0509a 100644 --- a/examples/Notebooks/Circuits/VS_R2L3.ipynb +++ b/examples/Notebooks/Circuits/VS_R2L3.ipynb @@ -369,7 +369,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -383,7 +383,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.9" + "version": "3.9.10" }, "widgets": { "application/vnd.jupyter.widget-state+json": { diff --git a/examples/Notebooks/Circuits/VS_RC1.ipynb b/examples/Notebooks/Circuits/VS_RC1.ipynb index 41a9f1bd0d..9e82bc12f3 100644 --- a/examples/Notebooks/Circuits/VS_RC1.ipynb +++ b/examples/Notebooks/Circuits/VS_RC1.ipynb @@ -298,7 +298,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -312,7 +312,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.9" + "version": "3.9.10" }, "widgets": { "application/vnd.jupyter.widget-state+json": { diff --git a/examples/Notebooks/Circuits/VS_RL1.ipynb b/examples/Notebooks/Circuits/VS_RL1.ipynb index eb8699147a..daea032b8b 100644 --- a/examples/Notebooks/Circuits/VS_RL1.ipynb +++ b/examples/Notebooks/Circuits/VS_RL1.ipynb @@ -306,7 +306,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -320,7 +320,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.9" + "version": "3.9.10" }, "widgets": { "application/vnd.jupyter.widget-state+json": {