DPsim
Loading...
Searching...
No Matches
PFSolverPowerPolar.cpp
1/* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
2 * EONERC, RWTH Aachen University
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7 *********************************************************************************/
8
9#include <dpsim/PFSolverPowerPolar.h>
10
11using namespace DPsim;
12using namespace CPS;
13
15 const CPS::SystemTopology &system,
16 CPS::Real timeStep,
17 CPS::Logger::Level logLevel)
18 : PFSolver(name, system, timeStep, logLevel) {}
19
21 bool keep_last_solution) {
22 const UInt n = mSystem.mNodes.size();
23
24 bool can_keep = keep_last_solution && mHasLastConvergedSolution &&
25 mLastConvergedV.size() == n && mLastConvergedD.size() == n;
26
27 SPDLOG_LOGGER_INFO(mSLog,
28 "PF initialization: keep_last_solution={}, can_keep={}",
29 keep_last_solution, can_keep);
30
31 resize_sol(n);
33
34 if (can_keep) {
35 sol_V = mLastConvergedV;
36 sol_D = mLastConvergedD;
37 }
38
39 // update components
40 for (auto comp : mSystem.mComponents) {
41 if (auto load = std::dynamic_pointer_cast<CPS::SP::Ph1::Load>(comp)) {
42 if (load->use_profile)
43 load->updatePQ(time);
44
45 load->calculatePerUnitParameters(mBaseApparentPower,
46 mSystem.mSystemOmega);
47 }
48
49 if (auto gen =
50 std::dynamic_pointer_cast<CPS::SP::Ph1::SynchronGenerator>(comp)) {
51 gen->calculatePerUnitParameters(mBaseApparentPower, mSystem.mSystemOmega);
52 }
53 }
54
55 // PQ buses
56 for (auto pq : mPQBuses) {
57 UInt idx = pq->matrixNodeIndex();
58
59 sol_P(idx) = 0.0;
60 sol_Q(idx) = 0.0;
61
62 if (!can_keep) {
63 sol_V(idx) = 1.0;
64 sol_D(idx) = 0.0;
65 }
66
67 for (auto comp : mSystem.mComponentsAtNode[pq]) {
68 if (auto load = std::dynamic_pointer_cast<CPS::SP::Ph1::Load>(comp)) {
69 sol_P(idx) -= load->attributeTyped<CPS::Real>("P_pu")->get();
70 sol_Q(idx) -= load->attributeTyped<CPS::Real>("Q_pu")->get();
71 } else if (auto sst = std::dynamic_pointer_cast<
73 sol_P(idx) -= sst->getNodalInjection(pq).real();
74 sol_Q(idx) -= sst->getNodalInjection(pq).imag();
75 } else if (auto vsi = std::dynamic_pointer_cast<
77 sol_P(idx) +=
78 vsi->attributeTyped<CPS::Real>("P_ref")->get() / mBaseApparentPower;
79 sol_Q(idx) +=
80 vsi->attributeTyped<CPS::Real>("Q_ref")->get() / mBaseApparentPower;
81 } else if (auto gen =
82 std::dynamic_pointer_cast<CPS::SP::Ph1::SynchronGenerator>(
83 comp)) {
84 sol_P(idx) += gen->attributeTyped<CPS::Real>("P_set_pu")->get();
85 sol_Q(idx) += gen->attributeTyped<CPS::Real>("Q_set_pu")->get();
86 }
87 }
88
89 sol_S_complex(idx) = CPS::Complex(sol_P(idx), sol_Q(idx));
90 sol_V_complex(idx) = Math::polar(sol_V(idx), sol_D(idx));
91 }
92
93 // PV buses
94 for (auto pv : mPVBuses) {
95 UInt idx = pv->matrixNodeIndex();
96
97 sol_P(idx) = 0.0;
98 sol_Q(idx) = 0.0;
99
100 if (!can_keep) {
101 sol_D(idx) = 0.0;
102 sol_V(idx) = 1.0;
103 }
104
105 for (auto comp : mSystem.mComponentsAtNode[pv]) {
106 if (auto gen = std::dynamic_pointer_cast<CPS::SP::Ph1::SynchronGenerator>(
107 comp)) {
108 sol_P(idx) += gen->attributeTyped<CPS::Real>("P_set_pu")->get();
109 sol_V(idx) = gen->attributeTyped<CPS::Real>("V_set_pu")->get();
110 } else if (auto load =
111 std::dynamic_pointer_cast<CPS::SP::Ph1::Load>(comp)) {
112 sol_P(idx) -= load->attributeTyped<CPS::Real>("P_pu")->get();
113 sol_Q(idx) -= load->attributeTyped<CPS::Real>("Q_pu")->get();
114 } else if (auto vsi = std::dynamic_pointer_cast<
116 sol_P(idx) +=
117 vsi->attributeTyped<CPS::Real>("P_ref")->get() / mBaseApparentPower;
118 } else if (auto extnet =
119 std::dynamic_pointer_cast<CPS::SP::Ph1::NetworkInjection>(
120 comp)) {
121 sol_P(idx) += extnet->attributeTyped<CPS::Real>("p_inj")->get() /
123 sol_V(idx) = extnet->attributeTyped<CPS::Real>("V_set_pu")->get();
124 }
125 }
126
127 sol_S_complex(idx) = CPS::Complex(sol_P(idx), sol_Q(idx));
128 sol_V_complex(idx) = Math::polar(sol_V(idx), sol_D(idx));
129 }
130
131 // VD / slack buses
132 for (auto vd : mVDBuses) {
133 UInt idx = vd->matrixNodeIndex();
134
135 sol_P(idx) = 0.0;
136 sol_Q(idx) = 0.0;
137 sol_D(idx) = 0.0;
138 sol_V(idx) = 1.0;
139
140 for (auto comp : mSystem.mComponentsAtNode[vd]) {
141 if (auto extnet =
142 std::dynamic_pointer_cast<CPS::SP::Ph1::NetworkInjection>(comp)) {
143 sol_V(idx) = extnet->attributeTyped<CPS::Real>("V_set_pu")->get();
144 } else if (auto load =
145 std::dynamic_pointer_cast<CPS::SP::Ph1::Load>(comp)) {
146 sol_P(idx) -= load->attributeTyped<CPS::Real>("P_pu")->get();
147 sol_Q(idx) -= load->attributeTyped<CPS::Real>("Q_pu")->get();
148 } else if (auto gen =
149 std::dynamic_pointer_cast<CPS::SP::Ph1::SynchronGenerator>(
150 comp)) {
151 sol_P(idx) += gen->attributeTyped<CPS::Real>("P_set_pu")->get();
152 sol_Q(idx) += gen->attributeTyped<CPS::Real>("Q_set_pu")->get();
153 sol_V(idx) = gen->attributeTyped<CPS::Real>("V_set_pu")->get();
154 }
155 }
156
157 sol_S_complex(idx) = CPS::Complex(sol_P(idx), sol_Q(idx));
158 sol_V_complex(idx) = Math::polar(sol_V(idx), sol_D(idx));
159 }
160
161 solutionInitialized = true;
163
164 Pesp = sol_P;
165 Qesp = sol_Q;
166}
167
169 UInt npqpv = mNumPQBuses + mNumPVBuses;
170 UInt k;
171 mF.setZero();
172
173 for (UInt a = 0; a < npqpv; ++a) {
174 // For PQ and PV buses calculate active power mismatch
175 k = mPQPVBusIndices[a];
176 mF(a) = Pesp.coeff(k) - P(k);
177
178 //only for PQ buses calculate reactive power mismatch
179 if (a < mNumPQBuses)
180 mF(a + npqpv) = Qesp.coeff(k) - Q(k);
181 }
182}
183
185 UInt npqpv = mNumPQBuses + mNumPVBuses;
186 double val;
187 UInt k, j;
188 UInt da, db;
189
190 mJ.setZero();
191
192 //J1
193 for (UInt a = 0; a < npqpv; ++a) { //rows
194 k = mPQPVBusIndices[a];
195 //diagonal
196 mJ.coeffRef(a, a) = -Q(k) - B(k, k) * sol_V.coeff(k) * sol_V.coeff(k);
197
198 //non diagonal elements
199 for (UInt b = 0; b < npqpv; ++b) {
200 if (b != a) {
201 j = mPQPVBusIndices[b];
202 val = sol_V.coeff(k) * sol_V.coeff(j) *
203 (G(k, j) * sin(sol_D.coeff(k) - sol_D.coeff(j)) -
204 B(k, j) * cos(sol_D.coeff(k) - sol_D.coeff(j)));
205 //if (val != 0.0)
206 mJ.coeffRef(a, b) = val;
207 }
208 }
209 }
210
211 //J2
212 da = 0;
213 db = npqpv;
214 for (UInt a = 0; a < npqpv; ++a) { //rows
215 k = mPQPVBusIndices[a];
216 //diagonal
217 //std::cout << "J2D:" << (a + da) << "," << (a + db) << std::endl;
218 if (a < mNumPQBuses)
219 mJ.coeffRef(a + da, a + db) =
220 P(k) + G(k, k) * sol_V.coeff(k) * sol_V.coeff(k);
221
222 //non diagonal elements
223 for (UInt b = 0; b < mNumPQBuses; ++b) {
224 if (b != a) {
225 j = mPQPVBusIndices[b];
226 val = sol_V.coeff(k) * sol_V.coeff(j) *
227 (G(k, j) * cos(sol_D.coeff(k) - sol_D.coeff(j)) +
228 B(k, j) * sin(sol_D.coeff(k) - sol_D.coeff(j)));
229 //if (val != 0.0)
230 //std::cout << "J2ij:" << (a + da) << "," << (b + db) << std::endl;
231 mJ.coeffRef(a + da, b + db) = val;
232 }
233 }
234 }
235
236 //J3
237 da = npqpv;
238 db = 0;
239 for (UInt a = 0; a < mNumPQBuses; ++a) { //rows
240 k = mPQPVBusIndices[a];
241 //diagonal
242 //std::cout << "J3:" << (a + da) << "," << (a + db) << std::endl;
243 mJ.coeffRef(a + da, a + db) =
244 P(k) - G(k, k) * sol_V.coeff(k) * sol_V.coeff(k);
245
246 //non diagonal elements
247 for (UInt b = 0; b < npqpv; ++b) {
248 if (b != a) {
249 j = mPQPVBusIndices[b];
250 val = sol_V.coeff(k) * sol_V.coeff(j) *
251 (G(k, j) * cos(sol_D.coeff(k) - sol_D.coeff(j)) +
252 B(k, j) * sin(sol_D.coeff(k) - sol_D.coeff(j)));
253 //if (val != 0.0)
254 //std::cout << "J3:" << (a + da) << "," << (b + db) << std::endl;
255 mJ.coeffRef(a + da, b + db) = -val;
256 }
257 }
258 }
259
260 //J4
261 da = npqpv;
262 db = npqpv;
263 for (UInt a = 0; a < mNumPQBuses; ++a) { //rows
264 k = mPQPVBusIndices[a];
265 //diagonal
266 //std::cout << "J4:" << (a + da) << "," << (a + db) << std::endl;
267 mJ.coeffRef(a + da, a + db) =
268 Q(k) - B(k, k) * sol_V.coeff(k) * sol_V.coeff(k);
269
270 //non diagonal elements
271 for (UInt b = 0; b < mNumPQBuses; ++b) {
272 if (b != a) {
273 j = mPQPVBusIndices[b];
274 val = sol_V.coeff(k) * sol_V.coeff(j) *
275 (G(k, j) * sin(sol_D.coeff(k) - sol_D.coeff(j)) -
276 B(k, j) * cos(sol_D.coeff(k) - sol_D.coeff(j)));
277 if (val != 0.0) {
278 //std::cout << "J4:" << (a + da) << "," << (b + db) << std::endl;
279 mJ.coeffRef(a + da, b + db) = val;
280 }
281 }
282 }
283 }
284}
285
287 UInt npqpv = mNumPQBuses + mNumPVBuses;
288
289 // Scale the whole Newton step by one factor (=1 near solution) to bound the
290 // max voltage/angle change without altering the search direction.
291 const double maxDVpu = 0.1; // max |dV| per step [pu]
292 const double maxDThetaRad = 0.2; // max |dTheta| per step [rad]
293
294 // mX: [0,npqpv) angle incr (PQ+PV), then rel. voltage dV/V (PQ only).
295 double scale = 1.0;
296 for (UInt a = 0; a < npqpv; ++a) {
297 double dTheta = std::abs(mX.coeff(a));
298 if (dTheta > maxDThetaRad)
299 scale = std::min(scale, maxDThetaRad / dTheta);
300 }
301 for (UInt b = 0; b < mNumPQBuses; ++b) {
302 double dVrel = std::abs(mX.coeff(npqpv + b));
303 if (dVrel > maxDVpu)
304 scale = std::min(scale, maxDVpu / dVrel);
305 }
306
307 for (UInt a = 0; a < npqpv; ++a) {
308 UInt k = mPQPVBusIndices[a];
309 sol_D(k) += scale * mX.coeff(a);
310 // additive-relative update, consistent with the Jacobian
311 if (a < mNumPQBuses)
312 sol_V(k) *= (1.0 + scale * mX.coeff(a + npqpv));
313 }
314
315 for (auto node : mSystem.mNodes) {
316 UInt idx = node->matrixNodeIndex();
317 sol_V_complex(idx) = Math::polar(sol_V(idx), sol_D(idx));
318 }
319}
320
322
323 if (!isConverged) {
324 SPDLOG_LOGGER_WARN(mSLog, "Not converged within {} iterations",
326
327 SPDLOG_LOGGER_WARN(mSLog, "Writing last iterate to result state "
328 "(not stored as warm-start solution).");
329 } else {
333
334 mLastConvergedV = sol_V;
335 mLastConvergedD = sol_D;
336 mHasLastConvergedSolution = true;
337
338 SPDLOG_LOGGER_INFO(mSLog, "Converged in {} iterations", mIterations);
339 }
340
341 SPDLOG_LOGGER_INFO(mSLog, "Solution written to result state:");
342
343 SPDLOG_LOGGER_INFO(mSLog, "Name\tP\t\tQ\t\tV\t\tD");
344
345 for (auto node : mSystem.mNodes) {
346 UInt idx = node->matrixNodeIndex();
347
348 SPDLOG_LOGGER_INFO(
349 mSLog, "{}\t{}\t{}\t{}\t{}",
350 std::dynamic_pointer_cast<CPS::SimNode<CPS::Complex>>(node)->name(),
351 sol_P[idx], sol_Q[idx], sol_V[idx], sol_D[idx]);
352 }
353
354 mSLog->flush();
355
356 for (UInt i = 0; i < mSystem.mNodes.size(); ++i) {
357 sol_S_complex(i) = CPS::Complex(sol_P.coeff(i), sol_Q.coeff(i));
358 sol_V_complex(i) = Math::polar(sol_V.coeff(i), sol_D.coeff(i));
359 }
360
361 for (auto node : mSystem.mNodes) {
362 auto simNode = std::dynamic_pointer_cast<CPS::SimNode<CPS::Complex>>(node);
363
364 UInt idx = node->matrixNodeIndex();
365
366 simNode->setVoltage(sol_V_complex(idx) * mBaseVoltageAtNode[node]);
367
368 simNode->setPower(sol_S_complex(idx) * mBaseApparentPower);
369 }
370
373}
374
376 for (auto line : mLines) {
377 VectorComp v(2);
378 v(0) = sol_V_complex.coeff(line->node(0)->matrixNodeIndex());
379 v(1) = sol_V_complex.coeff(line->node(1)->matrixNodeIndex());
381 VectorComp current = line->Y_element() * v;
383 VectorComp flow_on_branch = v.array() * current.conjugate().array();
384 line->updateBranchFlow(current, flow_on_branch);
385 }
386 for (auto trafo : mTransformers) {
387 VectorComp v(2);
388 v(0) = sol_V_complex.coeff(trafo->node(0)->matrixNodeIndex());
389 v(1) = sol_V_complex.coeff(trafo->node(1)->matrixNodeIndex());
391 VectorComp current = trafo->Y_element() * v;
393 VectorComp flow_on_branch = v.array() * current.conjugate().array();
394 trafo->updateBranchFlow(current, flow_on_branch);
395 }
396}
397
399 for (auto node : mSystem.mNodes) {
400 std::list<std::shared_ptr<CPS::SP::Ph1::PiLine>> lines;
401 for (auto comp : mSystem.mComponentsAtNode[node]) {
402 if (std::shared_ptr<CPS::SP::Ph1::PiLine> line =
403 std::dynamic_pointer_cast<CPS::SP::Ph1::PiLine>(comp)) {
404 line->storeNodalInjection(sol_S_complex.coeff(node->matrixNodeIndex()));
405 lines.push_back(line);
406 break;
407 }
408 }
409 if (lines.empty()) {
410 for (auto comp : mSystem.mComponentsAtNode[node]) {
411 if (std::shared_ptr<CPS::SP::Ph1::Transformer> trafo =
412 std::dynamic_pointer_cast<CPS::SP::Ph1::Transformer>(comp)) {
413 trafo->storeNodalInjection(
414 sol_S_complex.coeff(node->matrixNodeIndex()));
415 break;
416 }
417 }
418 }
419 }
420}
421
423 Real val = 0.0;
424 for (UInt j = 0; j < mSystem.mNodes.size(); ++j) {
425 val += sol_V.coeff(j) * (G(k, j) * cos(sol_D.coeff(k) - sol_D.coeff(j)) +
426 B(k, j) * sin(sol_D.coeff(k) - sol_D.coeff(j)));
427 }
428 return sol_V.coeff(k) * val;
429}
430
432 Real val = 0.0;
433 for (UInt j = 0; j < mSystem.mNodes.size(); ++j) {
434 val += sol_V.coeff(j) * (G(k, j) * sin(sol_D.coeff(k) - sol_D.coeff(j)) -
435 B(k, j) * cos(sol_D.coeff(k) - sol_D.coeff(j)));
436 }
437 return sol_V.coeff(k) * val;
438}
439
441 for (auto topoNode : mVDBuses) {
442 auto node_idx = topoNode->matrixNodeIndex();
443
444 // Net nodal injection into the network: S_inj = V * conj(YV)
445 CPS::Complex I(0.0, 0.0);
446 for (UInt j = 0; j < mSystem.mNodes.size(); ++j)
447 I += mY.coeff(node_idx, j) * sol_Vcx(j);
448
449 CPS::Complex S = sol_Vcx(node_idx) * conj(I);
450
451 // Generator/source power: S_gen = S_inj + S_load
452 CPS::Complex Sgen = S;
453 for (auto comp : mSystem.mComponentsAtNode[topoNode]) {
454 if (auto loadPtr = std::dynamic_pointer_cast<CPS::SP::Ph1::Load>(comp)) {
455 Sgen += CPS::Complex(**(loadPtr->mActivePowerPerUnit),
456 **(loadPtr->mReactivePowerPerUnit));
457 }
458 }
459
460 // Update connected VD source/generator with actual generated power
461 for (auto comp : mSystem.mComponentsAtNode[topoNode]) {
462 if (auto extnetPtr =
463 std::dynamic_pointer_cast<CPS::SP::Ph1::NetworkInjection>(comp)) {
464 extnetPtr->updatePowerInjection(Sgen * mBaseApparentPower);
465 break;
466 }
467
468 if (auto sgPtr =
469 std::dynamic_pointer_cast<CPS::SP::Ph1::SynchronGenerator>(
470 comp)) {
471 sgPtr->updatePowerInjection(Sgen * mBaseApparentPower);
472 break;
473 }
474 }
475
476 // Store net nodal injection, not generator power
477 sol_P(node_idx) = S.real();
478 sol_Q(node_idx) = S.imag();
479 }
480}
482 for (auto topoNode : mPVBuses) {
483 auto node_idx = topoNode->matrixNodeIndex();
484
485 // Net nodal injection into the network: S_inj = V * conj(YV)
486 CPS::Complex I(0.0, 0.0);
487 for (UInt j = 0; j < mSystem.mNodes.size(); ++j)
488 I += mY.coeff(node_idx, j) * sol_Vcx(j);
489
490 CPS::Complex S = sol_Vcx(node_idx) * conj(I);
491
492 // Generator power: S_gen = S_inj + S_load
493 CPS::Complex Sgen = S;
494 for (auto comp : mSystem.mComponentsAtNode[topoNode]) {
495 if (auto loadPtr = std::dynamic_pointer_cast<CPS::SP::Ph1::Load>(comp)) {
496 Sgen += CPS::Complex(**(loadPtr->mActivePowerPerUnit),
497 **(loadPtr->mReactivePowerPerUnit));
498 }
499 }
500
501 // Update PV generator with actual generator Q
502 for (auto comp : mSystem.mComponentsAtNode[topoNode]) {
503 if (auto sgPtr =
504 std::dynamic_pointer_cast<CPS::SP::Ph1::SynchronGenerator>(
505 comp)) {
506 sgPtr->updateReactivePowerInjection(Sgen * mBaseApparentPower);
507 break;
508 }
509 }
510
511 // Store net nodal Q injection, not generator Q
512 sol_Q(node_idx) = S.imag();
513 }
514}
515
517 // calculates apparent power injection at PQ buses flowing to other nodes (i.e. S_inj_to_other = S_inj - S_shunt, with S_inj = S_gen - S_load)
518 for (auto topoNode : mPQBuses) {
519 auto node_idx = topoNode->matrixNodeIndex();
520
521 // calculate power flowing out of the node into the admittance matrix (i.e. S_inj)
522 CPS::Complex I(0.0, 0.0);
523 for (UInt j = 0; j < mSystem.mNodes.size(); ++j)
524 I += mY.coeff(node_idx, j) * sol_Vcx(j);
525 CPS::Complex S = sol_Vcx(node_idx) * conj(I);
526
527 // Subtracting shunt power to obtain power injection flowing from this node to the other nodes (i.e. S_inj_to_other)
528 CPS::Real V = sol_V.coeff(node_idx);
529 for (auto comp : mSystem.mComponentsAtNode[topoNode])
530 if (auto shuntPtr = std::dynamic_pointer_cast<CPS::SP::Ph1::Shunt>(comp))
531 // capacitive susceptance is positive --> q is injected into the node
532 S += std::pow(V, 2) * Complex(-**(shuntPtr->mConductancePerUnit),
533 **(shuntPtr->mSusceptancePerUnit));
534
535 // TODO: check whether S_inj_to_other should be stored in sol_P and sol_Q or rather S_inj
536 sol_P(node_idx) = S.real();
537 sol_Q(node_idx) = S.imag();
538 }
539}
540
542 sol_P = CPS::Vector(n);
543 sol_Q = CPS::Vector(n);
544 sol_V = CPS::Vector(n);
545 sol_D = CPS::Vector(n);
546 sol_P.setZero(n);
547 sol_Q.setZero(n);
548 sol_V.setZero(n);
549 sol_D.setZero(n);
550}
551
553 sol_S_complex = CPS::VectorComp(n);
554 sol_V_complex = CPS::VectorComp(n);
555 sol_S_complex.setZero(n);
556 sol_V_complex.setZero(n);
557}
558
559CPS::Real PFSolverPowerPolar::sol_Vr(UInt k) {
560 return sol_V.coeff(k) * cos(sol_D.coeff(k));
561}
562
563CPS::Real PFSolverPowerPolar::sol_Vi(UInt k) {
564 return sol_V.coeff(k) * sin(sol_D.coeff(k));
565}
566
567CPS::Complex PFSolverPowerPolar::sol_Vcx(UInt k) {
568 return CPS::Complex(sol_Vr(k), sol_Vi(k));
569}
CPS::TopologicalNode::List mPQBuses
Vector of nodes characterized as PQ buses.
Definition PFSolver.h:32
UInt mNumPQBuses
Number of PQ nodes.
Definition PFSolver.h:24
std::vector< std::shared_ptr< CPS::SP::Ph1::PiLine > > mLines
Vector of line components.
Definition PFSolver.h:69
std::vector< std::shared_ptr< CPS::SP::Ph1::Transformer > > mTransformers
Vector of transformer components.
Definition PFSolver.h:59
CPS::Matrix mJ
Jacobian matrix.
Definition PFSolver.h:50
CPS::Vector mX
Solution vector.
Definition PFSolver.h:52
CPS::Bool solutionInitialized
Flag whether solution vectors are initialized.
Definition PFSolver.h:91
CPS::Real mBaseApparentPower
Base power of per-unit system.
Definition PFSolver.h:87
CPS::SparseMatrixCompRow mY
Admittance matrix.
Definition PFSolver.h:47
CPS::Bool solutionComplexInitialized
Flag whether complex solution vectors are initialized.
Definition PFSolver.h:93
UInt mNumPVBuses
Number of PV nodes.
Definition PFSolver.h:26
CPS::Real B(int i, int j)
Gets the imaginary part of admittance matrix element.
Definition PFSolver.cpp:465
CPS::Bool isConverged
Convergence flag.
Definition PFSolver.h:89
CPS::Vector mF
Vector of mismatch values.
Definition PFSolver.h:54
CPS::UInt mIterations
Actual number of iterations.
Definition PFSolver.h:85
PFSolver(CPS::String name, CPS::SystemTopology system, Real timeStep, CPS::Logger::Level logLevel)
Constructor to be used in simulation examples.
Definition PFSolver.cpp:16
CPS::SystemTopology mSystem
System list.
Definition PFSolver.h:57
std::map< CPS::TopologicalNode::Ptr, CPS::Real > mBaseVoltageAtNode
Map providing determined base voltages for each node.
Definition PFSolver.h:78
CPS::TopologicalNode::List mVDBuses
Vector of nodes characterized as VD buses.
Definition PFSolver.h:36
CPS::TopologicalNode::List mPVBuses
Vector of nodes characterized as PV buses.
Definition PFSolver.h:34
CPS::Real G(int i, int j)
Gets the real part of admittance matrix element.
Definition PFSolver.cpp:463
std::vector< CPS::UInt > mPQPVBusIndices
Vector with indices of both PQ and PV buses.
Definition PFSolver.h:44
CPS::Vector sol_P
Solution vector of active power.
void resize_complex_sol(CPS::Int n)
Resize complex solution vector.
void calculateBranchFlow()
Calculate branch flows from current solution and store them in line and transformer components.
void calculateQAtPVBuses()
Calculate the reactive power at all PV buses from current solution.
CPS::VectorComp sol_S_complex
Solution vector of representing sol_P and sol_Q as complex quantity.
PFSolverPowerPolar(CPS::String name, const CPS::SystemTopology &system, CPS::Real timeStep, CPS::Logger::Level logLevel)
Constructor to be used in simulation examples.
CPS::Vector sol_D
Solution vector of voltage angle.
CPS::Real sol_Vi(CPS::UInt k)
Calculate imaginary part of voltage from sol_V and sol_D.
void calculatePAndQAtSlackBus()
Calculate P and Q at slack bus from current solution.
CPS::Vector sol_Q
Solution vector of reactive power.
CPS::Real Q(CPS::UInt k)
Calculate the reactive power at a bus from current solution.
void calculateMismatch() override
Calculate mismatch.
CPS::Complex sol_Vcx(CPS::UInt k)
Calculate complex voltage from sol_V and sol_D.
void generateInitialSolution(Real time, bool keep_last_solution=false) override
Generate initial solution for current time step.
void calculateJacobian() override
Calculate the Jacobian.
void updateSolution() override
Update solution in each iteration.
void resize_sol(CPS::Int n)
Resize solution vector.
CPS::Real sol_Vr(CPS::UInt k)
Calculate real part of voltage from sol_V and sol_D.
CPS::Real P(CPS::UInt k)
Calculate active power at a bus from current solution.
void calculateNodalInjection()
Calculate nodal power injections and store them in first line or transformer (in case no line is conn...
CPS::Vector sol_V
Solution vector of voltage magnitude.
void calculatePAndQInjectionPQBuses()
Calculate complex power flowing from this node to the other nodes.
CPS::VectorComp sol_V_complex
Solution vector of representing sol_V and sol_D as complex quantity.
void setSolution() override
Set final solution.
CPS::Logger::Log mSLog
Logger.
Definition Solver.h:45