VM2D  1.12
Vortex methods for 2D flows simulation
Velocity2DBiotSavart.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: Velocity2DBiotSavart.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 "Velocity2DBiotSavart.h"
41 
42 #include "Airfoil2D.h"
43 #include "Boundary2D.h"
44 #include "MeasureVP2D.h"
45 #include "Mechanics2D.h"
46 #include "Passport2D.h"
47 #include "StreamParser.h"
48 #include "Wake2D.h"
49 #include "World2D.h"
50 
51 #include "wrapper.h"
52 
53 #include <algorithm>
54 
55 using namespace VM2D;
56 
59  Velocity(W_)
60 {
61 };
62 
65 {
66 };
67 
68 //Вычисление конвективных скоростей вихрей и виртуальных вихрей в вихревом следе, а также в точках wakeVP
70 {
71  //const int checkStep = 3;
72 
73 
74  double tt1 = omp_get_wtime();
75 
76  W.getTimestat().timeCalcVortexConvVelo.first += omp_get_wtime();
77 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_CONV_TOWAKE))
78  //if (W.getCurrentStep() == checkStep)
79  GPUWakeToWakeFAST(W.getWake(), wakeVortexesParams.convVelo, wakeVortexesParams.epsastWake, true, true);
80  //else
81  //GPUCalcConvVeloToSetOfPointsFromWake(W.getWake(), wakeVortexesParams.convVelo, wakeVortexesParams.epsastWake, true, true);
82 #else
84 #endif
85 
86 
87 
88 
89  double tt2 = omp_get_wtime();
90 
91 
92 /*
93  if (W.getCurrentStep() == checkStep)
94  {
95  std::ofstream pos("checkPos.txt");
96  pos.precision(17);
97  pos << W.getWake().vtx.size() << std::endl;
98  for (int i = 0; i < W.getWake().vtx.size(); ++i)
99  pos << W.getWake().vtx[i].r()[0] << " " << W.getWake().vtx[i].r()[1] << " " << W.getWake().vtx[i].g() << std::endl;
100  pos.close();
101 
102  std::ofstream of("checkVelo.txt");
103  of.precision(16);
104  for (int i = 0; i < wakeVortexesParams.convVelo.size(); ++i)
105  of << i << " " << wakeVortexesParams.convVelo[i][0] << " " << wakeVortexesParams.convVelo[i][1] << " " \
106  << wakeVortexesParams.epsastWake[i] << std::endl;
107  of.close();
108  exit(100500);
109  }
110 */
111 
112  //W.getInfo('t') << "Convective velocities time = " << int(((tt2 - tt1) * 1000)*10) / 10.0 << " ms, bodies = " << W.getWake().vtx.size() << std::endl;
113 
114 
115  std::vector<Point2D> nullVector(0);
116 
117  for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
118  {
119 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_CONV_TOBOU))
120  GPUCalcConvVeloToSetOfPointsFromWake(W.getBoundary(bou).virtualWake, nullVector, virtualVortexesParams[bou].epsastWake, false, true);
121 #else
122  CalcConvVeloToSetOfPointsFromWake(W.getBoundary(bou).virtualWake, nullVector, virtualVortexesParams[bou].epsastWake, false, true);
123 #endif
124  }
125 
126  //double tt3 = omp_get_wtime();
127 
128 //вычисление конвективных скоростей по закону Био-Савара от виртуальных вихрей
129  for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
130  {
131  //Влияние на пелену от виртуальных вихрей
132 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_CONVVIRT))
133  W.getBoundary(bou).GPUCalcConvVelocityToSetOfPointsFromSheets(W.getWake(), wakeVortexesParams.convVelo);
134 #else
136 #endif
137  }
138 
139  //double tt4 = omp_get_wtime();
140 
141  for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
142  {
143  //Скороcти самих виртуальных вихрей
145  }
146 
147  //double tt5 = omp_get_wtime();
148 
149  //std::cout << tt2 - tt1 << " " << tt3 - tt2 << " " << tt4 - tt3 << " " << tt5 - tt4 << std::endl;
150 
151  W.getTimestat().timeCalcVortexConvVelo.second += omp_get_wtime();
152 
153  W.getTimestat().timeVP.first += omp_get_wtime();
154 
155  //вычисление скоростей в заданных точках только на соответствующем шаге по времени
157  CalcVeloToWakeVP();
158  W.getTimestat().timeVP.second += omp_get_wtime();
159 }//CalcConvVelo()
160 
161 
162 //Вычисление конвективных скоростей вихрей в точках wakeVP
164 {
165  std::vector<Point2D> velConvWake;
166  std::vector<std::vector<Point2D>> velConvBou;
167 
168  int addWSize = (int)W.getMeasureVP().getWakeVP().vtx.size();
169 
170  velConvWake.resize(addWSize, { 0.0, 0.0 });
171 
172  velConvBou.resize(W.getNumberOfBoundary());
173  for (size_t i = 0; i < W.getNumberOfBoundary(); ++i)
174  velConvBou[i].resize(addWSize, { 0.0, 0.0 });
175 
176 #if (defined(USE_CUDA))
177  W.getNonConstCuda().RefreshVP();
178 #endif
179 
180 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_VP))
181  GPUCalcConvVeloToSetOfPointsFromWake(W.getMeasureVP().getWakeVP(), velConvWake, W.getNonConstMeasureVP().getNonConstDomainRadius(), true, false);
182 #else
184 #endif
185 
186  for (size_t i = 0; i < W.getNumberOfBoundary(); ++i)
187 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_VP))
188  W.getNonConstBoundary(i).GPUCalcConvVelocityToSetOfPointsFromSheets(W.getMeasureVP().getWakeVP(), velConvBou[i]);
189 #else
191 #endif
192 
193  std::vector<Point2D>& velocityRef = W.getNonConstMeasureVP().getNonConstVelocity();
194  velocityRef.assign(addWSize, W.getPassport().physicalProperties.V0());
195 
196  for (int i = 0; i < addWSize; ++i)
197  velocityRef[i] += velConvWake[i];
198 
199  for (size_t bou = 0; bou < velConvBou.size(); ++bou)
200  for (int j = 0; j < addWSize; ++j)
201  velocityRef[j] += velConvBou[bou][j];
202 
203 }// CalcVeloToWakeVP()
204 
205 
206 inline void ModifyE2(double* ee2, double dst2)
207 {
208  if (dst2 > 0)
209  {
210  if (dst2<ee2[0])
211  {
212  ee2[2] = ee2[1];
213  ee2[1] = ee2[0];
214  ee2[0] = dst2;
215  }//if (dist2<ee2[0])
216  else
217  {
218  if (dst2<ee2[1])
219  {
220  ee2[2] = ee2[1];
221  ee2[1] = dst2;
222  }// if (dist2<ee2[1])
223  else
224  if (dst2<ee2[2])
225  ee2[2] = dst2;
226  }//else
227  }//if (dst2>0)
228 }
229 
230 //Вычисление конвективных скоростей и радиусов вихревых доменов в заданном наборе точек от следа
231 void VelocityBiotSavart::CalcConvVeloToSetOfPointsFromWake(const WakeDataBase& pointsDb, std::vector<Point2D>& velo, std::vector<double>& domainRadius, bool calcVelo, bool calcRadius)
232 {
233  std::vector<Point2D> selfVelo(pointsDb.vtx.size());
234  domainRadius.resize(pointsDb.vtx.size());
235 
236  double cft = IDPI;
237 
238 #pragma warning (push)
239 #pragma warning (disable: 4101)
240  //Локальные переменные для цикла
241  Point2D velI;
242  Point2D tempVel;
243  double dst2eps, dst2;
244 #pragma warning (pop)
245 
247 
248  if (calcVelo)
249  {
250 #pragma omp parallel for default(none) shared(selfVelo, cft, calcVelo, calcRadius, eps2, pointsDb, domainRadius) private(tempVel, velI, dst2, dst2eps) schedule(dynamic, DYN_SCHEDULE)
251  for (int i = 0; i < pointsDb.vtx.size(); ++i)
252  {
253  double ee2[3] = { 10000.0, 10000.0, 10000.0 };
254 
255  velI.toZero();
256 
257  const Point2D& posI = pointsDb.vtx[i].r();
258 
259  for (size_t j = 0; j < W.getWake().vtx.size(); ++j)
260  {
261  const Point2D& posJ = W.getWake().vtx[j].r();
262 
263  dst2 = (posI-posJ).length2();
264 
265  //Модифицируем массив квадратов расстояний до ближайших вихрей из wake
266 #ifndef TESTONLYVELO
267  if (calcRadius)
268  VMlib::ModifyE2(ee2, dst2);
269 #endif // !TESTONLYVELO
270 
271  const double& gamJ = W.getWake().vtx[j].g();
272 
273  tempVel.toZero();
274  dst2eps = VMlib::boundDenom(dst2, eps2); //Сглаживать надо!!!
275 
276  tempVel = { -posI[1] + posJ[1], posI[0] - posJ[0] };
277  tempVel *= (gamJ / dst2eps);
278  velI += tempVel;
279  }
280 
281  for (size_t j = 0; j < W.getSource().vtx.size(); ++j)
282  {
283  const Point2D& posJ = W.getSource().vtx[j].r();
284  const double& gamJ = W.getPassport().physicalProperties.accelCft() * W.getSource().vtx[j].g();
285 
286  tempVel.toZero();
287 
288  dst2 = dist2(posI, posJ);
289  dst2eps = VMlib::boundDenom(dst2, W.getPassport().wakeDiscretizationProperties.eps2); //Сглаживать надо!!!
290 
291  tempVel = { posI[0] - posJ[0], posI[1] - posJ[1] };
292  tempVel *= (gamJ / dst2eps);
293  velI += tempVel;
294  }
295 #ifndef TESTONLYVELO
296  if (calcRadius)
297  {
298  for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
299  {
300  const auto& bou = W.getBoundary(s);
301  //Модифицируем массив квадратов расстояний до ближайших вихрей из virtualWake
302  for (size_t j = 0; j < bou.virtualWake.vtx.size(); ++j)
303  ModifyE2(ee2, dist2(posI, bou.virtualWake.vtx[j].r()));
304  }
305  }
306 #endif
307 
308  velI *= cft;
309  selfVelo[i] = velI;
310 
311 #ifndef TESTONLYVELO
312  if (calcRadius)
313  domainRadius[i] = 1.0 * sqrt((ee2[0] + ee2[1] + ee2[2]) / 3.0);
314 #endif
315  }
316  }
317  else if (calcRadius)
318  {
319 #pragma omp parallel for default(none) shared(selfVelo, cft, calcVelo, calcRadius, pointsDb, domainRadius) private(tempVel, velI, dst2) schedule(dynamic, DYN_SCHEDULE)
320  for (int i = 0; i < pointsDb.vtx.size(); ++i)
321  {
322  double ee2[3] = { 10000.0, 10000.0, 10000.0 };
323 
324  velI.toZero();
325 
326  const Point2D& posI = pointsDb.vtx[i].r();
327 
328  for (size_t j = 0; j < W.getWake().vtx.size(); ++j)
329  {
330  const Point2D& posJ = W.getWake().vtx[j].r();
331 
332  dst2 = dist2(posI, posJ);
333 
334  //Модифицируем массив квадратов расстояний до ближайших вихрей из wake
335  VMlib::ModifyE2(ee2, dst2);
336  }
337 
338  for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
339  {
340  for (size_t j = 0; j < W.getBoundary(s).virtualWake.vtx.size(); ++j)
341  {
342  const Point2D& posJ = W.getBoundary(s).virtualWake.vtx[j].r();
343  dst2 = dist2(posI, posJ);
344 
345  //Модифицируем массив квадратов расстояний до ближайших вихрей из virtualWake
346  ModifyE2(ee2, dst2);
347  /*
348  if (dst2 < ee2[0])
349  {
350  size_t pnl = W.getBoundary(s).virtualWake.aflPan[j].second;
351  ee2[0] = ee2[1] = ee2[2] = 0.5 * W.getBoundary(s).afl.len[pnl] / (W.getBoundary(s).vortexBeginEnd[pnl].second - W.getBoundary(s).vortexBeginEnd[pnl].first);
352  }
353  else
354  ModifyE2(ee2, dst2);
355  */
356 
357  }
358  }
359 
360  domainRadius[i] = 1.0 * sqrt((ee2[0] + ee2[1] + ee2[2]) / 3.0);
361  }
362  } //else
363 
364 
365  if (calcVelo)
366  for (size_t i = 0; i < velo.size(); ++i)
367  velo[i] += selfVelo[i];
368 }//CalcConvVeloToSetOfPointsFromWake(...)
369 
370 
371 #if defined(USE_CUDA)
372 void VelocityBiotSavart::GPUWakeToWakeFAST(const WakeDataBase& pointsDb, std::vector<Point2D>& velo, std::vector<double>& domainRadius, bool calcVelo, bool calcRadius)
373 {
374  size_t npt = pointsDb.vtx.size();
375  double*& dev_ptr_pt = pointsDb.devVtxPtr;
376 
377  const size_t nvt = W.getWake().vtx.size();
378  double*& dev_ptr_vt = W.getWake().devVtxPtr;
379 
380  const size_t nsr = W.getSource().vtx.size();
381  double*& dev_ptr_sr = W.getSource().devVtxPtr;
382  const size_t nbou = W.getNumberOfBoundary();
383 
384  //size_t* const& dev_nPanels = W.getCuda().dev_ptr_nPanels;
385  size_t* const& dev_nVortices = W.getCuda().dev_ptr_nVortices;
386 
387  double** const& dev_ptr_ptr_vtx = W.getCuda().dev_ptr_ptr_vtx;
388 
389  std::vector<Point2D> Vel(npt);
390  std::vector<double> Rad(npt);
391 
392  std::vector<Point2D> newV(npt);
393 
394 
395  double*& dev_ptr_vel = pointsDb.devVelPtr;
396  double*& dev_ptr_rad = pointsDb.devRadPtr;
397  const double& eps2 = W.getPassport().wakeDiscretizationProperties.eps2;
398 
399  if (npt > 0)
400  {
401  //double t1 = omp_get_wtime();
402  //cuCalculateConvVeloWake(par.myDisp, par.myLen, dev_ptr_pt, nvt, dev_ptr_vt, nsr, dev_ptr_sr, nbou, dev_nVortices, dev_ptr_ptr_vtx, dev_ptr_vel, dev_ptr_rad, eps2, calcVelo, calcRadius);
403 
404  double timings[7];
405 
406  wrapperInfluence((Vortex2D*)dev_ptr_pt, (Point2D*)dev_ptr_vel, dev_ptr_rad,
407  W.getNonConstCuda().CUDAptrs, (int)npt, timings, sqrt(eps2), 1.30,
408  W.getNonConstCuda().n_CUDA_bodies, (int)W.getNonConstCuda().n_CUDA_wake, 8,
409  nbou, dev_nVortices, dev_ptr_ptr_vtx);
410 
411  //double t2 = omp_get_wtime();
412  //std::cout << "KERNEL_TIME = " << t2 - t1 << std::endl;
413 
414 
415  if (calcVelo)
416  {
417  //double tt1 = omp_get_wtime();
418 
419  W.getCuda().CopyMemFromDev<double, 2>(npt, dev_ptr_vel, (double*)newV.data(), 20);
420 
421 
422 /*
424  size_t maxp = W.getWake().vtx.size();
425  if (par.myLen >= maxp)
426  {
427  std::vector<Vortex2D> controlPoints_h(maxp);
428  for (int i = 0; i < maxp; ++i)
429  {
430  controlPoints_h[i].r() = W.getWake().vtx[i].r();
431  controlPoints_h[i].g() = 0.0;
432  }
433 
434  realVortex* ptr_points;
435  realPoint* ptr_velos;
436  double* ptr_epsast;
437 
438  size_t maxpUp;
439 
440  ptr_points = (realVortex*)W.getNonConstCuda().ReserveDevMem<double, 3>(maxp, maxpUp);
441  ptr_velos = (realPoint*)W.getNonConstCuda().ReserveDevMem<double, 2>(maxp, maxpUp);
442  ptr_epsast = W.getNonConstCuda().ReserveDevMem<double, 1>(maxp, maxpUp);
443 
444  W.getNonConstCuda().CopyMemToDev<double, 3>(maxp, (double*)controlPoints_h.data(), (double*)ptr_points);
445 
446  double timingsToPoints[7];
447 
448  wrapperInfluenceToPoints((Vortex2D*)dev_ptr_pt, (Vortex2D*)ptr_points, (Point2D*)ptr_velos, ptr_epsast,
449  W.getNonConstCuda().CUDAptrs, false,
450  (int)npt, (int)maxp, timingsToPoints, sqrt(eps2), 0.31,
451  W.getNonConstCuda().n_CUDA_bodies, (int)W.getNonConstCuda().n_CUDA_wake, 14,
452  nbou, dev_nVortices, dev_ptr_ptr_vtx);
453 
454 
455  std::cout << "Time_base = " << timings[6] << ", Time_points = " << timingsToPoints[6] << std::endl;
456 
457 
458  std::vector<Point2D> velos_h(maxp);
459  W.getNonConstCuda().CopyMemFromDev<double, 2>(maxp, (double*)ptr_velos, (double*)&velos_h[0], 20);
460 
461  std::cout.precision(16);
462 
463  //for (int i = 0; i < maxp; ++i)
464  //{
465  // std::cout << i << ": " << "vel = " << locvel[i] << ", new_vel = " << velos_h[i] << ", dv = " << locvel[i] - velos_h[i] << std::endl;
466  //}
467 
468  W.getNonConstCuda().ReleaseDevMem(ptr_points, 800);
469  W.getNonConstCuda().ReleaseDevMem(ptr_velos, 801);
470  W.getNonConstCuda().ReleaseDevMem(ptr_epsast, 802);
471 
472 
473  //if (maxp > 100)
474  // exit(-300);
475  }
476  */
478 
479 
480 
481  //double tt2 = omp_get_wtime();
482  //std::cout << "COPY_TIME = " << tt2 - tt1 << std::endl;
483 
484  //double tt3 = omp_get_wtime();
485 
486 
487  for (size_t q = 0; q < npt; ++q)
488  Vel[q] = newV[q];
489 
490  for (size_t q = 0; q < npt; ++q)
491  velo[q] += Vel[q];
492 
493  //double tt4 = omp_get_wtime();
494  //std::cout << "GATHER_TIME = " << tt4 - tt3 << std::endl;
495 
496  }//if calcVelo
497 
498  //double tt5 = omp_get_wtime();
499 
500  if (calcRadius)
501  {
502  Rad.resize(npt);
503  W.getCuda().CopyMemFromDev<double, 1>(npt, dev_ptr_rad, Rad.data(), 212);
504 
505  //cuCopyFixedArray(dev_ptr_rad, Rad.data(), sizeof(double) * Rad.size());
506 
507  for (size_t q = 0; q < Rad.size(); ++q)
508  domainRadius[q] = Rad[q];
509 
510  //std::ofstream filo("filo.txt");
511  //for (int i = 0; i < npt; ++i)
512  // filo << i << " " << Rad[i] << std::endl;
513  // //filo << i << " " << locvel[i][0] << " " << locvel[i][1] << std::endl;
514  //filo.close();
515 
516  }//if calcRadius
517 
518  //double tt6 = omp_get_wtime();
519  //std::cout << "RADIUS_TIME = " << tt6 - tt5 << std::endl;
520 
521  }//if npt > 0
522 }
523 #endif
524 
525 
526 #if defined(USE_CUDA)
527 void VelocityBiotSavart::GPUCalcConvVeloToSetOfPointsFromWake(const WakeDataBase& pointsDb, std::vector<Point2D>& velo, std::vector<double>& domainRadius, bool calcVelo, bool calcRadius)
528 {
529  if ((&pointsDb == &W.getWake()) || (&pointsDb == &W.getBoundary(0).virtualWake) || (&pointsDb == &W.getMeasureVP().getWakeVP()))
530  {
531  size_t npt = pointsDb.vtx.size();
532  double*& dev_ptr_pt = pointsDb.devVtxPtr;
533 
534  if ((W.getNumberOfBoundary() >0) && (&pointsDb == &W.getBoundary(0).virtualWake))
535  {
536  for (size_t q = 1; q < W.getNumberOfBoundary(); ++q)
537  npt += W.getBoundary(q).virtualWake.vtx.size();
538  }
539 
540  const size_t nvt = W.getWake().vtx.size();
541  double*& dev_ptr_vt = W.getWake().devVtxPtr;
542  const size_t nsr = W.getSource().vtx.size();
543  double*& dev_ptr_sr = W.getSource().devVtxPtr;
544  const size_t nbou = W.getNumberOfBoundary();
545 
546  //size_t* const& dev_nPanels = W.getCuda().dev_ptr_nPanels;
547  size_t* const& dev_nVortices = W.getCuda().dev_ptr_nVortices;
548 
549  double** const& dev_ptr_ptr_vtx = W.getCuda().dev_ptr_ptr_vtx;
550 
551  std::vector<Point2D> Vel(npt);
552  std::vector<double> Rad(npt);
553 
554  std::vector<Point2D> newV(npt);
555 
556  double*& dev_ptr_vel = pointsDb.devVelPtr;
557  double*& dev_ptr_rad = pointsDb.devRadPtr;
558  const double& eps2 = W.getPassport().wakeDiscretizationProperties.eps2;
559 
560  if (npt > 0)
561  {
562  //double t1 = omp_get_wtime();
563  cuCalculateConvVeloWake(npt, dev_ptr_pt, nvt, dev_ptr_vt, nsr, dev_ptr_sr, nbou, dev_nVortices, dev_ptr_ptr_vtx, dev_ptr_vel, dev_ptr_rad, eps2, calcVelo, calcRadius);
564  //double t2 = omp_get_wtime();
565  //std::cout << "KERNEL_TIME = " << t2 - t1 << std::endl;
566 
567  if (calcVelo)
568  {
569  //double tt1 = omp_get_wtime();
570 
571  W.getCuda().CopyMemFromDev<double, 2>(npt, dev_ptr_vel, (double*)newV.data(), 20);
572 
573  //double tt2 = omp_get_wtime();
574  //std::cout << "COPY_TIME = " << tt2 - tt1 << std::endl;
575 
576  //double tt3 = omp_get_wtime();
577 
578  for (size_t q = 0; q < npt; ++q)
579  Vel[q] = newV[q];
580 
581  if ((&pointsDb == &W.getWake()) || (&pointsDb == &W.getMeasureVP().getWakeVP()))
582  {
583  for (size_t q = 0; q < npt; ++q)
584  velo[q] += Vel[q];
585  }//if &pointsDb
586 
587 
588  if ((W.getNumberOfBoundary() > 0) && (&pointsDb == &W.getBoundary(0).virtualWake))
589  {
590  //Сюда в принципе не должно быть попадания
591  exit(123);
592  }//if &pointsDb
593 
594  //double tt4 = omp_get_wtime();
595  //std::cout << "GATHER_TIME = " << tt4 - tt3 << std::endl;
596 
597  }//if calcVelo
598 
599  //double tt5 = omp_get_wtime();
600 
601  if (calcRadius)
602  {
603  Rad.resize(npt);
604  W.getCuda().CopyMemFromDev<double, 1>(npt, dev_ptr_rad, Rad.data(), 211);
605 
606  //cuCopyFixedArray(dev_ptr_rad, Rad.data(), sizeof(double) * Rad.size());
607 
608 
609  if ((&pointsDb == &W.getWake()) || (&pointsDb == &W.getMeasureVP().getWakeVP()))
610  {
611  for (size_t q = 0; q < Rad.size(); ++q)
612  domainRadius[q] = Rad[q];
613  }//if &pointsDb
614 
615 
616  if ((W.getNumberOfBoundary() > 0) && (&pointsDb == &W.getBoundary(0).virtualWake))
617  {
618  size_t curGlobPnl = 0;
619  for (size_t s = 0; s < W.getNumberOfAirfoil(); ++s) //W.getNumberOfAirfoil()
620  {
621  size_t nv = W.getVelocity().virtualVortexesParams[s].epsastWake.size();
622  for (size_t q = 0; q < nv; ++q)
623  W.getNonConstVelocity().virtualVortexesParams[s].epsastWake[q] = Rad[curGlobPnl + q];
624 
625  curGlobPnl += nv;
626  }//for s
627  }//if &pointsDb
628  }//if calcRadius
629 
630  //double tt6 = omp_get_wtime();
631  //std::cout << "RADIUS_TIME = " << tt6 - tt5 << std::endl;
632 
633  }//if npt > 0
634  }//if &pointsDb
635 }//GPUCalcConvVeloToSetOfPointsFromWake(...)
636 #endif
637 
638 
639 
640 //Генерация вектора влияния вихревого следа на профиль
641 void VelocityBiotSavart::GetWakeInfluenceToRhs(const Airfoil& afl, std::vector<double>& wakeRhs) const
642 {
643  size_t np = afl.getNumberOfPanels();
644  size_t shDim = W.getBoundary(afl.numberInPassport).sheetDim;
645 
646  wakeRhs.resize(W.getBoundary(afl.numberInPassport).GetUnknownsSize());
647 
648  //локальные переменные для цикла
649  std::vector<double> velI(shDim, 0.0);
650 
651 #pragma omp parallel for default(none) shared(shDim, afl, np, wakeRhs, IDPI) private(velI)
652  for (int i = 0; i < np; ++i)
653  {
654  velI.assign(shDim, 0.0);
655 
656  if (W.getWake().vtx.size() > 0)
657  {
658  //Учет влияния следа
659  afl.GetInfluenceFromVorticesToPanel(i, W.getWake().vtx.data(), W.getWake().vtx.size(), velI);
660  }
661 
662  if (W.getSource().vtx.size() > 0)
663  {
664  //Учет влияния источников
665  afl.GetInfluenceFromSourcesToPanel(i, W.getSource().vtx.data(), W.getSource().vtx.size(), velI);
666  }
667 
668  for (size_t j = 0; j < shDim; ++j)
669  velI[j] *= IDPI / afl.len[i];
670 
671  wakeRhs[i] = velI[0];
672 
673  if (shDim != 1)
674  wakeRhs[np + i] = velI[1];
675  }//for i
676 }//GetWakeInfluenceToRhs(...)
677 
678 
679 
680 #if defined(USE_CUDA)
681 //Генерация вектора влияния вихревого следа на профиль
682 void VelocityBiotSavart::GPUGetWakeInfluenceToRhs(const Airfoil& afl, std::vector<double>& wakeVelo) const
683 {
684  size_t shDim = W.getBoundary(afl.numberInPassport).sheetDim;
685 
686  const size_t& nvt = W.getWake().vtx.size();
687  const size_t& nsr = W.getSource().vtx.size();
688  const double eps2 = W.getPassport().wakeDiscretizationProperties.eps2;
689 
690  if (afl.numberInPassport == 0)
691  {
692  size_t nTotPan = 0;
693  for (size_t s = 0; s < W.getNumberOfAirfoil(); ++s)
694  nTotPan += W.getAirfoil(s).getNumberOfPanels();
695 
696  double*& dev_ptr_pt = afl.devRPtr;
697  double*& dev_ptr_vt = W.getWake().devVtxPtr;
698  double*& dev_ptr_sr = W.getSource().devVtxPtr;
699  double*& dev_ptr_rhs = afl.devRhsPtr;
700  double*& dev_ptr_rhsLin = afl.devRhsLinPtr;
701 
702  std::vector<double> locrhs(nTotPan);
703  std::vector<double> locrhsLin(nTotPan);
704 
705 
706 
707  if ((nvt > 0) || (nsr > 0))
708  {
709  cuCalculateRhs(nTotPan, dev_ptr_pt, nvt, dev_ptr_vt, nsr, dev_ptr_sr, eps2, dev_ptr_rhs, dev_ptr_rhsLin);
710 
711  std::vector<double> newRhs(nTotPan), newRhsLin(nTotPan);
712 
713  W.getCuda().CopyMemFromDev<double, 1>(nTotPan, dev_ptr_rhs, newRhs.data(), 22);
714  if (shDim != 1)
715  W.getCuda().CopyMemFromDev<double, 1>(nTotPan, dev_ptr_rhsLin, newRhsLin.data(), 22);
716 
717 
718  //for (int qq = 0; qq < (int)newRhs.size(); ++qq)
719  // std::cout << "qq = " << qq << ", " << newRhs[qq] << std::endl;
720 
721  size_t curGlobPnl = 0;
722  for (size_t s = 0; s < W.getNumberOfAirfoil(); ++s)
723  {
724  std::vector<double>& tmpRhs = W.getNonConstAirfoil(s).tmpRhs;
725  const size_t& np = W.getAirfoil(s).getNumberOfPanels();
726  tmpRhs.resize(0);
727  tmpRhs.insert(tmpRhs.end(), newRhs.begin() + curGlobPnl, newRhs.begin() + curGlobPnl + np);
728  if (shDim != 1)
729  tmpRhs.insert(tmpRhs.end(), newRhsLin.begin() + curGlobPnl, newRhsLin.begin() + curGlobPnl + np);
730 
731  curGlobPnl += np;
732  }
733  }
734  }
735 
736  if ((nvt > 0) || (nsr > 0))
737  wakeVelo = std::move(afl.tmpRhs);
738  else
739  wakeVelo.resize(afl.getNumberOfPanels() * (W.getPassport().numericalSchemes.boundaryCondition.second + 1), 0.0);
740 
741 }//GPUGetWakeInfluenceToRhs(...)
742 #endif
743 
744 #if defined(USE_CUDA)
745 //Генерация вектора влияния вихревого следа на профиль
746 void VelocityBiotSavart::GPUFASTGetWakeInfluenceToRhs(const Airfoil& afl, std::vector<double>& wakeVelo) const
747 {
748  size_t shDim = W.getBoundary(afl.numberInPassport).sheetDim;
749 
750  const size_t& nvt = W.getWake().vtx.size();
751  const size_t& nsr = W.getSource().vtx.size();
752 
753 
754  if (afl.numberInPassport == 0)
755  {
756  size_t nTotPan = 0;
757  for (size_t s = 0; s < W.getNumberOfAirfoil(); ++s)
758  nTotPan += W.getAirfoil(s).getNumberOfPanels();
759 
760  double*& dev_ptr_pt = afl.devRPtr;
761  double*& dev_ptr_vt = W.getWake().devVtxPtr;
762  double*& dev_ptr_sr = W.getSource().devVtxPtr;
763  double*& dev_ptr_rhs = afl.devRhsPtr;
764  double*& dev_ptr_rhsLin = afl.devRhsLinPtr;
765  std::vector<double> locrhs(nTotPan);
766  std::vector<double> locrhsLin(nTotPan);
767 
768  if ((nvt > 0) || (nsr > 0))
769  {
770  //cuCalculateRhs(par.myDisp, par.myLen, nTotPan, dev_ptr_pt, nvt, dev_ptr_vt, nsr, dev_ptr_sr, eps2, dev_ptr_rhs, dev_ptr_rhsLin);
771 
772  double timingsToRHS[7];
773 
775  (Vortex2D*)dev_ptr_vt, //вихри в следе
776  (double*)dev_ptr_pt, //начала и концы панелей
777  (double*)dev_ptr_rhs, //куда сохранить результат
778  (double*)((shDim == 1) ? nullptr : dev_ptr_rhsLin),
779  W.getNonConstCuda().CUDAptrs, //указатели на дерево вихрей
780  false, //признак перестроения дерева вихрей
781 
782  (int)nvt, //число вихрей в следе
783  (int)nTotPan, //общее число панелей на всех профилях
784  timingsToRHS, //засечки времени
785  //sqrt(eps2), //eps
786  1.2, //theta
787  W.getNonConstCuda().n_CUDA_bodies, //для следа
788  (int)W.getNonConstCuda().n_CUDA_wake, //для следа
789  8, //order
791  );
792 
793  //printf("timings = %f: ( %f, %f, %f, %f, %f, %f )\n", timingsToRHS[6],
794  // timingsToRHS[0], timingsToRHS[1], timingsToRHS[2], timingsToRHS[3], timingsToRHS[4], timingsToRHS[5]);
795 
796  std::vector<double> newRhs(nTotPan), newRhsLin(nTotPan);
797 
798  W.getCuda().CopyMemFromDev<double, 1>(nTotPan, dev_ptr_rhs, newRhs.data(), 22);
799  if (shDim != 1)
800  W.getCuda().CopyMemFromDev<double, 1>(nTotPan, dev_ptr_rhsLin, newRhsLin.data(), 22);
801 
802 
803  //for (int qq = 0; qq < (int)newRhs.size(); ++qq)
804  // std::cout << "qq = " << qq << ", " << newRhs[qq] << std::endl;
805 
806  size_t curGlobPnl = 0;
807  for (size_t s = 0; s < W.getNumberOfAirfoil(); ++s)
808  {
809  std::vector<double>& tmpRhs = W.getNonConstAirfoil(s).tmpRhs;
810  const size_t& np = W.getAirfoil(s).getNumberOfPanels();
811  tmpRhs.resize(0);
812  tmpRhs.insert(tmpRhs.end(), newRhs.begin() + curGlobPnl, newRhs.begin() + curGlobPnl + np);
813  if (shDim != 1)
814  tmpRhs.insert(tmpRhs.end(), newRhsLin.begin() + curGlobPnl, newRhsLin.begin() + curGlobPnl + np);
815 
816  curGlobPnl += np;
817  }
818 
819  }
820  }
821 
822  if ((nvt > 0) || (nsr > 0))
823  wakeVelo = std::move(afl.tmpRhs);
824  else
825  wakeVelo.resize(afl.getNumberOfPanels() * (W.getPassport().numericalSchemes.boundaryCondition.second + 1), 0.0);
826 
827 }//GPUGetWakeInfluenceToRhsFAST(...)
828 #endif
829 
830 
831 
832 void VelocityBiotSavart::FillRhs(Eigen::VectorXd& rhs) const
833 {
834  Eigen::VectorXd locRhs;
835  std::vector<double> lastRhs(W.getNumberOfBoundary());
836 
837  size_t currentRow = 0;
838 
839  for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
840  {
841  //double tt0 = omp_get_wtime();
842 
843  const Airfoil& afl = W.getAirfoil(bou);
844  size_t np = afl.getNumberOfPanels();
845 
846  size_t nVars;
847 
848  nVars = W.getBoundary(bou).GetUnknownsSize();
849  locRhs.resize(nVars);
850 
851 
852  std::vector<double> wakeRhs;
853 
854  double tt1 = omp_get_wtime();
855 
856 #if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_RHS))
857  //GPUGetWakeInfluenceToRhs(afl, wakeRhs);
858  GPUFASTGetWakeInfluenceToRhs(afl, wakeRhs);
859  //GetWakeInfluenceToRhs(afl, wakeRhs);
860 
861 #else
862  GetWakeInfluenceToRhs(afl, wakeRhs);
863 #endif
864 
865 
866  double tt2 = omp_get_wtime();
867  //W.getInfo('t') << "Rhs time = " << int(((tt2 - tt1) * 1000) * 10) / 10.0 << " ms, bodies = " << W.getWake().vtx.size() << std::endl;
868 
869 
870  std::vector<double> vInfRhs;
871  afl.GetInfluenceFromVInfToPanel(vInfRhs);
872 
873  /*
874  //if (W.currentStep == 200)
875  {
876  std::stringstream ss;
877  ss << "rhsWake-" << W.currentStep;
878  std::ofstream of(W.getPassport().dir + "dbg/" + ss.str());
879  for (size_t i = 0; i < wakeRhs.size(); ++i)
880  of << wakeRhs[i] << std::endl;
881  of.close();
882  }
883  */
884 
885 
886 
887 #pragma omp parallel for \
888  default(none) \
889  shared(locRhs, afl, bou, wakeRhs, vInfRhs, np) \
890  schedule(dynamic, DYN_SCHEDULE)
891  for (int i = 0; i < (int)afl.getNumberOfPanels(); ++i)
892  {
893  locRhs(i) = -vInfRhs[i] - wakeRhs[i] + 0.25 * ((afl.getV(i) + afl.getV(i + 1)) & afl.tau[i]); //0.25 * (afl.getV(i) + afl.getV(i + 1))*afl.tau[i] - прямолинейные
894  if (W.getBoundary(bou).sheetDim > 1)
895  locRhs(np + i) = -vInfRhs[np + i] - wakeRhs[np + i];
896 
897  //влияние присоединенных слоев от самого себя и от других профилей
898  for (size_t q = 0; q < W.getNumberOfBoundary(); ++q)
899  {
900  const auto& sht = W.getBoundary(q).sheets;
901  const auto& iq = W.getIQ(bou, q);
902 
903  const Airfoil& aflOther = W.getAirfoil(q);
905  {
906  for (size_t j = 0; j < aflOther.getNumberOfPanels(); ++j)
907  {
908  if ((i != j) || (bou != q))
909  {
910  locRhs(i) += -iq.first(i, j) * sht.attachedVortexSheet(j, 0);
911  locRhs(i) += -iq.second(i, j) * sht.attachedSourceSheet(j, 0); // getIQ(bou, q).second(i, j) пока забито нулем для криволинейных
912  }//if (i != j)
913  }//for j
914  }
915  }//for q
916  }//for i
917 
918  lastRhs[bou] = 0.0;
919 
920  for (size_t q = 0; q < afl.gammaThrough.size(); ++q)
921  lastRhs[bou] += afl.gammaThrough[q];
922 
923 
924 
925 
927 
928  double dwcm; //wcm0, wcm1, wcmOld0, wcmOld1, dwc0, dwc1;
929  const double currT = W.getPassport().timeDiscretizationProperties.currTime;
930  const double dt = W.getPassport().timeDiscretizationProperties.dt;
931 
932  //wcm0 = W.getNonConstMechanics(bou).AngularVelocityOfAirfoil(currT);
933  //wcmOld0 = W.getNonConstMechanics(bou).AngularVelocityOfAirfoil(currT - dt);
934  //dwc0 = wcm0 - wcmOld0;
935 
937  lastRhs[bou] += 2.0 * dwcm * W.getAirfoil(bou).area * (W.getAirfoil(bou).inverse ? 1.0 : -1.0);
938 
939  /*
940  if (bou == 0)
941  {
942  lastRhs[bou] -= (2.0 * PI * 0.5) * dwc0 * 0.5;
943  }
944 
945  if (bou == 1)
946  {
947  wcm1 = W.getNonConstMechanics(bou).AngularVelocityOfAirfoil(currT);
948  wcmOld1 = W.getNonConstMechanics(bou).AngularVelocityOfAirfoil(currT - dt);
949  dwc1 = wcm1 - wcmOld1;
950  //std::cout << "dwc0,1 = " << dwc0 << " " << dwc1 << std::endl;
951  lastRhs[bou] += (2.0 * PI * 1.0) * (dwc1) * 1.0;
952  }
953  */
955 
956  //размазываем правую часть
957  for (size_t i = 0; i < nVars; ++i)
958  rhs(i + currentRow) = locRhs(i);
959 
960  rhs(currentRow + nVars) = lastRhs[bou];
961 
962  currentRow += nVars + 1;
963  }// for bou
964 }
965 
966 
967 void VelocityBiotSavart::CalcDiffVeloI1I2ToWakeFromWake(const WakeDataBase& pointsDb, const std::vector<double>& domainRadius, const WakeDataBase& vorticesDb, std::vector<double>& I1, std::vector<Point2D>& I2)
968 {
969  CalcDiffVeloI1I2ToSetOfPointsFromWake(pointsDb, domainRadius, vorticesDb, I1, I2);
970 }//CalcDiffVeloI1I2ToWakeFromWake(...)
971 
972 void VelocityBiotSavart::CalcDiffVeloI1I2ToWakeFromSheets(const WakeDataBase& pointsDb, const std::vector<double>& domainRadius, const Boundary& bnd, std::vector<double>& I1, std::vector<Point2D>& I2)
973 {
974  CalcDiffVeloI1I2ToSetOfPointsFromSheets(pointsDb, domainRadius, bnd, I1, I2);
975 }//CalcDiffVeloI1I2ToWakeFromSheets(...)
const std::pair< Eigen::MatrixXd, Eigen::MatrixXd > & getIQ(size_t i, size_t j) const
Возврат константной ссылки на объект, связанный с матрицей интегралов от (r-xi)/|r-xi|^2.
Definition: World2D.h:237
Заголовочный файл с описанием класса Passport (двумерный) и cоответствующими структурами ...
Times & getTimestat() const
Возврат ссылки на временную статистику выполнения шага расчета по времени
Definition: World2D.h:242
virtual void CalcConvVelocityAtVirtualVortexes(std::vector< Point2D > &velo) const =0
Вычисление конвективной скорости в точках расположения виртуальных вихрей
double wrapperInfluence(const realVortex *vtxl, realPoint *vell, real *epsastl, CUDApointers &ptrs, 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:280
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
Заголовочный файл с описанием класса Wake.
std::pair< std::string, int > boundaryCondition
Метод аппроксимации граничных условий
Definition: Passport2D.h:199
Заголовочный файл с описанием класса World2D.
double area
Площадь профиля
Definition: Airfoil2D.h:83
Boundary & getNonConstBoundary(size_t i) const
Возврат неконстантной ссылки на объект граничного условия
Definition: World2D.h:159
Gpu & getNonConstCuda() const
Возврат неконстантной ссылки на объект, связанный с видеокартой (GPU)
Definition: World2D.h:232
bool inverse
Признак разворота нормалей (для расчета внутренних течений)
Definition: Airfoil2D.h:139
void CalcDiffVeloI1I2ToWakeFromSheets(const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const Boundary &bnd, std::vector< double > &I1, std::vector< Point2D > &I2) override
size_t getNumberOfBoundary() const
Возврат количества граничных условий в задаче
Definition: World2D.h:164
Заголовочный файл с описанием класса Airfoil.
const Velocity & getVelocity() const
Возврат константной ссылки на объект для вычисления скоростей
Definition: World2D.h:212
double currTime
Текущее время
Definition: PassportGen.h:56
Абстрактный класс, определяющий способ удовлетворения граничного условия на обтекаемом профиле ...
Definition: Boundary2D.h:63
const double IDPI
Число .
Definition: defs.h:76
const Wake & getWake() const
Возврат константной ссылки на вихревой след
Definition: World2D.h:197
Заголовочный файл с описанием класса VelocityBiotSavart.
std::vector< double > gammaThrough
Суммарные циркуляции вихрей, пересекших панели профиля на прошлом шаге
Definition: Airfoil2D.h:196
#define CU_VP
Definition: Gpudefs.h:83
if(currentStep%10==0)
Definition: gammaCirc.h:22
Mechanics & getNonConstMechanics(size_t i) const
Возврат неконстантной ссылки на объект механики
Definition: World2D.h:192
const size_t numberInPassport
Номер профиля в паспорте
Definition: Airfoil2D.h:74
virtual ~VelocityBiotSavart()
Деструктор
void CalcConvVeloToSetOfPointsFromWake(const WakeDataBase &pointsDb, std::vector< Point2D > &velo, std::vector< double > &domainRadius, bool calcVelo, bool calcRadius)
Вычисление конвективных скоростей и радиусов вихревых доменов в заданном наборе точек от следа ...
Заголовочный файл с описанием класса Mechanics.
PhysicalProperties physicalProperties
Структура с физическими свойствами задачи
Definition: Passport2D.h:296
const World2D & W
Константная ссылка на решаемую задачу
Definition: Velocity2D.h:101
const Point2D & getV(size_t q) const
Возврат константной ссылки на скорость вершины профиля
Definition: Airfoil2D.h:113
timePeriod timeCalcVortexConvVelo
Начало и конец процесса вычисления конвективных скоростей вихрей
Definition: Times2D.h:86
const bool isMoves
Переменная, отвечающая за то, двигается профиль или нет
Definition: Mechanics2D.h:130
void ModifyE2(double *ee2, double dst2)
Модифицирует массив квадратов расстояний до ближайших вихрей из wake.
Definition: defs.cpp:233
const Mechanics & getMechanics(size_t i) const
Возврат константной ссылки на объект механики
Definition: World2D.h:186
const WakeDataBase & getSource() const
Возврат константной ссылки на источники в области течения
Definition: World2D.h:207
size_t getNumberOfPanels() const
Возврат количества панелей на профиле
Definition: Airfoil2D.h:139
void CalcDiffVeloI1I2ToWakeFromWake(const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const WakeDataBase &vorticesDb, std::vector< double > &I1, std::vector< Point2D > &I2) override
double dt
Шаг по времени
Definition: PassportGen.h:65
VelocityBiotSavart(const World2D &W_)
Конструктор
void GetWakeInfluenceToRhs(const Airfoil &afl, std::vector< double > &wakeRhs) const
Генерация вектора влияния вихревого следа на профиль
virtual void FillRhs(Eigen::VectorXd &rhs) const override
Расчет вектора правой части (всего)
std::vector< VortexesParams > virtualVortexesParams
Вектор струтур, определяющий параметры виртуальных вихрей для профилей
Definition: Velocity2D.h:108
double accelCft() const
Функция-множитель, позволяющая моделировать разгон
Definition: Passport2D.cpp:51
TimeDiscretizationProperties timeDiscretizationProperties
Структура с параметрами процесса интегрирования по времени
Definition: PassportGen.h:127
double wrapperInfluenceToRHS(const realVortex *dev_ptr_vt, const double *dev_ptr_pt, double *dev_ptr_rhs, double *dev_ptr_rhslin, CUDApointers &ptrs, bool rebuild, int nvt, int nTotPan, double *timingsToRHS, double theta, size_t &nbodiesOld, int nbodiesUp, int order, int scheme)
Definition: wrapper.cpp:410
const Boundary & getBoundary(size_t i) const
Возврат константной ссылки на объект граничного условия
Definition: World2D.h:153
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
virtual void CalcConvVelocityToSetOfPointsFromSheets(const WakeDataBase &pointsDb, std::vector< Point2D > &velo) const =0
Вычисление конвективных скоростей в наборе точек, вызываемых наличием слоев вихрей и источников на пр...
Definition: Airfoil2D.h:45
const MeasureVP & getMeasureVP() const
Возврат константной ссылки на measureVP.
Definition: World2D.h:175
int saveVPstep
Шаг вычисления и сохранения скорости и давления
Definition: PassportGen.h:78
Заголовочный файл с описанием класса StreamParser.
auto dist2(const numvector< T, n > &x, const numvector< P, n > &y) -> typename std::remove_const< decltype(x[0]-y[0])>::type
Вычисление квадрата расстояния между двумя точками
Definition: numvector.h:788
std::vector< Vortex2D > vtx
Список вихревых элементов
NumericalSchemes numericalSchemes
Структура с используемыми численными схемами
Definition: Passport2D.h:302
virtual double AngularVelocityOfAirfoil(double currTime)=0
Вычисление угловой скорости профиля
std::vector< Point2D > & getNonConstVelocity()
Возврат velocity.
Definition: MeasureVP2D.h:130
virtual void GetInfluenceFromVorticesToPanel(size_t panel, const Vortex2D *ptr, ptrdiff_t count, std::vector< double > &panelRhs) const =0
Вычисление влияния части подряд идущих вихрей из вихревого следа на панель для правой части ...
Velocity & getNonConstVelocity() const
Возврат неконстантной ссылки на объект для вычисления скоростей
Definition: World2D.h:217
Класс, опеделяющий двумерный вектор
Definition: Point2D.h:75
std::vector< Point2D > tau
Касательные к панелям профиля
Definition: Airfoil2D.h:182
void ModifyE2(double *ee2, double dst2)
Модифицирует массив квадратов расстояний до ближайших вихрей из wake.
Sheet sheets
Слои на профиле
Definition: Boundary2D.h:95
virtual void CalcConvVelo() override
Вычисление конвективных скоростей вихрей и виртуальных вихрей в вихревом следе, а также в точках wake...
Заголовочный файл с описанием класса MeasureVP.
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition: World2D.h:222
const Gpu & getCuda() const
Возврат константной ссылки на объект, связанный с видеокартой (GPU)
Definition: World2D.h:227
VortexesParams wakeVortexesParams
Струтура, определяющая параметры вихрей в следе
Definition: Velocity2D.h:105
virtual void GetInfluenceFromVInfToPanel(std::vector< double > &vInfRhs) const =0
Вычисление влияния набегающего потока на панель для правой части
Класс, опеделяющий двумерный вихревой элемент
Definition: Vortex2D.h:51
double boundDenom(double r2, double eps2)
Способ сглаживания скорости вихря (вихрь Рэнкина или вихрь Ламба)
Definition: defs.h:536
std::vector< double > epsastWake
Вектор характерных радиусов вихревых доменов (eps*)
Definition: Velocity2D.h:85
const bool isDeform
Переменная, отвечающая за то, деформируется профиль или нет
Definition: Mechanics2D.h:133
VirtualWake virtualWake
Виртуальный вихревой след конкретного профиля
Definition: Boundary2D.h:85
MeasureVP & getNonConstMeasureVP() const
Возврат неконстантной ссылки на measureVP.
Definition: World2D.h:180
timePeriod timeVP
Начало и конец процесса подсчета полей скоростей и давления и сохранения их в файл ...
Definition: Times2D.h:110
Абстрактный класс, определяющий обтекаемый профиль
Definition: Airfoil2D.h:60
size_t getCurrentStep() const
Возврат константной ссылки на параметры распараллеливания по MPI.
Definition: WorldGen.h:91
size_t sheetDim
Размерность параметров каждого из слоев на каждой из панелей
Definition: Boundary2D.h:92
const Airfoil & getAirfoil(size_t i) const
Возврат константной ссылки на объект профиля
Definition: World2D.h:130
Point2D V0() const
Функция скорости набегающего потока с учетом разгона
Definition: Passport2D.h:93
Класс, опеделяющий текущую решаемую задачу
Definition: World2D.h:68
Абстрактный класс, определяющий способ вычисления скоростей
Definition: Velocity2D.h:97
Класс, опеделяющий набор вихрей
numvector< T, n > & toZero(P val=0)
Установка всех компонент вектора в константу (по умолчанию — нуль)
Definition: numvector.h:524
WakeDiscretizationProperties wakeDiscretizationProperties
Структура с параметрами дискретизации вихревого следа
Definition: Passport2D.h:299
std::vector< double > len
Длины панелей профиля
Definition: Airfoil2D.h:185
const WakeDataBase & getWakeVP() const
Возврат wakeVP.
Definition: MeasureVP2D.h:120
std::vector< double > & getNonConstDomainRadius()
Возврат domainRadius.
Definition: MeasureVP2D.h:140
Airfoil & getNonConstAirfoil(size_t i) const
Возврат неконстантной ссылки на объект профиля
Definition: World2D.h:142
std::vector< Point2D > convVelo
Вектор конвективных скоростей вихрей
Definition: Velocity2D.h:67
virtual void CalcVeloToWakeVP() override
Вычисление скоростей в точках wakeVP.
virtual void GetInfluenceFromSourcesToPanel(size_t panel, const Vortex2D *ptr, ptrdiff_t count, std::vector< double > &panelRhs) const =0
Вычисление влияния части подряд идущих источников из области течения на панель для правой части ...
double eps2
Квадрат радиуса вихря
Definition: Passport2D.h:142
Заголовочный файл с описанием класса Boundary.
size_t GetUnknownsSize() const
Возврат размерности вектора решения
Definition: Boundary2D.cpp:71