VM2D 1.14
Vortex methods for 2D flows simulation
Loading...
Searching...
No Matches
Gmres2D.cpp
Go to the documentation of this file.
1/*--------------------------------*- VM2D -*-----------------*---------------*\
2| ## ## ## ## #### ##### | | Version 1.14 |
3| ## ## ### ### ## ## ## ## | VM2D: Vortex Method | 2026/03/06 |
4| ## ## ## # ## ## ## ## | for 2D Flow Simulation *----------------*
5| #### ## ## ## ## ## | Open Source Code |
6| ## ## ## ###### ##### | https://www.github.com/vortexmethods/VM2D |
7| |
8| Copyright (C) 2017-2026 I. Marchevsky, K. Sokol, E. Ryatina, A. Kolganova |
9*-----------------------------------------------------------------------------*
10| File name: Gmres2D.cpp |
11| Info: Source code of VM2D |
12| |
13| This file is part of VM2D. |
14| VM2D is free software: you can redistribute it and/or modify it |
15| under the terms of the GNU General Public License as published by |
16| the Free Software Foundation, either version 3 of the License, or |
17| (at your option) any later version. |
18| |
19| VM2D is distributed in the hope that it will be useful, but WITHOUT |
20| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
21| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
22| for more details. |
23| |
24| You should have received a copy of the GNU General Public License |
25| along with VM2D. If not, see <http://www.gnu.org/licenses/>. |
26\*---------------------------------------------------------------------------*/
27
28
42#include "Gmres2D.h"
43
44#include "Airfoil2D.h"
45#include "Boundary2D.h"
46#include "MeasureVP2D.h"
47#include "Mechanics2D.h"
48#include "Preprocessor.h"
49#include "StreamParser.h"
50#include "Velocity2D.h"
51#include "Wake2D.h"
52#include "World2D.h"
53
54
55using namespace VM2D;
56
57typedef Eigen::Map<const Eigen::VectorXd> MapVec;
58
59bool GmresSolver::IterRot(const double nrmRhs, double& gs, int m, bool residualShow)
60{
61 bool fl;
62 double buf;
63
64 double epsGMRES = W.getPassport().numericalSchemes.gmresEps;
65
66 for (int i = 0; i < m - 1; ++i)
67 {
68 buf = H[i][m - 1];
69
70 H[i][m - 1] = c[i] * buf + s[i] * H[i + 1][m - 1];
71 H[i + 1][m - 1] = -s[i] * buf + c[i] * H[i + 1][m - 1];
72 }
73
74 double izn = 1.0 / sqrt(H[m - 1][m - 1] * H[m - 1][m - 1] + H[m][m - 1] * H[m][m - 1]);
75
76 c.push_back(H[m - 1][m - 1] * izn);
77 s.push_back(H[m][m - 1] * izn);
78 gs *= -s[m - 1];
79
80 H[m - 1][m - 1] = c[m - 1] * H[m - 1][m - 1] + s[m - 1] * H[m][m - 1];
81 H[m][m - 1] = 0.0;
82
83 if (residualShow)
84 std::cout << "Iteration: " << m << ", residual = " << (fabs(gs) / nrmRhs) << std::endl;
85
86 fl = ((fabs(gs) / nrmRhs) < epsGMRES);
87 return fl;
88}
89
90
91void GmresSolver::SolCircleRundirect(const std::vector<double>& A, const std::vector<double>& rhs, size_t startRow, size_t startRowReg, size_t np, std::vector<double>& res)
92{
93 size_t nAllVars = rhs.size();
94 std::vector<double> alpha(np + 2), beta(np + 2), gamma(np + 2);
95 std::vector<double> u(np), v(np);
96
97 double zn = A[(startRow + np + 1) * nAllVars + (startRow + np + 1)];
98 alpha[2] = -A[(startRow + np + 1) * nAllVars + (startRow + np + 2)] / zn;
99 beta[2] = rhs[startRow + np + 1] / zn;
100 gamma[2] = -A[(startRow + np + 1) * nAllVars + (startRow + np + 0)] / zn;
101
102 for (size_t i = 2; i <= np; ++i)
103 {
104 zn = A[(startRow + np + (i % np)) * nAllVars + (startRow + np + (i % np))] + alpha[i] * A[(startRow + np + (i % np)) * nAllVars + (startRow + np + ((i - 1) % np))];
105 alpha[i + 1] = -A[(startRow + np + (i % np)) * nAllVars + (startRow + np + ((i + 1) % np))] / zn;
106 beta[i + 1] = (rhs[startRow + np + (i % np)] - beta[i] * A[(startRow + np + (i % np)) * nAllVars + (startRow + np + ((i - 1) % np))]) / zn;
107 gamma[i + 1] = -(gamma[i] * A[(startRow + np + (i % np)) * nAllVars + (startRow + np + ((i - 1) % np))]) / zn;
108 }
109
110 u[np - 1] = beta[np];
111 v[np - 1] = alpha[np] + gamma[np];
112 for (size_t i = np - 2; i >= 1; --i)
113 {
114 u[i] = alpha[i + 1] * u[i + 1] + beta[i + 1];
115 v[i] = alpha[i + 1] * v[i + 1] + gamma[i + 1];
116 }
117
118 res[startRow + np] = (beta[np + 1] + alpha[np + 1] * u[1]) / (1.0 - gamma[np + 1] - alpha[np + 1] * v[1]);
119 for (size_t i = 1; i < np; ++i)
120 res[startRow + np + i] = u[i] + res[startRow + np] * v[i];
121
122 return;
123}
124
125
126
127
128void GmresSolver::SolMdirect(const std::vector<double>& A, const std::vector<double>& rhs, size_t startRow, size_t startRowReg, size_t np, std::vector<double>& res, bool lin)
129{
130 std::vector<double> alpha(np), beta(np), gamma(np), delta(np), phi(np), xi(np), psi(np);
131 double yn, ynn;
132 double lam1, lam2, mu1, mu2, xi1, xi2;
133 double a;
134
135 size_t nAllVars = rhs.size();
136
137 double izn = 1.0 / A[(startRow + 0) * nAllVars + (startRow + 0)];
138 alpha[1] = -A[(startRow + 0) * nAllVars + (startRow + 1)] * izn;
139 beta[1] = -A[(startRow + 0) * nAllVars + (startRow + np - 1)] * izn;
140 gamma[1] = -A[(startRow + 0) * nAllVars + (startRowReg)] * izn;
141 delta[1] = rhs[startRow] * izn;
142 double zn;
143
144
145 for (size_t i = 1; i < np - 1; ++i)
146 {
147 a = A[(startRow + i) * nAllVars + (startRow + i - 1)];
148 zn = a * alpha[i] + A[(startRow + i) * nAllVars + (startRow + i)];
149 alpha[i + 1] = -A[(startRow + i) * nAllVars + (startRow + i + 1)] / zn;
150 beta[i + 1] = -a * beta[i] / zn;
151 gamma[i + 1] = -(A[(startRow + i) * nAllVars + (startRowReg)] + a * gamma[i]) / zn;
152 delta[i + 1] = (rhs[startRow + i] - a * delta[i]) / zn;
153 }
154
155 a = A[(startRow + (np - 2)) * nAllVars + (startRow + (np - 3))];
156 zn = alpha[np - 2] * a + A[(startRow + (np - 2)) * nAllVars + (startRow + (np - 2))];
157
158 phi[np - 1] = -(A[(startRow + np - 2) * nAllVars + (startRow + np - 1)] + a * beta[np - 2]) / zn;
159 psi[np - 1] = -(A[(startRow + np - 2) * nAllVars + (startRowReg)] + gamma[np - 2] * a) / zn;
160 xi[np - 1] = (rhs[startRow + np - 2] - delta[np - 2] * a) / zn;
161
162 for (size_t i = np - 2; i > 0; --i)
163 {
164 phi[i] = alpha[i] * phi[i + 1] + beta[i];
165 psi[i] = alpha[i] * psi[i + 1] + gamma[i];
166 xi[i] = alpha[i] * xi[i + 1] + delta[i];
167 }
168
169
170 double e = A[(startRow + np - 1) * nAllVars + (startRow + 0)];
171 a = A[(startRow + np - 1) * nAllVars + (startRow + np - 2)];
172 lam1 = e * phi[1] + a * phi[np - 1] + A[(startRow + np - 1) * nAllVars + (startRow + np - 1)];
173 mu1 = e * psi[1] + a * psi[np - 1] + A[(startRow + np - 1) * nAllVars + (startRowReg)];
174 xi1 = rhs[startRow + np - 1] - e * xi[1] - a * xi[np - 1];
175
176 lam2 = mu2 = xi2 = 0.0;
177 for (size_t j = 0; j < np - 1; ++j)
178 {
179 lam2 += phi[j + 1];
180 mu2 += psi[j + 1];
181 xi2 -= xi[j + 1];
182 }
183 lam2 += 1.0;
184
185 xi2 += rhs[startRowReg];
186
187 zn = lam1 * mu2 - lam2 * mu1;
188 yn = (xi1 * mu2 - xi2 * mu1) / zn;
189 ynn = -(xi1 * lam2 - xi2 * lam1) / zn;
190
191 res[startRowReg] = ynn;
192
193 res[startRow + np - 1] = yn;
194 for (size_t i = np - 2; i + 1 > 0; --i)
195 res[startRow + i] = phi[i + 1] * yn + psi[i + 1] * ynn + xi[i + 1];
196
197//
198 if (lin)
199 SolCircleRundirect(A, rhs, startRow, startRowReg, np, res);
200}
201
202
203
205 int nAllVars,
206 int nafl,
207 const std::vector<double>& mtrDir,
208 const std::vector<double>& rhsDir,
209 const std::vector<int>& pos,
210 const std::vector<int>& vsize,
211 std::vector<std::vector<double>>& gam,
212 std::vector<double>& R)
213{
214 const size_t maxIter = nAllVars + 1;
215 std::vector<double> x(nAllVars, 0.0);
216 std::vector<double> y(nAllVars, 0.0);
217 std::vector<double> residual(nAllVars, 0.0);
218 std::vector<double> r(nAllVars, 0.0);
219 std::vector<double> w(nAllVars, 0.0);
220 std::vector<double> wOld(nAllVars, 0.0);
221 std::vector<double> g(nAllVars, 0.0);
222 std::vector<double> c(nAllVars, 0.0);
223 std::vector<double> s(nAllVars, 0.0);
224 std::vector<double> hisGs(nAllVars + 1, 0.0);
225 std::vector<double> v(nAllVars * (maxIter + 1), 0.0);
226
227 std::vector<double> vecFromV(nAllVars, 0.0);
228
229 std::vector<double> h((nAllVars + 1) * maxIter, 0.0);
230 double beta = 0.0, gs, normb = 0.0;
231 size_t m = 0;
232
233 for (size_t i = 0; i < nAllVars; ++i)
234 normb += rhsDir[i] * rhsDir[i];
235 normb = sqrt(normb);
236
237 for (size_t i = 0; i < nAllVars; ++i)
238 residual[i] = rhsDir[i];
239
240#pragma omp parallel for
241 for (int aflI = 0; aflI < nafl; ++aflI)
242 {
243 // SolMdirect(mtrDir, residual, pos[aflI], nAllVars - nafl + aflI, W.getAirfoil(aflI).getNumberOfPanels(), r, (vsize[aflI] == 2*n[aflI]));
244 r = residual;
245 }
246
247 for (size_t i = 0; i < nAllVars; ++i)
248 beta += r[i] * r[i];
249 beta = sqrt(beta);
250 gs = beta;
251 g[0] = beta;
252
253 // ,
254 if (beta == 0)
255 {
256 for (size_t aflI = 0; aflI < nafl; ++aflI)
257 {
258 for (size_t i = 0; i < vsize[aflI]; ++i)
259 gam[aflI][i] = 0.0;
260 R[aflI] = 0.0;
261 }
262 return;
263 }
264
265 for (size_t aflI = 0; aflI < nafl; ++aflI)
266 R[aflI] = x[x.size() - nafl + aflI];
267
268 for (size_t i = 0; i < nAllVars; ++i)
269 v[i * (maxIter + 1) + 0] = r[i] / beta;
270
271 for (size_t j = 0; j < nAllVars; ++j)
272 {
273 double timer1 = omp_get_wtime();
274
275 for (size_t p = 0; p < nAllVars; ++p)
276 vecFromV[p] = v[p * (maxIter + 1) + j];
277
278 //cblas_dgemv(CblasRowMajor, CblasNoTrans, nAllVars, nAllVars, 1.0, mtrDir.data(), nAllVars, &v[0 * (maxIter + 1) + j], (nAllVars + 1), 0.0, wOld.data(), 1);
279 //cblas_dgemv(CblasRowMajor, CblasNoTrans, nAllVars, nAllVars, 1.0, mtrDir.data(), nAllVars, vecFromV.data(), 1, 0.0, wOld.data(), 1);
280 for (int i = 0; i < nAllVars; ++i)
281 {
282 wOld[i] = 0.0;
283 for (int jj = 0; jj < nAllVars; ++jj)
284 {
285 wOld[i] += mtrDir[i * nAllVars + jj] * vecFromV[jj];
286 }
287 }
288
289 double timer2 = omp_get_wtime();
290
291#pragma omp parallel for
292 for (int aflI = 0; aflI < nafl; ++aflI)
293 {
294 // SolMdirect(mtrDir, wOld, pos[aflI], nAllVars - nafl + aflI, W.getAirfoil(aflI).getNumberOfPanels(), w, (vsize[aflI] == 2 * n[aflI]));
295 w = wOld;
296 }
297
298 for (size_t i = 0; i <= j; ++i)
299 {
300 h[i * maxIter + j] = 0.0;
301 for (size_t q = 0; q < nAllVars; ++q)
302 h[i * maxIter + j] += w[q] * v[q * (maxIter + 1) + i];
303
304 for (size_t q = 0; q < nAllVars; ++q)
305 w[q] -= h[i * maxIter + j] * v[q * (maxIter + 1) + i];
306 }//for i
307
308 h[(j + 1) * maxIter + j] = 0.0;
309 for (size_t p = 0; p < nAllVars; ++p)
310 h[(j + 1) * maxIter + j] += w[p] * w[p];
311 h[(j + 1) * maxIter + j] = sqrt(h[(j + 1) * maxIter + j]);
312
313 for (size_t p = 0; p < nAllVars; ++p)
314 v[p * (maxIter + 1) + (j + 1)] = w[p] / h[(j + 1) * maxIter + j];
315
316 for (size_t i = 0; i < j; ++i)
317 {
318 double buf = h[i * maxIter + j];
319 h[i * maxIter + j] = c[i] * buf + s[i] * h[(i + 1) * maxIter + j];
320 h[(i + 1) * maxIter + j] = -s[i] * buf + c[i] * h[(i + 1) * maxIter + j];
321 }
322
323 double zn = sqrt(h[j * maxIter + j] * h[j * maxIter + j] + h[(j + 1) * maxIter + j] * h[(j + 1) * maxIter + j]);
324 c[j] = fabs(h[j * maxIter + j] / zn);
325 s[j] = c[j] * h[(j + 1) * maxIter + j] / h[j * maxIter + j];
326
327 gs *= -s[j];
328
329 h[j * maxIter + j] = c[j] * h[j * maxIter + j] + s[j] * h[(j + 1) * maxIter + j];
330 h[(j + 1) * maxIter + j] = 0.0;
331 hisGs[j] = fabs(gs) / normb;
332
333 if ((fabs(gs) / normb) < W.getPassport().numericalSchemes.gmresEps)
334 {
335 m = j + 1;
336 break;
337 }
338 }//for j
339
340 //
341 for (size_t i = 0; i < m; ++i)
342 {
343 double buf = g[i];
344 g[i] *= c[i];
345 if (i < (m - 1))
346 g[i + 1] = -s[i] * buf;
347
348 }
349 y[m - 1] = g[m - 1] / h[(m - 1) * maxIter + (m - 1)];
350
351 for (size_t i = m - 2; i + 1 > 0; --i)
352 {
353 double sum = 0;
354 for (size_t j = i + 1; j < m; ++j)
355 sum += h[i * maxIter + j] * y[j];
356
357 y[i] = (g[i] - sum) / h[i * maxIter + i];
358 }
359
360 for (size_t p = 0; p < nAllVars; ++p)
361 {
362 for (size_t q = 0; q < m; ++q)
363 x[p] += v[p * (maxIter + 1) + q] * y[q];
364 }
365
366 std::cout << "#iterations: " << m << std::endl;
367
368 for (size_t aflI = 0; aflI < nafl; ++aflI)
369 {
370 for (size_t i = 0; i < vsize[aflI]; ++i)
371 gam[aflI][i] = x[pos[aflI] + i];
372 }
373
374 for (size_t aflI = 0; aflI < nafl; ++aflI)
375 R[aflI] = x[x.size() - nafl + aflI];
376}
377
378
379
380
381
382
383
384
385
387
388
389
390void GmresSolver::SolCircleRun(std::vector<double>& AX, const std::vector<double>& rhs, int p)
391{
392 const Airfoil& afl = W.getAirfoil(p);
393 int n = (int)afl.getNumberOfPanels();
394 sweepVectors& sw = allSW[p];
396
397 std::vector<double>& alpha = sw.alpha;
398 std::vector<double>& beta = sw.beta;
399 std::vector<double>& delta = sw.delta;
400 std::vector<double>& phi = sw.phi;
401 std::vector<double>& xi = sw.xi;
402
403 double yn, a;
404
405 double len24 = afl.len[0] * 24.0;
406
407 alpha[1] = (afl.tau[0] & prec1[p][0]) * len24;
408 beta[1] = (afl.tau[0] & prea1[p][0]) * len24;
409 delta[1] = -len24 * rhs[n + 0];
410 double zn;
411
412 for (int i = 1; i < n - 1; ++i)
413 {
414 a = (afl.tau[i] & prea1[p][i]);
415 zn = a * alpha[i] - 1.0 / (24.0 * afl.len[i]);
416 alpha[i + 1] = -(afl.tau[i] & prec1[p][i]) / zn;
417 beta[i + 1] = -a * beta[i] / zn;
418 delta[i + 1] = (rhs[n + i] - a * delta[i]) / zn;
419 }
420
421 a = afl.tau[n - 2] & prea1[p][n - 2];
422 zn = alpha[n - 2] * a - 1.0 / (24.0 * afl.len[n - 2]);
423 phi[n - 1] = -((afl.tau[n - 2] & prec1[p][n - 2]) + beta[n - 2] * a) / zn;
424 xi[n - 1] = (rhs[n + n - 2] - delta[n - 2] * a) / zn;
425
426 for (int i = n - 2; i > 0; --i)
427 {
428 phi[i] = alpha[i] * phi[i + 1] + beta[i];
429 xi[i] = alpha[i] * xi[i + 1] + delta[i];
430 }
431
432
433 double e = (afl.tau[n - 1] & prec1[p][n - 1]);
434 a = (afl.tau[n - 1] & prea1[p][n - 1]);
435
436 yn = (rhs[n + n - 1] - e * xi[1] - a * xi[n - 1]) / (e * phi[1] + a * phi[n - 1] - 1.0 / (24.0 * afl.len[n - 1]));
437
438 AX[n + n - 1] = yn;
439 for (int i = n - 2; i >= 0; --i)
440 AX[n + i] = phi[i + 1] * yn + xi[i + 1];
441}
442
443
444
445void GmresSolver::SolM(std::vector<double>& AX, const std::vector<double>& rhs, int p)
446{
447 const Airfoil& afl = W.getAirfoil(p);
448 int n = (int)afl.getNumberOfPanels();
449 sweepVectors& sw = allSW[p];
451
452 std::vector<double>& alpha = sw.alpha;
453 std::vector<double>& beta = sw.beta;
454 std::vector<double>& gamma = sw.gamma;
455 std::vector<double>& delta = sw.delta;
456 std::vector<double>& phi = sw.phi;
457 std::vector<double>& xi = sw.xi;
458 std::vector<double>& psi = sw.psi;
459
460 double yn, ynn;
461 double lam1, lam2, mu1, mu2, xi1, xi2;
462 double a;
463
464 double len2 = afl.len[0] * 2.0;
465
466 alpha[1] = (afl.tau[0] & prec[p][0]) * len2;
467 beta[1] = (afl.tau[0] & prea[p][0]) * len2;
468 gamma[1] = len2;
469 delta[1] = -len2 * rhs[0];
470
471 double zn;
472
473 for (int i = 1; i < n - 1; ++i)
474 {
475 a = (afl.tau[i] & prea[p][i]);
476 zn = a * alpha[i] - 0.5 / afl.len[i];
477 alpha[i + 1] = -(afl.tau[i] & prec[p][i]) / zn;
478 beta[i + 1] = -a * beta[i] / zn;
479 gamma[i + 1] = -(1.0 + a * gamma[i]) / zn;
480 delta[i + 1] = (rhs[i] - a * delta[i]) / zn;
481 }
482
483 a = afl.tau[n - 2] & prea[p][n - 2];
484 zn = alpha[n - 2] * a - 0.5 / afl.len[n - 2];
485 phi[n - 1] = -((afl.tau[n - 2] & prec[p][n - 2]) + beta[n - 2] * a) / zn;
486 psi[n - 1] = -(1.0 + gamma[n - 2] * a) / zn;
487 xi[n - 1] = (rhs[n - 2] - delta[n - 2] * a) / zn;
488
489 for (int i = n - 2; i > 0; --i)
490 {
491 phi[i] = alpha[i] * phi[i + 1] + beta[i];
492 psi[i] = alpha[i] * psi[i + 1] + gamma[i];
493 xi[i] = alpha[i] * xi[i + 1] + delta[i];
494 }
495
496 double e = (afl.tau[n - 1] & prec[p][n - 1]);
497 a = (afl.tau[n - 1] & prea[p][n - 1]);
498 lam1 = e * phi[1] + a * phi[n - 1] - 0.5 / afl.len[n - 1];
499 mu1 = e * psi[1] + a * psi[n - 1] + 1.0;
500 xi1 = rhs[n - 1] - e * xi[1] - a * xi[n - 1];
501 lam2 = mu2 = xi2 = 0.0;
502 for (int j = 0; j < n - 1; ++j)
503 {
504 lam2 += phi[j + 1];
505 mu2 += psi[j + 1];
506 xi2 -= xi[j + 1];
507 }
508 lam2 += 1.0;
509
510 if (!linScheme)
511 xi2 += rhs[n];
512 else if (linScheme)
513 xi2 += rhs[2 * n];
514
515 zn = lam1 * mu2 - lam2 * mu1;
516 yn = (xi1 * mu2 - xi2 * mu1) / zn;
517 ynn = -(xi1 * lam2 - xi2 * lam1) / zn;
518
519 if (!linScheme)
520 AX[n] = ynn;
521 else if (linScheme)
522 AX[2 * n] = ynn;
523
524 AX[n - 1] = yn;
525 for (int i = n - 2; i >= 0; --i)
526 AX[i] = phi[i + 1] * yn + psi[i + 1] * ynn + xi[i + 1];
527}
528
529
530
531//
533{
534 Point2D p1, s1, p2, s2, di, dj;
535 numvector<double, 3> alpha, lambda;
536 numvector<Point2D, 3> v00, v11;
537 Point2D i00, i11;
538
539 const Airfoil& aflP = W.getAirfoil(aflIndex);
540
541 size_t nPanelsP = aflP.getNumberOfPanels();
543
544 for (size_t i = 0; i < nPanelsP; ++i)
545 {
546 std::array<int, 2> vecV = { ((int)i - 1 >= 0) ? int(i - 1) : int(nPanelsP - 1), (i + 1 < nPanelsP) ? int(i + 1) : 0 };
547 for (int j : vecV)
548 {
549 p1 = aflP.getR(i + 1) - aflP.getR(j + 1);
550 s1 = aflP.getR(i + 1) - aflP.getR(j);
551 p2 = aflP.getR(i) - aflP.getR(j + 1);
552 s2 = aflP.getR(i) - aflP.getR(j);
553 di = aflP.getR(i + 1) - aflP.getR(i);
554 dj = aflP.getR(j + 1) - aflP.getR(j);
555
556 alpha = { \
557 (aflP.isAfter(j, i)) ? 0.0 : VMlib::Alpha(s2, s1), \
558 VMlib::Alpha(s2, p1), \
559 (aflP.isAfter(i, j)) ? 0.0 : VMlib::Alpha(p1, p2) \
560 };
561
562 lambda = { \
563 (aflP.isAfter(j, i)) ? 0.0 : VMlib::Lambda(s2, s1), \
564 VMlib::Lambda(s2, p1), \
565 (aflP.isAfter(i, j)) ? 0.0 : VMlib::Lambda(p1, p2) \
566 };
567
568 v00 = {
569 VMlib::Omega(s1, di.unit(), dj.unit()),
570 -VMlib::Omega(di, di.unit(), dj.unit()),
571 VMlib::Omega(p2, di.unit(), dj.unit())
572 };
573
574 i00 = IDPI / di.length() * (-(alpha[0] * v00[0] + alpha[1] * v00[1] + alpha[2] * v00[2]).kcross() \
575 + (lambda[0] * v00[0] + lambda[1] * v00[1] + lambda[2] * v00[2]));
576
577 if (aflP.isAfter(j, i))
578 prec[aflIndex][i] = (i00.kcross()) * (1.0 / dj.length());
579 if (aflP.isAfter(i, j))
580 prea[aflIndex][i] = (i00.kcross()) * (1.0 / dj.length());
581
582 if (linScheme) {
583
584 v11 = { 1.0 / (12.0 * di.length() * dj.length()) * \
585 (2.0 * (s1 & Omega(s1 - 3.0 * p2, di.unit(), dj.unit())) * VMlib::Omega(s1, di.unit(), dj.unit()) - \
586 s1.length2() * (s1 - 3.0 * p2)) - 0.25 * VMlib::Omega(s1, di.unit(), dj.unit()),
587 -di.length() / (12.0 * dj.length()) * Omega(di, dj.unit(), dj.unit()),
588 -dj.length() / (12.0 * di.length()) * Omega(dj, di.unit(), di.unit()) };
589
590 i11 = (IDPI / di.length()) * ((alpha[0] + alpha[2]) * v11[0] + (alpha[1] + alpha[2]) * v11[1] + alpha[2] * v11[2]\
591 + ((lambda[0] + lambda[2]) * v11[0] + (lambda[1] + lambda[2]) * v11[1] + lambda[2] * v11[2] \
592 + 1.0 / 12.0 * (dj.length() * di.unit() + di.length() * dj.unit() - 2.0 * VMlib::Omega(s1, di.unit(), dj.unit()))).kcross());
593 if (aflP.isAfter(j, i))
594 prec1[aflIndex][i] = (i11) * (1.0 / dj.length());
595 if (aflP.isAfter(i, j))
596 prea1[aflIndex][i] = (i11) * (1.0 / dj.length());
597 }
598 }
599 }
600}
601
603 : W(W_)
604{
605#ifdef USE_CUDA
606 cublasCreate(&cublas_handle);
607#endif
608
610 const size_t nAfl = W.getNumberOfAirfoil();
611
612 nTotPan = 0;
613 for (size_t s = 0; s < nAfl; ++s)
615
617
618#ifdef USE_CUDA
619 cudaMalloc((void**)&devViBund, (totalVsize + nAfl) * sizeof(double) * iterSize);
620 cudaMalloc((void**)&devw, (totalVsize + nAfl) * sizeof(double));
621
622 //cudaMalloc(&mulptr, iterSize * sizeof(double));
623 //std::vector<double> mul(iterSize);
624#endif
625
626 w.resize(totalVsize + nAfl);
627 c.reserve(iterSize);
628 s.reserve(iterSize);
629
630 Vflat.reserve((totalVsize + nAfl) * iterSize);
631
632 diag.resize(nAfl);
633 H.resize(iterSize + 1);
634 for (int i = 0; i < iterSize + 1; ++i)
635 H[i].resize(iterSize);
636
637 for (int p = 0; p < (int)nAfl; ++p)
638 {
639 size_t nPanelsP = W.getAirfoil(p).getNumberOfPanels();
640 if (!linScheme)
641 diag[p].resize(nPanelsP);
642 else
643 diag[p].resize(2 * nPanelsP);
644 }
645
646 // PRECONDITIONER
647 prea.resize(nAfl);
648 prec.resize(nAfl);
649
650 if (linScheme)
651 {
652 prea1.resize(nAfl);
653 prec1.resize(nAfl);
654 }
655
656#pragma omp parallel for
657 for (int p = 0; p < nAfl; ++p)
658 {
659 const auto& aflP = W.getAirfoil(p);
660 size_t nPanelsP = aflP.getNumberOfPanels();
661
662 prea[p].resize(nPanelsP);
663 prec[p].resize(nPanelsP);
664 if (linScheme)
665 {
666 prea1[p].resize(nPanelsP);
667 prec1[p].resize(nPanelsP);
668 }
669 }
670
671 allSW.resize(nAfl);
672 allBuf2.resize(nAfl);
673 np.resize(nAfl, 0);
674
675 for (size_t p = 0; p < nAfl; ++p)
676 {
677 size_t nPanelsP = W.getAirfoil(p).getNumberOfPanels();
678
679 allSW[p].resize(nPanelsP);
680
681 if (!linScheme)
682 allBuf2[p].resize(nPanelsP + 1);
683 else
684 allBuf2[p].resize(2 * nPanelsP + 1);
685
686 if (p == 0)
687 continue;
688
689 np[p] = np[p - 1];
690 if (!linScheme)
691 np[p] += (/*(p == 0) ? 0 :*/ W.getAirfoil(p - 1).getNumberOfPanels());
692 else
693 np[p] += (/*(p == 0) ? 0 :*/ 2 * W.getAirfoil(p - 1).getNumberOfPanels());
694 }
695
696 bufnewSol.resize(totalVsize);
697 bufcurrentSol.resize(totalVsize, 0.0);
698
699 g.reserve(iterSize);
700 Y.reserve(iterSize);
701
702#ifdef USE_CUDA
703 W.getNonConstCuda().AllocateSolution(W.getNonConstCuda().dev_sol, nTotPan);
704 if (linScheme)
705 W.getNonConstCuda().AllocateSolution(W.getNonConstCuda().dev_solLin, nTotPan);
706 else
707 W.getNonConstCuda().dev_solLin = nullptr;
708#endif
709};
710
712{
713#ifdef USE_CUDA
714 cublasDestroy(cublas_handle);
715
717 W.getNonConstCuda().ReleaseSolution(W.getNonConstCuda().dev_sol);
718 if (linScheme)
719 W.getNonConstCuda().ReleaseSolution(W.getNonConstCuda().dev_solLin);
720
721 //W.getNonConstCuda().inflTreePnlVortex->MemoryFreeForGMRES();
722 cudaFree(devViBund);
723 cudaFree(devw);
724 //cudaFree(mulptr);
725
726#endif
727}
728
729
730#ifdef USE_CUDA
731void GmresSolver::GMRES(
732 std::vector<std::vector<double>>& X,
733 std::vector<double>& R,
734 const std::vector<std::vector<double>>& rhs,
735 const std::vector<double>& rhsReg,
736 int& niter
737)
738{
739 VMlib::vmTimer tAll("All"), tPre("Pre"), tIter("Iter"), tPost("Post"), tIter1("Iter1"), tIterOther("IterOther"),
740 tCG("tCG"), tGC("tGC"), tWrapper("tWrapper"), tSplit("tSplit"), tPrecond("tPrecond"), tRot("tRot"),
741 tRotA("tRotA"), tRotB("tRotB"), tRotC("tRotC"), tRotD("tRotD");
742
743 tAll.start();
744 tPre.start();
745
746 size_t m;
747 double beta;
748 const size_t nAfl = W.getNumberOfAirfoil();
751 double theta = W.getPassport().numericalSchemes.gmresTheta;
752 double itheta2 = 1.0 / (theta * theta);
753 auto& treePnlInfl = *W.getNonConstCuda().inflTreePnlVortex;
754
756 treePnlInfl.MemoryAllocateForGMRES((W.getCurrentStep() == 0), itheta2);
757
759#pragma omp parallel for
760 for (int p = 0; p < (int)nAfl; ++p)
761 {
762 size_t nPanelsP = W.getAirfoil(p).getNumberOfPanels();
763 for (int i = 0; i < nPanelsP; ++i)
764 {
765 double lenI = W.getAirfoil(p).len[i];
766 diag[p][i] = 0.5 / lenI;
767
768 if (linScheme)
769 diag[p][i + nPanelsP] = (1.0 / 24.0) / lenI;
770 }
771 }
772
773 double nrmRhs = 0.0;
774#pragma omp parallel for reduction(+:nrmRhs)
775 for (int p = 0; p < (int)nAfl; ++p)
776 nrmRhs += norm2(rhs[p]);
777 nrmRhs = sqrt(nrmRhs);
778
779 c.resize(0);
780 s.resize(0);
781 Vflat.resize(0);
782 for (size_t i = 0; i < nAfl; ++i)
783 Vflat.insert(Vflat.end(), rhs[i].begin(), rhs[i].end());
784
785 for (size_t i = 0; i < nAfl; ++i)
786 Vflat.push_back(rhsReg[i]);
787
788
790 {
791#pragma omp parallel for
792 for (int p = 0; p < nAfl; ++p)
794 }
795
796
797#pragma omp parallel for
798 for (int p = 0; p < (int)nAfl; ++p)
799 {
800 std::vector<double>& vbuf1 = allBuf2[p];
801 size_t nPanelsP = W.getAirfoil(p).getNumberOfPanels();
802
803 for (size_t i = 0; i < nPanelsP; ++i)
804 {
805 vbuf1[i] = Vflat[np[p] + i];
806 if (linScheme)
807 vbuf1[i + nPanelsP] = Vflat[np[p] + nPanelsP + i];
808 }
809
810 if (!linScheme)
811 vbuf1[nPanelsP] = Vflat[(totalVsize + nAfl) - (nAfl - p)];
812 else
813 vbuf1[2 * nPanelsP] = Vflat[(totalVsize + nAfl) - (nAfl - p)];
814
815
816 //
817 SolM(vbuf1, vbuf1, p);
818 if (linScheme)
819 SolCircleRun(vbuf1, vbuf1, p);
820
821 for (size_t j = np[p]; j < np[p] + nPanelsP; ++j)
822 {
823 Vflat[j] = vbuf1[j - np[p]];
824 if (linScheme)
825 Vflat[j + nPanelsP] = vbuf1[j - np[p] + nPanelsP];
826 }
827 Vflat[(totalVsize + nAfl) - (nAfl - p)] = vbuf1[vbuf1.size() - 1];
828 }
829
830 beta = 0;
831#pragma omp parallel for reduction(+:beta)
832 for (int t = 0; t < (totalVsize + nAfl); ++t)
833 beta += Vflat[t] * Vflat[t];
834
835 beta = sqrt(beta);
836 if (beta > 0)
837#pragma omp parallel for
838 for (int t = 0; t < (totalVsize + nAfl); ++t)
839 Vflat[t] /= beta;
840 else
841 {
842 for (auto& xp : X)
843 for (auto& x : xp)
844 x = 0.0;
845 return;
846 }
847
848 double gs = beta;
849
850 double* dev_ptr_rhs = W.getAirfoil(0).devRhsPtr;
851 double* dev_ptr_rhsLin = (linScheme ? W.getAirfoil(0).devRhsLinPtr : nullptr);
852
853
854
855 const double zero = 0.0, unit = 1.0;
856
857 tPre.stop();
858 tIter.start();
859
860
861
862 //Iterations
863 for (int j = 0; j < totalVsize - 1; ++j) //+ n.size()
864 {
865 if (j == 0)
866 tIter1.start();
867 else if (j == 1)
868 tIterOther.start();
869
870 tCG.start();
871
872 size_t npred = 0;
873 if (!linScheme)
874 for (size_t i = 0; i < W.getNumberOfAirfoil(); ++i)
875 {
876#pragma omp parallel for
877 for (int p = 0; p < (int)W.getAirfoil(i).getNumberOfPanels(); ++p)
878 bufcurrentSol[npred + p] = Vflat[(totalVsize + nAfl)*(j) + npred + p] / W.getAirfoil(i).len[p];
879
880 npred += W.getAirfoil(i).getNumberOfPanels();
881 }
882 else
883 {
884 for (size_t i = 0; i < W.getNumberOfAirfoil(); ++i)
885 {
886#pragma omp parallel for
887 for (int p = 0; p < (int)W.getAirfoil(i).getNumberOfPanels(); ++p)
888 {
889 bufcurrentSol[npred + p] = Vflat[(totalVsize + nAfl) * j + (2 * npred + p)] / W.getAirfoil(i).len[p];
890 bufcurrentSol[nTotPan + npred + p] = Vflat[(totalVsize + nAfl) * j + (2 * npred + W.getAirfoil(i).getNumberOfPanels() + p)] / W.getAirfoil(i).len[p];
891 }
892 npred += W.getAirfoil(i).getNumberOfPanels();
893 }
894 W.getNonConstCuda().SetSolution(bufcurrentSol.data() + nTotPan, W.getNonConstCuda().dev_solLin, nTotPan);
895 }
896 W.getNonConstCuda().SetSolution(bufcurrentSol.data(), W.getNonConstCuda().dev_sol, nTotPan);
897
898 tCG.stop();
899
900 if (j>0)
901 tWrapper.start();
902
903 treePnlInfl.UpdatePanelFreeVortexIntensity(W.getNonConstCuda().dev_sol, W.getNonConstCuda().dev_solLin);
904 treePnlInfl.UpwardTraversal(order);
905 treePnlInfl.DownwardTraversalGMRES(dev_ptr_rhs, dev_ptr_rhsLin, itheta2, order, j, (W.isAnyMovableOrDeformable() || W.getCurrentStep()==0));
906
907 if (j>0)
908 tWrapper.stop();
909
910 tGC.start();
911
912 if (!linScheme)
913 W.getCuda().CopyMemFromDev<double, 1>(nTotPan, dev_ptr_rhs, w.data(), 22);
914
915 if (linScheme)
916 {
917 W.getCuda().CopyMemFromDev<double, 1>(nTotPan, dev_ptr_rhs, bufnewSol.data(), 22);
918 W.getCuda().CopyMemFromDev<double, 1>(nTotPan, dev_ptr_rhsLin, bufnewSol.data() + nTotPan, 22);
919 }
920
921 tGC.stop();
922
923 tSplit.start();
924
925 npred = 0;
926 if (linScheme)
927 for (size_t i = 0; i < W.getNumberOfAirfoil(); ++i)
928 {
929#pragma omp parallel for
930 for (int j = 0; j < (int)W.getAirfoil(i).getNumberOfPanels(); ++j)
931 {
932 w[2 * npred + j] = bufnewSol[npred + j];
933 w[2 * npred + W.getAirfoil(i).getNumberOfPanels() + j] = bufnewSol[nTotPan + npred + j];
934 }
935 npred += W.getAirfoil(i).getNumberOfPanels();
936 }
937
938 size_t cntr = 0;
939 for (size_t pi = 0; pi < nAfl; ++pi)
940 {
941 size_t nPanelsPi = W.getAirfoil(pi).getNumberOfPanels();
942#pragma omp parallel for
943 for (int i = 0; i < (int)nPanelsPi; ++i)
944 {
945 w[cntr + i] += Vflat[(totalVsize + nAfl) * j + (totalVsize + pi)] - Vflat[(totalVsize + nAfl) * j + (cntr + i)] * diag[pi][i];
946 if (linScheme)
947 w[cntr + i + nPanelsPi] += -Vflat[(totalVsize + nAfl) * j + (cntr + i + nPanelsPi)] * diag[pi][i + nPanelsPi];
948 }
949
950 cntr += nPanelsPi;
951 if (linScheme)
952 cntr += nPanelsPi;
953 }
954
955 for (size_t i = 0; i < nAfl; ++i)
956 w[totalVsize + i] = 0.0;
957
958 cntr = 0;
959 for (size_t i = 0; i < nAfl; ++i)
960 {
961 size_t nPanelsI = W.getAirfoil(i).getNumberOfPanels();
962 for (size_t k = 0; k < nPanelsI; ++k)
963 w[totalVsize + i] += Vflat[(totalVsize + nAfl) * j + (cntr + k)];
964 cntr += nPanelsI;
965 if (linScheme)
966 cntr += nPanelsI;
967 }
968 tSplit.stop();
969
970 tPrecond.start();
971
972 // PRECONDITIONER
973
974#pragma omp parallel for
975 for (int p = 0; p < (int)nAfl; ++p)
976 {
977 std::vector<double>& vbuf2 = allBuf2[p];
978
979 size_t nPanelsP = W.getAirfoil(p).getNumberOfPanels();
980
981 for (size_t i = 0; i < nPanelsP; ++i)
982 {
983 vbuf2[i] = w[np[p] + i];
984 if (linScheme)
985 vbuf2[i + nPanelsP] = w[np[p] + nPanelsP + i];
986 }
987
988 if (!linScheme)
989 vbuf2[nPanelsP] = w[w.size() - (nAfl - p)];
990 else
991 vbuf2[2 * nPanelsP] = w[w.size() - (nAfl - p)];
992
993
994 //
995 SolM(vbuf2, vbuf2, p);
996 if (linScheme)
997 SolCircleRun(vbuf2, vbuf2, p);
998
999 for (size_t j = np[p]; j < np[p] + nPanelsP; ++j)
1000 {
1001 w[j] = vbuf2[j - np[p]];
1002 if (linScheme)
1003 w[j + nPanelsP] = vbuf2[j - np[p] + nPanelsP];
1004 }
1005
1006 w[w.size() - (nAfl - p)] = vbuf2[vbuf2.size() - 1];
1007 }
1008 tPrecond.stop();
1009
1010
1011
1012 tRot.start();
1013
1014 tRotA.start();
1015
1016 if (j == H.size() - 1)
1017 {
1018 std::cout << "Reallocation for GMRES" << std::endl;
1019 H.resize(j * 2 + 2);
1020 for (int i = 0; i < j * 2 + 2; ++i)
1021 H[i].resize(j * 2 + 1);
1022
1023 Vflat.reserve((totalVsize + nAfl) * j * 2);
1024 c.reserve(j * 2);
1025 s.reserve(j * 2);
1026
1027 //mul.reserve(j * 2);
1028 //cudaFree(mulptr);
1029 //cudaMalloc((void**)&mulptr, j * 2 * sizeof(double));
1030
1031 double* devViBund_new;
1032 cudaMalloc((void**)&devViBund_new, (totalVsize + nAfl) * j * 2 * sizeof(double));
1033 cudaMemcpy(devViBund_new, devViBund, (totalVsize + nAfl) * j * sizeof(double), cudaMemcpyDeviceToDevice);
1034 cudaFree(devViBund);
1035 devViBund = devViBund_new;
1036 }
1037
1038 tRotA.stop();
1039 tRotB.start();
1040
1041 //blas
1042 /*
1043 cudaMemcpy(devViBund + w.size() * j, Vflat.data() + w.size() * j, (1) * w.size() * sizeof(double), cudaMemcpyHostToDevice); //was
1044 cudaMemcpy(devw, w.data(), w.size() * sizeof(double), cudaMemcpyHostToDevice); //was
1045 cublasDgemv(cublas_handle, CUBLAS_OP_T, (int)w.size(), (int)Vflat.size() / (int)w.size(), &unit, devViBund, (int)w.size(), devw, 1, &zero, mulptr, 1);
1046 cudaMemcpy(mul.data(), mulptr, (j+1) * sizeof(double), cudaMemcpyDeviceToHost);
1047
1048 for (int i = 0; i <= j; ++i)
1049 {
1050 double scal = 0.0;
1051 scal = mul[i];
1052 H[i][j] = scal;
1053 scal *= -1;
1054
1055 cublasDaxpy(cublas_handle, \
1056 (int)w.size(), \
1057 &scal, \
1058 devViBund + w.size() * i, 1, \
1059 devw, 1);
1060 }
1061 cudaMemcpy(w.data(), devw, w.size() * sizeof(double), cudaMemcpyDeviceToHost);
1062 //*/
1063
1064 //half-blas
1065 /*
1066 cudaMemcpy(devViBund + w.size() * j, Vflat.data() + w.size() * j, (1) * w.size() * sizeof(double), cudaMemcpyHostToDevice); //was
1067 cudaMemcpy(devw, w.data(), w.size() * sizeof(double), cudaMemcpyHostToDevice); //was
1068
1069 cublasDgemv(cublas_handle, CUBLAS_OP_T, (int)w.size(), (int)Vflat.size() / (int)w.size(), &unit, devViBund, (int)w.size(), devw, 1, &zero, mulptr, 1);
1070 cudaMemcpy(mul.data(), mulptr, (j+1) * sizeof(double), cudaMemcpyDeviceToHost);
1071
1072 for (int i = 0; i <= j; ++i)
1073 {
1074 double scal = 0.0;
1075 scal = mul[i];
1076 H[i][j] = scal;
1077 scal *= -1;
1078
1079#pragma omp for
1080 for (int q = 0; q < (int)w.size(); ++q)
1081 w[q] += scal * Vflat[(totalVsize + nAfl) * i + q];//V[i][q];
1082
1083 //cublasDaxpy(cublas_handle, \
1084 (int)w.size(), \
1085 &scal, \
1086 devViBund + w.size() * i, 1, \
1087 devw, 1);
1088 }
1089 //cudaMemcpy(w.data(), devw, w.size() * sizeof(double), cudaMemcpyDeviceToHost);
1090 //*/
1091
1092
1093 //non-blas
1094 //*
1095 for (int i = 0; i <= j; ++i)
1096 {
1097 double scal = 0.0;
1098#pragma omp parallel
1099 {
1100#pragma omp for reduction(+:scal)
1101 for (int q = 0; q < (int)w.size(); ++q)
1102 scal += w[q] * Vflat[(totalVsize + nAfl) * i + q];//V[i][q];
1103
1104 H[i][j] = scal;
1105#pragma omp for
1106 for (int q = 0; q < (int)w.size(); ++q)
1107 w[q] -= scal * Vflat[(totalVsize + nAfl) * i + q];//V[i][q];
1108 }
1109 }//*/
1110
1111
1112 tRotB.stop();
1113
1114 tRotC.start();
1115
1116 m = j + 1;
1117
1118 double nrmw = 0.0;
1119
1120 //cublasDdot(cublas_handle, \
1121 // w.size(), \
1122 // devw, 1, /* w, 1 */ \
1123 // devw, 1, /* w, 1 */ \
1124 // &nrmw);
1125 //nrmw = sqrt(nrmw);
1126 //H[m][j] = nrmw;
1127
1128 nrmw = norm(w);
1129 H[m][j] = nrmw;
1130
1131 Vflat.insert(Vflat.end(), w.begin(), w.end());
1132 for (int t = 0; t < (totalVsize + nAfl); ++t)
1133 Vflat[Vflat.size() - t - 1] /= nrmw;
1134
1135 tRotC.stop();
1136
1137 tRotD.start();
1138
1139 if (IterRot(nrmRhs, gs, (int)m, false))
1140 {
1141 //std::cout << "iterations in GMRES = " << j + 1 << std::endl;
1142 if (j != 0)
1143 tIterOther.stop();
1144 tRotD.stop();
1145 tRot.stop();
1146
1147 break;
1148 }
1149
1150 tRotD.stop();
1151 tRot.stop();
1152
1153 if (j == 0)
1154 tIter1.stop();
1155 } // end of iterations
1156
1157 tIter.stop();
1158
1159 tPost.start();
1160
1161
1162 niter = (int)m;
1163
1164 g.resize(m + 1);
1165 g[0] = beta;
1166
1167 //GivensRotations
1168 double oldValue;
1169 for (int i = 0; i < m; i++)
1170 {
1171 oldValue = g[i];
1172 g[i] = c[i] * oldValue;
1173 g[i + 1] = -s[i] * oldValue;
1174 }
1175 //end of GivensRotations
1176
1177 // Solve HY=g
1178 Y.resize(m);
1179 Y[m - 1] = g[m - 1] / H[m - 1][m - 1];
1180
1181 double sum;
1182 for (int k = (int)m - 2; k >= 0; --k)
1183 {
1184 sum = 0.0;
1185 for (int s = k + 1; s < m; ++s)
1186 sum += H[k][s] * Y[s];
1187 Y[k] = (g[k] - sum) / H[k][k];
1188 }
1189 // end of Solve HY=g
1190
1191 size_t cntr = 0;
1192 for (size_t p = 0; p < nAfl; p++) {
1193
1194 size_t nPanelsP = W.getAirfoil(p).getNumberOfPanels();
1195
1196 if (!linScheme)
1197 for (size_t i = 0; i < nPanelsP; i++)
1198 {
1199 sum = 0.0;
1200 for (size_t j = 0; j < m; j++)
1201 sum += Vflat[(totalVsize + nAfl) * j + (i + cntr)] * Y[j];
1202 X[p][i] += sum;
1203 }
1204 else {
1205 for (size_t i = 0; i < 2 * nPanelsP; i++)
1206 {
1207 sum = 0.0;
1208 for (size_t j = 0; j < m; j++)
1209 sum += Vflat[(totalVsize + nAfl) * j + (i + cntr)] * Y[j];
1210 X[p][i] += sum;
1211 }
1212 }
1213 cntr += nPanelsP;
1214
1215 if (linScheme)
1216 cntr += nPanelsP;
1217
1218 }
1219
1220 sum = 0.0;
1221 for (size_t p = 0; p < nAfl; p++)
1222 {
1223 for (size_t j = 0; j < m; j++)
1224 sum += Vflat[(totalVsize + nAfl) * j + (totalVsize + p)] * Y[j];
1225 R[p] += sum;
1226 }
1227
1228 tPost.stop();
1229
1230 tAll.stop();
1231
1232 /*
1233 std::cout << "tAll = " << tAll.duration() << std::endl;
1234 std::cout << "tPre = " << tPre.duration() << std::endl;
1235 std::cout << "tIter = " << tIter.duration() << std::endl;
1236 std::cout << "tIter1 = " << tIter1.duration() << std::endl;
1237 if(m > 1)
1238 std::cout << "tIterN = " << tIterOther.duration() / (m-1.0) << std::endl;
1239 else
1240 std::cout << "tIterN = " << 0.0 << std::endl;
1241 std::cout << "tPost = " << tPost.duration() << std::endl;
1242
1243 std::cout << "tCG = " << tCG.duration() / (double)(m) << std::endl;
1244 std::cout << "tGC = " << tGC.duration() / (double)(m) << std::endl;
1245 std::cout << "tWrap(>0)= " << tWrapper.duration() / (double)(m - 1) << std::endl;
1246 std::cout << "tSplit = " << tSplit.duration() / (double)(m) << std::endl;
1247 std::cout << "tPrecond = " << tPrecond.duration() / (double)(m) << std::endl;
1248 std::cout << "tRot = " << (tRotA.duration() + tRotB.duration() + tRotC.duration() +tRotD.duration()) / (double)(m) << std::endl;
1249 //*/
1250
1251 //std::cout << " tRotA = " << tRotA.duration() / (double)(m) << std::endl;
1252 //std::cout << " tRotB = " << tRotB.duration() / (double)(m) << std::endl;
1253 //std::cout << " tRotC = " << tRotC.duration() / (double)(m) << std::endl;
1254 //std::cout << " tRotD = " << tRotD.duration() / (double)(m) << std::endl;
1255}
1256
1257#endif
Заголовочный файл с описанием класса Airfoil.
Заголовочный файл с описанием класса Boundary.
Eigen::Map< const Eigen::VectorXd > MapVec
Definition Gmres2D.cpp:57
Заголовочный файл с функциями для метода GMRES.
Заголовочный файл с описанием класса MeasureVP.
Заголовочный файл с описанием класса Mechanics.
Заголовочный файл с описанием класса Preprocessor.
Заголовочный файл с описанием класса StreamParser.
const double IDPI
Число .
Definition defs.h:79
Заголовочный файл с описанием класса Velocity.
Заголовочный файл с описанием класса Wake.
Заголовочный файл с описанием класса World2D.
std::vector< double > len
Длины панелей профиля
Definition Airfoil2D.h:94
const Point2D & getR(size_t q) const
Возврат константной ссылки на вершину профиля
Definition Airfoil2D.h:113
std::vector< Point2D > tau
Касательные к панелям профиля
Definition Airfoil2D.h:91
size_t getNumberOfPanels() const
Возврат количества панелей на профиле
Definition Airfoil2D.h:163
Абстрактный класс, определяющий обтекаемый профиль
Definition Airfoil2D.h:182
bool isAfter(size_t i, size_t j) const
Проверка, идет ли вершина i следом за вершиной j.
Definition Airfoil2D.cpp:76
std::vector< double > bufcurrentSol
Definition Gmres2D.h:166
std::vector< double > s
Definition Gmres2D.h:156
void SolCircleRun(std::vector< double > &AX, const std::vector< double > &rhs, int p)
Definition Gmres2D.cpp:390
std::vector< std::vector< Point2D > > prec
Definition Gmres2D.h:160
void SolMdirect(const std::vector< double > &A, const std::vector< double > &rhs, size_t startRow, size_t startRowReg, size_t np, std::vector< double > &res, bool lin)
Definition Gmres2D.cpp:128
const World2D & W
Definition Gmres2D.h:148
std::vector< std::vector< double > > allBuf2
Definition Gmres2D.h:163
std::vector< std::vector< Point2D > > prea1
Definition Gmres2D.h:160
std::vector< std::vector< Point2D > > prea
Definition Gmres2D.h:160
std::vector< double > c
Definition Gmres2D.h:156
size_t totalVsize
Definition Gmres2D.h:169
std::vector< double > bufnewSol
Definition Gmres2D.h:166
std::vector< std::vector< double > > H
Definition Gmres2D.h:158
void PreCalculateCoef(int aflIndex)
Definition Gmres2D.cpp:532
std::vector< size_t > np
Definition Gmres2D.h:164
void SolCircleRundirect(const std::vector< double > &A, const std::vector< double > &rhs, size_t startRow, size_t startRowReg, size_t np, std::vector< double > &res)
Definition Gmres2D.cpp:91
std::vector< double > Vflat
Definition Gmres2D.h:157
const size_t iterSize
Definition Gmres2D.h:172
std::vector< sweepVectors > allSW
Definition Gmres2D.h:162
GmresSolver(const World2D &W_)
Definition Gmres2D.cpp:602
bool IterRot(const double nrmRhs, double &gs, int m, bool residualShow)
Контроль невязки после выполнения очередной итерации GMRES.
Definition Gmres2D.cpp:59
void GMRES_Direct(int nAllVars, int nafl, const std::vector< double > &mtrDir, const std::vector< double > &rhsDir, const std::vector< int > &pos, const std::vector< int > &vsize, std::vector< std::vector< double > > &gam, std::vector< double > &R)
Definition Gmres2D.cpp:204
std::vector< std::vector< double > > diag
Definition Gmres2D.h:158
std::vector< std::vector< Point2D > > prec1
Definition Gmres2D.h:160
void SolM(std::vector< double > &AX, const std::vector< double > &rhs, int p)
Definition Gmres2D.cpp:445
std::vector< double > Y
Definition Gmres2D.h:167
std::vector< double > g
Definition Gmres2D.h:167
std::vector< double > w
Definition Gmres2D.h:156
NumericalSchemes numericalSchemes
Структура с используемыми численными схемами
Definition Passport2D.h:307
Класс, опеделяющий текущую решаемую задачу
Definition World2D.h:77
size_t getNumberOfAirfoil() const
Возврат количества профилей в задаче
Definition World2D.h:180
bool isAnyMovableOrDeformable() const
Возврат признака того, что хотя бы один из профилей подвижный или деформируемый
Definition World2D.cpp:2349
const Airfoil & getAirfoil(size_t i) const
Возврат константной ссылки на объект профиля
Definition World2D.h:163
Gpu & getNonConstCuda() const
Возврат неконстантной ссылки на объект, связанный с видеокартой (GPU)
Definition World2D.h:278
const Gpu & getCuda() const
Возврат константной ссылки на объект, связанный с видеокартой (GPU)
Definition World2D.h:273
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition World2D.h:263
size_t getCurrentStep() const
Возврат константной ссылки на параметры распараллеливания по MPI.
Definition WorldGen.h:99
Шаблонный класс, определяющий вектор фиксированной длины Фактически представляет собой массив,...
Definition numvector.h:99
numvector< T, 2 > kcross() const
Геометрический поворот двумерного вектора на 90 градусов
Definition numvector.h:511
auto length2() const -> typename std::remove_const< typename std::remove_reference< decltype(this->data[0])>::type >::type
Вычисление квадрата нормы (длины) вектора
Definition numvector.h:386
auto unit(P newlen=1) const -> numvector< typename std::remove_const< decltype(this->data[0] *newlen)>::type, n >
Вычисление орта вектора или вектора заданной длины, коллинеарного данному
Definition numvector.h:402
P length() const
Вычисление 2-нормы (длины) вектора
Definition numvector.h:374
Класс засекания времени
Definition TimesGen.h:59
double norm(const std::vector< T > &b)
Шаблонная функция вычисления евклидовой нормы вектора или списка
Definition Gmres2D.h:102
double norm2(const std::vector< T > &b)
Шаблонная функция вычисления евклидовой нормы вектора или списка
Definition Gmres2D.h:117
double Lambda(const Point2D &p, const Point2D &s)
Вспомогательная функция вычисления логарифма отношения норм векторов
Definition defs.cpp:268
double Alpha(const Point2D &p, const Point2D &s)
Вспомогательная функция вычисления угла между векторами
Definition defs.cpp:262
Point2D Omega(const Point2D &a, const Point2D &b, const Point2D &c)
Вспомогательная функция вычисления величины .
Definition defs.cpp:274
std::pair< std::string, int > boundaryCondition
Метод аппроксимации граничных условий
Definition Passport2D.h:190
Структура, определяющий необходимые массивы для рализации метода прогонки
Definition Gmres2D.h:69
std::vector< double > phi
Definition Gmres2D.h:74
std::vector< double > beta
Definition Gmres2D.h:71
std::vector< double > psi
Definition Gmres2D.h:76
std::vector< double > delta
Definition Gmres2D.h:73
std::vector< double > alpha
Definition Gmres2D.h:70
std::vector< double > gamma
Definition Gmres2D.h:72
std::vector< double > xi
Definition Gmres2D.h:75