From bd38116d8143e03941642a6aa1b0a44526b71ad4 Mon Sep 17 00:00:00 2001 From: Jonas Schroeder Date: Sat, 29 Oct 2022 16:22:42 +0000 Subject: [PATCH] move method implementations into source files pt. 3 Signed-off-by: Jonas Schroeder --- .../include/dpsim-models/CIM/Reader.h | 21 +- dpsim-models/include/dpsim-models/Logger.h | 61 +----- dpsim-models/include/dpsim-models/MathUtils.h | 202 ++++-------------- .../include/dpsim-models/SP/SP_Ph1_Switch.h | 12 +- .../SP/SP_Ph1_SynchronGenerator.h | 2 +- .../SP/SP_Ph1_SynchronGeneratorVBR.h | 2 +- .../dpsim-models/SP/SP_Ph1_VoltageSource.h | 12 +- .../dpsim-models/SP/SP_Ph1_varResSwitch.h | 2 +- .../dpsim-models/SP/SP_Ph3_VoltageSource.h | 12 +- dpsim-models/include/dpsim-models/SimNode.h | 37 +--- .../include/dpsim-models/SimPowerComp.h | 53 ++--- .../include/dpsim-models/SystemTopology.h | 141 ++---------- .../include/dpsim-models/TopologicalNode.h | 14 +- dpsim-models/src/CIM/Reader.cpp | 24 +++ dpsim-models/src/Logger.cpp | 54 +++++ dpsim-models/src/MathUtils.cpp | 177 +++++++++++++++ dpsim-models/src/SP/SP_Ph1_Switch.cpp | 2 + .../src/SP/SP_Ph1_SynchronGenerator.cpp | 1 + .../src/SP/SP_Ph1_SynchronGeneratorVBR.cpp | 2 + dpsim-models/src/SP/SP_Ph1_varResSwitch.cpp | 2 + dpsim-models/src/SimNode.cpp | 42 ++++ dpsim-models/src/SimPowerComp.cpp | 72 +++++++ dpsim-models/src/SystemTopology.cpp | 145 +++++++++++++ dpsim-models/src/TopologicalNode.cpp | 16 ++ dpsim-models/src/TopologicalTerminal.cpp | 24 +++ 25 files changed, 683 insertions(+), 449 deletions(-) diff --git a/dpsim-models/include/dpsim-models/CIM/Reader.h b/dpsim-models/include/dpsim-models/CIM/Reader.h index 3159917092..dae2e40d34 100644 --- a/dpsim-models/include/dpsim-models/CIM/Reader.h +++ b/dpsim-models/include/dpsim-models/CIM/Reader.h @@ -169,28 +169,15 @@ namespace CIM { GeneratorType genType = GeneratorType::None); /// SystemTopology loadCIM(Real systemFrequency, const std::list &filenamesString, Domain domain = Domain::DP, PhaseType phase = PhaseType::Single, - GeneratorType genType = GeneratorType::None) { - std::list filenames; - for (auto f : filenamesString) - filenames.emplace_back(f); - - return loadCIM(systemFrequency, filenames, domain, phase, genType); - } + GeneratorType genType = GeneratorType::None); // #### shunt component settings #### /// set shunt capacitor value - void setShuntCapacitor(Real v) { - mShuntCapacitorValue = v; - mSetShuntCapacitor = true; - } + void setShuntCapacitor(Real v); /// set shunt conductance value - void setShuntConductance(Real v) { - mShuntConductanceValue = v; - mSetShuntConductance = true; - } - + void setShuntConductance(Real v); /// If set, some components like loads include protection switches - void useProtectionSwitches(Bool value = true) { mUseProtectionSwitches = value; } + void useProtectionSwitches(Bool value = true); }; } } diff --git a/dpsim-models/include/dpsim-models/Logger.h b/dpsim-models/include/dpsim-models/Logger.h index c06006c994..8df7e8db3a 100644 --- a/dpsim-models/include/dpsim-models/Logger.h +++ b/dpsim-models/include/dpsim-models/Logger.h @@ -45,59 +45,20 @@ namespace CPS { /// static Log get(const std::string &name, Level filelevel = Level::info, Level clilevel = Level::off); /// - static void setLogLevel(std::shared_ptr logger, Logger::Level level) { - logger->set_level(level); - } + static void setLogLevel(std::shared_ptr logger, Logger::Level level); /// - static void setLogPattern(std::shared_ptr logger, std::string pattern) { - logger->set_pattern(pattern); - } + static void setLogPattern(std::shared_ptr logger, std::string pattern); // #### to string methods #### - static String matrixToString(const Matrix& mat) { - std::stringstream ss; - ss << std::scientific << "\n" << mat; - return ss.str(); - } - - static String matrixCompToString(const MatrixComp& mat) { - std::stringstream ss; - ss << std::scientific << "\n" << mat; - return ss.str(); - } - - static String sparseMatrixToString(const SparseMatrix& mat) { - return matrixToString(Matrix(mat)); - } - - static String sparseMatrixCompToString(const SparseMatrixComp& mat) { - return matrixCompToString(MatrixComp(mat)); - } - - static String phasorMatrixToString(const MatrixComp& mat) { - std::stringstream ss; - ss << std::scientific << Math::abs(mat) << "\n\n" << Math::phase(mat); - return ss.str(); - } - - static String phasorToString(const Complex& num) { - std::stringstream ss; - ss << std::defaultfloat << Math::abs(num) << "<" << Math::phaseDeg(num); - return ss.str(); - } - - static String complexToString(const Complex& num) { - std::stringstream ss; - ss << std::defaultfloat << num.real() << "+j" << num.imag(); - return ss.str(); - } - - static String realToString(const Real& num) { - std::stringstream ss; - ss << std::defaultfloat << num; - return ss.str(); - } - + static String matrixToString(const Matrix& mat); + static String matrixCompToString(const MatrixComp& mat); + static String sparseMatrixToString(const SparseMatrix& mat); + static String sparseMatrixCompToString(const SparseMatrixComp& mat); + static String phasorMatrixToString(const MatrixComp& mat); + static String phasorToString(const Complex& num); + static String complexToString(const Complex& num); + static String realToString(const Real& num); + static String getCSVColumnNames(std::vector names); static String getCSVLineFromData(Real time, Real data); static String getCSVLineFromData(Real time, const Matrix& data); diff --git a/dpsim-models/include/dpsim-models/MathUtils.h b/dpsim-models/include/dpsim-models/MathUtils.h index 7a0a789563..95053ea27c 100644 --- a/dpsim-models/include/dpsim-models/MathUtils.h +++ b/dpsim-models/include/dpsim-models/MathUtils.h @@ -17,59 +17,22 @@ namespace CPS { typedef Real(*DeriveFnPtr) (Matrix inputs); // #### Angular Operations #### - static Real radtoDeg(Real rad) { - return rad * 180 / PI; - } - - static Real degToRad(Real deg) { - return deg * PI / 180; - } - - static Real phase(Complex value) { - return std::arg(value); - } - - static Real phaseDeg(Complex value) { - return radtoDeg(phase(value)); - } - - static Real abs(Complex value) { - return std::abs(value); - } - - static Matrix abs(const MatrixComp& mat) { - size_t nRows = mat.rows(); - size_t nCols = mat.cols(); - Matrix res(mat.rows(), mat.cols()); - - for (size_t i = 0; i < nRows; ++i) { - for (size_t j = 0; j < nCols; ++j) { - res(i,j) = std::abs(mat(i,j)); - } - } - return res; - } - - static Matrix phase(const MatrixComp& mat) { - size_t nRows = mat.rows(); - size_t nCols = mat.cols(); - Matrix res(mat.rows(), mat.cols()); - - for (size_t i = 0; i < nRows; ++i) { - for (size_t j = 0; j < nCols; ++j) { - res(i,j) = std::arg(mat(i,j)); - } - } - return res; - } - - static Complex polar(Real abs, Real phase) { - return std::polar(abs, phase); - } - - static Complex polarDeg(Real abs, Real phase) { - return std::polar(abs, radtoDeg(phase)); - } + static Real radtoDeg(Real rad); + + static Real degToRad(Real deg); + + static Real phase(Complex value); + + static Real phaseDeg(Complex value); + + static Real abs(Complex value); + + static Matrix abs(const MatrixComp& mat); + + static Matrix phase(const MatrixComp& mat); + + static Complex polar(Real abs, Real phase); + static Complex polarDeg(Real abs, Real phase); // #### Vector Operations #### // @@ -78,43 +41,16 @@ namespace CPS { // | Re(row,0)_harm2 | Re(row,colOffset)_harm2 | // | Im(row,0)_harm2 | Im(row,colOffset)_harm2 | - static void setVectorElement(Matrix& mat, Matrix::Index row, Complex value, Int maxFreq = 1, Int freqIdx = 0, Matrix::Index colOffset = 0) { - Eigen::Index harmonicOffset = mat.rows() / maxFreq; - Eigen::Index complexOffset = harmonicOffset / 2; - Eigen::Index harmRow = row + harmonicOffset * freqIdx; - - mat(harmRow, colOffset) = value.real(); - mat(harmRow + complexOffset, colOffset) = value.imag(); - } + static void setVectorElement(Matrix& mat, Matrix::Index row, Complex value, Int maxFreq = 1, Int freqIdx = 0, Matrix::Index colOffset = 0); - static void addToVectorElement(Matrix& mat, Matrix::Index row, Complex value, Int maxFreq = 1, Int freqIdx = 0) { - Eigen::Index harmonicOffset = mat.rows() / maxFreq; - Eigen::Index complexOffset = harmonicOffset / 2; - Eigen::Index harmRow = row + harmonicOffset * freqIdx; + static void addToVectorElement(Matrix& mat, Matrix::Index row, Complex value, Int maxFreq = 1, Int freqIdx = 0); - mat(harmRow, 0) = mat(harmRow, 0) + value.real(); - mat(harmRow + complexOffset, 0) = mat(harmRow + complexOffset, 0) + value.imag(); - } + static Complex complexFromVectorElement(const Matrix& mat, Matrix::Index row, Int maxFreq = 1, Int freqIdx = 0); - static Complex complexFromVectorElement(const Matrix& mat, Matrix::Index row, Int maxFreq = 1, Int freqIdx = 0) { - Eigen::Index harmonicOffset = mat.rows() / maxFreq; - Eigen::Index complexOffset = harmonicOffset / 2; - Eigen::Index harmRow = row + harmonicOffset * freqIdx; + static void addToVectorElement(Matrix& mat, Matrix::Index row, Real value); + static void setVectorElement(Matrix& mat, Matrix::Index row, Real value); - return Complex(mat(harmRow, 0), mat(harmRow + complexOffset, 0)); - } - - static void addToVectorElement(Matrix& mat, Matrix::Index row, Real value) { - mat(row, 0) = mat(row, 0) + value; - } - - static void setVectorElement(Matrix& mat, Matrix::Index row, Real value) { - mat(row, 0) = value; - } - - static Real realFromVectorElement(const Matrix& mat, Matrix::Index row) { - return mat(row, 0); - } + static Real realFromVectorElement(const Matrix& mat, Matrix::Index row); // #### Matric Operations #### // @@ -122,63 +58,18 @@ namespace CPS { // | Re-Im(row,col)_harm1 | Im-Im(row,col)_harm1 | Interharmonics harm1-harm2 // | Interharmonics harm1-harm2 | Re(row,col)_harm2 | Re(row,col)_harm2 | // | Interharmonics harm1-harm2 | Im(row,col)_harm2 | Im(row,col)_harm2 | + static void setMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Complex value, Int maxFreq = 1, Int freqIdx = 0); + + static void addToMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Complex value, Int maxFreq = 1, Int freqIdx = 0); + + static void addToMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Matrix value, Int maxFreq = 1, Int freqIdx = 0); + + static void setMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Real value); + + static void addToMatrixElement(Matrix& mat, std::vector rows, std::vector columns, Complex value); - static void setMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Complex value, Int maxFreq = 1, Int freqIdx = 0) { - // Assume square matrix - Eigen::Index harmonicOffset = mat.rows() / maxFreq; - Eigen::Index complexOffset = harmonicOffset / 2; - Eigen::Index harmRow = row + harmonicOffset * freqIdx; - Eigen::Index harmCol = column + harmonicOffset * freqIdx; - - mat(harmRow, harmCol) = value.real(); - mat(harmRow + complexOffset, harmCol + complexOffset) = value.real(); - mat(harmRow, harmCol + complexOffset) = - value.imag(); - mat(harmRow + complexOffset, harmCol) = value.imag(); - } - - static void addToMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Complex value, Int maxFreq = 1, Int freqIdx = 0) { - // Assume square matrix - Eigen::Index harmonicOffset = mat.rows() / maxFreq; - Eigen::Index complexOffset = harmonicOffset / 2; - Eigen::Index harmRow = row + harmonicOffset * freqIdx; - Eigen::Index harmCol = column + harmonicOffset * freqIdx; - - mat(harmRow, harmCol) = mat(harmRow, harmCol) + value.real(); - mat(harmRow + complexOffset, harmCol + complexOffset) = mat(harmRow + complexOffset, harmCol + complexOffset) + value.real(); - mat(harmRow, harmCol + complexOffset) = mat(harmRow, harmCol + complexOffset) - value.imag(); - mat(harmRow + complexOffset, harmCol) = mat(harmRow + complexOffset, harmCol) + value.imag(); - } - - static void addToMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Matrix value, Int maxFreq = 1, Int freqIdx = 0) { - // Assume square matrix - Eigen::Index harmonicOffset = mat.rows() / maxFreq; - Eigen::Index complexOffset = harmonicOffset / 2; - Eigen::Index harmRow = row + harmonicOffset * freqIdx; - Eigen::Index harmCol = column + harmonicOffset * freqIdx; - - mat(harmRow, harmCol) = mat(harmRow, harmCol) + value(0,0); - mat(harmRow + complexOffset, harmCol + complexOffset) = mat(harmRow + complexOffset, harmCol + complexOffset) + value(1,1); - mat(harmRow, harmCol + complexOffset) = mat(harmRow, harmCol + complexOffset) + value(0,1); - mat(harmRow + complexOffset, harmCol) = mat(harmRow + complexOffset, harmCol) + value(1,0); - } - - static void setMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Real value) { - mat(row, column) = value; - } - - static void addToMatrixElement(Matrix& mat, std::vector rows, std::vector columns, Complex value) { - for (UInt phase = 0; phase < rows.size(); phase++) - addToMatrixElement(mat, rows[phase], columns[phase], value); - } - - static void addToMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Real value) { - mat(row, column) = mat(row, column) + value; - } - - static void addToMatrixElement(Matrix& mat, std::vector rows, std::vector columns, Real value) { - for (UInt phase = 0; phase < rows.size(); phase++) - addToMatrixElement(mat, rows[phase], columns[phase], value); - } + static void addToMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Real value); + static void addToMatrixElement(Matrix& mat, std::vector rows, std::vector columns, Real value); // #### Integration Methods #### static Matrix StateSpaceTrapezoidal(Matrix states, Matrix A, Matrix B, Real dt, Matrix u_new, Matrix u_old); @@ -200,33 +91,12 @@ namespace CPS { static Complex rotatingFrame2to1(Complex f2, Real theta1, Real theta2); /// To convert single phase complex variables (voltages, currents) to symmetrical three phase ones - static MatrixComp singlePhaseVariableToThreePhase(Complex var_1ph) { - MatrixComp var_3ph = MatrixComp::Zero(3, 1); - var_3ph << - var_1ph, - var_1ph * SHIFT_TO_PHASE_B, - var_1ph * SHIFT_TO_PHASE_C; - return var_3ph; - } + static MatrixComp singlePhaseVariableToThreePhase(Complex var_1ph); /// To convert single phase parameters to symmetrical three phase ones - static Matrix singlePhaseParameterToThreePhase(Real parameter) { - Matrix param_3ph = Matrix::Zero(3, 3); - param_3ph << - parameter, 0., 0., - 0., parameter, 0., - 0, 0., parameter; - return param_3ph; - } + static Matrix singlePhaseParameterToThreePhase(Real parameter); /// To convert single phase power to symmetrical three phase - static Matrix singlePhasePowerToThreePhase(Real power) { - Matrix power_3ph = Matrix::Zero(3, 3); - power_3ph << - power/3., 0., 0., - 0., power/3., 0., - 0, 0., power/3.; - return power_3ph; - } + static Matrix singlePhasePowerToThreePhase(Real power); }; } diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Switch.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Switch.h index 98eeb3b1bb..53fc0cd2f6 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Switch.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Switch.h @@ -56,6 +56,12 @@ namespace Ph1 { void mnaAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector); + + // #### MNA section for switch #### + /// Check if switch is closed + Bool mnaIsClosed(); + /// Stamps system matrix considering the defined switch position + void mnaApplySwitchSystemMatrixStamp(Bool closed, Matrix& systemMatrix, Int freqIdx); class MnaPostStep : public Task { public: @@ -69,12 +75,6 @@ namespace Ph1 { Switch& mSwitch; Attribute::Ptr mLeftVector; }; - - // #### MNA section for switch #### - /// Check if switch is closed - Bool mnaIsClosed() { return isClosed(); } - /// Stamps system matrix considering the defined switch position - void mnaApplySwitchSystemMatrixStamp(Bool closed, Matrix& systemMatrix, Int freqIdx); }; } } diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGenerator.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGenerator.h index 93abcae184..385736b0f9 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGenerator.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGenerator.h @@ -73,7 +73,7 @@ namespace Ph1 { /// Update active & reactive power injection (VD bus) void updatePowerInjection(Complex powerInj); /// Get Apparent power of Powerflow solution - Complex getApparentPower() { return Complex (**mSetPointActivePower, **mSetPointReactivePower);} + Complex getApparentPower(); }; } } diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGeneratorVBR.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGeneratorVBR.h index c4b2c815c2..30cb864bfb 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGeneratorVBR.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGeneratorVBR.h @@ -56,7 +56,7 @@ namespace Ph1 { virtual ~SynchronGeneratorVBR(); /// Mark that parameter changes so that system matrix is updated - Bool hasParameterChanged() override { return 1; }; + Bool hasParameterChanged() override; }; } } diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_VoltageSource.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_VoltageSource.h index e1b20b243f..b3b414de7f 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_VoltageSource.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_VoltageSource.h @@ -95,6 +95,12 @@ namespace Ph1 { /// Add MNA post step dependencies void mnaAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector); + // #### DAE Section #### + /// Residual function for DAE Solver + void daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector& off); + ///Voltage Getter + Complex daeInitialize(); + class MnaPreStep : public Task { public: MnaPreStep(VoltageSource& voltageSource) : @@ -118,12 +124,6 @@ namespace Ph1 { VoltageSource& mVoltageSource; Attribute::Ptr mLeftVector; }; - - // #### DAE Section #### - /// Residual function for DAE Solver - void daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector& off); - ///Voltage Getter - Complex daeInitialize(); }; } } diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_varResSwitch.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_varResSwitch.h index 94b20a0bf7..815864dde2 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_varResSwitch.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_varResSwitch.h @@ -86,7 +86,7 @@ namespace Ph1 { // #### MNA section for switch #### /// Check if switch is closed - Bool mnaIsClosed() { return isClosed(); } + Bool mnaIsClosed(); /// Stamps system matrix considering the defined switch position void mnaApplySwitchSystemMatrixStamp(Bool closed, Matrix& systemMatrix, Int freqIdx); diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph3_VoltageSource.h b/dpsim-models/include/dpsim-models/SP/SP_Ph3_VoltageSource.h index 76763b2732..4d325e3bc2 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph3_VoltageSource.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph3_VoltageSource.h @@ -60,6 +60,12 @@ namespace CPS { /// Returns current through the component void mnaUpdateCurrent(const Matrix& leftVector); + // #### DAE Section #### + /// Residual function for DAE Solver + void daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector& off); + ///Voltage Getter + Complex daeInitialize(); + class MnaPreStep : public CPS::Task { public: MnaPreStep(VoltageSource& voltageSource) : @@ -90,12 +96,6 @@ namespace CPS { VoltageSource& mVoltageSource; Attribute::Ptr mLeftVector; }; - - // #### DAE Section #### - /// Residual function for DAE Solver - void daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector& off); - ///Voltage Getter - Complex daeInitialize(); }; } } diff --git a/dpsim-models/include/dpsim-models/SimNode.h b/dpsim-models/include/dpsim-models/SimNode.h index 767b19b75f..c8beb3ef3d 100644 --- a/dpsim-models/include/dpsim-models/SimNode.h +++ b/dpsim-models/include/dpsim-models/SimNode.h @@ -61,40 +61,15 @@ namespace CPS { /// Initialize state matrices with size according to phase type and frequency number void initialize(Matrix frequencies); /// Returns matrix index for specified phase - UInt matrixNodeIndex(PhaseType phaseType = PhaseType::Single) { - if ((phaseType == PhaseType::A || phaseType == PhaseType::Single) - && (mPhaseType == PhaseType::Single - || mPhaseType == PhaseType::A - || mPhaseType == PhaseType::ABC)) - return mMatrixNodeIndex[0]; - else if (phaseType == PhaseType::B - && (mPhaseType == PhaseType::B - || mPhaseType == PhaseType::ABC)) - return mMatrixNodeIndex[1]; - else if (phaseType == PhaseType::C - && (mPhaseType == PhaseType::C - || mPhaseType == PhaseType::ABC)) - return mMatrixNodeIndex[2]; - else - return 0; - } + UInt matrixNodeIndex(PhaseType phaseType = PhaseType::Single); /// Returns all matrix indices - std::vector matrixNodeIndices() { - if (mPhaseType == PhaseType::B) - return { mMatrixNodeIndex[1] }; - else if (mPhaseType == PhaseType::C) - return { mMatrixNodeIndex[2] }; - else if (mPhaseType == PhaseType::ABC) - return mMatrixNodeIndex; - else // phaseType == PhaseType::Single || mPhaseType == PhaseType::A - return { mMatrixNodeIndex[0] }; - } + std::vector matrixNodeIndices(); /// VarType singleVoltage(PhaseType phaseType = PhaseType::Single); /// - MatrixVar voltage() { return **mVoltage; } + MatrixVar voltage(); /// - void setMatrixNodeIndex(UInt phase, UInt matrixNodeIndex) { mMatrixNodeIndex[phase] = matrixNodeIndex; } + void setMatrixNodeIndex(UInt phase, UInt matrixNodeIndex); /// void setVoltage(VarType newVoltage) { } /// @@ -108,9 +83,7 @@ namespace CPS { /// void mnaUpdateVoltageHarm(const Matrix& leftVector, Int freqIdx); /// Return list of MNA tasks - const Task::List& mnaTasks() { - return mMnaTasks; - } + const Task::List& mnaTasks(); /// class MnaPostStepHarm : public Task { public: diff --git a/dpsim-models/include/dpsim-models/SimPowerComp.h b/dpsim-models/include/dpsim-models/SimPowerComp.h index 18a0e143f9..429cf842b3 100644 --- a/dpsim-models/include/dpsim-models/SimPowerComp.h +++ b/dpsim-models/include/dpsim-models/SimPowerComp.h @@ -56,11 +56,11 @@ namespace CPS { /// Returns a modified copy of the component with the given suffix added to the name and without /// connected nodes / terminals /// DEPRECATED: This method should be removed - virtual Ptr clone(String name) { return nullptr; } + virtual Ptr clone(String name); // #### Terminals #### /// Returns nominal number of Terminals for this component type. - UInt terminalNumber() { return mNumTerminals; } + UInt terminalNumber(); /// Returns the number of connected Terminals UInt terminalNumberConnected(); /// @@ -68,7 +68,7 @@ namespace CPS { /// void checkForUnconnectedTerminals(); /// Return list of Terminal pointers - typename SimTerminal::List terminals() { return mTerminals; } + typename SimTerminal::List terminals(); /// Get pointer to Terminal typename SimTerminal::Ptr terminal(UInt index); /// Returns the list of terminals as TopologicalTerminal pointers @@ -88,56 +88,49 @@ namespace CPS { /// Returns the actual number of Nodes / Terminals that are already set to valid Nodes. UInt nodeNumber(); /// Get pointer to node - typename SimNode::Ptr node(UInt index) { - if (index >= mTerminals.size()) { - throw SystemError("Node not available for " + **mUID); - } - return mTerminals[index]->node(); - }; - UInt matrixNodeIndex(UInt nodeIndex) { - return mMatrixNodeIndices[nodeIndex * 3]; - } - UInt matrixNodeIndex(UInt nodeIndex, UInt phaseIndex) { - return mMatrixNodeIndices[nodeIndex * 3 + phaseIndex]; - } + typename SimNode::Ptr node(UInt index); + + UInt matrixNodeIndex(UInt nodeIndex); + + UInt matrixNodeIndex(UInt nodeIndex, UInt phaseIndex); /// TODO replace with access to mMatrixNodeIndices - std::vector matrixNodeIndices(UInt index) { return node(index)->matrixNodeIndices(); } + std::vector matrixNodeIndices(UInt index); /// Get nodes as base type TopologicalNode TopologicalNode::List topologicalNodes(); // #### Virtual Nodes #### /// Returns nominal number of virtual nodes for this component type. - UInt virtualNodesNumber() { return mNumVirtualNodes; } + UInt virtualNodesNumber(); /// Returns true if virtual node number is greater than zero. - Bool hasVirtualNodes() { return mNumVirtualNodes > 0; } + Bool hasVirtualNodes(); /// Returns true if subcomponents included in this component - Bool hasSubComponents() { return mSubComponents.size() > 0; } + Bool hasSubComponents(); /// Get list of subcomponents - typename SimPowerComp::List subComponents() { return mSubComponents; } + typename SimPowerComp::List subComponents(); /// - typename SimNode::List& virtualNodes() { return mVirtualNodes; } + typename SimNode::List& virtualNodes(); /// Get pointer to virtual node typename SimNode::Ptr virtualNode(UInt index); /// Get vector of simulation node numbers from virtual Node - std::vector virtualMatrixNodeIndices(UInt index) { return virtualNode(index)->matrixNodeIndices(); } + std::vector virtualMatrixNodeIndices(UInt index); /// Get simulation node number from virtual node - UInt virtualSimNode(UInt nodeIndex, UInt phaseIndex = 0) { return virtualMatrixNodeIndices(nodeIndex)[phaseIndex]; } + UInt virtualSimNode(UInt nodeIndex, UInt phaseIndex = 0); // #### States #### - const MatrixVar& intfCurrent() { return **mIntfCurrent; } + const MatrixVar& intfCurrent(); /// - const MatrixVar& intfVoltage() { return **mIntfVoltage; } + const MatrixVar& intfVoltage(); /// - MatrixComp initialVoltage(UInt index) { return mTerminals[index]->initialVoltage(); } + MatrixComp initialVoltage(UInt index); /// - Complex initialSingleVoltage(UInt index) { return mTerminals[index]->initialSingleVoltage(); } + Complex initialSingleVoltage(UInt index); /// - Bool terminalNotGrounded(UInt index) { return !mMatrixNodeIndexIsGround[index]; } + Bool terminalNotGrounded(UInt index); // #### Setters #### - void setIntfCurrent(MatrixVar current) { **mIntfCurrent = current; } + void setIntfCurrent(MatrixVar current); /// - void setIntfVoltage(MatrixVar voltage) { **mIntfVoltage = voltage; } + void setIntfVoltage(MatrixVar voltage); /// void setVirtualNodeNumber(UInt num); /// Sets the virtual node at index nodeNum. diff --git a/dpsim-models/include/dpsim-models/SystemTopology.h b/dpsim-models/include/dpsim-models/SystemTopology.h index dbfa2d5945..f16ddff161 100644 --- a/dpsim-models/include/dpsim-models/SystemTopology.h +++ b/dpsim-models/include/dpsim-models/SystemTopology.h @@ -47,12 +47,6 @@ namespace CPS { /// Do not use this constructor SystemTopology() { } - Matrix initFrequency(Real frequency) { - Matrix frequencies(1,1); - frequencies << frequency; - return frequencies; - } - /// Constructor to be used if components /// and nodes are added one by one SystemTopology(Real frequency) @@ -85,161 +79,58 @@ namespace CPS { componentsAtNodeList(); } + Matrix initFrequency(Real frequency); + /// Reset state of components void reset(); // #### Add Objects to SystemTopology #### /// Adds node and initializes frequencies - void addNode(TopologicalNode::Ptr topNode) { - auto nodeComplex = std::dynamic_pointer_cast>(topNode); - if (nodeComplex) nodeComplex->initialize(mFrequencies); - - auto nodeReal = std::dynamic_pointer_cast>(topNode); - if (nodeReal) nodeReal->initialize(mFrequencies); - - mNodes.push_back(topNode); - } + void addNode(TopologicalNode::Ptr topNode); /// Adds node at specified position and initializes frequencies - void addNodeAt(TopologicalNode::Ptr topNode, UInt index) { - auto node = std::dynamic_pointer_cast>(topNode); - if (node) node->initialize(mFrequencies); - - auto nodeReal = std::dynamic_pointer_cast>(topNode); - if (nodeReal) nodeReal->initialize(mFrequencies); - - if (index > mNodes.capacity()) - mNodes.resize(index+1); - - mNodes[index] = topNode; - } + void addNodeAt(TopologicalNode::Ptr topNode, UInt index); /// Add multiple nodes - void addNodes(TopologicalNode::List topNodes) { - for (auto topNode : topNodes) - addNode(topNode); - } + void addNodes(TopologicalNode::List topNodes); /// Adds component and initializes frequencies - void addComponent(IdentifiedObject::Ptr component) { - auto powerCompComplex = std::dynamic_pointer_cast>(component); - if (powerCompComplex) powerCompComplex->initialize(mFrequencies); - - auto powerCompReal = std::dynamic_pointer_cast>(component); - if (powerCompReal) powerCompReal->initialize(mFrequencies); - - mComponents.push_back(component); - } + void addComponent(IdentifiedObject::Ptr component); /// Connect component to simNodes template - void connectComponentToNodes(typename SimPowerComp::Ptr component, typename SimNode::List simNodes) { - component->connect(simNodes); - for (auto simNode : simNodes) - mComponentsAtNode[simNode].push_back(component); - } + void connectComponentToNodes(typename SimPowerComp::Ptr component, typename SimNode::List simNodes); - void componentsAtNodeList() { - for (auto comp : mComponents) { - auto powerComp = std::dynamic_pointer_cast(comp); - if (powerComp) - for (auto topoNode : powerComp->topologicalNodes()) - mComponentsAtNode[topoNode].push_back(powerComp); - } - } + void componentsAtNodeList(); /// Add multiple components - void addComponents(IdentifiedObject::List components) { - for (auto comp : components) - addComponent(comp); - } + void addComponents(IdentifiedObject::List components); /// Initialize nodes from PowerFlow - void initWithPowerflow(SystemTopology& systemPF) { - for (auto nodePF : systemPF.mNodes) { - if (auto node = this->node(nodePF->name())) { - //mSLog->info("Updating initial voltage of {} according to powerflow", node->name()); - //mSLog->info("Former initial voltage: {}", node->initialSingleVoltage()); - node->setInitialVoltage(std::dynamic_pointer_cast>(nodePF)->singleVoltage()); - //mSLog->info("Updated initial voltage: {}", node->initialSingleVoltage()); - } - } - } + void initWithPowerflow(SystemTopology& systemPF); /// Adds component and initializes frequencies - void addTearComponent(IdentifiedObject::Ptr component) { - auto powerCompComplex = std::dynamic_pointer_cast>(component); - if (powerCompComplex) powerCompComplex->initialize(mFrequencies); - - auto powerCompReal = std::dynamic_pointer_cast>(component); - if (powerCompReal) powerCompReal->initialize(mFrequencies); - - mTearComponents.push_back(component); - } + void addTearComponent(IdentifiedObject::Ptr component); /// Add multiple components - void addTearComponents(IdentifiedObject::List components) { - for (auto comp : components) - addTearComponent(comp); - } + void addTearComponents(IdentifiedObject::List components); // #### Get Objects from SystemTopology #### /// Returns TopologicalNode by index in node list template - typename std::shared_ptr node(UInt index) { - if (index < mNodes.size()) { - auto topoNode = mNodes[index]; - auto node = std::dynamic_pointer_cast(topoNode); - if (node) - return node; - } - - return nullptr; - } + typename std::shared_ptr node(UInt index); /// Returns TopologicalNode by name template - typename std::shared_ptr node(const String &name) { - for (auto topoNode : mNodes) { - if (topoNode->name() == name) { - auto node = std::dynamic_pointer_cast(topoNode); - if (node) - return node; - else - return nullptr; - } - } - return nullptr; - } + typename std::shared_ptr node(const String &name); /// Returns Component by name template - typename std::shared_ptr component(const String &name) { - for (auto comp : mComponents) { - if (comp->name() == name) { - auto comp2 = std::dynamic_pointer_cast(comp); - if (comp2) - return comp2; - else - return nullptr; - } - } - return nullptr; - } - - std::map listIdObjects() { - std::map objTypeMap; + typename std::shared_ptr component(const String &name); - for (auto node : mNodes) { - objTypeMap[node->name()] = node->type(); - } - for (auto comp : mComponents) { - objTypeMap[comp->name()] = comp->type(); - } - return objTypeMap; - } + std::map listIdObjects(); // #### Operations on the SystemTopology #### diff --git a/dpsim-models/include/dpsim-models/TopologicalNode.h b/dpsim-models/include/dpsim-models/TopologicalNode.h index d1ca494f0f..dc90f11d0d 100644 --- a/dpsim-models/include/dpsim-models/TopologicalNode.h +++ b/dpsim-models/include/dpsim-models/TopologicalNode.h @@ -32,21 +32,19 @@ namespace CPS { virtual ~TopologicalNode() { } /// - Bool isGround() { return mIsGround; } + Bool isGround(); /// - MatrixComp initialVoltage() { return **mInitialVoltage; } + MatrixComp initialVoltage(); /// - void setInitialVoltage(MatrixComp voltage) { **mInitialVoltage = voltage; } + void setInitialVoltage(MatrixComp voltage); /// - void setInitialVoltage(Complex voltage) { (**mInitialVoltage)(0,0) = voltage; } + void setInitialVoltage(Complex voltage); /// - void setInitialVoltage(Complex voltage, Int phaseIndex) { - (**mInitialVoltage)(phaseIndex, 0) = voltage; - } + void setInitialVoltage(Complex voltage, Int phaseIndex); /// Complex initialSingleVoltage(PhaseType phaseType = PhaseType::Single); /// - PhaseType phaseType() { return mPhaseType; } + PhaseType phaseType(); /// virtual UInt matrixNodeIndex(PhaseType phaseType = PhaseType::Single) = 0; /// diff --git a/dpsim-models/src/CIM/Reader.cpp b/dpsim-models/src/CIM/Reader.cpp index be10726fab..04ddb82209 100644 --- a/dpsim-models/src/CIM/Reader.cpp +++ b/dpsim-models/src/CIM/Reader.cpp @@ -30,6 +30,30 @@ Reader::~Reader() { delete mModel; } +SystemTopology Reader::loadCIM(Real systemFrequency, const std::list &filenamesString, Domain domain = Domain::DP, PhaseType phase = PhaseType::Single, + GeneratorType genType = GeneratorType::None) { + std::list filenames; + for (auto f : filenamesString) + filenames.emplace_back(f); + + return loadCIM(systemFrequency, filenames, domain, phase, genType); +} + +// #### shunt component settings #### +/// set shunt capacitor value +void Reader::setShuntCapacitor(Real v) { + mShuntCapacitorValue = v; + mSetShuntCapacitor = true; +} +/// set shunt conductance value +void Reader::setShuntConductance(Real v) { + mShuntConductanceValue = v; + mSetShuntConductance = true; +} + +/// If set, some components like loads include protection switches +void Reader::useProtectionSwitches(Bool value = true) { mUseProtectionSwitches = value; } + Real Reader::unitValue(Real value, CIMPP::UnitMultiplier mult) { switch (mult) { case UnitMultiplier::p: diff --git a/dpsim-models/src/Logger.cpp b/dpsim-models/src/Logger.cpp index 18763ba3dd..750b619e36 100644 --- a/dpsim-models/src/Logger.cpp +++ b/dpsim-models/src/Logger.cpp @@ -18,6 +18,60 @@ namespace fs = std::experimental::filesystem; using namespace CPS; + +void Logger::setLogLevel(std::shared_ptr logger, Logger::Level level) { + logger->set_level(level); +} + +void Logger::setLogPattern(std::shared_ptr logger, std::string pattern) { + logger->set_pattern(pattern); +} + +// #### to string methods #### +String Logger::matrixToString(const Matrix& mat) { + std::stringstream ss; + ss << std::scientific << "\n" << mat; + return ss.str(); +} + +String Logger::matrixCompToString(const MatrixComp& mat) { + std::stringstream ss; + ss << std::scientific << "\n" << mat; + return ss.str(); +} + +String Logger::sparseMatrixToString(const SparseMatrix& mat) { + return matrixToString(Matrix(mat)); +} + +String Logger::sparseMatrixCompToString(const SparseMatrixComp& mat) { + return matrixCompToString(MatrixComp(mat)); +} + +String Logger::phasorMatrixToString(const MatrixComp& mat) { + std::stringstream ss; + ss << std::scientific << Math::abs(mat) << "\n\n" << Math::phase(mat); + return ss.str(); +} + +String Logger::phasorToString(const Complex& num) { + std::stringstream ss; + ss << std::defaultfloat << Math::abs(num) << "<" << Math::phaseDeg(num); + return ss.str(); +} + +String Logger::complexToString(const Complex& num) { + std::stringstream ss; + ss << std::defaultfloat << num.real() << "+j" << num.imag(); + return ss.str(); +} + +String Logger::realToString(const Real& num) { + std::stringstream ss; + ss << std::defaultfloat << num; + return ss.str(); +} + String Logger::prefix() { char *p = getenv("CPS_LOG_PREFIX"); diff --git a/dpsim-models/src/MathUtils.cpp b/dpsim-models/src/MathUtils.cpp index 44ab5003cf..af6ae79769 100644 --- a/dpsim-models/src/MathUtils.cpp +++ b/dpsim-models/src/MathUtils.cpp @@ -10,6 +10,183 @@ using namespace CPS; +// #### Angular Operations #### +Real Math::radtoDeg(Real rad) { + return rad * 180 / PI; +} + +Real Math::degToRad(Real deg) { + return deg * PI / 180; +} + +Real Math::phase(Complex value) { + return std::arg(value); +} + +Real Math::phaseDeg(Complex value) { + return radtoDeg(phase(value)); +} + +Real Math::abs(Complex value) { + return std::abs(value); +} + +Matrix Math::abs(const MatrixComp& mat) { + size_t nRows = mat.rows(); + size_t nCols = mat.cols(); + Matrix res(mat.rows(), mat.cols()); + + for (size_t i = 0; i < nRows; ++i) { + for (size_t j = 0; j < nCols; ++j) { + res(i,j) = std::abs(mat(i,j)); + } + } + return res; +} + +Matrix Math::phase(const MatrixComp& mat) { + size_t nRows = mat.rows(); + size_t nCols = mat.cols(); + Matrix res(mat.rows(), mat.cols()); + + for (size_t i = 0; i < nRows; ++i) { + for (size_t j = 0; j < nCols; ++j) { + res(i,j) = std::arg(mat(i,j)); + } + } + return res; +} + +Complex Math::polar(Real abs, Real phase) { + return std::polar(abs, phase); +} + +Complex Math::polarDeg(Real abs, Real phase) { + return std::polar(abs, radtoDeg(phase)); +} + +void Math::setVectorElement(Matrix& mat, Matrix::Index row, Complex value, Int maxFreq = 1, Int freqIdx = 0, Matrix::Index colOffset = 0) { + Eigen::Index harmonicOffset = mat.rows() / maxFreq; + Eigen::Index complexOffset = harmonicOffset / 2; + Eigen::Index harmRow = row + harmonicOffset * freqIdx; + + mat(harmRow, colOffset) = value.real(); + mat(harmRow + complexOffset, colOffset) = value.imag(); +} + +void Math::addToVectorElement(Matrix& mat, Matrix::Index row, Complex value, Int maxFreq = 1, Int freqIdx = 0) { + Eigen::Index harmonicOffset = mat.rows() / maxFreq; + Eigen::Index complexOffset = harmonicOffset / 2; + Eigen::Index harmRow = row + harmonicOffset * freqIdx; + + mat(harmRow, 0) = mat(harmRow, 0) + value.real(); + mat(harmRow + complexOffset, 0) = mat(harmRow + complexOffset, 0) + value.imag(); +} + +Complex Math::complexFromVectorElement(const Matrix& mat, Matrix::Index row, Int maxFreq = 1, Int freqIdx = 0) { + Eigen::Index harmonicOffset = mat.rows() / maxFreq; + Eigen::Index complexOffset = harmonicOffset / 2; + Eigen::Index harmRow = row + harmonicOffset * freqIdx; + + return Complex(mat(harmRow, 0), mat(harmRow + complexOffset, 0)); +} + +void Math::addToVectorElement(Matrix& mat, Matrix::Index row, Real value) { + mat(row, 0) = mat(row, 0) + value; +} + +void Math::setVectorElement(Matrix& mat, Matrix::Index row, Real value) { + mat(row, 0) = value; +} + +Real Math::realFromVectorElement(const Matrix& mat, Matrix::Index row) { + return mat(row, 0); +} + +void Math::setMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Complex value, Int maxFreq = 1, Int freqIdx = 0) { + // Assume square matrix + Eigen::Index harmonicOffset = mat.rows() / maxFreq; + Eigen::Index complexOffset = harmonicOffset / 2; + Eigen::Index harmRow = row + harmonicOffset * freqIdx; + Eigen::Index harmCol = column + harmonicOffset * freqIdx; + + mat(harmRow, harmCol) = value.real(); + mat(harmRow + complexOffset, harmCol + complexOffset) = value.real(); + mat(harmRow, harmCol + complexOffset) = - value.imag(); + mat(harmRow + complexOffset, harmCol) = value.imag(); +} + +void Math::addToMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Complex value, Int maxFreq = 1, Int freqIdx = 0) { + // Assume square matrix + Eigen::Index harmonicOffset = mat.rows() / maxFreq; + Eigen::Index complexOffset = harmonicOffset / 2; + Eigen::Index harmRow = row + harmonicOffset * freqIdx; + Eigen::Index harmCol = column + harmonicOffset * freqIdx; + + mat(harmRow, harmCol) = mat(harmRow, harmCol) + value.real(); + mat(harmRow + complexOffset, harmCol + complexOffset) = mat(harmRow + complexOffset, harmCol + complexOffset) + value.real(); + mat(harmRow, harmCol + complexOffset) = mat(harmRow, harmCol + complexOffset) - value.imag(); + mat(harmRow + complexOffset, harmCol) = mat(harmRow + complexOffset, harmCol) + value.imag(); +} + +void Math::addToMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Matrix value, Int maxFreq = 1, Int freqIdx = 0) { + // Assume square matrix + Eigen::Index harmonicOffset = mat.rows() / maxFreq; + Eigen::Index complexOffset = harmonicOffset / 2; + Eigen::Index harmRow = row + harmonicOffset * freqIdx; + Eigen::Index harmCol = column + harmonicOffset * freqIdx; + + mat(harmRow, harmCol) = mat(harmRow, harmCol) + value(0,0); + mat(harmRow + complexOffset, harmCol + complexOffset) = mat(harmRow + complexOffset, harmCol + complexOffset) + value(1,1); + mat(harmRow, harmCol + complexOffset) = mat(harmRow, harmCol + complexOffset) + value(0,1); + mat(harmRow + complexOffset, harmCol) = mat(harmRow + complexOffset, harmCol) + value(1,0); +} + +void Math::setMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Real value) { + mat(row, column) = value; +} + +void Math::addToMatrixElement(Matrix& mat, std::vector rows, std::vector columns, Complex value) { + for (UInt phase = 0; phase < rows.size(); phase++) + addToMatrixElement(mat, rows[phase], columns[phase], value); +} + +void Math::addToMatrixElement(Matrix& mat, Matrix::Index row, Matrix::Index column, Real value) { + mat(row, column) = mat(row, column) + value; +} + +void Math::addToMatrixElement(Matrix& mat, std::vector rows, std::vector columns, Real value) { + for (UInt phase = 0; phase < rows.size(); phase++) + addToMatrixElement(mat, rows[phase], columns[phase], value); +} + +MatrixComp Math::singlePhaseVariableToThreePhase(Complex var_1ph) { + MatrixComp var_3ph = MatrixComp::Zero(3, 1); + var_3ph << + var_1ph, + var_1ph * SHIFT_TO_PHASE_B, + var_1ph * SHIFT_TO_PHASE_C; + return var_3ph; +} + +Matrix Math::singlePhaseParameterToThreePhase(Real parameter) { + Matrix param_3ph = Matrix::Zero(3, 3); + param_3ph << + parameter, 0., 0., + 0., parameter, 0., + 0, 0., parameter; + return param_3ph; +} + +Matrix Math::singlePhasePowerToThreePhase(Real power) { + Matrix power_3ph = Matrix::Zero(3, 3); + power_3ph << + power/3., 0., 0., + 0., power/3., 0., + 0, 0., power/3.; + return power_3ph; +} + Matrix Math::StateSpaceTrapezoidal(Matrix states, Matrix A, Matrix B, Real dt, Matrix u_new, Matrix u_old) { Matrix::Index n = states.rows(); Matrix I = Matrix::Identity(n, n); diff --git a/dpsim-models/src/SP/SP_Ph1_Switch.cpp b/dpsim-models/src/SP/SP_Ph1_Switch.cpp index a0e07282e9..37bd50bcba 100644 --- a/dpsim-models/src/SP/SP_Ph1_Switch.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Switch.cpp @@ -53,6 +53,8 @@ void SP::Ph1::Switch::mnaInitialize(Real omega, Real timeStep, Attribute mMnaTasks.push_back(std::make_shared(*this, leftVector)); } +Bool SP::Ph1::Switch::mnaIsClosed() { return isClosed(); } + void SP::Ph1::Switch::mnaApplySystemMatrixStamp(Matrix& systemMatrix) { Complex conductance = (**mIsClosed) ? Complex( 1. / **mClosedResistance, 0 ) : Complex( 1. / **mOpenResistance, 0 ); diff --git a/dpsim-models/src/SP/SP_Ph1_SynchronGenerator.cpp b/dpsim-models/src/SP/SP_Ph1_SynchronGenerator.cpp index 516b43b19a..1afa4ffa9a 100644 --- a/dpsim-models/src/SP/SP_Ph1_SynchronGenerator.cpp +++ b/dpsim-models/src/SP/SP_Ph1_SynchronGenerator.cpp @@ -91,3 +91,4 @@ void SP::Ph1::SynchronGenerator::updatePowerInjection(Complex powerInj) { **mSetPointReactivePowerPerUnit= **mSetPointReactivePower / mBaseApparentPower; } +Complex SP::Ph1::SynchronGenerator::getApparentPower() { return Complex (**mSetPointActivePower, **mSetPointReactivePower);} diff --git a/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorVBR.cpp b/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorVBR.cpp index fc0b92b15a..261e132dc3 100644 --- a/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorVBR.cpp +++ b/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorVBR.cpp @@ -81,3 +81,5 @@ Matrix SP::Ph1::SynchronGeneratorVBR::get_DqToComplexATransformMatrix() { return dqToComplexA; } + +Bool SP::Ph1::SynchronGeneratorVBR::hasParameterChanged() { return true; }; diff --git a/dpsim-models/src/SP/SP_Ph1_varResSwitch.cpp b/dpsim-models/src/SP/SP_Ph1_varResSwitch.cpp index c6e21a2bd7..1f99555ee5 100644 --- a/dpsim-models/src/SP/SP_Ph1_varResSwitch.cpp +++ b/dpsim-models/src/SP/SP_Ph1_varResSwitch.cpp @@ -47,6 +47,8 @@ void SP::Ph1::varResSwitch::mnaInitialize(Real omega, Real timeStep, Attributeget().rows(), 1); } +Bool SP::Ph1::varResSwitch::mnaIsClosed() { return isClosed(); } + void SP::Ph1::varResSwitch::mnaApplySystemMatrixStamp(Matrix& systemMatrix) { Complex conductance = (**mIsClosed) ? Complex( 1. / **mClosedResistance, 0 ) : Complex( 1. / **mOpenResistance, 0 ); diff --git a/dpsim-models/src/SimNode.cpp b/dpsim-models/src/SimNode.cpp index db59d980d2..48e5f86960 100644 --- a/dpsim-models/src/SimNode.cpp +++ b/dpsim-models/src/SimNode.cpp @@ -55,6 +55,48 @@ VarType SimNode::singleVoltage(PhaseType phaseType) { return (**mVoltage)(0,0); } +template +UInt SimNode::matrixNodeIndex(PhaseType phaseType = PhaseType::Single) { + if ((phaseType == PhaseType::A || phaseType == PhaseType::Single) + && (mPhaseType == PhaseType::Single + || mPhaseType == PhaseType::A + || mPhaseType == PhaseType::ABC)) + return mMatrixNodeIndex[0]; + else if (phaseType == PhaseType::B + && (mPhaseType == PhaseType::B + || mPhaseType == PhaseType::ABC)) + return mMatrixNodeIndex[1]; + else if (phaseType == PhaseType::C + && (mPhaseType == PhaseType::C + || mPhaseType == PhaseType::ABC)) + return mMatrixNodeIndex[2]; + else + return 0; +} + +template +std::vector SimNode::matrixNodeIndices() { + if (mPhaseType == PhaseType::B) + return { mMatrixNodeIndex[1] }; + else if (mPhaseType == PhaseType::C) + return { mMatrixNodeIndex[2] }; + else if (mPhaseType == PhaseType::ABC) + return mMatrixNodeIndex; + else // phaseType == PhaseType::Single || mPhaseType == PhaseType::A + return { mMatrixNodeIndex[0] }; +} + +template +MatrixVar SimNode::voltage() { return **mVoltage; } + +template +void SimNode::setMatrixNodeIndex(UInt phase, UInt matrixNodeIndex) { mMatrixNodeIndex[phase] = matrixNodeIndex; } + +template +const Task::List& SimNode::mnaTasks() { + return mMnaTasks; +} + template<> void SimNode::setVoltage(Complex newVoltage) { (**mVoltage)(0, 0) = newVoltage; diff --git a/dpsim-models/src/SimPowerComp.cpp b/dpsim-models/src/SimPowerComp.cpp index 33ee097fc3..366fa04123 100644 --- a/dpsim-models/src/SimPowerComp.cpp +++ b/dpsim-models/src/SimPowerComp.cpp @@ -18,6 +18,78 @@ SimPowerComp::SimPowerComp(String uid, String name, Logger::Level logLe mTerminals.clear(); } +template +SimPowerComp::Ptr SimPowerComp::clone(String name) { return nullptr; } + +template +UInt SimPowerComp::terminalNumber() { return mNumTerminals; } + +template +typename SimTerminal::List SimPowerComp::terminals() { return mTerminals; } + +template +typename SimNode::Ptr SimPowerComp::node(UInt index) { + if (index >= mTerminals.size()) { + throw SystemError("Node not available for " + **mUID); + } + return mTerminals[index]->node(); +}; + +template +UInt SimPowerComp::matrixNodeIndex(UInt nodeIndex) { + return mMatrixNodeIndices[nodeIndex * 3]; +} + +template +UInt SimPowerComp::matrixNodeIndex(UInt nodeIndex, UInt phaseIndex) { + return mMatrixNodeIndices[nodeIndex * 3 + phaseIndex]; +} + +template +std::vector SimPowerComp::matrixNodeIndices(UInt index) { return node(index)->matrixNodeIndices(); } + +template +UInt SimPowerComp::virtualNodesNumber() { return mNumVirtualNodes; } + +template +Bool SimPowerComp::hasVirtualNodes() { return mNumVirtualNodes > 0; } + +template +Bool SimPowerComp::hasSubComponents() { return mSubComponents.size() > 0; } + +template +typename SimPowerComp::List SimPowerComp::subComponents() { return mSubComponents; } + +template +typename SimNode::List& SimPowerComp::virtualNodes() { return mVirtualNodes; } + +template +std::vector SimPowerComp::virtualMatrixNodeIndices(UInt index) { return virtualNode(index)->matrixNodeIndices(); } + +template +UInt SimPowerComp::virtualSimNode(UInt nodeIndex, UInt phaseIndex = 0) { return virtualMatrixNodeIndices(nodeIndex)[phaseIndex]; } + +template +const MatrixVar& SimPowerComp::intfCurrent() { return **mIntfCurrent; } + +template +const MatrixVar& SimPowerComp::intfVoltage() { return **mIntfVoltage; } + +template +MatrixComp SimPowerComp::initialVoltage(UInt index) { return mTerminals[index]->initialVoltage(); } + +template +Complex SimPowerComp::initialSingleVoltage(UInt index) { return mTerminals[index]->initialSingleVoltage(); } + +template +Bool SimPowerComp::terminalNotGrounded(UInt index) { return !mMatrixNodeIndexIsGround[index]; } + +template +void SimPowerComp::setIntfCurrent(MatrixVar current) { **mIntfCurrent = current; } + +template +void SimPowerComp::setIntfVoltage(MatrixVar voltage) { **mIntfVoltage = voltage; } + // #### Terminals #### template UInt SimPowerComp::terminalNumberConnected() { diff --git a/dpsim-models/src/SystemTopology.cpp b/dpsim-models/src/SystemTopology.cpp index 553627ec31..1dbc859843 100644 --- a/dpsim-models/src/SystemTopology.cpp +++ b/dpsim-models/src/SystemTopology.cpp @@ -15,6 +15,151 @@ using namespace CPS; +Matrix SystemTopology::initFrequency(Real frequency) { + Matrix frequencies(1,1); + frequencies << frequency; + return frequencies; +} + +void SystemTopology::addNode(TopologicalNode::Ptr topNode) { + auto nodeComplex = std::dynamic_pointer_cast>(topNode); + if (nodeComplex) nodeComplex->initialize(mFrequencies); + + auto nodeReal = std::dynamic_pointer_cast>(topNode); + if (nodeReal) nodeReal->initialize(mFrequencies); + + mNodes.push_back(topNode); +} + +void SystemTopology::addNodeAt(TopologicalNode::Ptr topNode, UInt index) { + auto node = std::dynamic_pointer_cast>(topNode); + if (node) node->initialize(mFrequencies); + + auto nodeReal = std::dynamic_pointer_cast>(topNode); + if (nodeReal) nodeReal->initialize(mFrequencies); + + if (index > mNodes.capacity()) + mNodes.resize(index+1); + + mNodes[index] = topNode; +} + + +void SystemTopology::addNodes(TopologicalNode::List topNodes) { + for (auto topNode : topNodes) + addNode(topNode); +} + +void SystemTopology::addComponent(IdentifiedObject::Ptr component) { + auto powerCompComplex = std::dynamic_pointer_cast>(component); + if (powerCompComplex) powerCompComplex->initialize(mFrequencies); + + auto powerCompReal = std::dynamic_pointer_cast>(component); + if (powerCompReal) powerCompReal->initialize(mFrequencies); + + mComponents.push_back(component); +} + +template +void SystemTopology::connectComponentToNodes(typename SimPowerComp::Ptr component, typename SimNode::List simNodes) { + component->connect(simNodes); + for (auto simNode : simNodes) + mComponentsAtNode[simNode].push_back(component); +} + +void SystemTopology::componentsAtNodeList() { + for (auto comp : mComponents) { + auto powerComp = std::dynamic_pointer_cast(comp); + if (powerComp) + for (auto topoNode : powerComp->topologicalNodes()) + mComponentsAtNode[topoNode].push_back(powerComp); + } +} + +void SystemTopology::addComponents(IdentifiedObject::List components) { + for (auto comp : components) + addComponent(comp); +} + +void SystemTopology::initWithPowerflow(SystemTopology& systemPF) { + for (auto nodePF : systemPF.mNodes) { + if (auto node = this->node(nodePF->name())) { + //mSLog->info("Updating initial voltage of {} according to powerflow", node->name()); + //mSLog->info("Former initial voltage: {}", node->initialSingleVoltage()); + node->setInitialVoltage(std::dynamic_pointer_cast>(nodePF)->singleVoltage()); + //mSLog->info("Updated initial voltage: {}", node->initialSingleVoltage()); + } + } +} + +void SystemTopology::addTearComponent(IdentifiedObject::Ptr component) { + auto powerCompComplex = std::dynamic_pointer_cast>(component); + if (powerCompComplex) powerCompComplex->initialize(mFrequencies); + + auto powerCompReal = std::dynamic_pointer_cast>(component); + if (powerCompReal) powerCompReal->initialize(mFrequencies); + + mTearComponents.push_back(component); +} + +void SystemTopology::addTearComponents(IdentifiedObject::List components) { + for (auto comp : components) + addTearComponent(comp); +} + + +template +typename std::shared_ptr SystemTopology::node(UInt index) { + if (index < mNodes.size()) { + auto topoNode = mNodes[index]; + auto node = std::dynamic_pointer_cast(topoNode); + if (node) + return node; + } + + return nullptr; +} + +template +typename std::shared_ptr SystemTopology::node(const String &name) { + for (auto topoNode : mNodes) { + if (topoNode->name() == name) { + auto node = std::dynamic_pointer_cast(topoNode); + if (node) + return node; + else + return nullptr; + } + } + return nullptr; +} + +template +typename std::shared_ptr SystemTopology::component(const String &name) { + for (auto comp : mComponents) { + if (comp->name() == name) { + auto comp2 = std::dynamic_pointer_cast(comp); + if (comp2) + return comp2; + else + return nullptr; + } + } + return nullptr; +} + +std::map SystemTopology::listIdObjects() { + std::map objTypeMap; + + for (auto node : mNodes) { + objTypeMap[node->name()] = node->type(); + } + for (auto comp : mComponents) { + objTypeMap[comp->name()] = comp->type(); + } + return objTypeMap; +} + template void SystemTopology::multiplyPowerComps(Int numberCopies) { typename SimNode::List newNodes; diff --git a/dpsim-models/src/TopologicalNode.cpp b/dpsim-models/src/TopologicalNode.cpp index 4fa9801cbb..c18e7ceb93 100644 --- a/dpsim-models/src/TopologicalNode.cpp +++ b/dpsim-models/src/TopologicalNode.cpp @@ -10,6 +10,20 @@ using namespace CPS; +Bool TopologicalNode::isGround() { return mIsGround; } + +MatrixComp TopologicalNode::initialVoltage() { return **mInitialVoltage; } + +void TopologicalNode::setInitialVoltage(MatrixComp voltage) { **mInitialVoltage = voltage; } + +void TopologicalNode::setInitialVoltage(Complex voltage) { (**mInitialVoltage)(0,0) = voltage; } + +void TopologicalNode::setInitialVoltage(Complex voltage, Int phaseIndex) { + (**mInitialVoltage)(phaseIndex, 0) = voltage; +} + +PhaseType TopologicalNode::phaseType() { return mPhaseType; } + TopologicalNode::TopologicalNode(String uid, String name, PhaseType phaseType, const std::vector &initialVoltage) : IdentifiedObject(uid, name), @@ -36,3 +50,5 @@ Complex TopologicalNode::initialSingleVoltage(PhaseType phaseType) { else // phaseType == PhaseType::Single || mPhaseType == PhaseType::A return (**mInitialVoltage)(0,0); } + + diff --git a/dpsim-models/src/TopologicalTerminal.cpp b/dpsim-models/src/TopologicalTerminal.cpp index 7f960b2eb6..11a3350873 100644 --- a/dpsim-models/src/TopologicalTerminal.cpp +++ b/dpsim-models/src/TopologicalTerminal.cpp @@ -15,6 +15,30 @@ TopologicalTerminal::TopologicalTerminal(String uid, String name, PhaseType phas setPhaseType(phase); } +MatrixComp TopologicalTerminal::power() { return mPower; } + +void TopologicalTerminal::setPower(Complex power) { mPower(0,0) = power; } + +void TopologicalTerminal::setPower(MatrixComp power) { mPower = power; } + +void TopologicalTerminal::setPhaseType(PhaseType type) { + mPhaseType = type; + if (mPhaseType == PhaseType::ABC) + mPower = MatrixComp::Zero(3, 1); + else + mPower = MatrixComp::Zero(1, 1); +} + +Real TopologicalTerminal::singleActivePower() { return singlePower().real(); } + +Real TopologicalTerminal::singleReactivePower() { return singlePower().imag(); } + +Complex TopologicalTerminal::initialSingleVoltage() { return topologicalNodes()->initialSingleVoltage(mPhaseType); } + +UInt TopologicalTerminal::matrixNodeIndex() { return topologicalNodes()->matrixNodeIndex(mPhaseType); } + +std::vector TopologicalTerminal::matrixNodeIndices() { return topologicalNodes()->matrixNodeIndices(); } + Complex TopologicalTerminal::singlePower() { if (mPhaseType == PhaseType::B) return mPower(1,0);