VM2D 1.14
Vortex methods for 2D flows simulation
Loading...
Searching...
No Matches
Boundary2DVortexCollocN.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: Boundary2DVortexCollocN.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
43
44#include "Airfoil2D.h"
45#include "MeasureVP2D.h"
46#include "Mechanics2D.h"
47#include "StreamParser.h"
48#include "Velocity2D.h"
49#include "Wake2D.h"
50#include "World2D.h"
51#include "Gmres2D.h"
52
53using namespace VM2D;
54
55//Конструктор
56BoundaryVortexCollocN::BoundaryVortexCollocN(const World2D& W_, size_t numberInPassport_) :
57 Boundary(W_, numberInPassport_, 1)
58 {
59 c.reserve(afl.getNumberOfPanels());
60 for (size_t i=0; i < afl.getNumberOfPanels(); ++i)
61 c.push_back(0.5*(afl.getR(i)+afl.getR(i+1)));
62 };
63
64
65//Пересчет решения на интенсивность вихревого слоя
67{
68 Vortex2D virtVort;
69 Point2D midNorm;
70
71 size_t np = afl.getNumberOfPanels();
72
74
76
77 //Очистка и резервирование памяти
79 virtualWake.vecHalfGamma.reserve(np * nVortPerPan);
80
81 //Очистка и резервирование памяти
82 virtualWake.aflPan.clear();
83 virtualWake.aflPan.reserve(np * nVortPerPan);
84
85 //Резервирование памяти
86 virtualWake.vtx.clear();
87 virtualWake.vtx.reserve(np * nVortPerPan);
88
89 //Очистка и резервирование памяти
90 vortexBeginEnd.clear();
91 vortexBeginEnd.reserve(np);
92
94
95 std::pair<int, int> pair;
96
97 for (size_t i = 0; i < np; ++i)
98 {
99 midNorm = afl.nrm[i] * delta;
100 size_t iNext = (i < np-1) ? i + 1 : 0;
101 size_t iPrev = (i > 0) ? i - 1 : np - 1;
102
103 double Gamma = (sol(i) / (afl.len[iPrev] + afl.len[i]) + sol(iNext) / (afl.len[iNext] + afl.len[i])) * afl.len[i];
104
105 size_t NEWnVortPerPan = std::max(static_cast<int>(std::ceil(fabs(Gamma) / W.getPassport().wakeDiscretizationProperties.maxGamma)), nVortPerPan);
106
107 pair.first = (int)virtualWake.vtx.size();
108
109
110 Point2D dr = 1.0 / NEWnVortPerPan * (afl.getR(i + 1) - afl.getR(i));
111 virtVort.g() = Gamma / NEWnVortPerPan;
112
113 for (size_t j = 0; j < NEWnVortPerPan; ++j)
114 {
115 virtVort.r() = afl.getR(i) + (0.5 + j) * dr + delta * afl.nrm[i];
116
117 virtualWake.vtx.push_back(virtVort);
118
119 virtualWake.vecHalfGamma.push_back(0.5 * Gamma / afl.len[i] * afl.tau[i]);
120 virtualWake.aflPan.push_back({ numberInPassport, i });
121 }
122
123 pair.second = (int)virtualWake.vtx.size();
124 vortexBeginEnd.push_back(pair);
125
126 sheets.freeVortexSheet(i, 0) = Gamma / afl.len[i];
127 }
128
129
130}//SolutionToFreeVortexSheetAndVirtualVortex(...)
131
132
133//Генерация блока матрицы
134void BoundaryVortexCollocN::FillMatrixSelf(Eigen::MatrixXd& matr, Eigen::VectorXd& lastLine, Eigen::VectorXd& lactCol)
135{
136 size_t np = afl.getNumberOfPanels();
137
138 for (size_t i = 0; i < np; ++i)
139 {
140 lactCol(i) = 1.0;
141 lastLine(i) = 1.0;
142 }
143
144
145#pragma omp parallel for shared(matr)
146 for (int i = 0; i < np; ++i)
147 for (size_t j = 0; j < np; ++j)
148 {
149 matr(i, j) = -(afl.tau[i] & (c[i]-afl.getR(j)) ) * IDPI / (c[i]-afl.getR(j)).length2();
150 }
151}//FillMatrixSelf(...)
152
153void BoundaryVortexCollocN::FillIQSelf(std::pair<Eigen::MatrixXd, Eigen::MatrixXd>& IQ)
154{
155 //afl.calcIQ(1, afl, IQ);
156}//FillIQSelf(...)
157
158//Генерация блока матрицы влияния от другого профиля того же типа
159void BoundaryVortexCollocN::FillMatrixFromOther(const Boundary& otherBoundary, Eigen::MatrixXd& matr)
160{
161#pragma omp parallel for shared(matr)
162 for (int i = 0; i < afl.getNumberOfPanels(); ++i)
163 for (size_t j = 0; j < otherBoundary.afl.getNumberOfPanels(); ++j)
164 {
165
166 matr(i, j) = -(afl.tau[i] & (c[i]-otherBoundary.afl.getR(j)) ) * IDPI / (c[i]-otherBoundary.afl.getR(j)).length2();
167 }
168}//FillMatrixFromOther(...)
169
170
171void BoundaryVortexCollocN::FillIQFromOther(const Boundary& otherBoundary, std::pair<Eigen::MatrixXd, Eigen::MatrixXd>& IQ)
172{
173 //afl.calcIQ(1, otherBoundary.afl, IQ);
174}//FillIQFromOther(...)
175
176
177//Вычисление скоростей в наборе точек, вызываемых наличием слоев вихрей и источников на профиле
178void BoundaryVortexCollocN::CalcConvVelocityToSetOfPointsFromSheets(const WakeDataBase& pointsDb, std::vector<Point2D>& velo) const
179{
180 std::vector<Point2D> selfVelo(pointsDb.vtx.size());
181
182 double cft = IDPI;
183
184#pragma warning (push)
185#pragma warning (disable: 4101)
186 //Локальные переменные для цикла
187 Point2D velI;
188 Point2D tempVel;
189 //double dst2eps, dst2;
190#pragma warning (pop)
191
192#pragma omp parallel for default(none) shared(selfVelo, pointsDb, cft, std::cout) private(velI, tempVel)
193 for (int i = 0; i < pointsDb.vtx.size(); ++i)
194 {
195 velI.toZero();
196
197 const Point2D& posI = pointsDb.vtx[i].r();
198
201 for (size_t j = 0; j < sheets.getSheetSize(); ++j)
202 {
203 Point2D dj = afl.getR(j + 1) - afl.getR(j);
204 Point2D tauj = dj.unit();
205
206 Point2D s = posI - afl.getR(j);
207 Point2D p = posI - afl.getR(j + 1);
208
209 double a = VMlib::Alpha(p, s);
210
211 double lambda;
212 if ( (s.length2() > 1e-16) && (p.length2() > 1e-16) )
213 lambda = VMlib::Lambda(p, s);
214 else
215 lambda = 0.0;
216
217 Point2D skos = -a * tauj.kcross() + lambda * tauj;
218
219 velI += sheets.freeVortexSheet(j, 0) * skos.kcross();
220 velI += sheets.attachedVortexSheet(j, 0) * skos.kcross();
221 velI += sheets.attachedSourceSheet(j, 0) * skos;
222 }//for j
223
224 velI *= cft;
225 selfVelo[i] = velI;
226
227 }//for i
228
229 for (size_t i = 0; i < velo.size(); ++i)
230 velo[i] += selfVelo[i];
231}//CalcConvVelocityToSetOfPointsFromSheets(...)
232
233
234#if defined(USE_CUDA)
235void BoundaryVortexCollocN::GPUCalcConvVelocityToSetOfPointsFromSheets(const WakeDataBase& pointsDb, std::vector<Point2D>& velo) const
236{
237 if (afl.numberInPassport == 0)
238 {
239 const size_t npt = pointsDb.vtx.size();
240 double*& dev_ptr_pt = pointsDb.devVtxPtr;
241
242 size_t npnl = afl.getNumberOfPanels();
243 for (size_t q = 1; q < W.getNumberOfAirfoil(); ++q)
244 npnl += W.getAirfoil(q).getNumberOfPanels();
245
246 double*& dev_ptr_r = afl.devRPtr;
247 double*& dev_ptr_freeVortexSheet = afl.devFreeVortexSheetPtr;
248 double*& dev_ptr_attachedVortexSheet = afl.devAttachedVortexSheetPtr;
249 double*& dev_ptr_attachedSourceSheet = afl.devAttachedSourceSheetPtr;
250
251 double*& dev_ptr_freeVortexSheetLin = afl.devFreeVortexSheetLinPtr;
252 double*& dev_ptr_attachedVortexSheetLin = afl.devAttachedVortexSheetLinPtr;
253 double*& dev_ptr_attachedSourceSheetLin = afl.devAttachedSourceSheetLinPtr;
254
255 std::vector<Point2D>& Vel = velo;
256 std::vector<Point2D> newV(npt);
257 double*& dev_ptr_vel = pointsDb.devVelPtr;
258
259 //Явная синхронизация слоев не нужна, т.к. она выполняется в Gpu::RefreshAfls()
260 if (npt > 0)
261 {
262 //double tt1 = omp_get_wtime();
263 cuCalculateConvVeloWakeFromVirtual(npt, dev_ptr_pt, npnl, dev_ptr_r, \
264 dev_ptr_freeVortexSheet, dev_ptr_freeVortexSheetLin, \
265 dev_ptr_attachedVortexSheet, dev_ptr_attachedVortexSheetLin, \
266 dev_ptr_attachedSourceSheet, dev_ptr_attachedSourceSheetLin, \
267 dev_ptr_vel);
268 //double tt2 = omp_get_wtime();
269 //std::cout << "SHEET: " << tt2 - tt1 << std::endl;
270
271 W.getCuda().CopyMemFromDev<double, 2>(npt, dev_ptr_vel, (double*)newV.data());
272
273
274 for (size_t q = 0; q < Vel.size(); ++q)
275 Vel[q] += newV[q];
276 }
277 }
278}
279//GPUCalcConvVelocityToSetOfPointsFromSheets(...)
280#endif
281
282
283//Вычисление интенсивностей присоединенного вихревого слоя и присоединенного слоя источников
285{
286
287 for (size_t i = 0; i < sheets.getSheetSize(); ++i)
288 {
291 }
292
293 for (size_t i = 0; i < sheets.getSheetSize(); ++i)
294 {
295 sheets.attachedVortexSheet(i, 0) = 0.5 * (afl.getV(i) + afl.getV(i + 1)) & afl.tau[i];
296 sheets.attachedSourceSheet(i, 0) = 0.5 * (afl.getV(i) + afl.getV(i + 1)) & afl.nrm[i];
297 }
298}//ComputeAttachedSheetsIntensity()
299
300
301//Вычисляет влияния части подряд идущих вихрей из вихревого следа на прямолинейную панель для правой части
302void BoundaryVortexCollocN::GetInfluenceFromVorticesToRectPanel(size_t panel, const Vortex2D* ptr, ptrdiff_t count, std::vector<double>& wakeRhs) const
303{
304 double& velI = wakeRhs[0];
305
306 const Point2D& posI = c[panel];
307
308 for (size_t it = 0; it != count; ++it)
309 {
310 const Vortex2D& vt = ptr[it];
311
312 const Point2D& posJ = vt.r();
313 const double& gamJ = vt.g();
314 const double sigma2 = sqr(vt.sigma());
315
316 Point2D d = posI - posJ;
317 velI -= (gamJ * afl.len[panel] / std::max(d.length2(), sigma2)) * (afl.tau[panel] & d);
318 }
319}// GetInfluenceFromVorticesToRectPanel(...)
320
321
322
323//Вычисляет влияния части подряд идущих источников в области течения на прямолинейную панель для правой части
324void BoundaryVortexCollocN::GetInfluenceFromSourcesToRectPanel(size_t panel, const Vortex2D* ptr, ptrdiff_t count, std::vector<double>& wakeRhs) const
325{
326 double& velI = wakeRhs[0];
327
328 const Point2D& posI = 0.5 * (afl.getR(panel) + afl.getR(panel + 1));
329
330 for (size_t it = 0; it != count; ++it)
331 {
332 const Vortex2D& vt = ptr[it];
333
334 const Point2D& posJ = vt.r();
335 const double& gamJ = vt.g();
336 const double sigma2 = sqr(vt.sigma());
337
338 Point2D d = posI - posJ;
339
340 velI += (gamJ * afl.len[panel] / std::max(d.length2(), sigma2)) * (afl.nrm[panel] & d);
341 }
342}// GetInfluenceFromSourcesToRectPanel(...)
343
344
345//Вычисление влияния слоя источников конкретной прямолинейной панели на вихрь в области течения
347{
348 vel.toZero();
349
350 const Point2D& posI = ptr.r();
351
352 Point2D dj = afl.getR(panel + 1) - afl.getR(panel);
353 Point2D tauj = dj.unit();
354
355 Point2D s = posI - afl.getR(panel);
356 Point2D p = posI - afl.getR(panel + 1);
357
358 double a = VMlib::Alpha(p, s);
359
360 double lambda;
361 if ((s.length2() > 1e-16) && (p.length2() > 1e-16))
362 lambda = VMlib::Lambda(p, s);
363 else
364 lambda = 0.0;
365
366 vel += sheets.attachedSourceSheet(panel, 0) * (-a * tauj.kcross() + lambda * tauj);
367}// GetInfluenceFromSourceSheetAtRectPanelToVortex(...)
368
369//Вычисление влияния вихревых слоев (свободный + присоединенный) конкретной прямолинейной панели на вихрь в области течения
371{
372 vel.toZero();
373
374 const Point2D& posI = ptr.r();
375
376 Point2D dj = afl.getR(panel + 1) - afl.getR(panel);
377 Point2D tauj = dj.unit();
378
379 Point2D s = posI - afl.getR(panel);
380 Point2D p = posI - afl.getR(panel + 1);
381 double a = VMlib::Alpha(p, s);
382
383 double lambda;
384 if ((s.length2() > 1e-16) && (p.length2() > 1e-16))
385 lambda = VMlib::Lambda(p, s);
386 else
387 lambda = 0.0;
388
389 Point2D skos = -a * tauj.kcross() + lambda * tauj;
390
391 vel += sheets.freeVortexSheet(panel, 0) * skos.kcross();
392 vel += sheets.attachedVortexSheet(panel, 0) * skos.kcross();
393
394}// GetInfluenceFromVortexSheetAtRectPanelToVortex(...)
395
396
397//Вычисляет влияния набегающего потока на прямолинейную панель для правой части
398void BoundaryVortexCollocN::GetInfluenceFromVInfToRectPanel(std::vector<double>& vInfRhs) const
399{
400 size_t np = afl.getNumberOfPanels();
401
402#pragma omp parallel for default(none) shared(vInfRhs, np)
403 for (int i = 0; i < np; ++i)
404 vInfRhs[i] = afl.nrm[i] & W.getV0();
405
406}// GetInfluenceFromVInfToRectPanel(...)
407
Заголовочный файл с описанием класса Airfoil.
Заголовочный файл с описанием класса BoundaryVortexCollocN.
Заголовочный файл с функциями для метода GMRES.
Заголовочный файл с описанием класса MeasureVP.
Заголовочный файл с описанием класса Mechanics.
Заголовочный файл с описанием класса StreamParser.
const double IDPI
Число .
Definition defs.h:79
Заголовочный файл с описанием класса Velocity.
Заголовочный файл с описанием класса Wake.
Заголовочный файл с описанием класса World2D.
std::vector< double > len
Длины панелей профиля
Definition Airfoil2D.h:94
const Point2D & getR(size_t q) const
Возврат константной ссылки на вершину профиля
Definition Airfoil2D.h:113
const Point2D & getV(size_t q) const
Возврат константной ссылки на скорость вершины профиля
Definition Airfoil2D.h:137
std::vector< Point2D > nrm
Нормали к панелям профиля
Definition Airfoil2D.h:81
std::vector< Point2D > tau
Касательные к панелям профиля
Definition Airfoil2D.h:91
size_t getNumberOfPanels() const
Возврат количества панелей на профиле
Definition Airfoil2D.h:163
const size_t numberInPassport
Номер профиля в паспорте
Definition Airfoil2D.h:188
Абстрактный класс, определяющий способ удовлетворения граничного условия на обтекаемом профиле
Definition Boundary2D.h:65
Sheet oldSheets
Слои на профиле с предыдущего шага
Definition Boundary2D.h:99
const World2D & W
Константная ссылка на решаемую задачу
Definition Boundary2D.h:68
const Airfoil & afl
Definition Boundary2D.h:77
Sheet sheets
Слои на профиле
Definition Boundary2D.h:96
std::vector< std::pair< int, int > > vortexBeginEnd
Номера первого и последнего вихрей, рождаемых на каждой панели профиля (формируется после решения СЛА...
Definition Boundary2D.h:83
VirtualWake virtualWake
Виртуальный вихревой след конкретного профиля
Definition Boundary2D.h:86
const size_t numberInPassport
Номер профиля в паспорте
Definition Boundary2D.h:71
virtual void GetInfluenceFromVortexSheetAtRectPanelToVortex(size_t panel, const Vortex2D &vtx, Point2D &vel) const override
Вычисление влияния вихревых слоев (свободный + присоединенный) конкретной прямолинейной панели на вих...
virtual void FillMatrixSelf(Eigen::MatrixXd &matr, Eigen::VectorXd &lastLine, Eigen::VectorXd &lactCol) override
Генерация блока матрицы
virtual void GetInfluenceFromVorticesToRectPanel(size_t panel, const Vortex2D *ptr, ptrdiff_t count, std::vector< double > &wakeRhs) const override
Вычисление влияния части подряд идущих вихрей из вихревого следа на прямолинейную панель для правой ч...
virtual void SolutionToFreeVortexSheetAndVirtualVortex(const Eigen::VectorXd &sol) override
Пересчет решения на интенсивность вихревого слоя и на рождаемые вихри на конкретном профиле
virtual void FillIQFromOther(const Boundary &otherBoundary, std::pair< Eigen::MatrixXd, Eigen::MatrixXd > &IQ) override
Генерация блока матрицы, состоящей из интегралов от (r-xi)/|r-xi|^2, влияние одного профиля на другой
virtual void GetInfluenceFromSourcesToRectPanel(size_t panel, const Vortex2D *ptr, ptrdiff_t count, std::vector< double > &wakeRhs) const override
Вычисление влияния части подряд источников из области течения на прямолинейную панель для правой част...
virtual void GetInfluenceFromVInfToRectPanel(std::vector< double > &vInfRhs) const override
Вычисление влияния набегающего потока на прямолинейную панель для правой части
virtual void ComputeAttachedSheetsIntensity() override
Вычисление интенсивностей присоединенного вихревого слоя и присоединенного слоя источников
virtual void FillIQSelf(std::pair< Eigen::MatrixXd, Eigen::MatrixXd > &IQ) override
Генерация блока матрицы, состоящей из интегралов от (r-xi)/|r-xi|^2, влияние профиля самого на себя
BoundaryVortexCollocN(const World2D &W_, size_t numberInPassport_)
Конструктор
virtual void CalcConvVelocityToSetOfPointsFromSheets(const WakeDataBase &pointsDb, std::vector< Point2D > &velo) const override
Вычисление конвективных скоростей в наборе точек, вызываемых наличием слоев вихрей и источников на пр...
virtual void GetInfluenceFromSourceSheetAtRectPanelToVortex(size_t panel, const Vortex2D &ptr, Point2D &vel) const override
Вычисление влияния слоя источников конкретной прямолинейной панели на вихрь в области течения
std::vector< Point2D > c
Контрольные точки - центры панелей
virtual void FillMatrixFromOther(const Boundary &otherBoundary, Eigen::MatrixXd &matr) override
Генерация блока матрицы влияния от другого профиля того же типа
WakeDiscretizationProperties wakeDiscretizationProperties
Структура с параметрами дискретизации вихревого следа
Definition Passport2D.h:304
const double & attachedVortexSheet(size_t n, size_t moment) const
Definition Sheet2D.h:105
const double & attachedSourceSheet(size_t n, size_t moment) const
Definition Sheet2D.h:110
const double & freeVortexSheet(size_t n, size_t moment) const
Definition Sheet2D.h:100
size_t getSheetSize() const
Definition Sheet2D.h:95
std::vector< Point2D > vecHalfGamma
Скорость вихрей виртуального следа конкретного профиля (равна Gamma/2) используется для расчета давле...
std::vector< std::pair< size_t, size_t > > aflPan
Пара чисел: номер профиля и номер панели, на которой рожден виртуальный вихрь
Класс, опеделяющий набор вихрей
std::vector< Vortex2D > vtx
Список вихревых элементов
Класс, опеделяющий текущую решаемую задачу
Definition World2D.h:77
size_t getNumberOfAirfoil() const
Возврат количества профилей в задаче
Definition World2D.h:180
const Airfoil & getAirfoil(size_t i) const
Возврат константной ссылки на объект профиля
Definition World2D.h:163
Point2D getV0() const
Возврат текущей скорости набегающего потока
Definition World2D.h:148
const Gpu & getCuda() const
Возврат константной ссылки на объект, связанный с видеокартой (GPU)
Definition World2D.h:273
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition World2D.h:263
Класс, опеделяющий двумерный вихревой элемент
Definition Vortex2D.h:59
HD Point2D & r()
Функция для доступа к радиус-вектору вихря
Definition Vortex2D.h:92
HD double & g()
Функция для доступа к циркуляции вихря
Definition Vortex2D.h:100
numvector< T, 2 > kcross() const
Геометрический поворот двумерного вектора на 90 градусов
Definition numvector.h:511
auto length2() const -> typename std::remove_const< typename std::remove_reference< decltype(this->data[0])>::type >::type
Вычисление квадрата нормы (длины) вектора
Definition numvector.h:386
numvector< T, n > & toZero(P val=0)
Установка всех компонент вектора в константу (по умолчанию — нуль)
Definition numvector.h:528
auto unit(P newlen=1) const -> numvector< typename std::remove_const< decltype(this->data[0] *newlen)>::type, n >
Вычисление орта вектора или вектора заданной длины, коллинеарного данному
Definition numvector.h:402
double Lambda(const Point2D &p, const Point2D &s)
Вспомогательная функция вычисления логарифма отношения норм векторов
Definition defs.cpp:268
double Alpha(const Point2D &p, const Point2D &s)
Вспомогательная функция вычисления угла между векторами
Definition defs.cpp:262
int minVortexPerPanel
Минимальное число вихрей, рождаемых на каждой панели профииля
Definition Passport2D.h:141
double delta
Расстояние, на которое рождаемый вихрь отодвигается от профиля
Definition Passport2D.h:138
double maxGamma
Максимально допустимая циркуляция вихря
Definition Passport2D.h:144