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
52using namespace VM2D;
53
54//Конструктор
55BoundaryVortexCollocN::BoundaryVortexCollocN(const World2D& W_, size_t numberInPassport_) :
56 Boundary(W_, numberInPassport_, 1)
57 {
58 c.reserve(afl.getNumberOfPanels());
59 for (size_t i=0; i < afl.getNumberOfPanels(); ++i)
60 c.push_back(0.5*(afl.getR(i)+afl.getR(i+1)));
61 };
62
63
64//Пересчет решения на интенсивность вихревого слоя
66{
67 Vortex2D virtVort;
68 Point2D midNorm;
69
70 size_t np = afl.getNumberOfPanels();
71
73
75
76 //Очистка и резервирование памяти
78 virtualWake.vecHalfGamma.reserve(np * nVortPerPan);
79
80 //Очистка и резервирование памяти
81 virtualWake.aflPan.clear();
82 virtualWake.aflPan.reserve(np * nVortPerPan);
83
84 //Резервирование памяти
85 virtualWake.vtx.clear();
86 virtualWake.vtx.reserve(np * nVortPerPan);
87
88 //Очистка и резервирование памяти
89 vortexBeginEnd.clear();
90 vortexBeginEnd.reserve(np);
91
93
94 std::pair<int, int> pair;
95
96 for (size_t i = 0; i < np; ++i)
97 {
98 midNorm = afl.nrm[i] * delta;
99 size_t iNext = (i < np-1) ? i + 1 : 0;
100 size_t iPrev = (i > 0) ? i - 1 : np - 1;
101
102 double Gamma = (sol(i) / (afl.len[iPrev] + afl.len[i]) + sol(iNext) / (afl.len[iNext] + afl.len[i])) * afl.len[i];
103
104 size_t NEWnVortPerPan = std::max(static_cast<int>(std::ceil(fabs(Gamma) / W.getPassport().wakeDiscretizationProperties.maxGamma)), nVortPerPan);
105
106 pair.first = (int)virtualWake.vtx.size();
107
108
109 Point2D dr = 1.0 / NEWnVortPerPan * (afl.getR(i + 1) - afl.getR(i));
110 virtVort.g() = Gamma / NEWnVortPerPan;
111
112 for (size_t j = 0; j < NEWnVortPerPan; ++j)
113 {
114 virtVort.r() = afl.getR(i) + (0.5 + j) * dr + delta * afl.nrm[i];
115
116 virtualWake.vtx.push_back(virtVort);
117
118 virtualWake.vecHalfGamma.push_back(0.5 * Gamma / afl.len[i] * afl.tau[i]);
119 virtualWake.aflPan.push_back({ numberInPassport, i });
120 }
121
122 pair.second = (int)virtualWake.vtx.size();
123 vortexBeginEnd.push_back(pair);
124
125 sheets.freeVortexSheet(i, 0) = Gamma / afl.len[i];
126 }
127
128
129}//SolutionToFreeVortexSheetAndVirtualVortex(...)
130
131
132//Генерация блока матрицы
133void BoundaryVortexCollocN::FillMatrixSelf(Eigen::MatrixXd& matr, Eigen::VectorXd& lastLine, Eigen::VectorXd& lactCol)
134{
135 size_t np = afl.getNumberOfPanels();
136
137 for (size_t i = 0; i < np; ++i)
138 {
139 lactCol(i) = 1.0;
140 lastLine(i) = 1.0;
141 }
142
143
144#pragma omp parallel for shared(matr)
145 for (int i = 0; i < np; ++i)
146 for (size_t j = 0; j < np; ++j)
147 {
148 matr(i, j) = -(afl.tau[i] & (c[i]-afl.getR(j)) ) * IDPI / (c[i]-afl.getR(j)).length2();
149 }
150}//FillMatrixSelf(...)
151
152void BoundaryVortexCollocN::FillIQSelf(std::pair<Eigen::MatrixXd, Eigen::MatrixXd>& IQ)
153{
154 //afl.calcIQ(1, afl, IQ);
155}//FillIQSelf(...)
156
157//Генерация блока матрицы влияния от другого профиля того же типа
158void BoundaryVortexCollocN::FillMatrixFromOther(const Boundary& otherBoundary, Eigen::MatrixXd& matr)
159{
160#pragma omp parallel for shared(matr)
161 for (int i = 0; i < afl.getNumberOfPanels(); ++i)
162 for (size_t j = 0; j < otherBoundary.afl.getNumberOfPanels(); ++j)
163 {
164
165 matr(i, j) = -(afl.tau[i] & (c[i]-otherBoundary.afl.getR(j)) ) * IDPI / (c[i]-otherBoundary.afl.getR(j)).length2();
166 }
167}//FillMatrixFromOther(...)
168
169
170void BoundaryVortexCollocN::FillIQFromOther(const Boundary& otherBoundary, std::pair<Eigen::MatrixXd, Eigen::MatrixXd>& IQ)
171{
172 //afl.calcIQ(1, otherBoundary.afl, IQ);
173}//FillIQFromOther(...)
174
175
176//Вычисление скоростей в наборе точек, вызываемых наличием слоев вихрей и источников на профиле
177void BoundaryVortexCollocN::CalcConvVelocityToSetOfPointsFromSheets(const WakeDataBase& pointsDb, std::vector<Point2D>& velo) const
178{
179 std::vector<Point2D> selfVelo(pointsDb.vtx.size());
180
181 double cft = IDPI;
182
183#pragma warning (push)
184#pragma warning (disable: 4101)
185 //Локальные переменные для цикла
186 Point2D velI;
187 Point2D tempVel;
188 //double dst2eps, dst2;
189#pragma warning (pop)
190
191#pragma omp parallel for default(none) shared(selfVelo, pointsDb, cft, std::cout) private(velI, tempVel)
192 for (int i = 0; i < pointsDb.vtx.size(); ++i)
193 {
194 velI.toZero();
195
196 const Point2D& posI = pointsDb.vtx[i].r();
197
200 for (size_t j = 0; j < sheets.getSheetSize(); ++j)
201 {
202 Point2D dj = afl.getR(j + 1) - afl.getR(j);
203 Point2D tauj = dj.unit();
204
205 Point2D s = posI - afl.getR(j);
206 Point2D p = posI - afl.getR(j + 1);
207
208 double a = VMlib::Alpha(p, s);
209
210 double lambda;
211 if ( (s.length2() > 1e-16) && (p.length2() > 1e-16) )
212 lambda = VMlib::Lambda(p, s);
213 else
214 lambda = 0.0;
215
216 Point2D skos = -a * tauj.kcross() + lambda * tauj;
217
218 velI += sheets.freeVortexSheet(j, 0) * skos.kcross();
219 velI += sheets.attachedVortexSheet(j, 0) * skos.kcross();
220 velI += sheets.attachedSourceSheet(j, 0) * skos;
221 }//for j
222
223 velI *= cft;
224 selfVelo[i] = velI;
225
226 }//for i
227
228 for (size_t i = 0; i < velo.size(); ++i)
229 velo[i] += selfVelo[i];
230}//CalcConvVelocityToSetOfPointsFromSheets(...)
231
232
233#if defined(USE_CUDA)
234void BoundaryVortexCollocN::GPUCalcConvVelocityToSetOfPointsFromSheets(const WakeDataBase& pointsDb, std::vector<Point2D>& velo) const
235{
236 if (afl.numberInPassport == 0)
237 {
238 const size_t npt = pointsDb.vtx.size();
239 double*& dev_ptr_pt = pointsDb.devVtxPtr;
240
241 size_t npnl = afl.getNumberOfPanels();
242 for (size_t q = 1; q < W.getNumberOfAirfoil(); ++q)
243 npnl += W.getAirfoil(q).getNumberOfPanels();
244
245 double*& dev_ptr_r = afl.devRPtr;
246 double*& dev_ptr_freeVortexSheet = afl.devFreeVortexSheetPtr;
247 double*& dev_ptr_attachedVortexSheet = afl.devAttachedVortexSheetPtr;
248 double*& dev_ptr_attachedSourceSheet = afl.devAttachedSourceSheetPtr;
249
250 double*& dev_ptr_freeVortexSheetLin = afl.devFreeVortexSheetLinPtr;
251 double*& dev_ptr_attachedVortexSheetLin = afl.devAttachedVortexSheetLinPtr;
252 double*& dev_ptr_attachedSourceSheetLin = afl.devAttachedSourceSheetLinPtr;
253
254 std::vector<Point2D>& Vel = velo;
255 std::vector<Point2D> newV(npt);
256 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, eps2);
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
315 Point2D d = posI - posJ;
316 //std::cout << "d = " << d << std::endl;
317
318 velI -= (gamJ * afl.len[panel] / std::max(d.length2(), W.getPassport().wakeDiscretizationProperties.eps2)) * (afl.tau[panel] & d);
319 }
320}// GetInfluenceFromVorticesToRectPanel(...)
321
322
323
324//Вычисляет влияния части подряд идущих источников в области течения на прямолинейную панель для правой части
325void BoundaryVortexCollocN::GetInfluenceFromSourcesToRectPanel(size_t panel, const Vortex2D* ptr, ptrdiff_t count, std::vector<double>& wakeRhs) const
326{
327 double& velI = wakeRhs[0];
328
329 const Point2D& posI = 0.5 * (afl.getR(panel) + afl.getR(panel + 1));
330
331 for (size_t it = 0; it != count; ++it)
332 {
333 const Vortex2D& vt = ptr[it];
334
335 const Point2D& posJ = vt.r();
336 const double& gamJ = vt.g();
337
338 Point2D d = posI - posJ;
339
340 velI += (gamJ * afl.len[panel] / std::max(d.length2(), W.getPassport().wakeDiscretizationProperties.eps2)) * (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.
Заголовочный файл с описанием класса MeasureVP.
Заголовочный файл с описанием класса Mechanics.
Заголовочный файл с описанием класса StreamParser.
Заголовочный файл с описанием класса 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:292
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:74
size_t getNumberOfAirfoil() const
Возврат количества профилей в задаче
Definition World2D.h:174
const Airfoil & getAirfoil(size_t i) const
Возврат константной ссылки на объект профиля
Definition World2D.h:157
Point2D getV0() const
Возврат текущей скорости набегающего потока
Definition World2D.h:142
const Gpu & getCuda() const
Возврат константной ссылки на объект, связанный с видеокартой (GPU)
Definition World2D.h:261
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition World2D.h:251
Класс, опеделяющий двумерный вихревой элемент
Definition Vortex2D.h:59
HD Point2D & r()
Функция для доступа к радиус-вектору вихря
Definition Vortex2D.h:87
HD double & g()
Функция для доступа к циркуляции вихря
Definition Vortex2D.h:95
numvector< T, 2 > kcross() const
Геометрический поворот двумерного вектора на 90 градусов
Definition numvector.h:510
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:527
auto unit(P newlen=1) const -> numvector< typename std::remove_const< decltype(this->data[0] *newlen)>::type, n >
Вычисление орта вектора или вектора заданной длины, коллинеарного данному
Definition numvector.h:402
const double IDPI
Число .
Definition defs.h:85
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
double eps2
Квадрат радиуса вихря
Definition Passport2D.h:129