VM2D 1.14
Vortex methods for 2D flows simulation
Loading...
Searching...
No Matches
MeasureVP2D.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: MeasureVP2D.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
39
40#if defined(_WIN32)
41#include <direct.h>
42#endif
43
44#include "MeasureVP2D.h"
45
46#include "Airfoil2D.h"
47#include "Boundary2D.h"
48
49#include "Mechanics2D.h"
51#include "Preprocessor.h"
52#include "StreamParser.h"
53#include "Velocity2D.h"
54#include "Wake2D.h"
55#include "World2D.h"
56#include "Gmres2D.h"
57
58using namespace VM2D;
59
60//Конструктор
62 : W(W_)
63#ifdef USE_CUDA
64 , treeWakeX(W_.getCuda().blocks, tree_T::vortex, object_T::point4, scheme_T::noScheme, false)
65 , treeWakeY(W_.getCuda().blocks, tree_T::vortex, object_T::point4, scheme_T::noScheme, false)
66#endif
67{
68 sstrCounter = 0;
69 wakeVP.reset(new WakeDataBase(W_));
70
71
72
73};//MeasureVP(...)
74
75//Чтение точек, в которых нужно посчитать давление и скорость
76void MeasureVP::ReadPointsFromFile(const std::string& dir)
77{
78 std::string filename = dir + "pointsVP";
79 std::ifstream VPFile;
80
81 if (fileExistTest(filename, W.getInfo(), true, { "txt", "TXT" }))
82 {
83 std::stringstream VPFile(VMlib::Preprocessor(filename).resultString);
84
85 VMlib::StreamParser VPParser(W.getInfo(), "velocity & pressure parser", VPFile);
86
87 VPParser.get("points", initialPoints);
88 VPParser.get("history", historyPoints);
89 VPParser.get("historyFrequency", historyFrequency, &defaults::defaultHistoryFrequency, false);
90
91 for (auto& pt : initialPoints)
92 pt = pt.rotated(-W.getPassport().rotateAngleVpPoints * PI / 180.0);
93
94 for (auto& pt : historyPoints)
95 pt = pt.rotated(-W.getPassport().rotateAngleVpPoints * PI / 180.0);
96
97 if (historyPoints.size() > 0)
98 {
99 sstr.resize(historyPoints.size());
100 sstrCounter = 0;
101
102 VMlib::CreateUserDirectory(dir, "velPres");
103 std::string VPFileNameList = W.getPassport().dir + "velPres/listPoints";
104 std::ofstream VPFileList(VPFileNameList.c_str());
105
106 VMlib::PrintLogoToTextFile(VPFileList, VPFileNameList.c_str(), "List of points, where velocity and pressure are measured in csv-files");
107
108 VMlib::PrintHeaderToTextFile(VPFileList, "No. FileName X Y");
109
110 for (size_t q = 0; q < historyPoints.size(); ++q)
111 {
112 VPFileList << '\n' << q << '\t' << VMlib::fileNameStep("VP-atPoint-", 2, q, "csv") << '\t' << historyPoints[q][0] << '\t' << historyPoints[q][1];
113
114 std::string VPFileNameCsv;
115 VPFileNameCsv = W.getPassport().dir + "velPres/" + VMlib::fileNameStep("VP-atPoint-", 2, q, "csv");
116
117 std::ofstream VPFileCsv(VPFileNameCsv.c_str());
118
119 if (!W.getPassport().calcCoefficients)
120 VPFileCsv << "pt,t,Vx,Vy,p" << std::endl;
121 else
122 VPFileCsv << "pt,t,CVx,CVy,Cp" << std::endl;
123
124 VPFileCsv.close();
125 VPFileCsv.clear();
126 }
127
128 VPFileList.close();
129 VPFileList.clear();
130 }
131 }
132}//ReadPointsFromFile(...)
133
134//Чтение точек, в которых нужно посчитать давление и скорость
135void MeasureVP::SetPoints(const std::vector<Point2D>& points, const std::vector<Point2D>& history)
136{
137 initialPoints = points;
138 historyPoints = history;
139
140 sstr.resize(historyPoints.size());
141 sstrCounter = 0;
142
143 for (auto& pt : initialPoints)
144 pt = pt.rotated(-W.getPassport().rotateAngleVpPoints * PI / 180.0);
145
146 for (auto& pt : historyPoints)
147 pt = pt.rotated(-W.getPassport().rotateAngleVpPoints * PI / 180.0);
148
149
150 if (historyPoints.size() > 0)
151 {
152 VMlib::CreateUserDirectory(W.getPassport().dir, "velPres");
153 std::string VPFileNameList = W.getPassport().dir + "velPres/listPoints";
154 std::ofstream VPFileList(VPFileNameList.c_str());
155
156 VMlib::PrintLogoToTextFile(VPFileList, VPFileNameList.c_str(), "List of points, where velocity and pressure are measured in csv-files");
157
158 VMlib::PrintHeaderToTextFile(VPFileList, "No. FileName X Y");
159
160 for (size_t q = 0; q < historyPoints.size(); ++q)
161 {
162 VPFileList << '\n' << q << '\t' << VMlib::fileNameStep("VP-atPoint-", 2, q, "csv") << '\t' << historyPoints[q][0] << '\t' << historyPoints[q][1];
163
164 std::string VPFileNameCsv;
165 VPFileNameCsv = W.getPassport().dir + "velPres/" + VMlib::fileNameStep("VP-atPoint-", 2, q, "csv");
166
167 std::ofstream VPFileCsv(VPFileNameCsv.c_str());
168
169 if (!W.getPassport().calcCoefficients)
170 VPFileCsv << "pt,t,Vx,Vy,p" << std::endl;
171 else
172 VPFileCsv << "pt,t,CVx,CVy,Cp" << std::endl;
173
174 VPFileCsv.close();
175 VPFileCsv.clear();
176 }
177
178 VPFileList.close();
179 VPFileList.clear();
180 }
181}//SetPoints(...)
182
183
184// Инициализация векторов для вычисления скоростей и давлений
186{
187 W.getTimers().start("VelPres");
188
189 //VMlib::vmTimer T1, T2, T3;
190
191
192 if ((W.getPassport().timeDiscretizationProperties.saveVPstep > 0) && (!(W.getCurrentStep() % W.getPassport().timeDiscretizationProperties.saveVPstep)))
193 {
194 //T1.start();
195
196 //W.getInfo('i') << "Preparing VP points" << std::endl;
197
198 wakeVP->vtx.clear();
199 wakeVP->vtx.reserve(initialPoints.size() + historyPoints.size() + elasticPoints.size());
200
201 Vortex2D addvtx;
202
203 velocity.clear();
204 pressure.clear();
205 domainRadius.clear();
206
207 //отключаем проверку того, что точки расположены вне профиля
208 /*
209 //определяем точки, которые не находятся внутри профилей
210 bool inside;
211 for (size_t i = 0; i < initialPoints.size(); ++i)
212 {
213 inside = false;
214 for (size_t j = 0; j < W.getNumberOfAirfoil(); ++j)
215 {
216 if (W.getAirfoil(j).isInsideGabarits(initialPoints[i]) && W.getAirfoil(j).IsPointInAirfoil(initialPoints[i]))
217 {
218 inside = true;
219 break;
220 }
221 }
222 if (!inside)
223 {
224 addvtx.r() = initialPoints[i];
225 wakeVP.vtx.push_back(addvtx);
226 }
227 }
228 */
229
230 //добавляем все точки, а не только те, которые вне профиля
231 for (size_t i = 0; i < initialPoints.size(); ++i)
232 {
233 addvtx.r() = initialPoints[i];
234 addvtx.g() = 0.0;
235 addvtx.sigma() = 0.0;
236 wakeVP->vtx.push_back(addvtx);
237
238 }//for i
239
240 for (size_t i = 0; i < historyPoints.size(); ++i)
241 {
242 addvtx.r() = historyPoints[i];
243 addvtx.g() = 0.0;
244 addvtx.sigma() = 0.0;
245 wakeVP->vtx.push_back(addvtx);
246 }//for i
247
248 //T1.stop();
249
250 elasticPoints.clear();
251
252 //T2.start();
253
254 for (size_t afl = 0; afl < W.getNumberOfAirfoil(); ++afl)
255 {
256 MechanicsDeformable* ptr = dynamic_cast<MechanicsDeformable*>(&(W.getNonConstMechanics(afl)));
257 if (ptr != nullptr)
258 {
259
260 if (ptr->beam->fsi)
261 {
262 if (afl > 0)
263 {
264 W.getInfo('e') << "Only airfoil 0 can be elastic!" << std::endl;
265 exit(-345);
266 }
267
268 //if (ptr->beam->fsi) //turek
269 {
270 elasticPoints.reserve(ptr->chord.size() * 2);
271 for (size_t q = 0; q < ptr->chord.size(); ++q)
272 {
273 std::pair<size_t, size_t> pnls = ptr->chord[q].infPanels;
274 elasticPoints.push_back(
275 0.5 * (W.getAirfoil(afl).getR(pnls.first) + W.getAirfoil(afl).getR(pnls.first + 1))
276 + 0.01 * W.getAirfoil(afl).len[pnls.first] * W.getAirfoil(afl).nrm[pnls.first]
277 );
278
279 elasticPoints.push_back(
280 0.5 * (W.getAirfoil(afl).getR(pnls.second) + W.getAirfoil(afl).getR(pnls.second + 1))
281 + 0.01 * W.getAirfoil(afl).len[pnls.second] * W.getAirfoil(afl).nrm[pnls.second]
282 );
283 }
284
285 //std::ofstream elastPointsPositionsFile(W.getPassport().dir + "elastPointsPos-" + std::to_string(W.getCurrentStep()) + ".txt");
286 //for (size_t q = 0; q < elasticPoints.size(); ++q)
287 // elastPointsPositionsFile << elasticPoints[q][0] << " " << elasticPoints[q][1] << std::endl;
288 //elastPointsPositionsFile.close();
289 }
290 }
291 else //fish and other types
292 {
293 elasticPoints.reserve(W.getAirfoil(afl).getNumberOfPanels());
294 for (size_t q = 0; q < W.getAirfoil(afl).getNumberOfPanels(); ++q)
295 elasticPoints.push_back(0.5 * (W.getAirfoil(afl).getR(q) + W.getAirfoil(afl).getR(q + 1)) + W.getAirfoil(afl).nrm[q] * 1e-10);
296 }
297 }
298 }
299
300 //T2.stop();
301
302 /*
303 std::cout << "Elast_points added!\n";
304 for (size_t afl = 0; afl < W.getNumberOfAirfoil(); ++afl)
305 {
306 elasticPoints.reserve(W.getAirfoil(afl).getNumberOfPanels());
307 for (size_t q = 0; q < W.getAirfoil(afl).getNumberOfPanels(); ++q)
308 elasticPoints.push_back(0.5 * (W.getAirfoil(afl).getR(q) + W.getAirfoil(afl).getR(q + 1)) + W.getAirfoil(afl).nrm[q] * 1e-4);
309 }
310 */
311
312 //T3.start();
313
314 for (size_t i = 0; i < elasticPoints.size(); ++i)
315 {
316 addvtx.r() = elasticPoints[i];
317 addvtx.g() = 0.0;
318 addvtx.sigma() = -1.0;
319 wakeVP->vtx.push_back(addvtx);
320 }//for i
321
322 //T3.stop();
323
324 //std::cout << "init: " << T1.duration() << " " << T2.duration() << " " << T3.duration() << "\n";
325
326 }
327 W.getTimers().stop("VelPres");
328
329}//Initialization()
330
331//Расчет поля давления
333{
334 W.getTimers().start("VelPres");
335
336 int addWSize = (int)wakeVP->vtx.size();
337 pressure.resize(addWSize);
338
339 Point2D dri;
340 Point2D Vi;
341 Point2D vi;
342
343 const Point2D& V0 = W.getV0();
344 const double& dt = W.getPassport().timeDiscretizationProperties.dt;
345
346 double P0 = /*1*/ 0.5 * V0.length2();
347
348 Point2D cPan;
349
350#pragma warning (push)
351#pragma warning (disable: 4101)
352 double alpha;
353 double lambda;
354 double dst2eps;
355#pragma warning (pop)
356
357 //Данные вихрей следа, нужные для слагаемого 3, собираются в один массив (не пересчитываются для каждой точки)
358 struct WakePressData
359 {
360 Point2D r, V;
361 double g, sigma2;
362 };
363
364 std::vector<WakePressData> wakeData(W.getWake().vtx.size());
365#pragma omp parallel for
366 for (int j = 0; j < (int)wakeData.size(); ++j)
367 {
368 wakeData[j].r = W.getWake().vtx[j].r();
369 wakeData[j].V = W.getVelocity().wakeVortexesParams.convVelo[j] + W.getVelocity().wakeVortexesParams.diffVelo[j] + V0;
370 wakeData[j].g = W.getWake().vtx[j].g();
371 wakeData[j].sigma2 = sqr(W.getWake().vtx[j].sigma());
372 }
373
374#pragma omp parallel for default(none) private(alpha, lambda, dri, Vi, vi, dst2eps, cPan) shared(P0, dt, V0, addWSize, wakeData, std::cout, IDPI)
375 for (int i = 0; i < addWSize; ++i)
376 {
377
378 pressure[i] = P0;
379 pressure[i] -= 0.5 * velocity[i].length2(); //2
380 Point2D pt = wakeVP->vtx[i].r();
381
382 for (size_t j = 0; j < wakeData.size(); ++j)
383 {
384 const WakePressData& wd = wakeData[j];
385
386 dri = pt - wd.r;
387 dst2eps = VMlib::boundDenom(dri.length2(), wd.sigma2);
388
389 vi = IDPI * wd.g / dst2eps * dri.kcross();
390 pressure[i] += vi & wd.V; //3
391 }
392
393
394 for (size_t q = 0; q < W.getNumberOfAirfoil(); ++q)
395 //size_t q = 0;
396 {
397 const Airfoil& afl = W.getAirfoil(q);
398 const Boundary& bou = W.getBoundary(q);
399
400 for (size_t pnl = 0; pnl < afl.getNumberOfPanels(); ++pnl)
401 {
402 Point2D s = pt - afl.getR(pnl);
403 Point2D p = pt - afl.getR(pnl + 1);
404 Point2D u0 = afl.tau[pnl];
405 double alpha = VMlib::Alpha(s, p);
406 double lambda = VMlib::Lambda(s, p);
407
408 Point2D skos = IDPI * ((alpha * u0).kcross() + (lambda * u0));
409
410 Vi = 0.5 * (bou.sheets.freeVortexSheet(pnl, 0) /* - afl.gammaThrough[pnl] / afl.len[pnl]*/) * u0;
411 vi = skos.kcross() * bou.sheets.freeVortexSheet(pnl, 0);
412 //if ((i == 0) && (pnl == 0))
413 // std::cout << "vi & Vi = " << (vi & Vi) << std::endl;
414
415 pressure[i] += vi & Vi; //4
416
417 Vi = 0.5 * (afl.getV(pnl) + afl.getV(pnl + 1));
418 vi = skos.kcross() * (bou.sheets.attachedVortexSheet(pnl, 0) - bou.oldSheets.attachedVortexSheet(pnl, 0));
419 pressure[i] += vi & Vi; //4a
420
421 vi = skos * (bou.sheets.attachedSourceSheet(pnl, 0) - bou.oldSheets.attachedSourceSheet(pnl, 0));
422 pressure[i] += vi & Vi; //4b
423 }
424 }
425
426 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
427 {
428 const Point2D& rcm = W.getAirfoil(bou).rcm;
429 const Point2D& startOfWays = W.getAirfoil(bou).startOfWays;
430
431
432 //
433 //if ((i==0) && (bou == 2))
434 //{
435 // for (int q = 0; q < W.getAirfoil(bou).possibleWays.size(); ++q)
436 // {
437 // std::cout << "Possible way #" << q << ": " << std::endl;
438 // for (size_t s = 0; s < W.getAirfoil(bou).possibleWays[q].size(); ++s)
439 // std::cout << W.getAirfoil(bou).possibleWays[q][s] << " ";
440 // std::cout << std::endl;
441 // }
442 //
443 // std::ofstream of(W.getPassport().dir + "ways2.txt");
444 // for (size_t q = 0; q < W.getAirfoil(bou).getNumberOfPanels(); ++q)
445 // {
446 // cPan = 0.5 * (W.getAirfoil(bou).getR(q) + W.getAirfoil(bou).getR(q + 1));
447
448 // alpha = 0.0;
449
450 // int way = W.getAirfoil(bou).wayToVertex[q];
451 // if (way == 0)
452 // of << q << " " << rcm[0] << " " << rcm[1] << " " << cPan[0] << " " << cPan[1] << std::endl;
453 // else
454 // {
455 // of << q << " " << rcm[0] << " " << rcm[1];
456 // for (int q = 0; q < W.getAirfoil(bou).possibleWays[way - 1].size() + 1; ++q)
457 // {
458 // Point2D start = ((q == 0) ? rcm : W.getAirfoil(bou).possibleWays[way - 1][q - 1]);
459 // Point2D finish = ((q == W.getAirfoil(bou).possibleWays[way - 1].size()) ? cPan : W.getAirfoil(bou).possibleWays[way - 1][q]);
460 // of << " " << finish[0] << " " << finish[1];
461 // }
462 // of << std::endl;
463 // }
464 // }
465 // of.close();
466 //}
467 //
468
469
470 for (size_t j = 0; j < W.getAirfoil(bou).getNumberOfPanels(); ++j)
471 {
472 cPan = 0.5 * (W.getAirfoil(bou).getR(j) + W.getAirfoil(bou).getR(j + 1));
473
474 alpha = 0.0;
475
476 int way = W.getAirfoil(bou).wayToVertex[j];
477 //if (way < 0)
478 // W.getInfo('i') << "Pressure computation is incorrect, way inside airfoil is undefined" << std::endl;
479
480 if (way == 0)
481 //alpha = atan2((cPan - pt) ^ (rcm - pt), (cPan - pt) & (rcm - pt));
482 alpha = atan2((cPan - pt) ^ (startOfWays - pt), (cPan - pt) & (startOfWays - pt));
483 else
484 if (way > 0)
485 {
486 for (int q = 0; q < W.getAirfoil(bou).possibleWays[way - 1].size() + 1; ++q)
487 {
488 Point2D start = ((q == 0) ? startOfWays : W.getAirfoil(bou).possibleWays[way - 1][q - 1]);
489 Point2D finish = ((q == W.getAirfoil(bou).possibleWays[way - 1].size()) ? cPan : W.getAirfoil(bou).possibleWays[way - 1][q]);
490 alpha += atan2((finish - pt) ^ (start - pt), (finish - pt) & (start - pt));
491 }
492 }
493
494
496 pressure[i] += IDPI * alpha * (W.getBoundary(bou).sheets.freeVortexSheet(j, 0) + W.getBoundary(bou).sheets.attachedVortexSheet(j, 0) - W.getBoundary(bou).oldSheets.attachedVortexSheet(j, 0)) * W.getAirfoil(bou).len[j] / dt;
497
498 pressure[i] -= IDPI * alpha * W.getAirfoil(bou).gammaThrough[j] / dt;
499
500 lambda = 0.5 * log((pt - cPan).length2());
501 pressure[i] -= IDPI * lambda * (W.getBoundary(bou).sheets.attachedSourceSheet(j, 0) - W.getBoundary(bou).oldSheets.attachedSourceSheet(j, 0)) * W.getAirfoil(bou).len[j] / dt;
502 }
503 }//for bou
504 }//for i
505
506 for (size_t i = 0; i < pressure.size(); ++i)
507 pressure[i] *= W.getPassport().physicalProperties.rho;
508
509 //std::cout << "!!!!!!!!!!\n";
510
511 W.getTimers().stop("VelPres");
512}//CalcPressure()
513
514
515//Расчет поля давления
516#ifdef USE_CUDA
517void MeasureVP::GPUCalcPressure()
518{
519 W.getTimers().start("VelPres");
520
521 //VMlib::vmTimer T1, T2, T3, T4, T5, T6, T7, T8;
522
523
524 //T1.start();
525 int addWSize = (int)wakeVP->vtx.size();
526 const Point2D& V0 = W.getV0();
527
528 cuCopyFixedArray(W.getWake().devVelPtr, W.getNonConstVelocity().wakeVortexesParams.convVelo.data(), 2 * sizeof(double) * W.getWake().vtx.size());
529 //W.getNonConstCuda().RefreshWake();
530
531 //T1.stop();
532
533 //T2.start();
534 size_t npnl = 0;
535 for (size_t q = 0; q < W.getNumberOfAirfoil(); ++q)
536 npnl += W.getAirfoil(q).getNumberOfPanels();
537
538 std::vector<double> oldAttVortexSheet, oldAttSourceSheet, gammaThroughIntensity;
539 oldAttVortexSheet.reserve(npnl);
540 oldAttSourceSheet.reserve(npnl);
541 gammaThroughIntensity.reserve(npnl);
542
543 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
544 for (size_t p = 0; p < W.getBoundary(bou).afl.getNumberOfPanels(); ++p)
545 {
546 oldAttVortexSheet.push_back(W.getBoundary(bou).oldSheets.attachedVortexSheet(p, 0));
547 oldAttSourceSheet.push_back(W.getBoundary(bou).oldSheets.attachedSourceSheet(p, 0));
548 gammaThroughIntensity.push_back(W.getAirfoil(bou).gammaThrough[p] / W.getAirfoil(bou).len[p]);
549 }
550 //T2.stop();
551
552
553 //T3.start();
554 double* devOldVortexSheet;
555 cudaMalloc(&devOldVortexSheet, npnl * sizeof(double));
556 cudaMemcpy(devOldVortexSheet, oldAttVortexSheet.data(), npnl * sizeof(double), cudaMemcpyHostToDevice);
557
558 double* devOldSourceSheet;
559 cudaMalloc(&devOldSourceSheet, npnl * sizeof(double));
560 cudaMemcpy(devOldSourceSheet, oldAttSourceSheet.data(), npnl * sizeof(double), cudaMemcpyHostToDevice);
561
562 double* devGammaThroughIntensity;
563 cudaMalloc(&devGammaThroughIntensity, npnl * sizeof(double));
564 cudaMemcpy(devGammaThroughIntensity, gammaThroughIntensity.data(), npnl * sizeof(double), cudaMemcpyHostToDevice);
565
566 double* devDiffVelo;
567 cudaMalloc(&devDiffVelo, W.getWake().vtx.size() * 2 * sizeof(double));
568 cudaMemcpy(devDiffVelo, W.getVelocity().wakeVortexesParams.diffVelo.data(), W.getWake().vtx.size() * 2 * sizeof(double), cudaMemcpyHostToDevice);
569 //T3.stop();
570
571 //T4.start();
572 std::vector<double> UVfast;
573 if (W.getPassport().numericalSchemes.velocityComputation.second == 0) //direct
574 {
575 cuCalculatePressure(addWSize, wakeVP->devVtxPtr,
576 W.getWake().vtx.size(), W.getWake().devVtxPtr, V0[0], V0[1], W.getWake().devVelPtr, devDiffVelo,
577 npnl, W.getAirfoil(0).devRPtr, W.getAirfoil(0).devFreeVortexSheetPtr, W.getAirfoil(0).devAttachedVortexSheetPtr, W.getAirfoil(0).devAttachedSourceSheetPtr,
578 devOldVortexSheet, devOldSourceSheet, devGammaThroughIntensity,
579 this->devPressurePtr, true, true);
580 }
581 else //fast
582 {
583 //VMlib::vmTimer F1, F2, F3, F4;
584
585 //F1.start();
586 cuCalculatePressure(addWSize, wakeVP->devVtxPtr,
587 W.getWake().vtx.size(), W.getWake().devVtxPtr, V0[0], V0[1], W.getWake().devVelPtr, devDiffVelo,
588 npnl, W.getAirfoil(0).devRPtr, W.getAirfoil(0).devFreeVortexSheetPtr, W.getAirfoil(0).devAttachedVortexSheetPtr, W.getAirfoil(0).devAttachedSourceSheetPtr,
589 devOldVortexSheet, devOldSourceSheet, devGammaThroughIntensity,
590 this->devPressurePtr, false, true);
591 //F1.stop();
592
593 UVfast.resize(addWSize);
594 if (W.getWake().vtx.size() > 0)
595 {
596 //F2.start();
597
598 double* gVx_dev;
599 double* gVy_dev;
600
601 cudaMalloc(&gVx_dev, W.getWake().vtx.size() * 4 * sizeof(double));
602 cudaMalloc(&gVy_dev, W.getWake().vtx.size() * 4 * sizeof(double));
603 cuCalcMulGammaVel(W.getWake().vtx.size(), W.getWake().devVtxPtr, V0[0], V0[1], W.getWake().devVelPtr, devDiffVelo, gVx_dev, gVy_dev);
604
605 //std::vector<Vortex2D> gVx(W.getWake().vtx.size()), gVy(W.getWake().vtx.size());
606 //#pragma omp parallel for
607 //for (int i = 0; i < (int)W.getWake().vtx.size(); ++i)
608 //{
609 // Point2D veloI = V0 + W.getVelocity().wakeVortexesParams.diffVelo[i] + W.getNonConstVelocity().wakeVortexesParams.convVelo[i];
610 // gVx[i].r() = gVy[i].r() = W.getWake().vtx[i].r();
611 // gVx[i].g() = W.getWake().vtx[i].g() * veloI[0];
612 // gVy[i].g() = W.getWake().vtx[i].g() * veloI[1];
613 // gVx[i].sigma() = gVy[i].sigma() = 0.0;
614 //}
615 //
616 //cudaMalloc(&gVx_dev, W.getWake().vtx.size() * 4 * sizeof(double));
617 //cudaMalloc(&gVy_dev, W.getWake().vtx.size() * 4 * sizeof(double));
618 //cudaMemcpy(gVx_dev, gVx.data(), W.getWake().vtx.size() * 4 * sizeof(double), cudaMemcpyHostToDevice);
619 //cudaMemcpy(gVy_dev, gVy.data(), W.getWake().vtx.size() * 4 * sizeof(double), cudaMemcpyHostToDevice);
620
621 //F2.stop();
622
623 //F3.start();
624 treeWakeX.MemoryAllocate((int)W.getCuda().n_CUDA_wake);
625 treeWakeY.MemoryAllocate((int)W.getCuda().n_CUDA_wake);
626 treeWakeX.Update((int)W.getWake().vtx.size(), gVx_dev);
627 treeWakeY.Update((int)W.getWake().vtx.size(), gVy_dev);
628
629 treeWakeX.Build();
630 treeWakeY.Build();
631
632 treeWakeX.UpwardTraversal(12);
633 treeWakeY.UpwardTraversal(12);
634
635 double* UVx_dev;
636 double* UVy_dev;
637 cudaMalloc(&UVx_dev, addWSize * 2 * sizeof(double));
638 cudaMalloc(&UVy_dev, addWSize * 2 * sizeof(double));
639 //F3.stop();
640
641 //F4.start();
642 treeWakeX.DownwardTraversalVorticesToPoints<32>(*W.getCuda().cntrTreeVP, (Point2D*)UVx_dev, nullptr, 1.0, 12, false, false);
643 treeWakeY.DownwardTraversalVorticesToPoints<32>(*W.getCuda().cntrTreeVP, (Point2D*)UVy_dev, nullptr, 1.0, 12, false, false);
644
645 std::vector<Point2D> UVx(addWSize), UVy(addWSize);
646 cudaMemcpy(UVx.data(), UVx_dev, addWSize * 2 * sizeof(double), cudaMemcpyDeviceToHost);
647 cudaMemcpy(UVy.data(), UVy_dev, addWSize * 2 * sizeof(double), cudaMemcpyDeviceToHost);
648
649#pragma omp parallel for
650 for (int i = 0; i < (int)addWSize; ++i)
651 UVfast[i] = UVx[i][0] + UVy[i][1];
652
653 cudaFree(gVx_dev);
654 cudaFree(gVy_dev);
655 cudaFree(UVx_dev);
656 cudaFree(UVy_dev);
657 //F4.stop();
658
659 //std::cout << "Trees: " << F1.duration() << " " << F2.duration() << " " << F3.duration() << " " << F4.duration() << "\n";
660 }
661 }
662 //T4.stop();
663
664
665 //T5.start();
666 cudaFree(devOldVortexSheet);
667 cudaFree(devOldSourceSheet);
668 cudaFree(devGammaThroughIntensity);
669 cudaFree(devDiffVelo);
670
671 std::vector<double> presGPU(addWSize);
672 cuCopyMemFromDev(presGPU.data(), this->devPressurePtr, addWSize * sizeof(double), 18);
673 if (UVfast.size() > 0)
674 {
675#pragma omp parallel for
676 for (int i = 0; i < (int)addWSize; ++i)
677 presGPU[i] += UVfast[i];
678 }
679
680 //T5.stop();
681
682 //printf("-------------------\n");
683
684 //T6.start();
685 pressure.resize(addWSize);
686
687 Point2D dri;
688 Point2D Vi;
689 Point2D vi;
690
691
692 const double& dt = W.getPassport().timeDiscretizationProperties.dt;
693
694 double P0 = /*1*/ 0.5 * V0.length2();
695
696 Point2D cPan;
697
698#pragma warning (push)
699#pragma warning (disable: 4101)
700 double alpha;
701 double lambda;
702 double dst2eps;
703#pragma warning (pop)
704
705 for (int i = 0; i < addWSize; ++i)
706 {
707 //if (fabs(pressure[i] - presGPU[i]) > 1e-5)
708 // printf("different pressure: %d, %f, %f\n", i, pressure[i], presGPU[i]);
709 pressure[i] = presGPU[i];
710 }
711 //T6.stop();
712
713 //T7.start();
714#pragma omp parallel for default(none) private(alpha, lambda, dri, Vi, vi, dst2eps, cPan) shared(P0, dt, V0, addWSize, std::cout, IDPI)
715 for (int i = 0; i < addWSize; ++i)
716 {
717 const Point2D& pt = wakeVP->vtx[i].r();
718 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
719 {
720 const Point2D& rcm = W.getAirfoil(bou).rcm;
721
722 for (size_t j = 0; j < W.getAirfoil(bou).getNumberOfPanels(); ++j)
723 {
724 cPan = 0.5 * (W.getAirfoil(bou).getR(j) + W.getAirfoil(bou).getR(j + 1));
725
726 alpha = 0.0;
727
728 int way = W.getAirfoil(bou).wayToVertex[j];
729 //if (way < 0)
730 // W.getInfo('i') << "Pressure computation is incorrect, way inside airfoil is undefined" << std::endl;
731
732 if (way == 0)
733 alpha = atan2((cPan - pt) ^ (W.getAirfoil(bou).startOfWays - pt), (cPan - pt) & (W.getAirfoil(bou).startOfWays - pt));
734 else
735 if (way > 0)
736 {
737 for (int q = 0; q < W.getAirfoil(bou).possibleWays[way - 1].size() + 1; ++q)
738 {
739 Point2D start = ((q == 0) ? W.getAirfoil(bou).startOfWays : W.getAirfoil(bou).possibleWays[way - 1][q - 1]);
740 Point2D finish = ((q == W.getAirfoil(bou).possibleWays[way - 1].size()) ? cPan : W.getAirfoil(bou).possibleWays[way - 1][q]);
741 alpha += atan2((finish - pt) ^ (start - pt), (finish - pt) & (start - pt));
742 }
743 }
744
746 pressure[i] += IDPI * alpha * (W.getBoundary(bou).sheets.freeVortexSheet(j, 0) + W.getBoundary(bou).sheets.attachedVortexSheet(j, 0) - W.getBoundary(bou).oldSheets.attachedVortexSheet(j, 0)) * W.getAirfoil(bou).len[j] / dt;
747
748 pressure[i] -= IDPI * alpha * W.getAirfoil(bou).gammaThrough[j] / dt;
749
750 lambda = 0.5 * log((pt - cPan).length2());
751 pressure[i] -= IDPI * lambda * (W.getBoundary(bou).sheets.attachedSourceSheet(j, 0) - W.getBoundary(bou).oldSheets.attachedSourceSheet(j, 0)) * W.getAirfoil(bou).len[j] / dt;
752 }
753 }//for bou
754 }//for i
755 //T7.stop();
756
757 //T8.start();
758 for (size_t i = 0; i < pressure.size(); ++i)
759 {
760 pressure[i] += P0 - 0.5 * velocity[i].length2(); //2;
761 pressure[i] *= W.getPassport().physicalProperties.rho;
762 }
763 //T8.stop();
764
765 //std::cout << "Calc: " << T1.duration() << " " << T2.duration() << " " << T3.duration() << " " << T4.duration() << " "
766 // << T5.duration() << " " << T6.duration() << " " << T7.duration() << " " << T8.duration() << "\n";
767
768 W.getTimers().stop("VelPres");
769}//GPUCalcPressure()
770#endif
771
772//Сохранение в файл вычисленных скоростей и давлений
774{
775 W.getTimers().start("Save");
776
777 double scaleV = 1.0, scaleP = 1.0;
778 if (W.getPassport().calcCoefficients)
779 {
780 const double& vRef = W.getPassport().physicalProperties.vRef;
781 scaleV = 1.0 / vRef;
782 scaleP = 1.0 / (0.5 * W.getPassport().physicalProperties.rho * sqr(vRef));
783 }
784
785
786 std::ofstream outfile;
787
788 VMlib::CreateUserDirectory(W.getPassport().dir, "velPres");
789 const size_t nRealPressurePoints = initialPoints.size() + historyPoints.size(); //число реальных точек - без учета тех, что для гидроупругости
790
791 if (W.getPassport().timeDiscretizationProperties.fileTypeVP.second == 0) //text format VTK
792 {
793 std::string fname = VMlib::fileNameStep("VelPres", W.getPassport().timeDiscretizationProperties.nameLength, W.getCurrentStep(), "vtk");
794 outfile.open(W.getPassport().dir + "velPres/" + fname);
795
796 outfile << "# vtk DataFile Version 2.0\n";
797 outfile << "VM2D VTK result: " << (W.getPassport().dir + "velPres/" + fname).c_str() << " saved " << VMlib::CurrentDataTime() << '\n';
798 outfile << "ASCII\n";
799 outfile << "DATASET UNSTRUCTURED_GRID\n";
800 outfile << "POINTS " << nRealPressurePoints << " float\n";
801
802 for (size_t i = 0; i < nRealPressurePoints; ++i)
803 {
804 double xi = (wakeVP->vtx[i].r())[0];
805 double yi = (wakeVP->vtx[i].r())[1];
806 outfile << xi << " " << yi << " " << "0.0\n";
807 }//for i
808
809 outfile << "CELLS " << nRealPressurePoints << " " << 2 * nRealPressurePoints << '\n';
810 for (size_t i = 0; i < nRealPressurePoints; ++i)
811 outfile << "1 " << i << '\n';
812
813 outfile << "CELL_TYPES " << nRealPressurePoints << '\n';
814 for (size_t i = 0; i < nRealPressurePoints; ++i)
815 outfile << "1\n";
816
817 outfile << '\n';
818 outfile << "POINT_DATA " << nRealPressurePoints << '\n';
819
820 if (!W.getPassport().calcCoefficients)
821 outfile << "VECTORS V float\n";
822 else
823 outfile << "VECTORS CV float\n";
824
825 for (size_t i = 0; i < nRealPressurePoints; ++i)
826 {
827 outfile << velocity[i][0] * scaleV << " " << velocity[i][1] * scaleV << " 0.0\n";
828 }//for i
829
830 outfile << '\n';
831
832 if (!W.getPassport().calcCoefficients)
833 outfile << "SCALARS P float 1\n";
834 else
835 outfile << "SCALARS CP float 1\n";
836
837 outfile << "LOOKUP_TABLE default\n";
838
839 for (size_t i = 0; i < nRealPressurePoints; ++i)
840 {
841 outfile << pressure[i] * scaleP << '\n';
842 }//for i
843
844 outfile.close();
845 }
846 else if (W.getPassport().timeDiscretizationProperties.fileTypeVP.second == 1) //binary format VTK
847 {
848 //Тест способа хранения чисел
849 uint16_t x = 0x0001;
850 bool littleEndian = (*((uint8_t*)&x));
851 const char eolnBIN[] = "\n";
852
853 std::string fname = VMlib::fileNameStep("VelPres", W.getPassport().timeDiscretizationProperties.nameLength, W.getCurrentStep(), "vtk");
854 outfile.open(W.getPassport().dir + "velPres/" + fname, std::ios::out | std::ios::binary);
855
856 outfile << "# vtk DataFile Version 3.0" << "\r\n" << "VM2D VTK result: " << (W.getPassport().dir + "velPres/" + fname).c_str() << " saved " << VMlib::CurrentDataTime() << eolnBIN;
857 outfile << "BINARY" << eolnBIN;
858 outfile << "DATASET UNSTRUCTURED_GRID" << eolnBIN << "POINTS " << nRealPressurePoints << " " << "float" << eolnBIN;
859
860
861 Eigen::VectorXf pData = Eigen::VectorXf::Zero(nRealPressurePoints);
862 Eigen::VectorXf vData = Eigen::VectorXf::Zero(nRealPressurePoints * 3);
863 Eigen::VectorXf rData = Eigen::VectorXf::Zero(nRealPressurePoints * 3);
864
865
866 for (size_t i = 0; i < nRealPressurePoints; ++i)
867 {
868 rData(3 * i + 0) = (float)(wakeVP->vtx[i].r())[0];
869 rData(3 * i + 1) = (float)(wakeVP->vtx[i].r())[1];
870 }//for i
871
872 for (size_t i = 0; i < nRealPressurePoints; ++i)
873 {
874 vData(3 * i + 0) = (float)(velocity[i][0] * scaleV);
875 vData(3 * i + 1) = (float)(velocity[i][1] * scaleV);
876 }//for i
877
878 for (size_t i = 0; i < nRealPressurePoints; ++i)
879 {
880 pData(i) = (float)(pressure[i] * scaleP);
881 }//for i
882
883 //POINTS
884 if (littleEndian)
885 for (int i = 0; i < nRealPressurePoints * 3; ++i)
886 VMlib::SwapEnd(rData(i));
887 outfile.write(reinterpret_cast<char*>(rData.data()), nRealPressurePoints * 3 * sizeof(float));
888
889 // CELLS
890 std::vector<int> cells(2 * nRealPressurePoints);
891 for (size_t i = 0; i < nRealPressurePoints; ++i)
892 {
893 cells[2 * i + 0] = 1;
894 cells[2 * i + 1] = (int)i;
895 }
896
897 std::vector<int> cellsTypes;
898 cellsTypes.resize(nRealPressurePoints, 1);
899
900 if (littleEndian)
901 {
902 for (int i = 0; i < nRealPressurePoints * 2; ++i)
903 VMlib::SwapEnd(cells[i]);
904
905 for (int i = 0; i < nRealPressurePoints; ++i)
906 VMlib::SwapEnd(cellsTypes[i]);
907 }
908
909 outfile << eolnBIN << "CELLS " << nRealPressurePoints << " " << nRealPressurePoints * 2 << eolnBIN;
910 outfile.write(reinterpret_cast<char*>(cells.data()), nRealPressurePoints * 2 * sizeof(int));
911 outfile << eolnBIN << "CELL_TYPES " << nRealPressurePoints << eolnBIN;
912 outfile.write(reinterpret_cast<char*>(cellsTypes.data()), nRealPressurePoints * sizeof(int));
913
914 //VECTORS V
915 if (littleEndian)
916 for (int i = 0; i < nRealPressurePoints * 3; ++i)
917 VMlib::SwapEnd(vData(i));
918
919 outfile << eolnBIN << "POINT_DATA " << nRealPressurePoints << eolnBIN;
920
921 if (!W.getPassport().calcCoefficients)
922 outfile << "VECTORS V " << "float" << eolnBIN;
923 else
924 outfile << "VECTORS CV " << "float" << eolnBIN;
925
926 outfile.write(reinterpret_cast<char*>(vData.data()), nRealPressurePoints * 3 * sizeof(float));
927
928 //SCALARS P
929 if (littleEndian)
930 for (int i = 0; i < nRealPressurePoints; ++i)
931 VMlib::SwapEnd(pData(i));
932
933 if (!W.getPassport().calcCoefficients)
934 outfile << eolnBIN << "SCALARS P " << "float" << " 1" << eolnBIN;
935 else
936 outfile << eolnBIN << "SCALARS CP " << "float" << " 1" << eolnBIN;
937
938 outfile << "LOOKUP_TABLE default" << eolnBIN;
939 outfile.write(reinterpret_cast<char*>(pData.data()), nRealPressurePoints * sizeof(float));
940
941 outfile << eolnBIN;
942
943 outfile.close();
944 }
945 else if (W.getPassport().timeDiscretizationProperties.fileTypeVP.second == 2) //csv
946 {
947 std::string fname = VMlib::fileNameStep("VelPres", W.getPassport().timeDiscretizationProperties.nameLength, W.getCurrentStep(), "csv");
948 outfile.open(W.getPassport().dir + "velPres/" + fname);
949
950 if (!W.getPassport().calcCoefficients)
951 outfile << "point,x,y,Vx,Vy,P\n";
952 else
953 outfile << "point,x,y,CVx,CVy,CP\n";
954
955 for (size_t i = 0; i < nRealPressurePoints; ++i)
956 {
957 double xi = (wakeVP->vtx[i].r())[0];
958 double yi = (wakeVP->vtx[i].r())[1];
959 outfile << i << "," << xi << "," << yi \
960 << "," << velocity[i][0] * scaleV << "," << velocity[i][1] * scaleV \
961 << "," << pressure[i] * scaleP << '\n';
962 }//for i
963 outfile.close();
964 }
965 else if (W.getPassport().timeDiscretizationProperties.fileTypeVP.second == 3) //csvBundle
966 {
967 std::string fnameBunCsv = W.getPassport().dir + "velPres/" + "velPresBundle.csv";
968 std::ofstream VPFileBunCsv(fnameBunCsv.c_str(), W.getCurrentStep() ? std::ios::app : std::ios::out);
969 {
970 if (W.getCurrentStep() == 0)
971 VPFileBunCsv << nRealPressurePoints << '\n';
972
973
974 for (size_t q = 0; q < nRealPressurePoints; ++q)
975 {
976 VPFileBunCsv << W.getCurrentStep() << "," \
977 << W.getCurrentTime() << "," \
978 << q << "," \
979 << wakeVP->vtx[q].r()[0] << "," << wakeVP->vtx[q].r()[1] << "," \
980 << velocity[q][0] * scaleV << "," << velocity[q][1] * scaleV << "," \
981 << pressure[q] * scaleP << '\n';
982 }
983 }
984
985 }
986
987
988 //Вывод в csv-файлы точек "historyPoints"
989 #pragma omp parallel for
990 for (int q = 0; q < (int)historyPoints.size(); ++q)
991 {
992
993 if (W.getCurrentStep() == 0)
994 {
995 std::string VPFileNameCsv;
996 VPFileNameCsv = W.getPassport().dir + "velPres/" + VMlib::fileNameStep("VP-atPoint-", 2, q, "csv");
997
998 std::ofstream VPFileCsv(VPFileNameCsv.c_str(), std::ios::out);
999
1000 if (!W.getPassport().calcCoefficients)
1001 VPFileCsv << "point,time,Vx,Vy,P\n";
1002 else
1003 VPFileCsv << "point,time,CVx,CVy,CP\n";
1004
1005 VPFileCsv.close();
1006 }
1007
1008 sstr[q] << q << "," << W.getCurrentTime() << ","
1009 << velocity[initialPoints.size() + q][0] * scaleV << ","
1010 << velocity[initialPoints.size() + q][1] * scaleV << ","
1011 << pressure[initialPoints.size() + q] * scaleP << '\n';
1012
1013 if (q == 0)
1014 sstrCounter += W.getPassport().timeDiscretizationProperties.saveVPstep;
1015 }
1016
1017 //Сохраняем буфера в файл рас в historyFrequency шагов
1019 {
1020 #pragma omp parallel for
1021 for (int q = 0; q < (int)historyPoints.size(); ++q)
1022 {
1023 std::string VPFileNameCsv;
1024 VPFileNameCsv = W.getPassport().dir + "velPres/" + VMlib::fileNameStep("VP-atPoint-", 2, q, "csv");
1025
1026 std::ofstream VPFileCsv(VPFileNameCsv.c_str(), std::ios::app);
1027
1028 VPFileCsv << sstr[q].str();
1029
1030 VPFileCsv.close();
1031
1032 sstr[q].str("");
1033 sstr[q].clear();
1034
1035
1036 if (q == 0)
1037 sstrCounter = 0;
1038 }
1039 }
1040
1041 W.getTimers().stop("Save");
1042}//SaveVP()
1043
1044std::vector<std::pair<Point2D, double>> MeasureVP::GetVPinElasticPoints()
1045{
1046 std::vector<std::pair<Point2D, double>> result;
1047 result.reserve(elasticPoints.size());
1048
1049 const size_t nRealPressurePoints = initialPoints.size() + historyPoints.size(); //число реальных точек - без учета тех, что для гидроупругости
1050
1051 for (size_t q = 0; q < elasticPoints.size(); ++q)
1052 result.push_back({ velocity[nRealPressurePoints + q], pressure[nRealPressurePoints + q] });
1053
1054 return result;
1055}
Заголовочный файл с описанием класса Airfoil.
Заголовочный файл с описанием класса Boundary.
Заголовочный файл с функциями для метода GMRES.
object_T
Definition Gpudefs.h:153
tree_T
Definition Gpudefs.h:146
@ vortex
Definition Gpudefs.h:149
scheme_T
Definition Gpudefs.h:158
@ noScheme
Definition Gpudefs.h:159
Заголовочный файл с описанием класса MeasureVP.
Заголовочный файл с описанием класса Mechanics.
Заголовочный файл с описанием класса MechanicsDeformable.
Заголовочный файл с описанием класса Preprocessor.
Заголовочный файл с описанием класса StreamParser.
const double PI
Число .
Definition defs.h:76
T sqr(T x)
Возведение числа в квадрат
Definition defs.h:463
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
const Point2D & getV(size_t q) const
Возврат константной ссылки на скорость вершины профиля
Definition Airfoil2D.h:137
std::vector< Point2D > tau
Касательные к панелям профиля
Definition Airfoil2D.h:91
size_t getNumberOfPanels() const
Возврат количества панелей на профиле
Definition Airfoil2D.h:163
Абстрактный класс, определяющий обтекаемый профиль
Definition Airfoil2D.h:182
std::vector< double > gammaThrough
Суммарные циркуляции вихрей, пересекших панели профиля на прошлом шаге
Definition Airfoil2D.h:277
Абстрактный класс, определяющий способ удовлетворения граничного условия на обтекаемом профиле
Definition Boundary2D.h:65
Sheet oldSheets
Слои на профиле с предыдущего шага
Definition Boundary2D.h:99
Sheet sheets
Слои на профиле
Definition Boundary2D.h:96
std::vector< Point2D > initialPoints
Точки, которые считываются из файла (давление пишется в vtk-файлы).
Definition MeasureVP2D.h:72
std::vector< double > pressure
Давление в нужных точках
void ReadPointsFromFile(const std::string &dir)
Чтение точек, в которых нужно посчитать давление и скорость
void SaveVP()
Сохранение в файл вычисленных скоростей и давлений
const World2D & W
Константная ссылка на решаемую задачу
std::vector< Point2D > historyPoints
Точки, которые считываются из файла (давление пишется в vtk и csv-файлы).
Definition MeasureVP2D.h:75
std::unique_ptr< WakeDataBase > wakeVP
Умный указатель на точки, в которых нужно вычислять в данный момент времени Хранятся в виде "мнимой" ...
Definition MeasureVP2D.h:94
std::vector< Point2D > elasticPoints
Точки, в которых давление нужно вычислять в служебных целях (для задач гидроупругости),...
Definition MeasureVP2D.h:89
std::vector< double > domainRadius
Радиусы вихрей в нужных точках
void Initialization()
Инициализация векторов для вычисления скоростей и давлений Вызывается только на тех шагах расчета,...
void SetPoints(const std::vector< Point2D > &points, const std::vector< Point2D > &history)
std::vector< std::pair< Point2D, double > > GetVPinElasticPoints()
Возврат давления в "гидроупругих" точках
void CalcPressure()
Расчет поля давления
MeasureVP(const World2D &W_)
Конструктор
std::vector< Point2D > velocity
Скорости в нужных точках
Definition MeasureVP2D.h:97
std::vector< std::ostringstream > sstr
Буферы для накопления временнОй истории сил в соответствующих точках
Definition MeasureVP2D.h:78
Класс, определяющий вид механической системы
std::vector< ChordPanel > chord
std::unique_ptr< Beam > beam
NumericalSchemes numericalSchemes
Структура с используемыми численными схемами
Definition Passport2D.h:310
const double & attachedVortexSheet(size_t n, size_t moment) const
Definition Sheet2D.h:105
const double & attachedSourceSheet(size_t n, size_t moment) const
Definition Sheet2D.h:110
const double & freeVortexSheet(size_t n, size_t moment) const
Definition Sheet2D.h:100
VortexesParams wakeVortexesParams
Струтура, определяющая параметры вихрей в следе
Definition Velocity2D.h:112
Класс, опеделяющий набор вихрей
std::vector< Vortex2D > vtx
Список вихревых элементов
Класс, опеделяющий текущую решаемую задачу
Definition World2D.h:77
size_t getNumberOfAirfoil() const
Возврат количества профилей в задаче
Definition World2D.h:180
const Wake & getWake() const
Возврат константной ссылки на вихревой след
Definition World2D.h:232
const Airfoil & getAirfoil(size_t i) const
Возврат константной ссылки на объект профиля
Definition World2D.h:163
Velocity & getNonConstVelocity() const
Возврат неконстантной ссылки на объект для вычисления скоростей
Definition World2D.h:258
VMlib::TimersGen & getTimers() const
Возврат ссылки на временную статистику выполнения шага расчета по времени
Definition World2D.h:288
Point2D getV0() const
Возврат текущей скорости набегающего потока
Definition World2D.h:148
const Velocity & getVelocity() const
Возврат константной ссылки на объект для вычисления скоростей
Definition World2D.h:253
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition World2D.h:263
const Boundary & getBoundary(size_t i) const
Возврат константной ссылки на объект граничного условия
Definition World2D.h:186
size_t getNumberOfBoundary() const
Возврат количества граничных условий в задаче
Definition World2D.h:197
Класс, позволяющий выполнять предварительную обработку файлов
Класс, позволяющий выполнять разбор файлов и строк с настройками и параметрами
bool get(const std::string &name, std::vector< Point2D > &res, const std::vector< Point2D > *defValue=nullptr, bool echoDefault=true) const
Считывание вектора из двумерных точек из базы данных
void start(const std::string &timerLabel)
Запуск счетчика
Definition TimesGen.cpp:55
Класс, опеделяющий двумерный вихревой элемент
Definition Vortex2D.h:59
HD double & sigma()
Функция для доступа к радиусу вихря
Definition Vortex2D.h:108
HD Point2D & r()
Функция для доступа к радиус-вектору вихря
Definition Vortex2D.h:92
HD double & g()
Функция для доступа к циркуляции вихря
Definition Vortex2D.h:100
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
void PrintHeaderToTextFile(std::ofstream &str, const std::string &header)
Формирование подзаголовка в текстовом файле вывода программы VM2D/VM3D.
Definition defs.cpp:175
void CreateUserDirectory(const std::string &dir, const std::string &name)
Создание каталога
Definition defs.h:447
double Lambda(const Point2D &p, const Point2D &s)
Вспомогательная функция вычисления логарифма отношения норм векторов
Definition defs.cpp:268
void PrintLogoToTextFile(std::ofstream &str, const std::string &fileName, const std::string &descr)
Формирование заголовка файла программы VM2D/VM3D.
Definition defs.cpp:139
std::string fileNameStep(const std::string &name, int length, size_t number, const std::string &ext)
Формирование имени файла
Definition defs.h:387
double boundDenom(double r2, double eps2)
Способ сглаживания скорости вихря (вихрь Рэнкина или вихрь Ламба).
Definition defs.h:577
double Alpha(const Point2D &p, const Point2D &s)
Вспомогательная функция вычисления угла между векторами
Definition defs.cpp:262
std::string CurrentDataTime()
Формирование строки с текущем временем и датой
Definition defs.cpp:47
void SwapEnd(T &var)
Вспомогательная функция перестановки байт местами (нужно для сохранения бинарных VTK).
Definition defs.h:569
const int defaultHistoryFrequency
Шаг сохранения буферов истории скорости и давления к контрольных точках в файл
Definition defs.h:114
std::pair< std::string, int > velocityComputation
Definition Passport2D.h:183
std::vector< Point2D > convVelo
Вектор конвективных скоростей вихрей
Definition Velocity2D.h:72
std::vector< Point2D > diffVelo
Вектор диффузионных скоростей вихрей
Definition Velocity2D.h:75