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
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
57using namespace VM2D;
58
59//Конструктор
61 : W(W_)
62{
63 sstrCounter = 0;
64 wakeVP.reset(new WakeDataBase(W_));
65};//MeasureVP(...)
66
67//Чтение точек, в которых нужно посчитать давление и скорость
68void MeasureVP::ReadPointsFromFile(const std::string& dir)
69{
70 std::string filename = dir + "pointsVP";
71 std::ifstream VPFile;
72
73 if (fileExistTest(filename, W.getInfo(), true, { "txt", "TXT" }))
74 {
75 std::stringstream VPFile(VMlib::Preprocessor(filename).resultString);
76
77 VMlib::StreamParser VPParser(W.getInfo(), "velocity & pressure parser", VPFile);
78
79 VPParser.get("points", initialPoints);
80 VPParser.get("history", historyPoints);
81
82 for (auto& pt : initialPoints)
83 pt = pt.rotated(-W.getPassport().rotateAngleVpPoints * PI / 180.0);
84
85 for (auto& pt : historyPoints)
86 pt = pt.rotated(-W.getPassport().rotateAngleVpPoints * PI / 180.0);
87
88
89 if (historyPoints.size() > 0)
90 {
91 sstr.resize(historyPoints.size());
92 sstrCounter = 0;
93
94 VMlib::CreateDirectory(dir, "velPres");
95 std::string VPFileNameList = W.getPassport().dir + "velPres/listPoints";
96 std::ofstream VPFileList(VPFileNameList.c_str());
97
98 VMlib::PrintLogoToTextFile(VPFileList, VPFileNameList.c_str(), "List of points, where velocity and pressure are measured in csv-files");
99
100 VMlib::PrintHeaderToTextFile(VPFileList, "No. FileName X Y");
101
102 for (size_t q = 0; q < historyPoints.size(); ++q)
103 {
104 VPFileList << '\n' << q << '\t' << VMlib::fileNameStep("VP-atPoint-", 2, q, "csv") << '\t' << historyPoints[q][0] << '\t' << historyPoints[q][1];
105
106 std::string VPFileNameCsv;
107 VPFileNameCsv = W.getPassport().dir + "velPres/" + VMlib::fileNameStep("VP-atPoint-", 2, q, "csv");
108
109 std::ofstream VPFileCsv(VPFileNameCsv.c_str());
110
112 VPFileCsv << "pt,t,Vx,Vy,p" << std::endl;
113 else
114 VPFileCsv << "pt,t,CVx,CVy,Cp" << std::endl;
115
116 VPFileCsv.close();
117 VPFileCsv.clear();
118 }
119
120 VPFileList.close();
121 VPFileList.clear();
122 }
123 }
124}//ReadPointsFromFile(...)
125
126//Чтение точек, в которых нужно посчитать давление и скорость
127void MeasureVP::SetPoints(const std::vector<Point2D>& points, const std::vector<Point2D>& history)
128{
129 initialPoints = points;
130 historyPoints = history;
131
132 sstr.resize(historyPoints.size());
133 sstrCounter = 0;
134
135 for (auto& pt : initialPoints)
136 pt = pt.rotated(-W.getPassport().rotateAngleVpPoints * PI / 180.0);
137
138 for (auto& pt : historyPoints)
139 pt = pt.rotated(-W.getPassport().rotateAngleVpPoints * PI / 180.0);
140
141
142 if (historyPoints.size() > 0)
143 {
145 std::string VPFileNameList = W.getPassport().dir + "velPres/listPoints";
146 std::ofstream VPFileList(VPFileNameList.c_str());
147
148 VMlib::PrintLogoToTextFile(VPFileList, VPFileNameList.c_str(), "List of points, where velocity and pressure are measured in csv-files");
149
150 VMlib::PrintHeaderToTextFile(VPFileList, "No. FileName X Y");
151
152 for (size_t q = 0; q < historyPoints.size(); ++q)
153 {
154 VPFileList << '\n' << q << '\t' << VMlib::fileNameStep("VP-atPoint-", 2, q, "csv") << '\t' << historyPoints[q][0] << '\t' << historyPoints[q][1];
155
156 std::string VPFileNameCsv;
157 VPFileNameCsv = W.getPassport().dir + "velPres/" + VMlib::fileNameStep("VP-atPoint-", 2, q, "csv");
158
159 std::ofstream VPFileCsv(VPFileNameCsv.c_str());
160
162 VPFileCsv << "pt,t,Vx,Vy,p" << std::endl;
163 else
164 VPFileCsv << "pt,t,CVx,CVy,Cp" << std::endl;
165
166 VPFileCsv.close();
167 VPFileCsv.clear();
168 }
169
170 VPFileList.close();
171 VPFileList.clear();
172 }
173}//SetPoints(...)
174
175
176// Инициализация векторов для вычисления скоростей и давлений
178{
179 W.getTimers().start("VelPres");
180
182 {
183 W.getInfo('i') << "Preparing VP points" << std::endl;
184
185 wakeVP->vtx.clear();
186 wakeVP->vtx.reserve(initialPoints.size() + historyPoints.size() + elasticPoints.size());
187
188 Vortex2D addvtx;
189
190 velocity.clear();
191 pressure.clear();
192 domainRadius.clear();
193
194 //отключаем проверку того, что точки расположены вне профиля
195 /*
196 //определяем точки, которые не находятся внутри профилей
197 bool inside;
198 for (size_t i = 0; i < initialPoints.size(); ++i)
199 {
200 inside = false;
201 for (size_t j = 0; j < W.getNumberOfAirfoil(); ++j)
202 {
203 if (W.getAirfoil(j).isInsideGabarits(initialPoints[i]) && W.getAirfoil(j).IsPointInAirfoil(initialPoints[i]))
204 {
205 inside = true;
206 break;
207 }
208 }
209 if (!inside)
210 {
211 addvtx.r() = initialPoints[i];
212 wakeVP.vtx.push_back(addvtx);
213 }
214 }
215 */
216
217 //добавляем все точки, а не только те, которые вне профиля
218 for (size_t i = 0; i < initialPoints.size(); ++i)
219 {
220 addvtx.r() = initialPoints[i];
221 wakeVP->vtx.push_back(addvtx);
222 }//for i
223
224 for (size_t i = 0; i < historyPoints.size(); ++i)
225 {
226 addvtx.r() = historyPoints[i];
227 wakeVP->vtx.push_back(addvtx);
228 }//for i
229
230
231 elasticPoints.clear();
232
233 for (size_t afl = 0; afl < W.getNumberOfAirfoil(); ++afl)
234 {
235 MechanicsDeformable* ptr = dynamic_cast<MechanicsDeformable*>(&(W.getNonConstMechanics(afl)));
236 if (ptr != nullptr)
237 {
238 if (afl > 0)
239 {
240 W.getInfo('e') << "Only airfoil 0 can be elastic!" << std::endl;
241 exit(-345);
242 }
243
244 if (ptr->beam->fsi) //turek
245 {
246 elasticPoints.reserve(ptr->chord.size() * 2);
247 for (size_t q = 0; q < ptr->chord.size(); ++q)
248 {
249 std::pair<size_t, size_t> pnls = ptr->chord[q].infPanels;
250 elasticPoints.push_back(
251 0.5 * (W.getAirfoil(afl).getR(pnls.first) + W.getAirfoil(afl).getR(pnls.first + 1))
252 + 0.01 * W.getAirfoil(afl).len[pnls.first] * W.getAirfoil(afl).nrm[pnls.first]
253 );
254
255 elasticPoints.push_back(
256 0.5 * (W.getAirfoil(afl).getR(pnls.second) + W.getAirfoil(afl).getR(pnls.second + 1))
257 + 0.01 * W.getAirfoil(afl).len[pnls.second] * W.getAirfoil(afl).nrm[pnls.second]
258 );
259 }
260
261 //std::ofstream elastPointsPositionsFile(W.getPassport().dir + "elastPointsPos.txt");
262 //for (size_t q = 0; q < elasticPoints.size(); ++q)
263 // elastPointsPositionsFile << elasticPoints[q][0] << " " << elasticPoints[q][1] << std::endl;
264 //elastPointsPositionsFile.close();
265 }
266 else //fish
267 {
269 for (size_t q = 0; q < W.getAirfoil(afl).getNumberOfPanels(); ++q)
270 elasticPoints.push_back(0.5 * (W.getAirfoil(afl).getR(q) + W.getAirfoil(afl).getR(q + 1)) + W.getAirfoil(afl).nrm[q] * 1e-4);
271 }
272 }
273 }
274
275
276 for (size_t i = 0; i < elasticPoints.size(); ++i)
277 {
278 addvtx.r() = elasticPoints[i];
279 wakeVP->vtx.push_back(addvtx);
280 }//for i
281
282 }
283 W.getTimers().stop("VelPres");
284
285}//Initialization()
286
287//Расчет поля давления
289{
290 W.getTimers().start("VelPres");
291
292 int addWSize = (int)wakeVP->vtx.size();
293 pressure.resize(addWSize);
294
295 Point2D dri;
296 Point2D Vi;
297 Point2D vi;
298
299 const Point2D& V0 = W.getV0();
300 const double& eps2 = W.getPassport().wakeDiscretizationProperties.eps2;
301 const double& dt = W.getPassport().timeDiscretizationProperties.dt;
302
303 double P0 = /*1*/ 0.5 * V0.length2();
304
305 Point2D cPan;
306
307#pragma warning (push)
308#pragma warning (disable: 4101)
309 double alpha;
310 double lambda;
311 double dst2eps;
312#pragma warning (pop)
313
314#pragma omp parallel for default(none) private(alpha, lambda, dri, Vi, vi, dst2eps, cPan) shared(P0, dt, eps2, V0, addWSize, std::cout, IDPI)
315 for (int i = 0; i < addWSize; ++i)
316 {
317 const Point2D& pt = wakeVP->vtx[i].r();
318
319 pressure[i] = P0;
320 pressure[i] -= 0.5 * velocity[i].length2(); //2
321
322 for (size_t j = 0; j < W.getWake().vtx.size(); ++j)
323 {
324 dri = pt - W.getWake().vtx[j].r();
326
327 dst2eps = VMlib::boundDenom(dri.length2(), eps2);
328
329 vi = IDPI * W.getWake().vtx[j].g() / dst2eps * dri.kcross();
330 pressure[i] += vi & Vi; //3
331 }
332
333 /*
334 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
335 for (size_t j = 0; j < W.getBoundary(bou).virtualWake.vtx.size(); ++j)
336 {
337 dri = pt - W.getBoundary(bou).virtualWake.vtx[j].r();
338
339 dst2eps = VMlib::boundDenom(dri.length2(), eps2);
340
341 Vi = W.getBoundary(bou).virtualWake.vecHalfGamma[j];
342 vi = IDPI * W.getBoundary(bou).virtualWake.vtx[j].g() / dst2eps * dri.kcross();
343
344 //pressure[i] += vi & Vi; //4
345 //if ((i==0) && (j==0))
346 // std::cout << "vi & Vi = " << (vi & Vi) << std::endl;
347 }
348 */
349
350 for (size_t q = 0; q < W.getNumberOfAirfoil(); ++q)
351 {
352 const Airfoil& afl = W.getAirfoil(q);
353 const Boundary& bou = W.getBoundary(q);
354
355 for (size_t pnl = 0; pnl < afl.getNumberOfPanels(); ++pnl)
356 {
357 Point2D s = pt - afl.getR(pnl);
358 Point2D p = pt - afl.getR(pnl + 1);
359 Point2D u0 = afl.tau[pnl];
360 double alpha = VMlib::Alpha(s, p);
361 double lambda = VMlib::Lambda(s, p);
362
363 Point2D skos = IDPI * ((alpha * u0).kcross() + (lambda * u0));
364
365
366 Vi = 0.5 * bou.sheets.freeVortexSheet(pnl, 0) * u0;
367 vi = skos.kcross() * bou.sheets.freeVortexSheet(pnl, 0);
368 //if ((i == 0) && (pnl == 0))
369 // std::cout << "vi & Vi = " << (vi & Vi) << std::endl;
370 pressure[i] += vi & Vi; //4
371
372 Vi = 0.5 * (afl.getV(pnl) + afl.getV(pnl + 1));
373 vi = skos.kcross() * (bou.sheets.attachedVortexSheet(pnl, 0) - bou.oldSheets.attachedVortexSheet(pnl, 0));
374 pressure[i] += vi & Vi; //4a
375
376 vi = skos * (bou.sheets.attachedSourceSheet(pnl, 0) - bou.oldSheets.attachedSourceSheet(pnl, 0));
377 pressure[i] += vi & Vi; //4b
378 }
379 }
380
381 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
382 {
383 const Point2D& rcm = W.getAirfoil(bou).rcm;
384
385
386 /*
387 if ((i==0) && (bou == 2))
388 {
389 for (int q = 0; q < W.getAirfoil(bou).possibleWays.size(); ++q)
390 {
391 std::cout << "Possible way #" << q << ": " << std::endl;
392 for (size_t s = 0; s < W.getAirfoil(bou).possibleWays[q].size(); ++s)
393 std::cout << W.getAirfoil(bou).possibleWays[q][s] << " ";
394 std::cout << std::endl;
395 }
396
397 std::ofstream of(W.getPassport().dir + "ways2.txt");
398 for (size_t q = 0; q < W.getAirfoil(bou).getNumberOfPanels(); ++q)
399 {
400 cPan = 0.5 * (W.getAirfoil(bou).getR(q) + W.getAirfoil(bou).getR(q + 1));
401
402 alpha = 0.0;
403
404 int way = W.getAirfoil(bou).wayToVertex[q];
405 if (way == 0)
406 of << q << " " << rcm[0] << " " << rcm[1] << " " << cPan[0] << " " << cPan[1] << std::endl;
407 else
408 {
409 of << q << " " << rcm[0] << " " << rcm[1];
410 for (int q = 0; q < W.getAirfoil(bou).possibleWays[way - 1].size() + 1; ++q)
411 {
412 Point2D start = ((q == 0) ? rcm : W.getAirfoil(bou).possibleWays[way - 1][q - 1]);
413 Point2D finish = ((q == W.getAirfoil(bou).possibleWays[way - 1].size()) ? cPan : W.getAirfoil(bou).possibleWays[way - 1][q]);
414 of << " " << finish[0] << " " << finish[1];
415 }
416 of << std::endl;
417 }
418 }
419 of.close();
420 }
421 */
422
423
424 for (size_t j = 0; j < W.getAirfoil(bou).getNumberOfPanels(); ++j)
425 {
426 cPan = 0.5 * (W.getAirfoil(bou).getR(j) + W.getAirfoil(bou).getR(j + 1));
427
428 alpha = 0.0;
429
430 int way = W.getAirfoil(bou).wayToVertex[j];
431 //if (way < 0)
432 // W.getInfo('i') << "Pressure computation is incorrect, way inside airfoil is undefined" << std::endl;
433
434 if (way == 0)
435 alpha = atan2((cPan - pt) ^ (rcm - pt), (cPan - pt) & (rcm - pt));
436 else
437 if (way > 0)
438 {
439 for (int q = 0; q < W.getAirfoil(bou).possibleWays[way - 1].size() + 1; ++q)
440 {
441 Point2D start = ((q == 0) ? rcm : W.getAirfoil(bou).possibleWays[way - 1][q-1]);
442 Point2D finish = ((q == W.getAirfoil(bou).possibleWays[way - 1].size()) ? cPan : W.getAirfoil(bou).possibleWays[way - 1][q]);
443 alpha += atan2((finish - pt) ^ (start - pt), (finish - pt) & (start - pt));
444 }
445 }
446
448 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;
449
450 pressure[i] -= IDPI * alpha * W.getAirfoil(bou).gammaThrough[j] / dt;
451
452 lambda = 0.5 * log((pt - cPan).length2());
453 pressure[i] -= IDPI * lambda * (W.getBoundary(bou).sheets.attachedSourceSheet(j, 0) - W.getBoundary(bou).oldSheets.attachedSourceSheet(j, 0)) * W.getAirfoil(bou).len[j] / dt;
454 }
455 }//for bou
456 }//for i
457
458 for (size_t i = 0; i < pressure.size(); ++i)
460
461 W.getTimers().stop("VelPres");
462}//CalcPressure()
463
464
465//Сохранение в файл вычисленных скоростей и давлений
467{
468 W.getTimers().start("Save");
469
470 double scaleV = 1.0, scaleP = 1.0;
472 {
473 const double& vRef = W.getPassport().physicalProperties.vRef;
474 scaleV = 1.0 / vRef;
475 scaleP = 1.0 / (0.5 * W.getPassport().physicalProperties.rho * sqr(vRef));
476 }
477
478
479 std::ofstream outfile;
480
482 const size_t nRealPressurePoints = initialPoints.size() + historyPoints.size(); //число реальных точек - без учета тех, что для гидроупругости
483
484 if (W.getPassport().timeDiscretizationProperties.fileTypeVP.second == 0) //text format VTK
485 {
486 std::string fname = VMlib::fileNameStep("VelPres", W.getPassport().timeDiscretizationProperties.nameLength, W.getCurrentStep(), "vtk");
487 outfile.open(W.getPassport().dir + "velPres/" + fname);
488
489 outfile << "# vtk DataFile Version 2.0\n";
490 outfile << "VM2D VTK result: " << (W.getPassport().dir + "velPres/" + fname).c_str() << " saved " << VMlib::CurrentDataTime() << '\n';
491 outfile << "ASCII\n";
492 outfile << "DATASET UNSTRUCTURED_GRID\n";
493 outfile << "POINTS " << nRealPressurePoints << " float\n";
494
495 for (size_t i = 0; i < nRealPressurePoints; ++i)
496 {
497 double xi = (wakeVP->vtx[i].r())[0];
498 double yi = (wakeVP->vtx[i].r())[1];
499 outfile << xi << " " << yi << " " << "0.0\n";
500 }//for i
501
502 outfile << "CELLS " << nRealPressurePoints << " " << 2 * nRealPressurePoints << '\n';
503 for (size_t i = 0; i < nRealPressurePoints; ++i)
504 outfile << "1 " << i << '\n';
505
506 outfile << "CELL_TYPES " << nRealPressurePoints << '\n';
507 for (size_t i = 0; i < nRealPressurePoints; ++i)
508 outfile << "1\n";
509
510 outfile << '\n';
511 outfile << "POINT_DATA " << nRealPressurePoints << '\n';
512
514 outfile << "VECTORS V float\n";
515 else
516 outfile << "VECTORS CV float\n";
517
518 for (size_t i = 0; i < nRealPressurePoints; ++i)
519 {
520 outfile << velocity[i][0] * scaleV << " " << velocity[i][1] * scaleV << " 0.0\n";
521 }//for i
522
523 outfile << '\n';
524
526 outfile << "SCALARS P float 1\n";
527 else
528 outfile << "SCALARS CP float 1\n";
529
530 outfile << "LOOKUP_TABLE default\n";
531
532 for (size_t i = 0; i < nRealPressurePoints; ++i)
533 {
534 outfile << pressure[i] * scaleP << '\n';
535 }//for i
536
537 outfile.close();
538 }
539 else if (W.getPassport().timeDiscretizationProperties.fileTypeVP.second == 1) //binary format VTK
540 {
541 //Тест способа хранения чисел
542 uint16_t x = 0x0001;
543 bool littleEndian = (*((uint8_t*)&x));
544 const char eolnBIN[] = "\n";
545
546 std::string fname = VMlib::fileNameStep("VelPres", W.getPassport().timeDiscretizationProperties.nameLength, W.getCurrentStep(), "vtk");
547 outfile.open(W.getPassport().dir + "velPres/" + fname, std::ios::out | std::ios::binary);
548
549 outfile << "# vtk DataFile Version 3.0" << "\r\n" << "VM2D VTK result: " << (W.getPassport().dir + "velPres/" + fname).c_str() << " saved " << VMlib::CurrentDataTime() << eolnBIN;
550 outfile << "BINARY" << eolnBIN;
551 outfile << "DATASET UNSTRUCTURED_GRID" << eolnBIN << "POINTS " << nRealPressurePoints << " " << "float" << eolnBIN;
552
553
554 Eigen::VectorXf pData = Eigen::VectorXf::Zero(nRealPressurePoints);
555 Eigen::VectorXf vData = Eigen::VectorXf::Zero(nRealPressurePoints * 3);
556 Eigen::VectorXf rData = Eigen::VectorXf::Zero(nRealPressurePoints * 3);
557
558
559 for (size_t i = 0; i < nRealPressurePoints; ++i)
560 {
561 rData(3 * i + 0) = (float)(wakeVP->vtx[i].r())[0];
562 rData(3 * i + 1) = (float)(wakeVP->vtx[i].r())[1];
563 }//for i
564
565 for (size_t i = 0; i < nRealPressurePoints; ++i)
566 {
567 vData(3 * i + 0) = (float)(velocity[i][0] * scaleV);
568 vData(3 * i + 1) = (float)(velocity[i][1] * scaleV);
569 }//for i
570
571 for (size_t i = 0; i < nRealPressurePoints; ++i)
572 {
573 pData(i) = (float)(pressure[i] * scaleP);
574 }//for i
575
576 //POINTS
577 if (littleEndian)
578 for (int i = 0; i < nRealPressurePoints * 3; ++i)
579 VMlib::SwapEnd(rData(i));
580 outfile.write(reinterpret_cast<char*>(rData.data()), nRealPressurePoints * 3 * sizeof(float));
581
582 // CELLS
583 std::vector<int> cells(2 * nRealPressurePoints);
584 for (size_t i = 0; i < nRealPressurePoints; ++i)
585 {
586 cells[2 * i + 0] = 1;
587 cells[2 * i + 1] = (int)i;
588 }
589
590 std::vector<int> cellsTypes;
591 cellsTypes.resize(nRealPressurePoints, 1);
592
593 if (littleEndian)
594 {
595 for (int i = 0; i < nRealPressurePoints * 2; ++i)
596 VMlib::SwapEnd(cells[i]);
597
598 for (int i = 0; i < nRealPressurePoints; ++i)
599 VMlib::SwapEnd(cellsTypes[i]);
600 }
601
602 outfile << eolnBIN << "CELLS " << nRealPressurePoints << " " << nRealPressurePoints * 2 << eolnBIN;
603 outfile.write(reinterpret_cast<char*>(cells.data()), nRealPressurePoints * 2 * sizeof(int));
604 outfile << eolnBIN << "CELL_TYPES " << nRealPressurePoints << eolnBIN;
605 outfile.write(reinterpret_cast<char*>(cellsTypes.data()), nRealPressurePoints * sizeof(int));
606
607 //VECTORS V
608 if (littleEndian)
609 for (int i = 0; i < nRealPressurePoints * 3; ++i)
610 VMlib::SwapEnd(vData(i));
611
612 outfile << eolnBIN << "POINT_DATA " << nRealPressurePoints << eolnBIN;
613
615 outfile << "VECTORS V " << "float" << eolnBIN;
616 else
617 outfile << "VECTORS CV " << "float" << eolnBIN;
618
619 outfile.write(reinterpret_cast<char*>(vData.data()), nRealPressurePoints * 3 * sizeof(float));
620
621 //SCALARS P
622 if (littleEndian)
623 for (int i = 0; i < nRealPressurePoints; ++i)
624 VMlib::SwapEnd(pData(i));
625
627 outfile << eolnBIN << "SCALARS P " << "float" << " 1" << eolnBIN;
628 else
629 outfile << eolnBIN << "SCALARS CP " << "float" << " 1" << eolnBIN;
630
631 outfile << "LOOKUP_TABLE default" << eolnBIN;
632 outfile.write(reinterpret_cast<char*>(pData.data()), nRealPressurePoints * sizeof(float));
633
634 outfile << eolnBIN;
635
636 outfile.close();
637 }
638 else if (W.getPassport().timeDiscretizationProperties.fileTypeVP.second == 2) //csv
639 {
640 std::string fname = VMlib::fileNameStep("VelPres", W.getPassport().timeDiscretizationProperties.nameLength, W.getCurrentStep(), "csv");
641 outfile.open(W.getPassport().dir + "velPres/" + fname);
642
644 outfile << "point,x,y,Vx,Vy,P\n";
645 else
646 outfile << "point,x,y,CVx,CVy,CP\n";
647
648 for (size_t i = 0; i < nRealPressurePoints; ++i)
649 {
650 double xi = (wakeVP->vtx[i].r())[0];
651 double yi = (wakeVP->vtx[i].r())[1];
652 outfile << i << "," << xi << "," << yi \
653 << "," << velocity[i][0] * scaleV << "," << velocity[i][1] * scaleV \
654 << "," << pressure[i] * scaleP << '\n';
655 }//for i
656 outfile.close();
657 }
658 else if (W.getPassport().timeDiscretizationProperties.fileTypeVP.second == 3) //csvBundle
659 {
660 std::string fnameBunCsv = W.getPassport().dir + "velPres/" + "velPresBundle.csv";
661 std::ofstream VPFileBunCsv(fnameBunCsv.c_str(), W.getCurrentStep() ? std::ios::app : std::ios::out);
662 {
663 if (W.getCurrentStep() == 0)
664 VPFileBunCsv << nRealPressurePoints << '\n';
665
666
667 for (size_t q = 0; q < nRealPressurePoints; ++q)
668 {
669 VPFileBunCsv << W.getCurrentStep() << "," \
670 << W.getCurrentTime() << "," \
671 << q << "," \
672 << wakeVP->vtx[q].r()[0] << "," << wakeVP->vtx[q].r()[1] << "," \
673 << velocity[q][0] * scaleV << "," << velocity[q][1] * scaleV << "," \
674 << pressure[q] * scaleP << '\n';
675 }
676 }
677
678 }
679
680
681 //Вывод в csv-файлы точек "historyPoints"
682 #pragma omp parallel for
683 for (int q = 0; q < (int)historyPoints.size(); ++q)
684 {
685
686 if (W.getCurrentStep() == 0)
687 {
688 std::string VPFileNameCsv;
689 VPFileNameCsv = W.getPassport().dir + "velPres/" + VMlib::fileNameStep("VP-atPoint-", 2, q, "csv");
690
691 std::ofstream VPFileCsv(VPFileNameCsv.c_str(), W.getCurrentStep() ? std::ios::app : std::ios::out);
692
694 VPFileCsv << "point,time,Vx,Vy,P\n";
695 else
696 VPFileCsv << "point,time,CVx,CVy,CP\n";
697
698 VPFileCsv.close();
699 }
700
701 sstr[q] << q << "," << W.getCurrentTime() << ","
702 << velocity[initialPoints.size() + q][0] * scaleV << ","
703 << velocity[initialPoints.size() + q][1] * scaleV << ","
704 << pressure[initialPoints.size() + q] * scaleP << '\n';
705
706 if (q == 0)
707 ++sstrCounter;
708 }
709
710 if (sstrCounter == 100)
711 {
712 #pragma omp parallel for
713 for (int q = 0; q < (int)historyPoints.size(); ++q)
714 {
715 std::string VPFileNameCsv;
716 VPFileNameCsv = W.getPassport().dir + "velPres/" + VMlib::fileNameStep("VP-atPoint-", 2, q, "csv");
717
718 std::ofstream VPFileCsv(VPFileNameCsv.c_str(), W.getCurrentStep() ? std::ios::app : std::ios::out);
719
720 VPFileCsv << sstr[q].str();
721
722 VPFileCsv.close();
723
724 sstr[q].str("");
725 sstr[q].clear();
726
727
728 if (q == 0)
729 sstrCounter = 0;
730 }
731 }
732
733 W.getTimers().stop("Save");
734}//SaveVP()
735
736std::vector<std::pair<Point2D, double>> MeasureVP::GetVPinElasticPoints()
737{
738 std::vector<std::pair<Point2D, double>> result;
739 result.reserve(elasticPoints.size());
740
741 const size_t nRealPressurePoints = initialPoints.size() + historyPoints.size(); //число реальных точек - без учета тех, что для гидроупругости
742
743 for (size_t q = 0; q < elasticPoints.size(); ++q)
744 result.push_back({ velocity[nRealPressurePoints + q], pressure[nRealPressurePoints + q] });
745
746 return result;
747}
Заголовочный файл с описанием класса Airfoil.
Заголовочный файл с описанием класса Boundary.
Заголовочный файл с описанием класса MeasureVP.
Заголовочный файл с описанием класса Mechanics.
Заголовочный файл с описанием класса MechanicsDeformable.
Заголовочный файл с описанием класса Preprocessor.
Заголовочный файл с описанием класса StreamParser.
Заголовочный файл с описанием класса 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 > nrm
Нормали к панелям профиля
Definition Airfoil2D.h:81
std::vector< Point2D > tau
Касательные к панелям профиля
Definition Airfoil2D.h:91
Point2D rcm
Положение центра масс профиля
Definition Airfoil2D.h:97
size_t getNumberOfPanels() const
Возврат количества панелей на профиле
Definition Airfoil2D.h:163
Абстрактный класс, определяющий обтекаемый профиль
Definition Airfoil2D.h:182
std::vector< double > gammaThrough
Суммарные циркуляции вихрей, пересекших панели профиля на прошлом шаге
Definition Airfoil2D.h:276
std::vector< int > wayToVertex
Номера путей к вершинам
Definition Airfoil2D.h:202
std::vector< std::vector< Point2D > > possibleWays
Возможные пути внутри профиля от точки (0, 0) к центрам всех панелей
Definition Airfoil2D.h:199
Абстрактный класс, определяющий способ удовлетворения граничного условия на обтекаемом профиле
Definition Boundary2D.h:65
Sheet oldSheets
Слои на профиле с предыдущего шага
Definition Boundary2D.h:99
Sheet sheets
Слои на профиле
Definition Boundary2D.h:96
std::vector< Point2D > initialPoints
Точки, которые считываются из файла (давление пишется в vtk-файлы)
Definition MeasureVP2D.h:68
std::vector< double > pressure
Давление в нужных точках
Definition MeasureVP2D.h:93
void ReadPointsFromFile(const std::string &dir)
Чтение точек, в которых нужно посчитать давление и скорость
void SaveVP()
Сохранение в файл вычисленных скоростей и давлений
const World2D & W
Константная ссылка на решаемую задачу
std::vector< Point2D > historyPoints
Точки, которые считываются из файла (давление пишется в vtk и csv-файлы)
Definition MeasureVP2D.h:71
std::unique_ptr< WakeDataBase > wakeVP
Умный указатель на точки, в которых нужно вычислять в данный момент времени Хранятся в виде "мнимой" ...
Definition MeasureVP2D.h:84
std::vector< Point2D > elasticPoints
Точки, в которых давление нужно вычислять в служебных целях (для задач гидроупругости),...
Definition MeasureVP2D.h:79
std::vector< double > domainRadius
Радиусы вихрей в нужных точках
Definition MeasureVP2D.h:90
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:87
std::vector< std::ostringstream > sstr
Definition MeasureVP2D.h:73
Класс, определяющий вид механической системы
std::vector< ChordPanel > chord
std::unique_ptr< Beam > beam
PhysicalProperties physicalProperties
Структура с физическими свойствами задачи
Definition Passport2D.h:289
bool calcCoefficients
Признак вычисления коэффициентов вместо сил
Definition Passport2D.h:282
double rotateAngleVpPoints
Угол поворота точек VP.
Definition Passport2D.h:285
WakeDiscretizationProperties wakeDiscretizationProperties
Структура с параметрами дискретизации вихревого следа
Definition Passport2D.h:292
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:74
size_t getNumberOfAirfoil() const
Возврат количества профилей в задаче
Definition World2D.h:174
const Wake & getWake() const
Возврат константной ссылки на вихревой след
Definition World2D.h:226
const Airfoil & getAirfoil(size_t i) const
Возврат константной ссылки на объект профиля
Definition World2D.h:157
VMlib::TimersGen & getTimers() const
Возврат ссылки на временную статистику выполнения шага расчета по времени
Definition World2D.h:276
Point2D getV0() const
Возврат текущей скорости набегающего потока
Definition World2D.h:142
const Velocity & getVelocity() const
Возврат константной ссылки на объект для вычисления скоростей
Definition World2D.h:241
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition World2D.h:251
const Boundary & getBoundary(size_t i) const
Возврат константной ссылки на объект граничного условия
Definition World2D.h:180
size_t getNumberOfBoundary() const
Возврат количества граничных условий в задаче
Definition World2D.h:191
Mechanics & getNonConstMechanics(size_t i) const
Возврат неконстантной ссылки на объект механики
Definition World2D.h:219
TimeDiscretizationProperties timeDiscretizationProperties
Структура с параметрами процесса интегрирования по времени
std::string dir
Рабочий каталог задачи
Класс, позволяющий выполнять предварительную обработку файлов
Класс, позволяющий выполнять разбор файлов и строк с настройками и параметрами
bool get(const std::string &name, std::vector< Point2D > &res, const std::vector< Point2D > *defValue=nullptr, bool echoDefault=true) const
Считывание вектора из двумерных точек из базы данных
void stop(const std::string &timerLabel)
Останов счетчика
Definition TimesGen.cpp:68
void start(const std::string &timerLabel)
Запуск счетчика
Definition TimesGen.cpp:55
Класс, опеделяющий двумерный вихревой элемент
Definition Vortex2D.h:59
HD Point2D & r()
Функция для доступа к радиус-вектору вихря
Definition Vortex2D.h:87
VMlib::LogStream & getInfo() const
Возврат ссылки на объект LogStream Используется в техничеcких целях для организации вывода
Definition WorldGen.h:82
double getCurrentTime() const
Definition WorldGen.h:100
size_t getCurrentStep() const
Возврат константной ссылки на параметры распараллеливания по MPI.
Definition WorldGen.h:99
numvector< T, 2 > kcross() const
Геометрический поворот двумерного вектора на 90 градусов
Definition numvector.h:510
auto length2() const -> typename std::remove_const< typename std::remove_reference< decltype(this->data[0])>::type >::type
Вычисление квадрата нормы (длины) вектора
Definition numvector.h:386
const double PI
Число .
Definition defs.h:82
const double IDPI
Число .
Definition defs.h:85
void PrintHeaderToTextFile(std::ofstream &str, const std::string &header)
Формирование подзаголовка в текстовом файле вывода программы VM2D/VM3D.
Definition defs.cpp:175
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:381
void CreateDirectory(const std::string &dir, const std::string &name)
Создание каталога
Definition defs.h:441
double boundDenom(double r2, double eps2)
Способ сглаживания скорости вихря (вихрь Рэнкина или вихрь Ламба)
Definition defs.h:563
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:555
double vRef
Референсная скорость
Definition Passport2D.h:81
double rho
Плотность потока
Definition Passport2D.h:75
std::vector< Point2D > convVelo
Вектор конвективных скоростей вихрей
Definition Velocity2D.h:72
double eps2
Квадрат радиуса вихря
Definition Passport2D.h:129
double dt
Шаг по времени
Definition PassportGen.h:67
int saveVPstep
Шаг вычисления и сохранения скорости и давления
Definition PassportGen.h:80
int nameLength
Число разрядов в имени файла
Definition PassportGen.h:70
std::pair< std::string, int > fileTypeVP
Тип файлов для сохранения скорости и давления
Definition PassportGen.h:78