Writes the main output file (.out) with full analysis results.
43 {
44 std::string outFile = jobName + ".out";
45 std::ofstream out(outFile);
46 if (!out.is_open()) return false;
47
48 int nBus = busData.
V.size();
49 int nBranch = branchData.
From.size();
51
53
54 out << fmt::format("\n deltaFlow v{:<32s}Date {:>14s} Time {:>8s}\n",
56 out << "\n";
57
60 out << fmt::format(" CMake Version : {}\n", CMake_VERSION);
61 out << fmt::format(" Compiler Version : GCC {}\n", gcc_VERSION);
62 out << fmt::format(" deltaFlow Version : {}\n", deltaFlow_VERSION);
63 out << "\n";
64
66 out << fmt::format(" Job Name : {}\n", jobName);
67 out << fmt::format(" Input File : {}\n", inputFile);
68 out << fmt::format(" Input Format : {}\n", formatName);
69 out << fmt::format(" Solver Method : {}\n", solverName);
70 out << fmt::format(" Convergence Tol. : {:.6e}\n", tolerance);
71 out << "\n";
72
74
76
77 out << fmt::format(" Number of Buses : {:>6d}\n", nBus);
78 out << fmt::format(" Slack Buses : {:>6d}\n", counts.nSlack);
79 out << fmt::format(" PV Buses : {:>6d}\n", counts.nPV);
80 out << fmt::format(" PQ Buses : {:>6d}\n", counts.nPQ);
81 out << fmt::format(" Number of Branches : {:>6d}\n", nBranch);
82 out << fmt::format(" Base MVA : {:>10.1f}\n", basemva);
83 out << "\n";
84
86 out << fmt::format(" Method : {}\n", solverName);
87 out << fmt::format(" Iterations : {:>6d}\n", iterations);
88 out << fmt::format(" Final Error : {:.6e}\n", finalError);
89 out << fmt::format(" Tolerance : {:.6e}\n", tolerance);
90 out << fmt::format(" Status : CONVERGED\n");
91 out << fmt::format(" Elapsed Time (sec) : {:.3f}\n", elapsedSec);
92 out << "\n";
93
95 out << fmt::format(" {:>4s} {:>9s} {:>9s} {:>10s} {:>10s} {:>10s} {:>10s} {:>10s}\n",
96 "Bus", "Voltage", "Angle", "Load", "Load", "Gen", "Gen", "Injected");
97 out << fmt::format(" {:>4s} {:>9s} {:>9s} {:>10s} {:>10s} {:>10s} {:>10s} {:>10s}\n",
98 "No.", "Mag.", "Degree", "MW", "Mvar", "MW", "Mvar", "Mvar");
99 out << " " << std::string(W - 4, '=') << "\n";
100
101 for (int i = 0; i < nBus; ++i) {
102 double injectedMvar = busData.
Qg(i) - busData.
Ql(i);
103 out << fmt::format(" {:>4d} {:>9.4f} {:>9.4f} {:>10.4f} {:>10.4f} {:>10.4f} {:>10.4f} {:>10.4f}\n",
104 i + 1, busData.
V(i), busData.
delta(i),
105 busData.
Pl(i), busData.
Ql(i), busData.
Pg(i), busData.
Qg(i), injectedMvar);
106 }
107
109
110 out << " " << std::string(W - 4, '=') << "\n";
111 out << fmt::format(" Total{:>27.4f} {:>10.4f} {:>10.4f} {:>10.4f} {:>10.4f}\n",
112 totals.totalPl, totals.totalQl, totals.totalPg, totals.totalQg, totals.totalInjected);
113 out << "\n";
114
116 out << fmt::format(" {:>4s} {:>4s} {:>9s} {:>9s} {:>9s} {:>9s} {:>9s} {:>9s}\n",
117 "From", "To", "MW", "Mvar", "MVA", "Loss MW", "Loss Mvar", "Tap");
118 out << " " << std::string(W - 4, '=') << "\n";
119
120 auto Bc = branchData.
B;
121 int nLine = nBranch;
122
123 Eigen::VectorXcd Vc(nBus);
124 Eigen::VectorXcd S(nBus);
125 for (int i = 0; i < nBus; ++i) {
126 double mag = busData.
V(i);
127 double ang_rad = busData.
delta(i) * M_PI / 180.0;
128 Vc(i) = std::polar(mag, ang_rad);
129 double P = busData.
Pg(i) - busData.
Pl(i);
130 double Q = busData.
Qg(i) - busData.
Ql(i);
131 S(i) = std::complex<double>(P, Q);
132 }
133
134 std::complex<double> SLT = 0.0;
135
136 for (int n = 1; n <= nBus; ++n) {
137 int n_idx = n - 1;
138 bool busprt = false;
139
140 for (int L = 0; L < nLine; ++L) {
141 if (!busprt) {
142 double P_inj = busData.
Pg(n_idx) - busData.
Pl(n_idx);
143 double Q_inj = busData.
Qg(n_idx) - busData.
Ql(n_idx);
144 double S_mag = std::abs(S(n_idx)) * basemva;
145 out << fmt::format(" {:>4d} {:>9.3f} {:>9.3f} {:>9.3f}\n",
146 n, P_inj, Q_inj, S_mag);
147 busprt = true;
148 }
149
150 auto writeLineFlow = [&](int from, int to, int L) {
151 int f_idx = from - 1;
152 int t_idx = to - 1;
153 double aL = (branchData.
tapRatio(L) == 0.0) ? 1.0 : branchData.tapRatio(L);
154
155 std::complex<double> In, Ik;
156 if (branchData.
From(L) == from) {
157 In = (Vc(f_idx) - aL * Vc(t_idx)) * Y(L) / (aL * aL) + Bc(L) / (aL * aL) * Vc(f_idx);
158 Ik = (Vc(t_idx) - Vc(f_idx) / aL) * Y(L) + Bc(L) * Vc(t_idx);
159 } else {
160 In = (Vc(f_idx) - Vc(t_idx) / aL) * Y(L) + Bc(L) * Vc(f_idx);
161 Ik = (Vc(t_idx) - aL * Vc(f_idx)) * Y(L) / (aL * aL) + Bc(L) / (aL * aL) * Vc(t_idx);
162 }
163 std::complex<double> Snk = Vc(f_idx) * std::conj(In) * basemva;
164 std::complex<double> Skn = Vc(t_idx) * std::conj(Ik) * basemva;
165 std::complex<double> SL = Snk + Skn;
166 SLT += SL;
167
168 if (aL != 1.0) {
169 out << fmt::format(" {:>4d} {:>9.3f} {:>9.3f} {:>9.3f} {:>9.3f} {:>9.3f} {:>9.3f}\n",
170 to, std::real(Snk), std::imag(Snk), std::abs(Snk),
171 std::real(SL), std::imag(SL), aL);
172 } else {
173 out << fmt::format(" {:>4d} {:>9.3f} {:>9.3f} {:>9.3f} {:>9.3f} {:>9.3f}\n",
174 to, std::real(Snk), std::imag(Snk), std::abs(Snk),
175 std::real(SL), std::imag(SL));
176 }
177 };
178
179 if (branchData.
From(L) == n) {
180 writeLineFlow(n, branchData.
To(L), L);
181 }
else if (branchData.
To(L) == n) {
182 writeLineFlow(n, branchData.
From(L), L);
183 }
184 }
185 }
186
187 SLT /= 2.0;
188 out << "\n";
189 out << fmt::format(" Total loss {:>9.3f} {:>9.3f}\n",
190 std::real(SLT), std::imag(SLT));
191 out << "\n";
192
193 out << "\n";
194 out << "\n";
195 out << " JOB TIME SUMMARY\n";
196 out << fmt::format(" TOTAL CPU TIME (SEC) = {:>12.5f}\n", elapsedSec);
197 out << fmt::format(" WALLCLOCK TIME (SEC) = {:>12d}\n", static_cast<int>(std::round(elapsedSec)));
198 out << "\n";
199
201 out <<
Display::center(
"THE ANALYSIS HAS BEEN COMPLETED SUCCESSFULLY") <<
"\n";
202 out << "\n";
203
204 out.close();
205 return true;
206}
std::string center(const std::string &text)
Returns a centered string within the page width.
constexpr int pageWidth
Standard output page width.
std::string sectionHeader(const std::string &title)
Returns a section header for output files.
std::string fileBanner()
Returns a full plain-text banner for output/log files.
std::string hostname()
Returns the current hostname.
std::string dateStr()
Returns the current date string.
BusTotals computeBusTotals(const BusData &busData)
Computes total load/gen/injected Mvar across all buses.
std::string timeStr()
Returns the current time string.
BusTypeCounts countBusTypes(const BusData &busData)
Counts buses by type (1=Slack, 2=PV, else PQ).
Eigen::VectorXd tapRatio
Transformer tap ratio ($$ a $$)
Eigen::VectorXd B
Line susceptance ($$ B $$) [p.u.].
Eigen::VectorXi From
From bus indices.
Eigen::VectorXi To
To bus indices.
Eigen::VectorXd Ql
Reactive power load [MVAr or p.u.].
Eigen::VectorXd V
Voltage magnitude [p.u.].
Eigen::VectorXd Pg
Active power generation [MW or p.u.].
Eigen::VectorXd delta
Voltage angle [rad or deg].
Eigen::VectorXd Pl
Active power load [MW or p.u.].
Eigen::VectorXd Qg
Reactive power generation [MVAr or p.u.].