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