VM2D 1.14
Vortex methods for 2D flows simulation
Loading...
Searching...
No Matches
Velocity2DBarnesHut.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: Velocity2DBarnesHut.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 "Velocity2DBarnesHut.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 "World2D.h"
49#include "Gmres2D.h"
50
51using namespace VM2D;
52
58
63
64
65float VelocityBarnesHut::CalcConvVeloToSetOfPointsFromWake(const WakeDataBase& pointsDb, std::vector<Point2D>& velo, std::vector<double>& domainRadius, bool calcVelo, bool calcRadius)
66{
67 VMlib::vmTimer timer;
68 timer.reset();
69 timer.start();
70
73
74 if (&pointsDb == &W.getWake())
75 W.getInflTreeWake().DownwardTraversalVorticesToPoints(W.getInflTreeWake(), velo, domainRadius, theta, order, calcRadius);
76 else
77 W.getInflTreeWake().DownwardTraversalVorticesToPoints(W.getCntrTreeWake(), velo, domainRadius, theta, order, calcRadius);
78 timer.stop();
79
80 //std::ofstream treeTimeFile;
81 //if (W.getCurrentStep() == 0)
82 //{
83 // treeTimeFile.open(W.getPassport().dir + "/dbg/treeTime.csv");
84 // treeTimeFile << "step,time,N,tBUI,tUPW,tDNW\n";
85 //}
86 //else
87 // treeTimeFile.open(W.getPassport().dir + "/dbg/treeTime.csv", std::ios::app);
88 //
89 //treeTimeFile << W.getCurrentStep() << ',' << W.getCurrentTime() << ',' << W.getInflTreeWake().object.size() << ',' << W.getCntrTreeWake().object.size() << ',' << timerA.duration() << '\n';
90 //
91 //treeTimeFile.close();
92
93#ifdef USE_CUDA
94 if (calcVelo)
95 W.getCuda().CopyMemToDev<double, 2>(velo.size(), (double*)velo.data(), pointsDb.devVelPtr);
96 if (calcRadius)
97 W.getCuda().CopyMemToDev<double, 1>(domainRadius.size(), domainRadius.data(), pointsDb.devRadPtr);
98#endif
99
100 return (float)timer.duration();
101}
102
103
104inline void ModifyE2(double* ee2, double dst2)
105{
106 if (dst2 > 0)
107 {
108 if (dst2 < ee2[0])
109 {
110 ee2[2] = ee2[1];
111 ee2[1] = ee2[0];
112 ee2[0] = dst2;
113 }//if (dist2<ee2[0])
114 else
115 {
116 if (dst2 < ee2[1])
117 {
118 ee2[2] = ee2[1];
119 ee2[1] = dst2;
120 }// if (dist2<ee2[1])
121 else
122 if (dst2 < ee2[2])
123 ee2[2] = dst2;
124 }//else
125 }//if (dst2>0)
126}
127
128
129
130
131
132//Вычисление конвективных скоростей и радиусов вихревых доменов в заданном наборе точек от следа
133void VelocityBarnesHut::CalcConvVPVeloToSetOfPointsFromWake(const WakeDataBase& pointsDb, std::vector<Point2D>& velo, std::vector<double>& domainRadius, bool calcVelo, bool calcRadius)
134{
135 std::vector<Point2D> selfVelo(pointsDb.vtx.size());
136 domainRadius.resize(pointsDb.vtx.size());
137
138 double cft = IDPI;
139
140#pragma warning (push)
141#pragma warning (disable: 4101)
142 //Локальные переменные для цикла
143 Point2D velI;
144 Point2D tempVel;
145 double dst2eps, dst2;
146#pragma warning (pop)
147
148 if (calcVelo)
149 {
150#pragma omp parallel for default(none) shared(selfVelo, cft, calcVelo, calcRadius, pointsDb, domainRadius) private(tempVel, velI, dst2, dst2eps) schedule(dynamic, DYN_SCHEDULE)
151 for (int i = 0; i < pointsDb.vtx.size(); ++i)
152 {
153 double ee2[3] = { 10000.0, 10000.0, 10000.0 };
154
155 velI.toZero();
156
157 const Point2D& posI = pointsDb.vtx[i].r();
158
159 for (size_t j = 0; j < W.getWake().vtx.size(); ++j)
160 {
161 const Point2D& posJ = W.getWake().vtx[j].r();
162
163 dst2 = (posI - posJ).length2();
164
165// //Модифицируем массив квадратов расстояний до ближайших вихрей из wake
166//#ifndef TESTONLYVELO
167// if (calcRadius)
168// VMlib::ModifyE2(ee2, dst2);
169//#endif //!TESTONLYVELO
170
171 const double& gamJ = W.getWake().vtx[j].g();
172
173 tempVel.toZero();
174 dst2eps = VMlib::boundDenom(dst2, sqr(W.getWake().vtx[j].sigma())); //Сглаживать надо!!!
175
176 tempVel = { -posI[1] + posJ[1], posI[0] - posJ[0] };
177 tempVel *= (gamJ / dst2eps);
178 velI += tempVel;
179 }
180
181 for (size_t j = 0; j < W.getSource().vtx.size(); ++j)
182 {
183 const Point2D& posJ = W.getSource().vtx[j].r();
184 const double& gamJ = W.getPassport().physicalProperties.accelCft(W.getCurrentTime()) * W.getSource().vtx[j].g();
185
186 tempVel.toZero();
187
188 dst2 = dist2(posI, posJ);
189 dst2eps = VMlib::boundDenom(dst2, sqr(W.getSource().vtx[j].sigma())); //Сглаживать надо!!!
190
191 tempVel = { posI[0] - posJ[0], posI[1] - posJ[1] };
192 tempVel *= (gamJ / dst2eps);
193 velI += tempVel;
194 }
195//#ifndef TESTONLYVELO
196// if (calcRadius)
197// {
198// for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
199// {
200// const auto& bou = W.getBoundary(s);
201// //Модифицируем массив квадратов расстояний до ближайших вихрей из virtualWake
202// for (size_t j = 0; j < bou.virtualWake.vtx.size(); ++j)
203// ModifyE2(ee2, dist2(posI, bou.virtualWake.vtx[j].r()));
204// }
205// }
206//#endif
207
208 velI *= cft;
209 selfVelo[i] = velI;
210
211//#ifndef TESTONLYVELO
212// if (calcRadius)
213// domainRadius[i] = 1.0 * sqrt((ee2[0] + ee2[1] + ee2[2]) / 3.0);
214//#endif
215 }
216 }
217// else if (calcRadius)
218// {
219//#pragma omp parallel for default(none) shared(selfVelo, cft, calcVelo, calcRadius, pointsDb, domainRadius) private(tempVel, velI, dst2) schedule(dynamic, DYN_SCHEDULE)
220// for (int i = 0; i < pointsDb.vtx.size(); ++i)
221// {
222// double ee2[3] = { 10000.0, 10000.0, 10000.0 };
223//
224// velI.toZero();
225//
226// const Point2D& posI = pointsDb.vtx[i].r();
227//
228// for (size_t j = 0; j < W.getWake().vtx.size(); ++j)
229// {
230// const Point2D& posJ = W.getWake().vtx[j].r();
231//
232// dst2 = dist2(posI, posJ);
233//
234// //Модифицируем массив квадратов расстояний до ближайших вихрей из wake
235// VMlib::ModifyE2(ee2, dst2);
236// }
237//
238// for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
239// {
240// for (size_t j = 0; j < W.getBoundary(s).virtualWake.vtx.size(); ++j)
241// {
242// const Point2D& posJ = W.getBoundary(s).virtualWake.vtx[j].r();
243// dst2 = dist2(posI, posJ);
244//
245// //Модифицируем массив квадратов расстояний до ближайших вихрей из virtualWake
246// ModifyE2(ee2, dst2);
247// }
248// }
249//
250// domainRadius[i] = 1.0 * sqrt((ee2[0] + ee2[1] + ee2[2]) / 3.0);
251// }
252// } //else
253
254
255 if (calcVelo)
256 for (size_t i = 0; i < velo.size(); ++i)
257 velo[i] += selfVelo[i];
258
259#ifdef USE_CUDA
260 if (calcVelo)
261 W.getCuda().CopyMemToDev<double, 2>(velo.size(), (double*)velo.data(), pointsDb.devVelPtr);
262// if (calcRadius)
263// W.getCuda().CopyMemToDev<double, 1>(domainRadius.size(), domainRadius.data(), pointsDb.devRadPtr);
264#endif
265
266}//CalcConvVPVeloToSetOfPointsFromWake(...)
267
268
269
270
271#if defined(USE_CUDA)
272double VelocityBarnesHut::GPUCalcConvVeloToSetOfPointsFromWake(std::unique_ptr<BHcu::CudaTreeInfo>& cntrTree, const WakeDataBase& pointsDb, std::vector<Point2D>& velo, std::vector<double>& domainRadius, bool calcVelo, bool calcRadius)
273{
274 const double& theta = W.getPassport().numericalSchemes.nbodyTheta;
276
277 int npt = cntrTree->nObject;
278
279 float tBLD = 0.0f, tUPW = 0.0f, tDNV;
280
281 auto& inflTree = *W.getCuda().inflTreeWake;
282
283
284 VMlib::vmTimer timerA;
285 timerA.start();
286 if (cntrTree->nObject > 1024 * 80)
287 tDNV = inflTree.DownwardTraversalVorticesToPoints<1024>(*cntrTree, (Point2D*)pointsDb.devVelPtr, pointsDb.devRadPtr, theta, order, calcRadius);
288 else
289 tDNV = inflTree.DownwardTraversalVorticesToPoints<32>(*cntrTree, (Point2D*)pointsDb.devVelPtr, pointsDb.devRadPtr, theta, order, calcRadius);
290 timerA.stop();
291
292 //std::cout << "nvt = " << npt << std::endl;
293 //std::cout << "tBLD = " << tBLD << std::endl;
294 //std::cout << "tUPW = " << tUPW << std::endl;
295 //std::cout << "tDNV = " << tDNV << std::endl;
296
297 std::vector<Point2D> Vel;
298 if (calcVelo)
299 {
300 Vel.resize(npt);
301 W.getCuda().CopyMemFromDev<double, 2>(npt, (double*)pointsDb.devVelPtr, (double*)Vel.data(), 20);
302
303 for (size_t q = 0; q < npt; ++q)
304 velo[q] += Vel[q];
305 }
306
307 if (calcRadius)
308 W.getCuda().CopyMemFromDev<double, 1>(npt, pointsDb.devRadPtr, domainRadius.data(), 212);
309
310 return timerA.duration();
311}
312
313
314void VelocityBarnesHut::GPUCalcConvVelocityToSetOfPointsFromSheets(std::unique_ptr<BHcu::CudaTreeInfo>& cntrTree, const WakeDataBase& pointsDb, std::vector<Point2D>& velo) const
315{
316 double*& velD = pointsDb.devVelPtr;
317
318 const double& theta = W.getPassport().numericalSchemes.nbodyTheta;
320
321 std::vector<Point2D> newV(velo.size());
322
323 int npt = cntrTree->nObject;
324
325 if (npt > 0)
326 {
327 int nTotPan = (int)W.getAirfoil(0).getNumberOfPanels();
328 for (size_t q = 1; q < W.getNumberOfAirfoil(); ++q)
329 nTotPan += (int)W.getAirfoil(q).getNumberOfPanels();
330 auto& afl = W.getAirfoil(0);
331
332 //Влияние вихревых слоев
333 W.getCuda().inflTreePnlVortex->DownwardTraversalPanelsToPoints(*cntrTree, (Point2D*)velD, theta, order);
334 W.getCuda().CopyMemFromDev<double, 2>(npt, velD, (double*)newV.data());
335
336 for (size_t q = 0; q < velo.size(); ++q)
337 velo[q] += newV[q];
338
340 {
341 //Влияние слоев источников
342 W.getCuda().inflTreePnlSource->DownwardTraversalPanelsToPoints(*cntrTree, (Point2D*)velD, theta, order);
343 W.getCuda().CopyMemFromDev<double, 2>(npt, velD, (double*)newV.data());
344
345 for (size_t q = 0; q < velo.size(); ++q)
346 velo[q] += newV[q];
347 }
348 }
349}//GPUCalcConvVelocityToSetOfPointsFromSheets(...)
350#endif
351
352
353
354
355
356
357
358
359
Заголовочный файл с описанием класса Airfoil.
Заголовочный файл с описанием класса Boundary.
Заголовочный файл с функциями для метода GMRES.
Заголовочный файл с описанием класса MeasureVP.
Заголовочный файл с описанием класса Mechanics.
Заголовочный файл с описанием класса StreamParser.
const double IDPI
Число .
Definition defs.h:79
void ModifyE2(double *ee2, double dst2)
Заголовочный файл с описанием класса VelocityBarnesHut.
Заголовочный файл с описанием класса Wake.
Заголовочный файл с описанием класса World2D.
size_t getNumberOfPanels() const
Возврат количества панелей на профиле
Definition Airfoil2D.h:163
float DownwardTraversalVorticesToPoints(CpuTreeInfo &cntrTree, std::vector< Point2D > &vel, std::vector< double > &epsast, double theta, int order, bool calcRadius)
PhysicalProperties physicalProperties
Структура с физическими свойствами задачи
Definition Passport2D.h:301
NumericalSchemes numericalSchemes
Структура с используемыми численными схемами
Definition Passport2D.h:307
VelocityBarnesHut(const World2D &W_)
Конструктор
virtual ~VelocityBarnesHut()
Деструктор
virtual void CalcConvVPVeloToSetOfPointsFromWake(const WakeDataBase &pointsDb, std::vector< Point2D > &velo, std::vector< double > &domainRadius, bool calcVelo, bool calcRadius) override
virtual float CalcConvVeloToSetOfPointsFromWake(const WakeDataBase &pointsDb, std::vector< Point2D > &velo, std::vector< double > &domainRadius, bool calcVelo, bool calcRadius) override
Вычисление конвективных скоростей и радиусов вихревых доменов в заданном наборе точек от следа
Абстрактный класс, определяющий способ вычисления скоростей
Definition Velocity2D.h:105
const World2D & W
Константная ссылка на решаемую задачу
Definition Velocity2D.h:108
Класс, опеделяющий набор вихрей
std::vector< Vortex2D > vtx
Список вихревых элементов
Класс, опеделяющий текущую решаемую задачу
Definition World2D.h:77
size_t getNumberOfAirfoil() const
Возврат количества профилей в задаче
Definition World2D.h:180
bool isAnyMovableOrDeformable() const
Возврат признака того, что хотя бы один из профилей подвижный или деформируемый
Definition World2D.cpp:2349
const Wake & getWake() const
Возврат константной ссылки на вихревой след
Definition World2D.h:232
const Airfoil & getAirfoil(size_t i) const
Возврат константной ссылки на объект профиля
Definition World2D.h:163
const WakeDataBase & getSource() const
Возврат константной ссылки на источники в области течения
Definition World2D.h:248
const Gpu & getCuda() const
Возврат константной ссылки на объект, связанный с видеокартой (GPU)
Definition World2D.h:273
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition World2D.h:263
CpuTreeInfo & getCntrTreeWake() const
Definition World2D.h:240
CpuTreeInfo & getInflTreeWake() const
Definition World2D.h:239
double getCurrentTime() const
Definition WorldGen.h:100
numvector< T, n > & toZero(P val=0)
Установка всех компонент вектора в константу (по умолчанию — нуль)
Definition numvector.h:528
Класс засекания времени
Definition TimesGen.h:59
double duration() const
Definition TimesGen.h:143
const vmTimer & stop() const
Останов работающего счетчика времени
Definition TimesGen.h:125
const vmTimer & start() const
Запуск (первый или повторный) счетчика времени
Definition TimesGen.h:109
const vmTimer & reset() const
Сброс счетчика времени
Definition TimesGen.h:101
double boundDenom(double r2, double eps2)
Способ сглаживания скорости вихря (вихрь Рэнкина или вихрь Ламба)
Definition defs.h:569
double accelCft(double currentTime) const
Функция-множитель, позволяющая моделировать разгон