VM2D  1.12
Vortex methods for 2D flows simulation
Velocity2D.cpp
Go to the documentation of this file.
1 /*--------------------------------*- VM2D -*-----------------*---------------*\
2 | ## ## ## ## #### ##### | | Version 1.12 |
3 | ## ## ### ### ## ## ## ## | VM2D: Vortex Method | 2024/01/14 |
4 | ## ## ## # ## ## ## ## | for 2D Flow Simulation *----------------*
5 | #### ## ## ## ## ## | Open Source Code |
6 | ## ## ## ###### ##### | https://www.github.com/vortexmethods/VM2D |
7 | |
8 | Copyright (C) 2017-2024 I. Marchevsky, K. Sokol, E. Ryatina, A. Kolganova |
9 *-----------------------------------------------------------------------------*
10 | File name: Velocity2D.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 #include "Velocity2D.h"
41 
42 #include "Airfoil2D.h"
43 #include "Boundary2D.h"
44 #include "MeasureVP2D.h"
45 #include "Mechanics2D.h"
46 #include "StreamParser.h"
47 #include "Wake2D.h"
48 #include "WakeDataBase2D.h"
49 #include "World2D.h"
50 #include "Passport2D.h"
51 
52 
53 using namespace VM2D;
54 
55 //Вычисление диффузионных скоростей вихрей и виртуальных вихрей в вихревом следе
57 {
58  // !!! пелена на пелену
59 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_I1I2))
61  {
62  double tt1 = omp_get_wtime();
63  //GPUCalcDiffVeloI1I2ToSetOfPointsFromWake(W.getWake(), wakeVortexesParams.epsastWake, W.getWake(), wakeVortexesParams.I1, wakeVortexesParams.I2);
65  double tt2 = omp_get_wtime();
66 
67  //W.getInfo('t') << "Diffusive velocities time = " << int(((tt2 - tt1) * 1000) * 10) / 10.0 << " ms, bodies = " << W.getWake().vtx.size() << std::endl;
68  //W.getInfo('t') << "I12_wake->wake = " << (tt2 - tt1) << std::endl;
69 
70  }
71  else
73 #else
75 #endif
76 
77 
78  for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
79  {
80  //не нужно, т.к. сделано выше перед началом вычисления скоростей
81  //W.getNonConstBoundary(bou).virtualWake.WakeSynchronize();
82 
83 
84  //виртуальные на границе на след
85 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_I1I2))
87  {
88  double tt1 = omp_get_wtime();
89  GPUCalcDiffVeloI1I2ToSetOfPointsFromSheets(W.getWake(), wakeVortexesParams.epsastWake, W.getBoundary(bou), wakeVortexesParams.I1, wakeVortexesParams.I2);
90  double tt2 = omp_get_wtime();
91  //W.getInfo('t') << "I12_layer->wake = " << (tt2 - tt1) << std::endl;
92  }
93  else
95 #else
97 #endif
98 
99  // !!! след на виртуальные
100 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_I1I2))
101  {
102  double tt1 = omp_get_wtime();
103  GPUCalcDiffVeloI1I2ToSetOfPointsFromWake(W.getBoundary(bou).virtualWake, virtualVortexesParams[bou].epsastWake, W.getWake(), virtualVortexesParams[bou].I1, virtualVortexesParams[bou].I2);
104  double tt2 = omp_get_wtime();
105  //W.getInfo('t') << "I12_wake->layer = " << (tt2 - tt1) << std::endl;
106  }
107 #else
109 #endif
110  for (size_t targetBou = 0; targetBou < W.getNumberOfBoundary(); ++targetBou)
111  {
112  // виртуальные на виртуальные
113 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_I1I2))
114  {
115  double tt1 = omp_get_wtime();
116  GPUCalcDiffVeloI1I2ToSetOfPointsFromSheets(W.getBoundary(targetBou).virtualWake, virtualVortexesParams[targetBou].epsastWake, W.getBoundary(bou), virtualVortexesParams[targetBou].I1, virtualVortexesParams[targetBou].I2);
117  double tt2 = omp_get_wtime();
118  //W.getInfo('t') << "I12_layer->layer = " << (tt2 - tt1) << std::endl;
119  }
120 #else
122 #endif
123  }
124 
125  } //for bou
126 
127 
128  double tDivstart, tDivfinish;
129 
130  Point2D I2;
131  double I1;
132 
133  tDivstart = omp_get_wtime();
134 
135 #pragma omp parallel for private(I1, I2)
136  for (int vt = 0; vt < (int)wakeVortexesParams.diffVelo.size(); ++vt)
137  {
138  I2 = wakeVortexesParams.I2[vt];
139  I1 = wakeVortexesParams.I1[vt];
140  if (fabs(I1) < 1.e-8)
141  wakeVortexesParams.diffVelo[vt] = { 0.0, 0.0 };
142  else
144  }
145 
146  for (size_t targetBou = 0; targetBou < W.getNumberOfBoundary(); ++targetBou)
147 #pragma omp parallel for private(I1, I2)
148  for (int vt = 0; vt < (int)virtualVortexesParams[targetBou].diffVelo.size(); ++vt)
149  {
150  I2 = virtualVortexesParams[targetBou].I2[vt];
151  I1 = virtualVortexesParams[targetBou].I1[vt];
152 
153  if (fabs(I1) < 1.e-8)
154  virtualVortexesParams[targetBou].diffVelo[vt] = { 0.0, 0.0 };
155  else
156  virtualVortexesParams[targetBou].diffVelo[vt] = I2 * (1.0 / (I1 * std::max(virtualVortexesParams[targetBou].epsastWake[vt], W.getPassport().wakeDiscretizationProperties.getMinEpsAst())));
157  }
158 
159  tDivfinish = omp_get_wtime();
160  //W.getInfo('t') << "I12_Div = " << (tDivfinish - tDivstart) << std::endl;
161 
162 }//CalcDiffVeloI1I2()
163 
164 
166 {
167  for (size_t afl = 0; afl < W.getNumberOfAirfoil(); ++afl)
168  {
169 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_I0I3))
171  {
172  double tt1 = omp_get_wtime();
173  W.getNonConstAirfoil(afl).GPUGetDiffVelocityI0I3ToSetOfPointsAndViscousStresses(W.getWake(), wakeVortexesParams.epsastWake, wakeVortexesParams.I0, wakeVortexesParams.I3);
174  double tt2 = omp_get_wtime();
175  //W.getInfo('t') << "I03_bou->wake = " << (tt2 - tt1) << std::endl;
176  }
177  else
179 #else
181 #endif
182  }
183 
184  //Порядок циклов именно такой, т.к. CUDA оптимизирует вызов ядер,
185  //и на один "слой" виртуальных вихрей считается влияние сразу от всех профилей
186  for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
187  {
188  for (size_t afl = 0; afl < W.getNumberOfAirfoil(); ++afl)
189 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_I0I3))
190  {
191  double tt1 = omp_get_wtime();
192  W.getNonConstAirfoil(afl).GPUGetDiffVelocityI0I3ToSetOfPointsAndViscousStresses(W.getBoundary(bou).virtualWake, virtualVortexesParams[bou].epsastWake, virtualVortexesParams[bou].I0, virtualVortexesParams[bou].I3);
193  double tt2 = omp_get_wtime();
194  //W.getInfo('t') << "I03_bou->layer = " << (tt2 - tt1) << std::endl;
195  }
196 #else
198 #endif
199  }
200  //влияние поверхности
201  Point2D I3;
202  double I0;
203 
204  double domrad = 0.0;
205 
206 #pragma omp parallel for private(I0, I3, domrad)
207  for (int vt = 0; vt < (int)wakeVortexesParams.diffVelo.size(); ++vt)
208  {
210 
211  wakeVortexesParams.I0[vt] *= domrad;
212  wakeVortexesParams.I0[vt] += DPI * sqr(domrad);
213 
214  I3 = wakeVortexesParams.I3[vt];
215  I0 = wakeVortexesParams.I0[vt];
216 
217  if (fabs(I0) > 1.e-8)
218  wakeVortexesParams.diffVelo[vt] += I3 * (1.0 / I0);
219  }
220 
221  for (size_t targetBou = 0; targetBou < W.getNumberOfBoundary(); ++targetBou)
222 #pragma omp parallel for private(I0, I3, domrad)
223  for (int vt = 0; vt < (int)virtualVortexesParams[targetBou].diffVelo.size(); ++vt)
224  {
225  domrad = std::max(virtualVortexesParams[targetBou].epsastWake[vt], W.getPassport().wakeDiscretizationProperties.getMinEpsAst());
226 
227  virtualVortexesParams[targetBou].I0[vt] *= domrad;
228  virtualVortexesParams[targetBou].I0[vt] += DPI * sqr(domrad);
229 
230  I3 = virtualVortexesParams[targetBou].I3[vt];
231  I0 = virtualVortexesParams[targetBou].I0[vt];
232 
233  if (fabs(I0) > 1.e-8)
234  virtualVortexesParams[targetBou].diffVelo[vt] += I3 * (1.0 / I0);
235  }
236 }//CalcDiffVeloI0I3()
237 
238 
239 void Velocity::LimitDiffVelo(std::vector<Point2D>& diffVel)
240 {
241  for (size_t i = 0; i < diffVel.size(); ++i)
242  {
243  Point2D& diffV = diffVel[i];
244 
245  diffV *= W.getPassport().physicalProperties.nu;
246 
247  if (diffV.length() > 1.5 * W.getPassport().physicalProperties.vRef)
249  }
250 }
251 
252 // Вычисление диффузионных скоростей
254 {
255  W.getTimestat().timeCalcVortexDiffVelo.first += omp_get_wtime();
256 
257  double t12start, t12finish;
258  double t03start, t03finish;
259  double tOtherstart, tOtherfinish;
260 
261  if (W.getPassport().physicalProperties.nu > 0.0)
262  {
263  t12start = omp_get_wtime();
265  t12finish = omp_get_wtime();
266 
267  t03start = omp_get_wtime();
269  t03finish = omp_get_wtime();
270 
271  //контроль застрелов диффузионной скорости
272  tOtherstart = omp_get_wtime();
274 
276  for (size_t bou = 0; bou < virtualVortexesParams.size(); ++bou)
277  LimitDiffVelo(virtualVortexesParams[bou].diffVelo);
278 
279 
280  for (size_t afl = 0; afl < W.getNumberOfAirfoil(); ++afl)
281  for (size_t i = 0; i < W.getAirfoil(afl).viscousStress.size(); ++i)
283 
284  SaveVisStress();
285  tOtherfinish = omp_get_wtime();
286 
287  }
288  W.getTimestat().timeCalcVortexDiffVelo.second += omp_get_wtime();
289 
290  //W.getInfo('t') << "diff_whole = " << W.getTimestat().timeCalcVortexDiffVelo.second - W.getTimestat().timeCalcVortexDiffVelo.first << std::endl;
291  //W.getInfo('t') << "diff_I12 = " << t12finish - t12start << std::endl;
292  //W.getInfo('t') << "diff_I03 = " << t03finish - t03start << std::endl;
293  //W.getInfo('t') << "diff_other = " << tOtherfinish - tOtherstart << std::endl;
294 
295 
296 }// CalcDiffVelo()
297 
298 
299 //Вычисление числителей и знаменателей диффузионных скоростей в заданном наборе точек
300 void Velocity::CalcDiffVeloI1I2ToSetOfPointsFromWake(const WakeDataBase& pointsDb, const std::vector<double>& domainRadius, const WakeDataBase& vorticesDb, std::vector<double>& I1, std::vector<Point2D>& I2)
301 {
302  double tCPUSTART, tCPUEND;
303 
304  tCPUSTART = omp_get_wtime();
305 
306  std::vector<double> selfI1(pointsDb.vtx.size(), 0.0);
307  std::vector<Point2D> selfI2(pointsDb.vtx.size(), { 0.0, 0.0 });
308 
309 #pragma warning (push)
310 #pragma warning (disable: 4101)
311  //Локальные переменные для цикла
312  Point2D Rij;
313  double rij, expr;
314  double diffRadius, domRad;
315  double left;
316  double right;
317  double posJx;
318 #pragma warning (pop)
319 
320 #pragma omp parallel for default(none) shared(selfI1, selfI2, domainRadius, vorticesDb, pointsDb) private(Rij, rij, expr, diffRadius, domRad, left, right, posJx)
321  for (int i = 0; i < pointsDb.vtx.size(); ++i)
322  {
323  const Vortex2D& vtxI = pointsDb.vtx[i];
324 
325  domRad = std::max(domainRadius[i], W.getPassport().wakeDiscretizationProperties.getMinEpsAst());
326 
328  diffRadius = 8.0 * domRad;
329 
330  left = vtxI.r()[0] - diffRadius;
331  right = vtxI.r()[0] + diffRadius;
332 
333  for (size_t j = 0; j < vorticesDb.vtx.size(); ++j)
334  {
335  const Vortex2D& vtxJ = vorticesDb.vtx[j];
336  posJx = vtxJ.r()[0];
337 
338  if ((left < posJx) && (posJx < right))
339  {
340  Rij = vtxI.r() - vtxJ.r();
341  rij = Rij.length();
342  if (rij < diffRadius && rij > 1.e-10)
343  {
344  expr = exp(-rij / domRad);
345  selfI2[i] += (vtxJ.g()* expr / rij) * Rij;
346  selfI1[i] += vtxJ.g()*expr;
347  }
348  }//if (rij>1e-6)
349  }//for j
350  } // for r
351 
352 
353  for (size_t i = 0; i < I1.size(); ++i)
354  {
355  I1[i] += selfI1[i];
356  I2[i] += selfI2[i];
357  }
358 
359  tCPUEND = omp_get_wtime();
360  //W.getInfo('t') << "DIFF_CPU: " << tCPUEND - tCPUSTART << std::endl;
361 }//CalcDiffVeloI1I2ToSetOfPointsFromWake(...)
362 
363 
364 //Вычисление числителей и знаменателей диффузионных скоростей в заданном наборе точек
365 void Velocity::CalcDiffVeloI1I2ToSetOfPointsFromSheets(const WakeDataBase& pointsDb, const std::vector<double>& domainRadius, const Boundary& bnd, std::vector<double>& I1, std::vector<Point2D>& I2)
366 {
367  double tCPUSTART, tCPUEND;
368 
369  tCPUSTART = omp_get_wtime();
370 
371  std::vector<double> selfI1(pointsDb.vtx.size(), 0.0);
372  std::vector<Point2D> selfI2(pointsDb.vtx.size(), { 0.0, 0.0 });
373 
374 #pragma warning (push)
375 #pragma warning (disable: 4101)
376  //Локальные переменные для цикла
377  Point2D Rij;
378  double rij, expr;
379  double diffRadius;
380  double left;
381  double right;
382  double posJx;
383  double domRad;
384 #pragma warning (pop)
385 
386 
387 #pragma omp parallel for default(none) shared(selfI1, selfI2, domainRadius, bnd, pointsDb, std::cout) private(Rij, rij, expr, domRad, diffRadius, left, right, posJx)
388  for (int i = 0; i < pointsDb.vtx.size(); ++i)
389  {
390  const Vortex2D& vtxI = pointsDb.vtx[i];
391 
392  domRad = std::max(domainRadius[i], W.getPassport().wakeDiscretizationProperties.getMinEpsAst());
393 
395  diffRadius = 8.0 * domRad;
396 
397  left = vtxI.r()[0] - diffRadius;
398  right = vtxI.r()[0] + diffRadius;
399 
400  for (size_t j = 0; j < bnd.afl.getNumberOfPanels(); ++j)
401  {
403  const int nQuadPt = 3;
404 
406  const double ptG = bnd.sheets.freeVortexSheet(j, 0) * bnd.afl.len[j] / nQuadPt;
407 
408  for (int q = 0; q < nQuadPt; ++q)
409  {
410  const Point2D& ptJ = bnd.afl.getR(j) + bnd.afl.tau[j] * (q + 0.5) * bnd.afl.len[j] * (1.0 / nQuadPt); // vorticesDb.vtx[j];
411  posJx = ptJ[0];
412 
413  if ((left < posJx) && (posJx < right))
414  {
415  Rij = vtxI.r() - ptJ;
416  rij = Rij.length();
417  if (rij < diffRadius && rij > 1.e-10)
418  {
419  expr = exp(-rij / domRad);
420  selfI2[i] += (ptG * expr / rij) * Rij;
421  selfI1[i] += ptG * expr;
422  }
423  }//if (rij>1e-6)
424  }
425  }//for j
426  } // for r
427 
428  for (size_t i = 0; i < I1.size(); ++i)
429  {
430  I1[i] += selfI1[i];
431  I2[i] += selfI2[i];
432  }
433 
434  tCPUEND = omp_get_wtime();
435  //W.getInfo('t') << "DIFF_CPU: " << tCPUEND - tCPUSTART << std::endl;
436 }//CalcDiffVeloI1I2ToSetOfPointsFromSheets(...)
437 
438 
439 
440 #if defined (USE_CUDA)
441 //Вычисление числителей и знаменателей диффузионных скоростей в заданном наборе точек
442 void Velocity::GPUCalcDiffVeloI1I2ToSetOfPointsFromWake(const WakeDataBase& pointsDb, const std::vector<double>& domainRadius, const WakeDataBase& vorticesDb, std::vector<double>& I1, std::vector<Point2D>& I2, bool useMesh)
443 {
444  if ( (&pointsDb == &W.getWake()) || (&pointsDb == &W.getBoundary(0).virtualWake) )
445  {
446  size_t npt = pointsDb.vtx.size();
447 
448  if ((W.getNumberOfBoundary() > 0) && (&pointsDb == &W.getBoundary(0).virtualWake))
449  {
450  for (size_t q = 1; q < W.getNumberOfBoundary(); ++q)
451  npt += W.getBoundary(q).virtualWake.vtx.size();
452  }
453 
454  double*& dev_ptr_pt = pointsDb.devVtxPtr;
455  double*& dev_ptr_dr = pointsDb.devRadPtr;
456 
457  const size_t nvt = vorticesDb.vtx.size();
458  double*& dev_ptr_vt = vorticesDb.devVtxPtr;
459 
460  std::vector<Point2D> newI2(npt); // I2.size());
461  std::vector<double> newI1(npt); // I1.size());
462 
463  double*& dev_ptr_i1 = pointsDb.devI1Ptr;
464  double*& dev_ptr_i2 = pointsDb.devI2Ptr;
466 
467  if ((nvt > 0) && (npt > 0))
468  {
469  //СЕТКА
470  if (!useMesh)
471  cuCalculateDiffVeloWake(npt, dev_ptr_pt, nvt, dev_ptr_vt, dev_ptr_i1, dev_ptr_i2, dev_ptr_dr, minRad);
472  else
473  cuCalculateDiffVeloWakeMesh(npt, dev_ptr_pt, nvt, dev_ptr_vt, W.getWake().devMeshPtr, W.getPassport().wakeDiscretizationProperties.epscol, dev_ptr_i1, dev_ptr_i2, dev_ptr_dr);
474 
475  W.getCuda().CopyMemFromDev<double, 2>(npt, dev_ptr_i2, (double*)newI2.data(), 10);
476  W.getCuda().CopyMemFromDev<double, 1>(npt, dev_ptr_i1, newI1.data(), 11);
477 
478  if (&pointsDb == &W.getWake())
479  {
480  for (size_t q = 0; q < I2.size(); ++q)
481  {
482  I1[q] += newI1[q];
483  I2[q] += newI2[q];
484  }
485  }
486 
487  if ((W.getNumberOfBoundary() > 0) && (&pointsDb == &W.getBoundary(0).virtualWake))
488  {
489  size_t curGlobPnl = 0;
490 
491  for (size_t s = 0; s < W.getNumberOfAirfoil(); ++s) //W.getNumberOfAirfoil()
492  {
493  size_t nv = W.getBoundary(s).virtualWake.vtx.size();
494  for (size_t q = 0; q < nv; ++q)
495  {
496  W.getNonConstVelocity().virtualVortexesParams[s].I1[q] += newI1[curGlobPnl + q];
497  W.getNonConstVelocity().virtualVortexesParams[s].I2[q] += newI2[curGlobPnl + q];
498  }
499  curGlobPnl += nv;
500  }
501  }
502  }
503  }
504 }//GPUCalcDiffVeloI1I2ToSetOfPointsFromWake(...)
505 
506 
507 //Вычисление числителей и знаменателей диффузионных скоростей в заданном наборе точек
508 void Velocity::GPUCalcDiffVeloI1I2ToSetOfPointsFromSheets(const WakeDataBase& pointsDb, const std::vector<double>& domainRadius, const Boundary& bou, std::vector<double>& I1, std::vector<Point2D>& I2, bool useMesh)
509 {
510  if ((&pointsDb == &W.getWake()) || (&pointsDb == &W.getBoundary(0).virtualWake))
511  {
512  if (bou.afl.numberInPassport == 0)
513  {
514  size_t npt = pointsDb.vtx.size();
515  double*& dev_ptr_pt = pointsDb.devVtxPtr;
516  double*& dev_ptr_dr = pointsDb.devRadPtr;
517 
518  if ((W.getNumberOfBoundary() > 0) && (&pointsDb == &W.getBoundary(0).virtualWake))
519  {
520  for (size_t q = 1; q < W.getNumberOfBoundary(); ++q)
521  npt += W.getBoundary(q).virtualWake.vtx.size();
522  }
523 
524  size_t npnl = bou.afl.getNumberOfPanels(); //vorticesDb.vtx.size();
525  double*& dev_ptr_r = bou.afl.devRPtr;
526  double*& dev_ptr_freeVortexSheet = bou.afl.devFreeVortexSheetPtr;
527 
528  for (size_t q = 1; q < W.getNumberOfBoundary(); ++q)
529  npnl += W.getBoundary(q).afl.getNumberOfPanels();
530 
531  std::vector<Point2D> newI2(npt);
532  std::vector<double> newI1(npt);
533 
534  double*& dev_ptr_i1 = pointsDb.devI1Ptr;
535  double*& dev_ptr_i2 = pointsDb.devI2Ptr;
537 
538  if ((npnl > 0) && (npt > 0))
539  {
541  //if (!useMesh)
542  cuCalculateDiffVeloWakeFromPanels(npt, dev_ptr_pt, npnl, dev_ptr_r, dev_ptr_freeVortexSheet, dev_ptr_i1, dev_ptr_i2, dev_ptr_dr, minRad);
543  //else
544  // cuCalculateDiffVeloWakeMesh(npt, dev_ptr_pt, nvt, dev_ptr_vt, W.getWake().devMeshPtr, W.getPassport().wakeDiscretizationProperties.epscol, dev_ptr_i1, dev_ptr_i2, dev_ptr_dr);
545 
546  W.getCuda().CopyMemFromDev<double, 2>(npt, dev_ptr_i2, (double*)newI2.data(), 12);
547  W.getCuda().CopyMemFromDev<double, 1>(npt, dev_ptr_i1, newI1.data(), 13);
548 
549  if (&pointsDb == &W.getWake())
550  {
551  for (size_t q = 0; q < I2.size(); ++q)
552  {
553  I1[q] += newI1[q];
554  I2[q] += newI2[q];
555  }
556  }
557 
558  if ((W.getNumberOfBoundary() > 0) && (&pointsDb == &W.getBoundary(0).virtualWake))
559  {
560  size_t curGlobPnl = 0;
561 
562  for (size_t s = 0; s < W.getNumberOfAirfoil(); ++s) //W.getNumberOfAirfoil()
563  {
564  size_t nv = W.getBoundary(s).virtualWake.vtx.size();
565  for (size_t q = 0; q < nv; ++q)
566  {
567  W.getNonConstVelocity().virtualVortexesParams[s].I1[q] += newI1[curGlobPnl + q];
568  W.getNonConstVelocity().virtualVortexesParams[s].I2[q] += newI2[curGlobPnl + q];
569  }
570  curGlobPnl += nv;
571  }
572  }
573  }
574  }
575  }
576 
577 }//GPUCalcDiffVeloI1I2ToSetOfPointsFromSheets(...)
578 #endif
579 
580 
581 #if defined(USE_CUDA)
582 void Velocity::GPUDiffVeloFAST(const WakeDataBase& pointsDb, const std::vector<double>& domainRadius, const WakeDataBase& vorticesDb, std::vector<double>& I1, std::vector<Point2D>& I2)
583 {
584  if ((&pointsDb == &W.getWake()) || (&pointsDb == &W.getBoundary(0).virtualWake))
585  {
586  size_t npt = pointsDb.vtx.size();
587 
588  if ((W.getNumberOfBoundary() > 0) && (&pointsDb == &W.getBoundary(0).virtualWake))
589  {
590  for (size_t q = 1; q < W.getNumberOfBoundary(); ++q)
591  npt += W.getBoundary(q).virtualWake.vtx.size();
592  }
593 
594  double*& dev_ptr_pt = pointsDb.devVtxPtr;
595  double*& dev_ptr_dr = pointsDb.devRadPtr;
596 
597  const size_t nvt = vorticesDb.vtx.size();
598  double*& dev_ptr_vt = vorticesDb.devVtxPtr;
599 
600  std::vector<Point2D> newI2(npt); // I2.size());
601  std::vector<double> newI1(npt); // I1.size());
602 
603  double*& dev_ptr_i1 = pointsDb.devI1Ptr;
604  double*& dev_ptr_i2 = pointsDb.devI2Ptr;
606  const double& eps2 = W.getPassport().wakeDiscretizationProperties.eps2;
607 
608  const size_t nbou = W.getNumberOfBoundary();
609 
610  size_t* const& dev_nVortices = W.getCuda().dev_ptr_nVortices;
611 
612  double** const& dev_ptr_ptr_vtx = W.getCuda().dev_ptr_ptr_vtx;
613 
614 
615  if ((nvt > 0) && (npt > 0))
616  {
617  double timings[7];
618 
619  wrapperDiffusiveVelo((Vortex2D*)dev_ptr_pt, dev_ptr_i1, (Point2D*)dev_ptr_i2,
620  dev_ptr_dr, W.getNonConstCuda().CUDAptrs, false, (int)npt, timings, sqrt(eps2), 1.30,
621  W.getNonConstCuda().n_CUDA_bodies, (int)W.getNonConstCuda().n_CUDA_wake, 8,
622  nbou, dev_nVortices, dev_ptr_ptr_vtx);
623 
624 
625  //printf("timings = %f: ( %f, %f, %f, %f, %f, %f )\n", timings[6],
626  // timings[0], timings[1], timings[2], timings[3], timings[4], timings[5]);
627 
628  W.getCuda().CopyMemFromDev<double, 2>(npt, dev_ptr_i2, (double*)newI2.data(), 10);
629  W.getCuda().CopyMemFromDev<double, 1>(npt, dev_ptr_i1, newI1.data(), 11);
630 
631  if (&pointsDb == &W.getWake())
632  {
633  for (size_t q = 0; q < I2.size(); ++q)
634  {
635  I1[q] += newI1[q];
636  I2[q] += newI2[q];
637  }
638  }
639 
640  if ((W.getNumberOfBoundary() > 0) && (&pointsDb == &W.getBoundary(0).virtualWake))
641  {
642  size_t curGlobPnl = 0;
643 
644  for (size_t s = 0; s < W.getNumberOfAirfoil(); ++s) //W.getNumberOfAirfoil()
645  {
646  size_t nv = W.getBoundary(s).virtualWake.vtx.size();
647  for (size_t q = 0; q < nv; ++q)
648  {
649  W.getNonConstVelocity().virtualVortexesParams[s].I1[q] += newI1[curGlobPnl + q];
650  W.getNonConstVelocity().virtualVortexesParams[s].I2[q] += newI2[curGlobPnl + q];
651  }
652  curGlobPnl += nv;
653  }
654  }
655  }
656  }
657 }
658 #endif
659 
660 // Очистка старых массивов под хранение скоростей, выделение новой памяти и обнуление
662 {
663  W.getTimestat().timeCalcVortexConvVelo.first += omp_get_wtime();
665  wakeVortexesParams.convVelo.resize(W.getWake().vtx.size(), { 0.0, 0.0 });
666  W.getTimestat().timeCalcVortexConvVelo.second += omp_get_wtime();
667 
668  W.getTimestat().timeCalcVortexDiffVelo.first += omp_get_wtime();
669  wakeVortexesParams.I0.clear();
670  wakeVortexesParams.I0.resize(W.getWake().vtx.size(), 0.0);
671 
672  wakeVortexesParams.I1.clear();
673  wakeVortexesParams.I1.resize(W.getWake().vtx.size(), 0.0);
674 
675  wakeVortexesParams.I2.clear();
676  wakeVortexesParams.I2.resize(W.getWake().vtx.size(), { 0.0, 0.0 });
677 
678  wakeVortexesParams.I3.clear();
679  wakeVortexesParams.I3.resize(W.getWake().vtx.size(), { 0.0, 0.0 });
680 
682  wakeVortexesParams.diffVelo.resize(W.getWake().vtx.size(), { 0.0, 0.0 });
683 
685  wakeVortexesParams.epsastWake.resize(W.getWake().vtx.size(), 0.0);
686  W.getTimestat().timeCalcVortexDiffVelo.second += omp_get_wtime();
687 
688  //Создаем массивы под виртуальные вихри
689  W.getTimestat().timeCalcVortexConvVelo.first += omp_get_wtime();
690  virtualVortexesParams.clear();
692  W.getTimestat().timeCalcVortexConvVelo.second += omp_get_wtime();
693 
694  for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
695  {
696  W.getTimestat().timeCalcVortexConvVelo.first += omp_get_wtime();
697  virtualVortexesParams[bou].convVelo.clear();
698  virtualVortexesParams[bou].convVelo.resize(W.getBoundary(bou).virtualWake.vtx.size(), { 0.0, 0.0 });
699  W.getTimestat().timeCalcVortexConvVelo.second += omp_get_wtime();
700 
701  W.getTimestat().timeCalcVortexDiffVelo.first += omp_get_wtime();
702  virtualVortexesParams[bou].I0.clear();
703  virtualVortexesParams[bou].I0.resize(W.getBoundary(bou).virtualWake.vtx.size(), 0.0);
704 
705  virtualVortexesParams[bou].I1.clear();
706  virtualVortexesParams[bou].I1.resize(W.getBoundary(bou).virtualWake.vtx.size(), 0.0);
707 
708  virtualVortexesParams[bou].I2.clear();
709  virtualVortexesParams[bou].I2.resize(W.getBoundary(bou).virtualWake.vtx.size(), { 0.0, 0.0 });
710 
711  virtualVortexesParams[bou].I3.clear();
712  virtualVortexesParams[bou].I3.resize(W.getBoundary(bou).virtualWake.vtx.size(), { 0.0, 0.0 });
713 
714  virtualVortexesParams[bou].diffVelo.clear();
715  virtualVortexesParams[bou].diffVelo.resize(W.getBoundary(bou).virtualWake.vtx.size(), { 0.0, 0.0 });
716 
717  virtualVortexesParams[bou].epsastWake.clear();
718  virtualVortexesParams[bou].epsastWake.resize(W.getBoundary(bou).virtualWake.vtx.size(), 0.0);
719 
720  W.getTimestat().timeCalcVortexDiffVelo.second += omp_get_wtime();
721  }
722 }//ResizeAndZero()
723 
724 
726 {
728  // if ((W.getPassport().timeDiscretizationProperties.saveVTK > 0) && (W.ifDivisible(10)) && (W.getNumberOfAirfoil() > 0))
729  {
730  for (size_t q = 0; q < W.getNumberOfAirfoil(); ++q)
731  {
732  if (q == 0)
733  VMlib::CreateDirectory(W.getPassport().dir, "visStress");
734 
735  std::stringstream ss;
736  ss << "VisStress_" << q << "-";
737  std::string fname = VMlib::fileNameStep(ss.str(), W.getPassport().timeDiscretizationProperties.nameLength, W.getCurrentStep(), "txt");
738  std::ofstream outfile;
739  outfile.open(W.getPassport().dir + "visStress/" + fname);
740 
741  outfile << W.getAirfoil(q).viscousStress.size() << std::endl; //Сохранение числа вихрей в пелене
742 
743  for (size_t i = 0; i < W.getAirfoil(q).viscousStress.size(); ++i)
744  {
745  const Point2D& r = 0.5 * (W.getAirfoil(q).getR(i + 1) + W.getAirfoil(q).getR(i));
746  double gi = W.getAirfoil(q).viscousStress[i];
747  outfile << static_cast<int>(i) << " " << r[0] << " " << r[1] << " " << gi << std::endl;
748  }//for i
749  outfile.close();
750  }
751  }
752 }//SaveVisStress()
const double & freeVortexSheet(size_t n, size_t moment) const
Definition: Sheet2D.h:99
std::vector< double > I0
Вектор знаменателей (I0) диффузионных скоростей вихрей (обусловленных профилем)
Definition: Velocity2D.h:73
virtual void GetDiffVelocityI0I3ToWakeAndViscousStresses(const WakeDataBase &pointsDb, std::vector< double > &domainRadius, std::vector< double > &I0, std::vector< Point2D > &I3)=0
std::vector< Point2D > I3
Вектор числителей (I3) диффузионных скоростей вихрей (обусловленных профилем)
Definition: Velocity2D.h:82
Заголовочный файл с описанием класса Passport (двумерный) и cоответствующими структурами ...
void CalcDiffVeloI1I2()
Вычисление диффузионных скоростей вихрей и виртуальных вихрей в вихревом следе
Definition: Velocity2D.cpp:56
std::vector< double > viscousStress
Касательные напряжения на панелях профиля
Definition: Airfoil2D.h:188
Times & getTimestat() const
Возврат ссылки на временную статистику выполнения шага расчета по времени
Definition: World2D.h:242
std::pair< std::string, int > velocityComputation
Definition: Passport2D.h:190
timePeriod timeCalcVortexDiffVelo
Начало и конец процесса вычисления диффузионных скоростей вихрей
Definition: Times2D.h:89
int saveVtxStep
Шаг сохранения кадров в бинарные файлы
Definition: PassportGen.h:73
void CalcDiffVeloI1I2ToSetOfPointsFromWake(const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const WakeDataBase &vorticesDb, std::vector< double > &I1, std::vector< Point2D > &I2)
Вычисление числителей и знаменателей диффузионных скоростей в заданном наборе точек ...
Definition: Velocity2D.cpp:300
void CalcDiffVelo()
Вычисление диффузионных скоростей
Definition: Velocity2D.cpp:253
Заголовочный файл с описанием класса Wake.
Заголовочный файл с описанием класса World2D.
Gpu & getNonConstCuda() const
Возврат неконстантной ссылки на объект, связанный с видеокартой (GPU)
Definition: World2D.h:232
double vRef
Референсная скорость
Definition: Passport2D.h:81
size_t getNumberOfBoundary() const
Возврат количества граничных условий в задаче
Definition: World2D.h:164
int nameLength
Число разрядов в имени файла
Definition: PassportGen.h:68
Заголовочный файл с описанием класса Airfoil.
Абстрактный класс, определяющий способ удовлетворения граничного условия на обтекаемом профиле ...
Definition: Boundary2D.h:63
const Wake & getWake() const
Возврат константной ссылки на вихревой след
Definition: World2D.h:197
double wrapperDiffusiveVelo(const realVortex *vtxl, real *i1l, realPoint *i2l, real *epsastl, CUDApointers &ptrs, bool rebuild, int nbodies, double *timing, real eps, real theta, size_t &nbodiesOld, int nbodiesUp, int order, size_t nAfls, size_t *nVtxs, double **ptrVtxs)
Definition: wrapper.cpp:497
Заголовочный файл с описанием класса WakeDataBase.
double nu
Коэффициент кинематической вязкости среды
Definition: Passport2D.h:96
const size_t numberInPassport
Номер профиля в паспорте
Definition: Airfoil2D.h:74
std::string dir
Рабочий каталог задачи
Definition: PassportGen.h:118
P length() const
Вычисление 2-нормы (длины) вектора
Definition: numvector.h:371
Заголовочный файл с описанием класса Mechanics.
PhysicalProperties physicalProperties
Структура с физическими свойствами задачи
Definition: Passport2D.h:296
const Point2D & getR(size_t q) const
Возврат константной ссылки на вершину профиля
Definition: Airfoil2D.h:101
const World2D & W
Константная ссылка на решаемую задачу
Definition: Velocity2D.h:101
timePeriod timeCalcVortexConvVelo
Начало и конец процесса вычисления конвективных скоростей вихрей
Definition: Times2D.h:86
HD Point2D & r()
Функция для доступа к радиус-вектору вихря
Definition: Vortex2D.h:85
HD double & g()
Функция для доступа к циркуляции вихря
Definition: Vortex2D.h:93
#define CU_I0I3
Definition: Gpudefs.h:78
size_t getNumberOfPanels() const
Возврат количества панелей на профиле
Definition: Airfoil2D.h:139
void ResizeAndZero()
Очистка старых массивов под хранение скоростей, выделение новой памяти и обнуление ...
Definition: Velocity2D.cpp:661
std::string fileNameStep(const std::string &name, int length, size_t number, const std::string &ext)
Формирование имени файла
Definition: defs.h:357
virtual void CalcDiffVeloI1I2ToWakeFromWake(const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const WakeDataBase &vorticesDb, std::vector< double > &I1, std::vector< Point2D > &I2)=0
std::vector< VortexesParams > virtualVortexesParams
Вектор струтур, определяющий параметры виртуальных вихрей для профилей
Definition: Velocity2D.h:108
bool ifDivisible(int val) const
Definition: World2D.h:244
T sqr(T x)
Возведение числа в квадрат
Definition: defs.h:430
TimeDiscretizationProperties timeDiscretizationProperties
Структура с параметрами процесса интегрирования по времени
Definition: PassportGen.h:127
void CalcDiffVeloI0I3()
Definition: Velocity2D.cpp:165
void normalize(P newlen=1.0)
Нормирование вектора на заданную длину
Definition: numvector.h:416
const Boundary & getBoundary(size_t i) const
Возврат константной ссылки на объект граничного условия
Definition: World2D.h:153
virtual void GetDiffVelocityI0I3ToSetOfPointsAndViscousStresses(const WakeDataBase &pointsDb, std::vector< double > &domainRadius, std::vector< double > &I0, std::vector< Point2D > &I3)=0
Вычисление числителей и знаменателей диффузионных скоростей в заданном наборе точек, обусловленных геометрией профиля, и вычисление вязкого трения
void CalcDiffVeloI1I2ToSetOfPointsFromSheets(const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const Boundary &bnd, std::vector< double > &I1, std::vector< Point2D > &I2)
Definition: Velocity2D.cpp:365
size_t getNumberOfAirfoil() const
Возврат количества профилей в задаче
Definition: World2D.h:147
Definition: Airfoil2D.h:45
Заголовочный файл с описанием класса StreamParser.
std::vector< Vortex2D > vtx
Список вихревых элементов
NumericalSchemes numericalSchemes
Структура с используемыми численными схемами
Definition: Passport2D.h:302
Velocity & getNonConstVelocity() const
Возврат неконстантной ссылки на объект для вычисления скоростей
Definition: World2D.h:217
Класс, опеделяющий двумерный вектор
Definition: Point2D.h:75
std::vector< double > I1
Вектор знаменателей (I1) диффузионных скоростей вихрей (обусловленных завихренностью) ...
Definition: Velocity2D.h:76
std::vector< Point2D > tau
Касательные к панелям профиля
Definition: Airfoil2D.h:182
const double DPI
Число .
Definition: defs.h:79
Sheet sheets
Слои на профиле
Definition: Boundary2D.h:95
Заголовочный файл с описанием класса MeasureVP.
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition: World2D.h:222
const Gpu & getCuda() const
Возврат константной ссылки на объект, связанный с видеокартой (GPU)
Definition: World2D.h:227
VortexesParams wakeVortexesParams
Струтура, определяющая параметры вихрей в следе
Definition: Velocity2D.h:105
Класс, опеделяющий двумерный вихревой элемент
Definition: Vortex2D.h:51
std::vector< double > epsastWake
Вектор характерных радиусов вихревых доменов (eps*)
Definition: Velocity2D.h:85
std::vector< Point2D > diffVelo
Вектор диффузионных скоростей вихрей
Definition: Velocity2D.h:70
VirtualWake virtualWake
Виртуальный вихревой след конкретного профиля
Definition: Boundary2D.h:85
int saveVisStress
Шаг вычисления и сохранения скорости и давления
Definition: PassportGen.h:81
std::vector< Point2D > I2
Вектор числителей (I2) диффузионных скоростей вихрей (обусловленных завихренностью) ...
Definition: Velocity2D.h:79
size_t getCurrentStep() const
Возврат константной ссылки на параметры распараллеливания по MPI.
Definition: WorldGen.h:91
const Airfoil & getAirfoil(size_t i) const
Возврат константной ссылки на объект профиля
Definition: World2D.h:130
Класс, опеделяющий набор вихрей
WakeDiscretizationProperties wakeDiscretizationProperties
Структура с параметрами дискретизации вихревого следа
Definition: Passport2D.h:299
std::vector< double > len
Длины панелей профиля
Definition: Airfoil2D.h:185
virtual void CalcDiffVeloI1I2ToWakeFromSheets(const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const Boundary &bnd, std::vector< double > &I1, std::vector< Point2D > &I2)=0
Заголовочный файл с описанием класса Velocity.
void LimitDiffVelo(std::vector< Point2D > &diffVel)
Контроль больших значений диффузионных скоростей
Definition: Velocity2D.cpp:239
void SaveVisStress()
Сохранение вязких напряжений
Definition: Velocity2D.cpp:725
Airfoil & getNonConstAirfoil(size_t i) const
Возврат неконстантной ссылки на объект профиля
Definition: World2D.h:142
std::vector< Point2D > convVelo
Вектор конвективных скоростей вихрей
Definition: Velocity2D.h:67
void CreateDirectory(const std::string &dir, const std::string &name)
Создание каталога
Definition: defs.h:414
double eps2
Квадрат радиуса вихря
Definition: Passport2D.h:142
Заголовочный файл с описанием класса Boundary.
double epscol
Радиус коллапса
Definition: Passport2D.h:145
double getMinEpsAst() const
Функция минимально возможного значения для epsAst.
Definition: Passport2D.h:166
const Airfoil & afl
Definition: Boundary2D.h:76