VM2D 1.14
Vortex methods for 2D flows simulation
Loading...
Searching...
No Matches
VM2D::World2D Class Reference

Класс, опеделяющий текущую решаемую задачу More...

#include <World2D.h>

Inheritance diagram for VM2D::World2D:
Collaboration diagram for VM2D::World2D:

Public Member Functions

Point2D getV0 () const
 Возврат текущей скорости набегающего потока
 
bool isAnyMovable () const
 Возврат признака того, что хотя бы один из профилей подвижный
 
bool isAnyMovableOrDeformable () const
 Возврат признака того, что хотя бы один из профилей подвижный или деформируемый
 
const AirfoilgetAirfoil (size_t i) const
 Возврат константной ссылки на объект профиля
 
const AirfoilGeometrygetOldAirfoil (size_t i) const
 Возврат константной ссылки на объект старого профиля
 
AirfoilgetNonConstAirfoil (size_t i) const
 Возврат неконстантной ссылки на объект профиля
 
size_t getNumberOfAirfoil () const
 Возврат количества профилей в задаче
 
const BoundarygetBoundary (size_t i) const
 Возврат константной ссылки на объект граничного условия
 
BoundarygetNonConstBoundary (size_t i) const
 Возврат неконстантной ссылки на объект граничного условия
 
size_t getNumberOfBoundary () const
 Возврат количества граничных условий в задаче
 
size_t getDispBoundaryInSystem (size_t i) const
 Возврат смещения в системе dispBoundaryInSystem.
 
const MeasureVPgetMeasureVP () const
 Возврат константной ссылки на measureVP.
 
MeasureVPgetNonConstMeasureVP () const
 Возврат неконстантной ссылки на measureVP.
 
const MechanicsgetMechanics (size_t i) const
 Возврат константной ссылки на объект механики
 
MechanicsgetNonConstMechanics (size_t i) const
 Возврат неконстантной ссылки на объект механики
 
const std::vector< std::unique_ptr< Mechanics > > & getMechanicsVector () const
 
const WakegetWake () const
 Возврат константной ссылки на вихревой след
 
WakegetNonConstWake () const
 Возврат неконстантной ссылки на вихревой след
 
CpuTreeInfogetInflTreeWake () const
 
CpuTreeInfogetCntrTreeWake () const
 
CpuTreeInfogetAuxTreePnl () const
 
CpuTreeInfogetCntrTreeVP () const
 
CpuTreeInfogetCntrTreePnl () const
 
const WakeDataBasegetSource () const
 Возврат константной ссылки на источники в области течения
 
const VelocitygetVelocity () const
 Возврат константной ссылки на объект для вычисления скоростей
 
VelocitygetNonConstVelocity () const
 Возврат неконстантной ссылки на объект для вычисления скоростей
 
const PassportgetPassport () const
 Возврат константной ссылки на паспорт
 
PassportgetNonConstPassport () const
 Возврат неконстантной ссылки на паспорт
 
const GpugetCuda () const
 Возврат константной ссылки на объект, связанный с видеокартой (GPU)
 
GpugetNonConstCuda () const
 Возврат неконстантной ссылки на объект, связанный с видеокартой (GPU)
 
const std::pair< Eigen::MatrixXd, Eigen::MatrixXd > & getIQ (size_t i, size_t j) const
 Возврат константной ссылки на объект, связанный с матрицей интегралов от (r-xi)/|r-xi|^2.
 
VMlib::TimersGengetTimers () const
 Возврат ссылки на временную статистику выполнения шага расчета по времени
 
bool ifDivisible (int val) const
 
void SolveLinearSystem ()
 Решение системы линейных алгебраических уравнений
 
void FillIQ ()
 Заполнение матрицы, состоящей из интегралов от (r-xi) / |r-xi|^2.
 
void FillMatrixAndRhs ()
 Заполнение матрицы системы для всех профилей
 
void ReserveMemoryForMatrixAndRhs ()
 Вычисляем размер матрицы и резервируем память под нее и под правую часть
 
void CalcVortexVelo ()
 Вычисление скоростей (и конвективных, и диффузионных) вихрей (в пелене и виртуальных), а также в точках вычисления VP.
 
void CalcPanelsVeloAndAttachedSheets ()
 Вычисление скоростей панелей и интенсивностей присоединенных слоев вихрей и источников
 
void CalcAndSolveLinearSystem ()
 Набор матрицы, правой части и решение СЛАУ
 
void MoveVortexes (std::vector< Point2D > &newPos, std::vector< double > *nutPtr=nullptr)
 Вычисляем новые положения вихрей (в пелене и виртуальных)
 
void CheckInside (std::vector< Point2D > &newPos, const std::vector< std::unique_ptr< AirfoilGeometry > > &oldAirfoil)
 Проверка проникновения вихрей внутрь профиля
 
void WakeAndAirfoilsMotion (bool dynamics, std::vector< double > *nutPtr=nullptr)
 Перемещение вихрей и профилей на шаге
 
 World2D (const VMlib::PassportGen &passport_)
 Конструктор
 
 ~World2D ()
 Деструктор
 
void GenerateMechanicsHeader (size_t mechanicsNumber)
 
virtual void Step () override
 Функция выполнения предварительного шага
 
VMlib::LogStreamgetInfo () const
 Возврат ссылки на объект LogStream Используется в техничеcких целях для организации вывода
 
std::ostream & getInfo (char x) const
 Возврат ссылки на поток вывода информации Необходимо для вывода телеметрической информации, информации об ошибках и т.п.
 
size_t getCurrentStep () const
 Возврат константной ссылки на параметры распараллеливания по MPI.
 
double getCurrentTime () const
 
const PassportGen & getPassportGen () const
 
bool isFinished () const
 Функция, возвращающая признак завершения счета в решаемой задаче
 

Public Attributes

int gabb
 
int check01
 
int check02
 
int checkPan
 
std::unique_ptr< CpuTreeInfoinflTreeWake
 Деревья для быстрого метода
 
std::unique_ptr< CpuTreeInfocntrTreeWake
 
std::unique_ptr< CpuTreeInfocntrTreeVP
 
std::unique_ptr< CpuTreeInfocntrTreePnl
 
std::unique_ptr< CpuTreeInfoauxTreePnl
 
VMlib::vmTimer timerInitialBuild
 
VMlib::vmTimer timerRhs
 
VMlib::vmTimer timerFillMatrix
 
VMlib::vmTimer timerSlaeSolve
 
VMlib::vmTimer timerConvVelo
 
VMlib::vmTimer timerInside
 
VMlib::vmTimer timerMerging
 
size_t nVtxBeforeMerging
 

Protected Attributes

LogStream info
 Поток для вывода логов и сообщений об ошибках
 
const PassportGen & passportGen
 Константная ссылка на паспорт конкретного расчета
 
std::unique_ptr< TimersGen > timers
 Сведения о временах выполнения основных операций
 
size_t currentStep
 Текущий номер шага в решаемой задаче
 
double currentTime
 Текущее время в решаемой задаче
 

Private Attributes

std::vector< std::unique_ptr< Airfoil > > airfoil
 Список умных указателей на обтекаемые профили
 
std::vector< std::unique_ptr< AirfoilGeometry > > oldAirfoil
 Список умных указателей на обтекаемые профили для сохранения старого положения
 
std::vector< std::unique_ptr< Boundary > > boundary
 Список умных указателей на формирователи граничных условий на профилях
 
std::vector< size_t > dispBoundaryInSystem
 Список номеров, с которых начинаются элементы правой части (или матрицы) системы для профилей
 
std::vector< std::unique_ptr< Mechanics > > mechanics
 Список умных указателей на типы механической системы для каждого профиля
 
std::unique_ptr< Velocityvelocity
 Умный укзатель на объект, определяющий методику вычисления скоростей
 
std::unique_ptr< Wakewake
 Умный указатель на вихревой след
 
std::unique_ptr< WakeDataBasesource
 Умный указатель на источники
 
std::unique_ptr< MeasureVPmeasureVP
 Умный указатель на алгоритм вычисления полей скоростей и давления (для сохранения в файл)
 
Eigen::MatrixXd matrReord
 Матрица системы
 
std::vector< std::vector< std::pair< Eigen::MatrixXd, Eigen::MatrixXd > > > IQ
 Матрица, состоящая из пар матриц, в которых хранятся касательные и нормальные компоненты интегралов от ядра
 
Eigen::MatrixXd invMatr
 Обратная матрица
 
bool useInverseMatrix
 Признак использования обратной матрицы
 
Eigen::VectorXd rhsReord
 Правая часть системы
 
Eigen::VectorXd sol
 Решение системы
 
const Passportpassport
 Константная ссылка на паспорт конкретного расчета
 
Gpu cuda
 Объект, управляющий графическим ускорителем
 

Detailed Description

Класс, опеделяющий текущую решаемую задачу

Author
Марчевский Илья Константинович
Сокол Ксения Сергеевна
Рятина Евгения Павловна
Колганова Александра Олеговна
Version
1.14
Date
6 марта 2026 г.

Definition at line 76 of file World2D.h.

Constructor & Destructor Documentation

◆ World2D()

World2D::World2D ( const VMlib::PassportGen passport_)

Конструктор

Parameters
[in]passport_константная ссылка на паспорт расчета

Definition at line 73 of file World2D.cpp.

73 :
74 WorldGen(passport_),
75 passport(dynamic_cast<const Passport&>(passport_)),
76 cuda(Gpu(*this))
77{
78 std::stringstream ss;
79 ss << "#" << passport.problemNumber << " (" << passport.problemName << ")";
81
83 currentStep = 0;
84
85 std::vector<std::string> timerLabels = { "Step", "MatRhs", "Solve", "ConvVel", "Nut", /*"Nbody",*/ "DiffVel", "Force", "VelPres", "Inside", "Restr", "Save"};
86 timers = std::make_unique<VMlib::TimersGen>(*this, timerLabels);
87
88 wake.reset(new Wake(*this));
89 // загрузка пелены из файла
91 wake->ReadFromFile(passport.wakesDir, passport.wakeDiscretizationProperties.fileWake); //Считываем из каталога с пеленой
92
93 source.reset(new WakeDataBase(*this));
94 // загрузка положений источников из файла
96 source->ReadFromFile(passport.dir, passport.wakeDiscretizationProperties.fileSource); //Считываем из текущего каталога
97
98
100 {
101 case 0:
102 velocity.reset(new VelocityBiotSavart(*this));
103 break;
104 case 1:
105 velocity.reset(new VelocityBarnesHut(*this));
111 else
113 break;
114 }
115
116 velocity->virtualVortexesParams.resize(passport.airfoilParams.size());
117
118 auto CreateBoundary = [this](size_t i) {
120 {
121 case 0:
122 this->boundary.emplace_back(new BoundaryVortexCollocN(*this, i));
123 //info('e') << "BoundaryMDV is not implemented now! " << std::endl;
124 //exit(1);
125 break;
126
127 case 1:
128 this->boundary.emplace_back(new BoundaryConstLayerAver(*this, i));
129 break;
130
131 case 2:
132 this->boundary.emplace_back(new BoundaryLinLayerAver(*this, i));
133 break;
134
135 default:
136 info('e') << "Unknown scheme!" << std::endl;
137 exit(1);
138 }
139 };
140
141
142 for (size_t i = 0; i < passport.airfoilParams.size(); ++i)
143 {
144
145 switch (passport.airfoilParams[i].mechanicalSystemType)
146 {
147 case 0:
148 airfoil.emplace_back(new AirfoilRigid(*this, i));
149 airfoil[i]->ReadFromFile(passport.airfoilsDir);
150 CreateBoundary(i);
151 mechanics.emplace_back(new MechanicsRigidImmovable(*this, i));
152 break;
153
154 case 1:
155 airfoil.emplace_back(new AirfoilRigid(*this, i));
156 airfoil[i]->ReadFromFile(passport.airfoilsDir);
157 CreateBoundary(i);
158 mechanics.emplace_back(new MechanicsRigidGivenLaw(*this, i));
159 break;
160
161 case 2:
162 airfoil.emplace_back(new AirfoilRigid(*this, i));
163 airfoil[i]->ReadFromFile(passport.airfoilsDir);
164 CreateBoundary(i);
165 mechanics.emplace_back(new MechanicsRigidOscillPart(*this, i));
166 break;
167
168 case 3:
169 airfoil.emplace_back(new AirfoilRigid(*this, i));
170 airfoil[i]->ReadFromFile(passport.airfoilsDir);
171 CreateBoundary(i);
172 mechanics.emplace_back(new MechanicsRigidRotatePart(*this, i));
173 break;
174
175 case 4:
176 airfoil.emplace_back(new AirfoilDeformable(*this, i));
177 airfoil[i]->ReadFromFile(passport.airfoilsDir);
178 CreateBoundary(i);
179 mechanics.emplace_back(new MechanicsDeformable(*this, i));
180 break;
181 }
182 }
183
184 if (getPassport().wakeDiscretizationProperties.sigma0 == 0)
185 {
186 double sumLength = 0.0;
187 size_t totNumPan = 0;
188 for (size_t bou = 0; bou < getNumberOfAirfoil(); ++bou)
189 {
190 for (size_t pnl = 0; pnl < getAirfoil(bou).getNumberOfPanels(); ++pnl)
191 sumLength += getAirfoil(bou).len[pnl];
192 totNumPan += getAirfoil(bou).getNumberOfPanels();
193 }
194 double eps = 0.5 * sumLength / totNumPan;
196 info('i') << "sigma0 = " << getPassport().wakeDiscretizationProperties.sigma0 << " is calculated automatically" << std::endl;
197 }
198
199 if (getPassport().wakeDiscretizationProperties.epscol == 0)
200 {
202
203 info('i') << "epscol = " << getPassport().wakeDiscretizationProperties.epscol << " is calculated automatically" << std::endl;
204 }
205
206 for (size_t afl = 0; afl < passport.airfoilParams.size(); ++afl)
207 if (passport.airfoilParams[afl].chord == 0)
208 {
209 auto& prm = getNonConstPassport().airfoilParams[afl];
210 prm.chord = (prm.initialGab.second[0] - prm.initialGab.first[0]) * prm.scale[0];
211 info('i') << "airfoil #" << afl << " chord = " << prm.chord << " is calculated automatically" << std::endl;
212 }
213
214
215#ifdef USE_CUDA
216 if (getNumberOfAirfoil() > 0)
218 cuda.Gmres.reset(new GmresSolver(*this));
219#endif
220
221 //2026-03-28
222 //считываем массив точек для подсчета и вывода поля скоростей и давлений
223 measureVP.reset(new MeasureVP(*this));
224
226 measureVP->ReadPointsFromFile(passport.dir);
227
228#ifdef OPTIMIZER
229// std::vector<Point2D> VPPoints, VPHistory;
230// for (size_t a = 0; a < getNumberOfAirfoil(); ++a)
231// {
232// const auto& afl = *airfoil[a];
233// for (size_t p = 0; p < afl.getNumberOfPanels(); ++p)
234// VPHistory.push_back(0.5 * (afl.getR(p) + afl.getR(p + 1)) + afl.nrm[p] * passport.airfoilParams[a].chord * 0.01);
235// }
236// if (passport.timeDiscretizationProperties.saveVPstep != 0)
237// measureVP->SetPoints(VPPoints, VPHistory);
238#endif
239
240 IQ.resize(passport.airfoilParams.size());
241 for (size_t i = 0; i < passport.airfoilParams.size(); ++i)
242 IQ[i].resize(passport.airfoilParams.size());
243
244
245 info.endl();
246 info.endl();
247 info('i') << "Start solving problem " << passport.problemName << std::endl;
248 info.endl();
249
250 VMlib::PrintLogoToStream(info('_') << std::endl);
251}//World2D(...)
Класс, определяющий тип обтекаемого профиля
std::vector< double > len
Длины панелей профиля
Definition Airfoil2D.h:94
size_t getNumberOfPanels() const
Возврат количества панелей на профиле
Definition Airfoil2D.h:163
Класс, определяющий тип обтекаемого профиля
Класс, определяющий способ удовлетворения граничного условия на обтекаемом профиле
Класс, определяющий способ удовлетворения граничного условия на обтекаемом профиле
Класс, определяющий способ удовлетворения граничного условия на обтекаемом профиле
Структура, хранящая данные и указатели на массивы на GPU для оптимизации итерационного решения СЛАУ н...
Definition cpuTreeInfo.h:96
Класс, обеспечивающий возможность выполнения вычислений на GPU по технологии Nvidia CUDA.
Definition Gpu2D.h:71
Класс, отвечающий за вычисление поля скорости и давления в заданых точках для вывода
Definition MeasureVP2D.h:65
Класс, определяющий вид механической системы
Класс, определяющий вид механической системы
Класс, определяющий вид механической системы
Класс, определяющий вид механической системы
Класс, определяющий вид механической системы
Класс, опеделяющий паспорт двумерной задачи
Definition Passport2D.h:253
std::string wakesDir
Каталог с файлами вихревых следов
Definition Passport2D.h:273
WakeDiscretizationProperties wakeDiscretizationProperties
Структура с параметрами дискретизации вихревого следа
Definition Passport2D.h:304
std::string airfoilsDir
Каталог с файлами профилей
Definition Passport2D.h:270
std::vector< AirfoilParams > airfoilParams
Список структур с параметрами профилей
Definition Passport2D.h:276
NumericalSchemes numericalSchemes
Структура с используемыми численными схемами
Definition Passport2D.h:307
Класс, определяющий способ вычисления скоростей
Класс, определяющий способ вычисления скоростей
Класс, опеделяющий набор вихрей
Класс, опеделяющий вихревой след (пелену)
Definition Wake2D.h:63
size_t getNumberOfAirfoil() const
Возврат количества профилей в задаче
Definition World2D.h:180
std::unique_ptr< CpuTreeInfo > inflTreeWake
Деревья для быстрого метода
Definition World2D.h:113
Gpu cuda
Объект, управляющий графическим ускорителем
Definition World2D.h:143
std::vector< std::unique_ptr< Airfoil > > airfoil
Список умных указателей на обтекаемые профили
Definition World2D.h:80
std::unique_ptr< MeasureVP > measureVP
Умный указатель на алгоритм вычисления полей скоростей и давления (для сохранения в файл)
Definition World2D.h:104
const Airfoil & getAirfoil(size_t i) const
Возврат константной ссылки на объект профиля
Definition World2D.h:163
std::unique_ptr< WakeDataBase > source
Умный указатель на источники
Definition World2D.h:101
std::vector< std::unique_ptr< Mechanics > > mechanics
Список умных указателей на типы механической системы для каждого профиля
Definition World2D.h:92
std::vector< std::unique_ptr< Boundary > > boundary
Список умных указателей на формирователи граничных условий на профилях
Definition World2D.h:86
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition World2D.h:263
std::unique_ptr< CpuTreeInfo > cntrTreePnl
Definition World2D.h:116
Passport & getNonConstPassport() const
Возврат неконстантной ссылки на паспорт
Definition World2D.h:268
std::unique_ptr< CpuTreeInfo > cntrTreeVP
Definition World2D.h:115
std::unique_ptr< Wake > wake
Умный указатель на вихревой след
Definition World2D.h:98
std::unique_ptr< Velocity > velocity
Умный укзатель на объект, определяющий методику вычисления скоростей
Definition World2D.h:95
const Passport & passport
Константная ссылка на паспорт конкретного расчета
Definition World2D.h:140
std::vector< std::vector< std::pair< Eigen::MatrixXd, Eigen::MatrixXd > > > IQ
Матрица, состоящая из пар матриц, в которых хранятся касательные и нормальные компоненты интегралов о...
Definition World2D.h:125
std::unique_ptr< CpuTreeInfo > cntrTreeWake
Definition World2D.h:114
void endl()
Вывод в поток логов пустой строки
Definition LogStream.h:103
void assignStream(std::ostream *pStr_, const std::string &label_)
Связывание потока логов с потоком вывода
Definition LogStream.h:80
TimeDiscretizationProperties timeDiscretizationProperties
Структура с параметрами процесса интегрирования по времени
std::string problemName
Название задачи
std::string dir
Рабочий каталог задачи
size_t problemNumber
Номер задачи
std::unique_ptr< TimersGen > timers
Сведения о временах выполнения основных операций
Definition WorldGen.h:66
double currentTime
Текущее время в решаемой задаче
Definition WorldGen.h:72
size_t currentStep
Текущий номер шага в решаемой задаче
Definition WorldGen.h:69
WorldGen(const VMlib::PassportGen &passport_)
Конструктор
Definition WorldGen.cpp:47
LogStream info
Поток для вывода логов и сообщений об ошибках
Definition WorldGen.h:60
void PrintLogoToStream(std::ostream &str)
Передача в поток вывода шапки программы VM2D/VM3D.
Definition defs.cpp:108
static std::ostream * defaultWorld2DLogStream
Поток вывода логов и ошибок задачи
Definition defs.h:222
std::pair< std::string, int > boundaryCondition
Метод аппроксимации граничных условий
Definition Passport2D.h:190
std::pair< std::string, int > velocityComputation
Definition Passport2D.h:180
std::pair< std::string, int > linearSystemSolver
Definition Passport2D.h:174
std::string fileSource
Имя файла с положениями источников (без полного пути)
Definition Passport2D.h:150
double epscol
Радиус коллапса
Definition Passport2D.h:132
std::string fileWake
Имя файла с начальным состоянием вихревого следа (без полного пути)
Definition Passport2D.h:147
double sigma0
Радиус вихря
Definition Passport2D.h:126
double timeStart
Начальное время
Definition PassportGen.h:61
int saveVPstep
Шаг вычисления и сохранения скорости и давления
Definition PassportGen.h:86
Here is the call graph for this function:

◆ ~World2D()

VM2D::World2D::~World2D ( )
inline

Деструктор

Definition at line 354 of file World2D.h.

354{};

Member Function Documentation

◆ CalcAndSolveLinearSystem()

void World2D::CalcAndSolveLinearSystem ( )

Набор матрицы, правой части и решение СЛАУ

Вызывается в Step()

Definition at line 2087 of file World2D.cpp.

2088{
2089 if (airfoil.size() > 0)
2090 {
2092
2093#if defined(__CUDACC__) || defined(USE_CUDA)
2096
2098
2099 if ((sch == 1) || (sch == 2) || (sch == 0))
2101 else
2102 {
2103 info('e') << "schemeSwitcher is not 0, or 1, or 2! " << std::endl;
2104 exit(1);
2105 }
2106
2107 cuda.RefreshWake(1);
2108 cuda.RefreshAfls(1);
2109 cuda.RefreshVirtualWakes(1);
2110
2111#endif
2112 const int linSystemScheme = passport.numericalSchemes.linearSystemSolver.second;
2113
2114 if (linSystemScheme == 0) //Gauss
2115 {
2116 if (currentStep == 0)
2117 {
2118#ifdef BRIDGE
2119 useInverseMatrix = true;
2120#endif //BRIDGE
2121
2122#ifdef INITIAL
2124 ((mechanics.size() == 1) && (!mechanics.front()->isDeform))
2125 ||
2126 (mechanics.size() > 1 && !isAnyMovableOrDeformable())
2127 );
2128#endif //INITIAL
2129 }
2130 }//if Gauss
2131
2132 if (linSystemScheme == 0 || linSystemScheme == 1 || (linSystemScheme == 2 && isAnyMovableOrDeformable()))
2133 FillIQ();
2134
2136
2137 //{
2138 // std::stringstream ss;
2139 // ss << "IQ1-" << currentStep;
2140 // std::ofstream of(passport.dir + "dbg/" + ss.str());
2141 // for (size_t i = 0; i < (IQ[0][0]).first.rows(); ++i)
2142 // {
2143 // for (size_t j = 0; j < (IQ[0][0]).first.cols(); ++j)
2144 // of << (IQ[0][0]).first(i, j) << " ";
2145 // of << std::endl;
2146 // }
2147 // of.close();
2148 //}
2149
2150 /*
2151 {
2152 std::stringstream ss;
2153 ss << "matr-" << currentStep;
2154 std::ofstream of(passport.dir + "dbg/" + ss.str());
2155 of.precision(16);
2156 for (size_t i = 0; i < matrReord.rows(); ++i)
2157 {
2158 for (size_t j = 0; j < matrReord.cols(); ++j)
2159 of << matrReord(i, j) << " ";
2160 of << std::endl;
2161 }
2162 of.close();
2163 }
2164
2165 {
2166 std::stringstream ss;
2167 ss << "rhs-" << currentStep;
2168 std::ofstream of(passport.dir + "dbg/" + ss.str());
2169 of.precision(16);
2170 for (size_t i = 0; i < rhsReord.rows(); ++i)
2171 {
2172 of << rhsReord(i) << std::endl;
2173 }
2174 of.close();
2175 }
2176
2177 //*/
2178
2180
2181 size_t currentRow = 0;
2182 for (size_t bou = 0; bou < boundary.size(); ++bou)
2183 {
2184 size_t nVars = boundary[bou]->GetUnknownsSize();
2185 Eigen::VectorXd locSol;
2186 locSol.resize(nVars);
2187 for (size_t i = 0; i < nVars; ++i)
2188 locSol(i) = sol(currentRow + i);
2189
2190 boundary[bou]->SolutionToFreeVortexSheetAndVirtualVortex(locSol);
2191 currentRow += nVars;// +1;
2192 }
2193
2194 //14-05-2024
2195 size_t nVirtVortices = 0;
2196 for (size_t bou = 0; bou < boundary.size(); ++bou)
2197 nVirtVortices += boundary[bou]->virtualWake.vtx.size();
2198
2199 wake->vtx.reserve(wake->vtx.size() + nVirtVortices);
2200 for (size_t bou = 0; bou < boundary.size(); ++bou)
2201 for (size_t v = 0; v < boundary[bou]->virtualWake.vtx.size(); ++v)
2202 wake->vtx.push_back(Vortex2D{ boundary[bou]->virtualWake.vtx[v].r(), 0.0, getPassport().wakeDiscretizationProperties.sigma0});
2203
2204 //for (size_t v = 0; v < wake->vtx.size(); ++v)
2205 //{
2206 // if (fabs(wake->vtx[v].g()) > 1.0)
2207 // std::cout << "Error gam! " << "v = " << v << ", gam[v] = " << wake->vtx[v].g() << std::endl;
2208 //}
2209
2210 //for (size_t bou = 0; bou < boundary.size(); ++bou)
2211 // for (size_t v = 0; v < airfoil[bou]->getNumberOfPanels(); ++v)
2212 // {
2213 // if (fabs(boundary[bou]->sheets.freeVortexSheet(v, 0)) > 1000.0)
2214 // std::cout << "Error gamma sheet! " << "bou = " << bou << ", v = " << v << ", gam[v] = " << boundary[bou]->sheets.freeVortexSheet(v, 0) << std::endl;
2215 // }
2216
2217 /*
2218 if (currentStep == 0)
2219 {
2220 Point2D addMass = { 0.0, 0.0 };
2221 for (size_t q = 0; q < airfoil[0]->getNumberOfPanels(); ++q)
2222 {
2223 addMass += (sol(q) + boundary[0]->sheets.attachedVortexSheet(q,0)) * 0.5 * (airfoil[0]->getR(q) + airfoil[0]->getR(q + 1)).kcross() * airfoil[0]->len[q];
2224 }
2225 addMass *= passport.physicalProperties.rho;
2226
2227 std::cout << "AddMass = " << addMass << std::endl;
2228 //exit(-42);
2229 }
2230 */
2231 }
2232}//CalcAndSolveLinearSystem()
void setAccelCoeff(double cft_)
Установка коэффициента разгона потока
Definition Gpu2D.h:281
void setMaxGamma(double gam_)
Установка максимально допустимой циркуляции вихря
Definition Gpu2D.h:304
void setSchemeSwitcher(int schemeSwitcher_)
Установка переключателя расчетных схем
Definition Gpu2D.h:318
PhysicalProperties physicalProperties
Структура с физическими свойствами задачи
Definition Passport2D.h:301
void ReserveMemoryForMatrixAndRhs()
Вычисляем размер матрицы и резервируем память под нее и под правую часть
Definition World2D.cpp:1375
bool isAnyMovableOrDeformable() const
Возврат признака того, что хотя бы один из профилей подвижный или деформируемый
Definition World2D.cpp:2349
bool useInverseMatrix
Признак использования обратной матрицы
Definition World2D.h:131
void FillIQ()
Заполнение матрицы, состоящей из интегралов от (r-xi) / |r-xi|^2.
Definition World2D.cpp:2045
void SolveLinearSystem()
Решение системы линейных алгебраических уравнений
Definition World2D.cpp:980
void FillMatrixAndRhs()
Заполнение матрицы системы для всех профилей
Definition World2D.cpp:1277
Eigen::VectorXd sol
Решение системы
Definition World2D.h:137
Класс, опеделяющий двумерный вихревой элемент
Definition Vortex2D.h:59
double getCurrentTime() const
Definition WorldGen.h:100
double accelCft(double currentTime) const
Функция-множитель, позволяющая моделировать разгон
double maxGamma
Максимально допустимая циркуляция вихря
Definition Passport2D.h:144
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CalcPanelsVeloAndAttachedSheets()

void World2D::CalcPanelsVeloAndAttachedSheets ( )

Вычисление скоростей панелей и интенсивностей присоединенных слоев вихрей и источников

Вызывается в Step()

Definition at line 1616 of file World2D.cpp.

1617{
1618 //вычисляем скорости панелей
1619 for (size_t i = 0; i < airfoil.size(); ++i)
1621
1622 //вычисляем интенсивности присоединенных слоев
1623 for (size_t i = 0; i < airfoil.size(); ++i)
1624 boundary[i]->ComputeAttachedSheetsIntensity();
1625
1626}//CalcPanelsVeloAndAttachedSheets(...)
double dt
Шаг по времени
Definition PassportGen.h:67
Here is the caller graph for this function:

◆ CalcVortexVelo()

void World2D::CalcVortexVelo ( )

Вычисление скоростей (и конвективных, и диффузионных) вихрей (в пелене и виртуальных), а также в точках вычисления VP.

Вызывается в Step()

Definition at line 1435 of file World2D.cpp.

1436{
1437 velocity->ResizeAndZero();
1438
1439 getTimers().start("ConvVel");
1440
1441 //Конвективные скорости всех вихрей (и в пелене, и виртуальных), индуцируемые вихрями в пелене
1442 //Подготовка CUDA
1443#if defined(__CUDACC__) || defined(USE_CUDA)
1444 cuda.RefreshWake(2);
1445
1446 cuda.RefreshAfls(2);
1447 cuda.RefreshVirtualWakes(2);
1448#endif
1449 getTimers().stop("ConvVel");
1450
1451 velocity->CalcConvVelo();
1452
1453 //Расчет средних значений eps для каждой панели и их передача на видеокарту
1454
1455 getTimers().start("DiffVel");
1456
1457 for (size_t bou = 0; bou < getNumberOfBoundary(); ++bou)
1459
1460#if defined(__CUDACC__) || defined(USE_CUDA)
1461 for (size_t i = 0; i < airfoil.size(); ++i)
1462 cuda.CopyMemToDev<double, 1>(airfoil[i]->getNumberOfPanels(), airfoil[i]->meanEpsOverPanel.data(), airfoil[i]->devMeanEpsOverPanelPtr);
1463#endif
1464
1465 getTimers().stop("DiffVel");
1466
1467 //Вычисление диффузионных скоростей вихрей (и в пелене, и виртуальных)
1468 velocity->CalcDiffVelo();
1469
1470 //Обнуление вязких напряжений, если они не были вычислены
1471 for (auto& afl : airfoil)
1472 {
1473 if (afl->viscousStress.size() == 0)
1474 afl->viscousStress.resize(afl->getNumberOfPanels(), 0.0);
1475 }
1476
1477 getTimers().start("Save");
1478
1479 /*
1480 //Сохранение всех параметров для вихрей в пелене
1481 if (!(currentStep % 1))
1482 {
1483 VMlib::CreateUserDirectory(passport.dir, "dbg");
1484 std::ostringstream sss, sss2;
1485 sss << "prmWake";
1486 sss << currentStep;
1487 sss2 << "testWake";
1488 sss2 << currentStep;
1489
1490 std::ofstream prmtFile(passport.dir + "dbg/" + sss.str());
1491 prmtFile.precision(11);
1492 prmtFile << "i x y g sigma epsast convVeloX convVeloY diffVeloX diffVeloY I0 I1 I2X I2Y I3X I3Y" << std::endl;
1493 for (size_t i = 0; i < wake->vtx.size(); ++i)
1494 prmtFile << i << " " \
1495 << wake->vtx[i].r()[0] << " " << wake->vtx[i].r()[1] << " " \
1496 << wake->vtx[i].g() << " " \
1497 << wake->vtx[i].sigma() << " " \
1498 << velocity->wakeVortexesParams.epsastWake[i] << " " \
1499 << velocity->wakeVortexesParams.convVelo[i][0] << " " << velocity->wakeVortexesParams.convVelo[i][1] << " "\
1500 << velocity->wakeVortexesParams.diffVelo[i][0] << " " << velocity->wakeVortexesParams.diffVelo[i][1] << " "\
1501 //<< std::endl;
1502 << velocity->wakeVortexesParams.I0[i] << " " \
1503 << velocity->wakeVortexesParams.I1[i] << " " \
1504 << velocity->wakeVortexesParams.I2[i][0] << " " << velocity->wakeVortexesParams.I2[i][1] << " " \
1505 << velocity->wakeVortexesParams.I3[i][0] << " " << velocity->wakeVortexesParams.I3[i][1] << " " \
1506 << "\n";
1507
1508 prmtFile.close();
1509
1510 std::ofstream prmtFile2(passport.dir + "dbg/" + sss2.str());
1511 prmtFile2 << wake->vtx.size() << "\n";
1512 prmtFile2.precision(16);
1513 for (size_t i = 0; i < wake->vtx.size(); ++i)
1514 prmtFile2 << wake->vtx[i].r()[0] << " " << wake->vtx[i].r()[1] << " " << wake->vtx[i].g() << "\n";
1515 prmtFile2.close();
1516 }
1517//*/
1518
1519/*
1520 //Сохранение всех параметров для виртуальных вихрей
1521 if (!(currentStep % 1))
1522 {
1523 for (size_t b = 0; b < boundary.size(); ++b)
1524 {
1525 std::ostringstream sss;
1526 sss << "prmVirtual_";
1527 sss << b << "-";
1528 sss << currentStep;
1529 std::ofstream prmFileVirt(passport.dir + "dbg/" + sss.str());
1530 //prmFileVirt.precision(16);
1531 prmFileVirt << "i x y g sigma epsast convVeloX convVeloY diffVeloX diffVeloY I0 I1 I2X I2Y I3X I3Y" << std::endl;
1532 for (size_t i = 0; i < boundary[b]->virtualWake.vtx.size(); ++i)
1533 prmFileVirt << i << " " \
1534 << boundary[b]->virtualWake.vtx[i].r()[0] << " " << boundary[b]->virtualWake.vtx[i].r()[1] << " " \
1535 << boundary[b]->virtualWake.vtx[i].g() << " " \
1536 << boundary[b]->virtualWake.vtx[i].sigma() << " " \
1537 << velocity->virtualVortexesParams[b].epsastWake[i] << " " \
1538 << velocity->virtualVortexesParams[b].convVelo[i][0] << " " << velocity->virtualVortexesParams[b].convVelo[i][1] << " "\
1539 << velocity->virtualVortexesParams[b].diffVelo[i][0] << " " << velocity->virtualVortexesParams[b].diffVelo[i][1] << " "\
1540 //<< std::endl;
1541 << velocity->virtualVortexesParams[b].I0[i] << " " \
1542 << velocity->virtualVortexesParams[b].I1[i] << " " \
1543 << velocity->virtualVortexesParams[b].I2[i][0] << " " << velocity->virtualVortexesParams[b].I2[i][1] << " " \
1544 << velocity->virtualVortexesParams[b].I3[i][0] << " " << velocity->virtualVortexesParams[b].I3[i][1] << " " \
1545 << std::endl;
1546 prmFileVirt.close();
1547 }
1548 //if (currentStep==3) exit(-123);
1549 }
1550//*/
1551
1552 getTimers().stop("Save");
1553
1554}//CalcVortexVelo()
void calcMeanEpsOverPanel()
Вычисление средних значений eps на панелях
Definition Airfoil2D.cpp:96
VMlib::TimersGen & getTimers() const
Возврат ссылки на временную статистику выполнения шага расчета по времени
Definition World2D.h:288
size_t getNumberOfBoundary() const
Возврат количества граничных условий в задаче
Definition World2D.h:197
Airfoil & getNonConstAirfoil(size_t i) const
Возврат неконстантной ссылки на объект профиля
Definition World2D.h:175
void stop(const std::string &timerLabel)
Останов счетчика
Definition TimesGen.cpp:68
void start(const std::string &timerLabel)
Запуск счетчика
Definition TimesGen.cpp:55
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CheckInside()

void World2D::CheckInside ( std::vector< Point2D > &  newPos,
const std::vector< std::unique_ptr< AirfoilGeometry > > &  oldAirfoil 
)

Проверка проникновения вихрей внутрь профиля

Вызывается в Step()

Parameters
[in]newPosновые позиции вихрей
[in]oldAirfoilконстантная ссылка на вектор из умных указателей на старые положения профилей

Definition at line 792 of file World2D.cpp.

793{
794 getTimers().start("Inside");
795
796 gabb = 0;
797 check01 = 0;
798 check02 = 0;
799 checkPan = 0;
800
801#if (!defined(USE_CUDA))
802 nVtxBeforeMerging = newPos.size();
803 for (size_t afl = 0; afl < airfoil.size(); ++afl)
804 wake->Inside(newPos, *airfoil[afl], mechanics[afl]->isMoves, *oldAirfoil[afl]);
805
806
807 //Тренируемся работать с древом панелей
808 /*
809 int nTotPan = 0;
810 for (size_t s = 0; s < getNumberOfAirfoil(); ++s)
811 nTotPan += (int)getAirfoil(s).getNumberOfPanels();
812
813 auxTreePnl.reset(new CpuTreeInfo(tree_T::aux, object_T::panel, scheme_T::noScheme));
814
815 std::vector<std::pair<Point2D, Point2D>> pnls(nTotPan);
816 int counter = 0;
817 for (size_t s = 0; s < getNumberOfAirfoil(); ++s)
818 for (size_t p = 0; p < getAirfoil(s).getNumberOfPanels(); ++p)
819 pnls[counter++] = { getAirfoil(s).getR(p), getAirfoil(s).getR(p + 1) };
820
821 auxTreePnl->UpdatePanelGeometry(pnls, 0);
822 auxTreePnl->Build();
823 auxTreePnl->UpwardTraversal(0);
824
825 std::unique_ptr<CpuTreeInfo> cntrTreePnt;
826 cntrTreePnt.reset(new CpuTreeInfo(tree_T::contr, object_T::point2, scheme_T::noScheme));
827
828 std::vector<Vortex2D> newPosVtx(newPos.size());
829 for (size_t i = 0; i < newPos.size(); ++i)
830 newPosVtx[i].r() = newPos[i];
831
832 cntrTreePnt->Update(newPosVtx);
833 float tBuild = cntrTreePnt->Build();
834 float tUpward = cntrTreePnt->UpwardTraversal(0);
835
836 std::vector<std::pair<int,double>> closeIndexDist(cntrTreePnt->object.size());
837
838
839 VMlib::vmTimer timerA;
840 timerA.start();
841 double tDownward = auxTreePnl->DownwardTraversalClosestPanelToPoints(*cntrTreePnt, closeIndexDist, false, nullptr);
842 timerA.stop();
843
844 std::ofstream treeTimeFile;
845 if (getCurrentStep() == 0)
846 {
847 treeTimeFile.open(passport.dir + "/dbg/treeTime.csv");
848 treeTimeFile << "step,time,N,tBUI,tUPW,tDNW\n";
849 }
850 else
851 treeTimeFile.open(passport.dir + "/dbg/treeTime.csv", std::ios::app);
852
853 treeTimeFile << getCurrentStep() << ',' << getCurrentTime() << ',' << newPos.size() << ',' << tBuild << ',' << tUpward << ',' << tDownward << '\n';
854
855 treeTimeFile.close();
856
857 //std::cout << "timeFastNeib = " << timerA.duration() << ", N = " << newPos.size() << "\n";
858 /*
859 std::ofstream closeFile(passport.dir + "closeFile.txt");
860 for (size_t i = 0; i < newPos.size(); ++i)
861 closeFile << newPos[i][0] << " " << newPos[i][1] << " " << closeIndexDist[i].first << "\n";
862 closeFile.close();
863 */
864
865 //*/
866
867 //std::cout << "gab: " << gabb << " check1: " << check01 << " check2: " << check02 << " checkPan: " << checkPan << std::endl;
868#else
869// //////////////////////// CUDA ///////////////////////
872
873 if ((newPos.size() > 0) && (getNumberOfAirfoil() > 0))
874 {
875 int nTotPanels = 0;
876 for (size_t afl = 0; afl < airfoil.size(); ++afl)
877 nTotPanels += (int)airfoil[afl]->getNumberOfPanels();
878
879 nVtxBeforeMerging = newPos.size();
880
881 auto& auxTree = *getNonConstCuda().auxTreePnl;
882
884 {
885 auxTree.MemoryAllocate((int)getCuda().n_CUDA_pnls);
886 auxTree.UpdatePanelGeometry(nTotPanels, (double4*)airfoil[0]->devRPtr);
887 auxTree.Build();
888 auxTree.UpwardTraversal(0);
889 }
890
891 std::vector<int> hit(newPos.size());
892
893 if (isAnyMovableOrDeformable()) //Если профили подвижны - метод псевдонормалей
894 {
895 double* devNewpos_ptr;
896 cudaMalloc(&devNewpos_ptr, newPos.size() * sizeof(double) * 2);
897 cudaMemcpy(devNewpos_ptr, newPos.data(), newPos.size() * sizeof(double) * 2, cudaMemcpyHostToDevice);
898
899 auto& cntrTreePnt = *getCuda().cntrTreePoint;
900 cntrTreePnt.MemoryAllocate((int)getCuda().n_CUDA_wake);
901 cntrTreePnt.Update((int)newPos.size(), devNewpos_ptr);
902 cntrTreePnt.Build();
903
904 BHcu::treeClosestPanelToPointsCalculationWrapper(auxTree, cntrTreePnt, getWake().devNearestPanelPtr, true, getAirfoil(0).devPsnPtr);
905
906 cudaMemcpy(hit.data(), getWake().devNearestPanelPtr, newPos.size() * sizeof(int), cudaMemcpyDeviceToHost);
907 cudaFree(devNewpos_ptr);
908
909
910 //std::ofstream vortexFile(getPassport().dir + "vortexFile.txt");
911 //for (size_t i = 0; i < getWake().vtx.size(); ++i)
912 // vortexFile << getWake().vtx[i].r()[0] << " " << getWake().vtx[i].r()[1] << " " << hit[i] << '\n';
913 //vortexFile.close();
914
915 //std::ofstream panelFile(getPassport().dir + "panelFile.txt");
916 //for (size_t i = 0; i < getAirfoil(0).getNumberOfPanels(); ++i)
917 // panelFile << getAirfoil(0).getR(i)[0] << " " << getAirfoil(0).getR(i)[1] << " " << \
918 // getAirfoil(0).getR(i + 1)[0] << " " << getAirfoil(0).getR(i + 1)[1] << " " << '\n';
919 //panelFile.close();
920
921
922 }
923 else //иначе (для неподвижного профиля - метод трассировки лучей
924 {
925 std::vector<std::pair<Point2D, Point2D>> segments(newPos.size());
926 for (size_t i = 0; i < newPos.size(); ++i)
927 {
928 segments[i].first = wake->vtx[i].r();
929 segments[i].second = newPos[i];
930 }
931 double* devSegments_ptr;
932
933 cudaMalloc(&devSegments_ptr, newPos.size() * sizeof(double) * 4);
934 cudaMemcpy(devSegments_ptr, segments.data(), newPos.size() * sizeof(double) * 4, cudaMemcpyHostToDevice);
935
936 auto& cntrTreeSeg = *getCuda().cntrTreeSegment;
937 cntrTreeSeg.MemoryAllocate((int)getCuda().n_CUDA_wake);
938 cntrTreeSeg.UpdatePanelGeometry((int)newPos.size(), (double4*)devSegments_ptr);
939 cntrTreeSeg.Build();
940
941 BHcu::treePanelsSegmentsIntersectionCalculationWrapper(auxTree, cntrTreeSeg, getWake().devNearestPanelPtr);
942 cudaMemcpy(hit.data(), getWake().devNearestPanelPtr, newPos.size() * sizeof(int), cudaMemcpyDeviceToHost);
943 cudaFree(devSegments_ptr);
944 }
945
946 size_t panCounter = 0;
947 for (size_t afl = 0; afl < airfoil.size(); ++afl)
948 {
949 std::vector<double> gamma(airfoil[afl]->getNumberOfPanels(), 0.0);
950 for (int i = 0; i < newPos.size(); ++i)
951 {
952 if (hit[i] != -1)
953 {
954 if ((hit[i] >= panCounter) && (hit[i] < panCounter + airfoil[afl]->getNumberOfPanels()))
955 {
956 if (fabs(wake->vtx[i].g()) > 1.0)
957 std::cout << "Too large gamma is through: i = " << i << ", " << hit[i] << ", " << "gamma[hit[i] - panCounter] += " << wake->vtx[i].g() << std::endl;
958
959 gamma[hit[i] - panCounter] += wake->vtx[i].g();
960 wake->vtx[i].g() = 0.0;
961 }
962 }
963 }
964 airfoil[afl]->gammaThrough = gamma;
965 panCounter += airfoil[afl]->getNumberOfPanels();
966 }//for afl
967 }
969
970#endif
971
972 getTimers().stop("Inside");
973}
const Wake & getWake() const
Возврат константной ссылки на вихревой след
Definition World2D.h:232
std::vector< std::unique_ptr< AirfoilGeometry > > oldAirfoil
Список умных указателей на обтекаемые профили для сохранения старого положения
Definition World2D.h:83
VMlib::vmTimer timerInside
Definition World2D.h:372
Gpu & getNonConstCuda() const
Возврат неконстантной ссылки на объект, связанный с видеокартой (GPU)
Definition World2D.h:278
const Gpu & getCuda() const
Возврат константной ссылки на объект, связанный с видеокартой (GPU)
Definition World2D.h:273
size_t nVtxBeforeMerging
Definition WorldGen.h:76
const vmTimer & stop() const
Останов работающего счетчика времени
Definition TimesGen.h:125
const vmTimer & start() const
Запуск (первый или повторный) счетчика времени
Definition TimesGen.h:109
const vmTimer & reset() const
Сброс счетчика времени
Definition TimesGen.h:101
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FillIQ()

void World2D::FillIQ ( )

Заполнение матрицы, состоящей из интегралов от (r-xi) / |r-xi|^2.

Вызывается в Step()

Definition at line 2045 of file World2D.cpp.

2046{
2047 getTimers().start("MatRhs");
2048
2049 for (size_t bou = 0; bou < boundary.size(); ++bou)
2050 {
2051 if (currentStep == 0 || mechanics[bou]->isDeform)
2052 {
2053 boundary[bou]->FillIQSelf(IQ[bou][bou]);
2054 }
2055
2056 for (size_t oth = 0; oth < boundary.size(); ++oth)
2057 {
2058
2059#ifdef INITIAL
2060 if (currentStep == 0 || !useInverseMatrix)
2061 {
2062 //size_t nVarsOther = boundary[oth]->GetUnknownsSize();
2063 if (bou != oth)
2064 {
2065 //std::cout << "matr!" << std::endl;
2066 boundary[bou]->FillIQFromOther(*boundary[oth], IQ[bou][oth]);
2067 }
2068 }// if (currentStep == 0 || !useInverseMatrix)
2069#endif
2070
2071#ifdef BRIDGE
2072 if (currentStep == 0)
2073 {
2074 //size_t nVarsOther = boundary[oth]->GetUnknownsSize();
2075 if (bou != oth)
2076 boundary[bou]->FillIQFromOther(*boundary[oth], IQ[bou][oth]);
2077 }// if (currentStep == 0)
2078#endif
2079
2080 }// for oth
2081
2082 }// for bou
2083
2084 getTimers().stop("MatRhs");
2085}//FillIQ()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FillMatrixAndRhs()

void World2D::FillMatrixAndRhs ( )

Заполнение матрицы системы для всех профилей

Вызывается в Step()

Definition at line 1277 of file World2D.cpp.

1278{
1279 getTimers().start("MatRhs");
1280
1281 const int linSystemScheme = passport.numericalSchemes.linearSystemSolver.second;
1282
1283 if (linSystemScheme == 0 || linSystemScheme == 1)
1284 {
1287
1288 Eigen::MatrixXd locMatr;
1289 Eigen::MatrixXd otherMatr;
1290 Eigen::VectorXd locLastLine, locLastCol;
1291
1292 std::vector<std::vector<Point2D>> locIQ;
1293 std::vector<std::vector<Point2D>> locOtherIQ;
1294
1295 //обнуляем матрицу на первом шаге расчета
1296 if (currentStep == 0)
1297 {
1298 for (int i = 0; i < matrReord.rows(); ++i)
1299 for (int j = 0; j < matrReord.cols(); ++j)
1300 matrReord(i, j) = 0.0;
1301 }
1302
1303 size_t currentRow = 0;
1304 size_t currentSkosRow = 0;
1305
1306 size_t nAllVars = 0;
1307 for (size_t bou = 0; bou < boundary.size(); ++bou)
1308 nAllVars += boundary[bou]->GetUnknownsSize();
1309
1310 for (size_t bou = 0; bou < boundary.size(); ++bou)
1311 {
1312 size_t nVars = boundary[bou]->GetUnknownsSize();
1313 if (currentStep == 0 || mechanics[bou]->isDeform)
1314 {
1315 locMatr.resize(nVars, nVars);
1316 locLastLine.resize(nVars);
1317 locLastCol.resize(nVars);
1318 }
1319
1320 if (currentStep == 0 || mechanics[bou]->isDeform)
1321 boundary[bou]->FillMatrixSelf(locMatr, locLastLine, locLastCol);
1322
1323
1324 //размазываем матрицу
1325 for (size_t i = 0; i < nVars; ++i)
1326 {
1327 if (currentStep == 0 || mechanics[bou]->isDeform)
1328 {
1329 for (size_t j = 0; j < nVars; ++j)
1330 matrReord(i + currentSkosRow, j + currentSkosRow) = locMatr(i, j);
1331
1332 matrReord(nAllVars + bou, i + currentSkosRow) = locLastLine(i);
1333 matrReord(i + currentSkosRow, nAllVars + bou) = locLastCol(i);
1334 }
1335 }
1336
1337 if ((currentStep == 0) || (!useInverseMatrix))
1338 {
1339 size_t currentCol = 0;
1340 size_t currentSkosCol = 0;
1341 for (size_t oth = 0; oth < boundary.size(); ++oth)
1342 {
1343 size_t nVarsOther = boundary[oth]->GetUnknownsSize();
1344
1345 if (bou != oth)
1346 {
1347 otherMatr.resize(nVars, nVarsOther);
1348
1349 boundary[bou]->FillMatrixFromOther(*boundary[oth], otherMatr);
1350
1351 //размазываем матрицу
1352 for (size_t i = 0; i < nVars; ++i)
1353 {
1354 for (size_t j = 0; j < nVarsOther; ++j)
1355 matrReord(i + currentSkosRow, j + currentSkosCol) = otherMatr(i, j);
1356 }
1357 }// if (bou != oth)
1358 currentCol += nVarsOther + 1;
1359 currentSkosCol += nVarsOther;
1360 }// for oth
1361 }// if (currentStep == 0 || mechanics[oth]->isMoves)
1362
1363 currentRow += nVars + 1;
1364 currentSkosRow += nVars;
1365 }// for bou
1367 }
1368
1369 velocity->FillRhs(rhsReord);
1370
1371 getTimers().stop("MatRhs");
1372}//FillMatrixAndRhs()
Eigen::MatrixXd matrReord
Матрица системы
Definition World2D.h:122
Eigen::VectorXd rhsReord
Правая часть системы
Definition World2D.h:134
VMlib::vmTimer timerFillMatrix
Definition World2D.h:368
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GenerateMechanicsHeader()

void World2D::GenerateMechanicsHeader ( size_t  mechanicsNumber)

Метод-обертка для вызова метода генерации заголовка файла нагрузок и заголовка файла положения (последнее — если профиль движется)

Parameters
[in]mechanicsNumberномер профиля, для которого генерируется заголовок файла

Definition at line 2038 of file World2D.cpp.

2039{
2040 mechanics[mechanicsNumber]->GenerateForcesHeader();
2041 mechanics[mechanicsNumber]->GeneratePositionHeader();
2042}//GenerateMechanicsHeader(...)
Here is the caller graph for this function:

◆ getAirfoil()

const Airfoil & VM2D::World2D::getAirfoil ( size_t  i) const
inline

Возврат константной ссылки на объект профиля

Parameters
[in]iномер профиля, константная ссылка на который возвращается
Returns
константную ссылку на i-й профиль

Definition at line 163 of file World2D.h.

163{ return *airfoil[i]; };
Here is the caller graph for this function:

◆ getAuxTreePnl()

CpuTreeInfo & VM2D::World2D::getAuxTreePnl ( ) const
inline

Definition at line 241 of file World2D.h.

241{ return *auxTreePnl; };
std::unique_ptr< CpuTreeInfo > auxTreePnl
Definition World2D.h:119

◆ getBoundary()

const Boundary & VM2D::World2D::getBoundary ( size_t  i) const
inline

Возврат константной ссылки на объект граничного условия

Parameters
[in]iномер граничного условия, константная ссылка на которое возвращается
Returns
константную ссылку на i-е граничное условие

Definition at line 186 of file World2D.h.

186{ return *boundary[i]; };
Here is the caller graph for this function:

◆ getCntrTreePnl()

CpuTreeInfo & VM2D::World2D::getCntrTreePnl ( ) const
inline

Definition at line 243 of file World2D.h.

243{ return *cntrTreePnl; }
Here is the caller graph for this function:

◆ getCntrTreeVP()

CpuTreeInfo & VM2D::World2D::getCntrTreeVP ( ) const
inline

Definition at line 242 of file World2D.h.

242{ return *cntrTreeVP; };
Here is the caller graph for this function:

◆ getCntrTreeWake()

CpuTreeInfo & VM2D::World2D::getCntrTreeWake ( ) const
inline

Definition at line 240 of file World2D.h.

240{ return *cntrTreeWake; };
Here is the caller graph for this function:

◆ getCuda()

const Gpu & VM2D::World2D::getCuda ( ) const
inline

Возврат константной ссылки на объект, связанный с видеокартой (GPU)

Returns
константную ссылку на объект, связанный с видеокартой (GPU)

Definition at line 273 of file World2D.h.

273{ return cuda; };
Here is the caller graph for this function:

◆ getCurrentStep()

size_t VMlib::WorldGen::getCurrentStep ( ) const
inlineinherited

Возврат константной ссылки на параметры распараллеливания по MPI.

Returns
константную ссылку на параметры распараллеливания по MPI const Parallel& getParallel() const { return parallel; };

Возврат номера текущего временного шага

Returns
номера текущего временного шага

Definition at line 99 of file WorldGen.h.

99{ return currentStep; };
Here is the caller graph for this function:

◆ getCurrentTime()

double VMlib::WorldGen::getCurrentTime ( ) const
inlineinherited

Definition at line 100 of file WorldGen.h.

100{ return currentTime; };
Here is the caller graph for this function:

◆ getDispBoundaryInSystem()

size_t VM2D::World2D::getDispBoundaryInSystem ( size_t  i) const
inline

Возврат смещения в системе dispBoundaryInSystem.

Parameters
[in]iномер граничного условия, константная ссылка на которое возвращается
Returns
константную ссылку на i-е граничное условие

Definition at line 203 of file World2D.h.

203{ return dispBoundaryInSystem[i]; };
std::vector< size_t > dispBoundaryInSystem
Список номеров, с которых начинаются элементы правой части (или матрицы) системы для профилей
Definition World2D.h:89

◆ getInflTreeWake()

CpuTreeInfo & VM2D::World2D::getInflTreeWake ( ) const
inline

Definition at line 239 of file World2D.h.

239{ return *inflTreeWake; };
Here is the caller graph for this function:

◆ getInfo() [1/2]

VMlib::LogStream & VMlib::WorldGen::getInfo ( ) const
inlineinherited

Возврат ссылки на объект LogStream Используется в техничеcких целях для организации вывода

Returns
ссылку на объект LogStream

Definition at line 82 of file WorldGen.h.

82{ return info; };
Here is the caller graph for this function:

◆ getInfo() [2/2]

std::ostream & VMlib::WorldGen::getInfo ( char  x) const
inlineinherited

Возврат ссылки на поток вывода информации Необходимо для вывода телеметрической информации, информации об ошибках и т.п.

Parameters
[in]xсимвол, определяющий стиль вывода сообщения
Returns
ссылку на поток вывода информации

Definition at line 89 of file WorldGen.h.

89{ return info(x); };

◆ getIQ()

const std::pair< Eigen::MatrixXd, Eigen::MatrixXd > & VM2D::World2D::getIQ ( size_t  i,
size_t  j 
) const
inline

Возврат константной ссылки на объект, связанный с матрицей интегралов от (r-xi)/|r-xi|^2.

Returns
константную ссылку на объект, связанный с матрицей интегралов от (r-xi)/|r-xi|^2

Definition at line 283 of file World2D.h.

283{ return IQ[i][j]; };
Here is the caller graph for this function:

◆ getMeasureVP()

const MeasureVP & VM2D::World2D::getMeasureVP ( ) const
inline

Возврат константной ссылки на measureVP.

Returns
константную ссылку на вихревой след

Definition at line 208 of file World2D.h.

208{ return *measureVP; };
Here is the caller graph for this function:

◆ getMechanics()

const Mechanics & VM2D::World2D::getMechanics ( size_t  i) const
inline

Возврат константной ссылки на объект механики

Parameters
[in]iномер механики, константная ссылка на который возвращается
Returns
константную ссылку на i-ю механику

Definition at line 219 of file World2D.h.

219{ return *mechanics[i]; };
Here is the caller graph for this function:

◆ getMechanicsVector()

const std::vector< std::unique_ptr< Mechanics > > & VM2D::World2D::getMechanicsVector ( ) const
inline

Definition at line 227 of file World2D.h.

227{ return mechanics; };
Here is the caller graph for this function:

◆ getNonConstAirfoil()

Airfoil & VM2D::World2D::getNonConstAirfoil ( size_t  i) const
inline

Возврат неконстантной ссылки на объект профиля

Parameters
[in]iномер профиля, неконстантная ссылка на который возвращается
Returns
неконстантную ссылку на i-й профиль

Definition at line 175 of file World2D.h.

175{ return *airfoil[i]; };
Here is the caller graph for this function:

◆ getNonConstBoundary()

Boundary & VM2D::World2D::getNonConstBoundary ( size_t  i) const
inline

Возврат неконстантной ссылки на объект граничного условия

Parameters
[in]iномер граничного условия, неконстантная ссылка на которое возвращается
Returns
неконстантную ссылку на i-е граничное условие

Definition at line 192 of file World2D.h.

192{ return *boundary[i]; };
Here is the caller graph for this function:

◆ getNonConstCuda()

Gpu & VM2D::World2D::getNonConstCuda ( ) const
inline

Возврат неконстантной ссылки на объект, связанный с видеокартой (GPU)

Returns
неконстантную ссылку на объект, связанный с видеокартой (GPU)

Definition at line 278 of file World2D.h.

278{ return cuda; };
Here is the caller graph for this function:

◆ getNonConstMeasureVP()

MeasureVP & VM2D::World2D::getNonConstMeasureVP ( ) const
inline

Возврат неконстантной ссылки на measureVP.

Returns
неконстантную ссылку на вихревой след

Definition at line 213 of file World2D.h.

213{ return *measureVP; };
Here is the caller graph for this function:

◆ getNonConstMechanics()

Mechanics & VM2D::World2D::getNonConstMechanics ( size_t  i) const
inline

Возврат неконстантной ссылки на объект механики

Parameters
[in]iномер механики, константная ссылка на который возвращается
Returns
неконстантную ссылку на i-ю механику

Definition at line 225 of file World2D.h.

225{ return *mechanics[i]; };
Here is the caller graph for this function:

◆ getNonConstPassport()

Passport & VM2D::World2D::getNonConstPassport ( ) const
inline

Возврат неконстантной ссылки на паспорт

Returns
неконстантную ссылку на паспорт

Definition at line 268 of file World2D.h.

268{ return const_cast<Passport&>(passport); };
Here is the caller graph for this function:

◆ getNonConstVelocity()

Velocity & VM2D::World2D::getNonConstVelocity ( ) const
inline

Возврат неконстантной ссылки на объект для вычисления скоростей

Returns
неконстантную ссылку на объект для вычисления скоростей

Definition at line 258 of file World2D.h.

258{ return *velocity; };

◆ getNonConstWake()

Wake & VM2D::World2D::getNonConstWake ( ) const
inline

Возврат неконстантной ссылки на вихревой след

Returns
неконстантную ссылку на вихревой след

Definition at line 237 of file World2D.h.

237{ return *wake; };
Here is the caller graph for this function:

◆ getNumberOfAirfoil()

size_t VM2D::World2D::getNumberOfAirfoil ( ) const
inline

Возврат количества профилей в задаче

Returns
количество профилей в задаче

Definition at line 180 of file World2D.h.

180{ return airfoil.size(); };
Here is the caller graph for this function:

◆ getNumberOfBoundary()

size_t VM2D::World2D::getNumberOfBoundary ( ) const
inline

Возврат количества граничных условий в задаче

Returns
количество граничных условий в задаче

Definition at line 197 of file World2D.h.

197{ return boundary.size(); };
Here is the caller graph for this function:

◆ getOldAirfoil()

const AirfoilGeometry & VM2D::World2D::getOldAirfoil ( size_t  i) const
inline

Возврат константной ссылки на объект старого профиля

Parameters
[in]iномер старого профиля, константная ссылка на который возвращается
Returns
константную ссылку на i-й старый профиль

Definition at line 169 of file World2D.h.

169{ return *oldAirfoil[i]; };
Here is the caller graph for this function:

◆ getPassport()

const Passport & VM2D::World2D::getPassport ( ) const
inline

Возврат константной ссылки на паспорт

Returns
константную ссылку на паспорт

Definition at line 263 of file World2D.h.

263{ return passport; };
Here is the caller graph for this function:

◆ getPassportGen()

const PassportGen & VMlib::WorldGen::getPassportGen ( ) const
inlineinherited

Definition at line 102 of file WorldGen.h.

102{ return passportGen; };
const PassportGen & passportGen
Константная ссылка на паспорт конкретного расчета
Definition WorldGen.h:63
Here is the caller graph for this function:

◆ getSource()

const WakeDataBase & VM2D::World2D::getSource ( ) const
inline

Возврат константной ссылки на источники в области течения

Returns
константную ссылку на источники в области течения

Definition at line 248 of file World2D.h.

248{ return *source; };
Here is the caller graph for this function:

◆ getTimers()

VMlib::TimersGen & VM2D::World2D::getTimers ( ) const
inline

Возврат ссылки на временную статистику выполнения шага расчета по времени

Returns
ссылку на временную статистику выполнения шага расчета по времени

Definition at line 288 of file World2D.h.

288{ return *timers; };
Here is the caller graph for this function:

◆ getV0()

Point2D VM2D::World2D::getV0 ( ) const
inline

Возврат текущей скорости набегающего потока

Definition at line 148 of file World2D.h.

149 {
151 }
Point2D V0(double currentTime) const
Функция скорости набегающего потока с учетом разгона
Definition Passport2D.h:93
Here is the call graph for this function:
Here is the caller graph for this function:

◆ getVelocity()

const Velocity & VM2D::World2D::getVelocity ( ) const
inline

Возврат константной ссылки на объект для вычисления скоростей

Returns
константную ссылку на объект для вычисления скоростей

Definition at line 253 of file World2D.h.

253{ return *velocity; };
Here is the caller graph for this function:

◆ getWake()

const Wake & VM2D::World2D::getWake ( ) const
inline

Возврат константной ссылки на вихревой след

Returns
константную ссылку на вихревой след

Definition at line 232 of file World2D.h.

232{ return *wake; };
Here is the caller graph for this function:

◆ ifDivisible()

bool VM2D::World2D::ifDivisible ( int  val) const
inline

Definition at line 290 of file World2D.h.

290{ return ((val > 0) && (!(currentStep % val))); };
Here is the caller graph for this function:

◆ isAnyMovable()

bool World2D::isAnyMovable ( ) const

Возврат признака того, что хотя бы один из профилей подвижный

Definition at line 2342 of file World2D.cpp.

2343{
2344 return std::any_of(getMechanicsVector().begin(), getMechanicsVector().end(),
2345 [](const std::unique_ptr<Mechanics>& m) {return (m->isMoves); });
2346}
const std::vector< std::unique_ptr< Mechanics > > & getMechanicsVector() const
Definition World2D.h:227
Here is the call graph for this function:

◆ isAnyMovableOrDeformable()

bool World2D::isAnyMovableOrDeformable ( ) const

Возврат признака того, что хотя бы один из профилей подвижный или деформируемый

Definition at line 2349 of file World2D.cpp.

2350{
2351 return std::any_of(getMechanicsVector().begin(), getMechanicsVector().end(),
2352 [](const std::unique_ptr<Mechanics>& m) {return (m->isMoves || m->isDeform); });
2353}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ isFinished()

bool WorldGen::isFinished ( ) const
inherited

Функция, возвращающая признак завершения счета в решаемой задаче

true, если задача решена и выполнен признак останова; false если требуется еще выполнять шаги по времени

Definition at line 52 of file WorldGen.cpp.

53{
55}
double timeStop
Конечное время
Definition PassportGen.h:64

◆ MoveVortexes()

void World2D::MoveVortexes ( std::vector< Point2D > &  newPos,
std::vector< double > *  nutPtr = nullptr 
)

Вычисляем новые положения вихрей (в пелене и виртуальных)

Вызывается в Step()

Parameters
[out]newPosновые позиции вихрей

Definition at line 1634 of file World2D.cpp.

1635{
1636 //getTimers().start("Move");
1637
1638 size_t nvt = wake->vtx.size();
1639 size_t nVirtVortex = 0;
1640 for (size_t i = 0; i < getNumberOfBoundary(); ++i)
1641 nVirtVortex += boundary[i]->virtualWake.vtx.size();
1642
1643
1644
1645
1646 size_t counter = wake->vtx.size() - nVirtVortex;
1647 for (size_t bou = 0; bou < boundary.size(); ++bou)
1648 {
1649 for (int i = 0; i < (int)boundary[bou]->virtualWake.vtx.size(); ++i)
1650 {
1651 wake->vtx[counter].g() = boundary[bou]->virtualWake.vtx[i].g();
1652 wake->vtx[counter].sigma() = getPassport().wakeDiscretizationProperties.sigma0;
1653 ++counter;
1654 }
1655 }
1656
1657
1658
1659
1661#if defined (SPH)
1662
1663 const double c = 4.5;
1664
1665 const auto& eps = velocity->wakeVortexesParams.epsastWake;
1666
1667 double minEpsast = *std::min_element(eps.begin(), eps.end());
1668 double meanEpsast = std::accumulate(eps.begin(), eps.end(), 0.0) / eps.size();
1669
1670 double uniformH = minEpsast + 0.2 * (meanEpsast - minEpsast);
1671
1672 std::vector<std::vector<int>> neib(wake->vtx.size());
1673 for (auto& nb : neib)
1674 nb.reserve(100);
1675
1676#pragma omp parallel for schedule(dynamic, 100)
1677 for (int i = 0; i < (int)wake->vtx.size(); ++i)
1678 {
1679 const double hati = c * eps[i];
1680 const double hati2 = sqr(hati);
1681 const int dist = std::ceil(hati / uniformH);
1682
1683 Point2D vtx = wake->vtx[i].r();
1684 int cx = (int)(vtx[0] / uniformH);
1685 int cy = (int)(vtx[1] / uniformH);
1686
1687 for (int j = 0; j < (int)wake->vtx.size(); ++j)
1688 {
1689 Point2D test = wake->vtx[j].r();
1690 int tx = (int)(test[0] / uniformH);
1691 int ty = (int)(test[1] / uniformH);
1692
1693 if (abs(cx - tx) <= dist && abs(cy - ty) <= dist)
1694 if ((vtx - test).length2() < hati2)
1695 neib[i].push_back(j);
1696 }
1697 }
1698
1699 //Ядро иранца
1700 //auto W = [](double xi, double R) {double t = xi / R; return (t > 1 ? 0.0 : (8.0 / ( PI * R * R)) * (0.75 * t * t - 1.5 * t + 0.75)); };
1701 //auto gW = [](double xi, double R) {double t = xi / R; return (t > 1 ? 0.0 : (12.0 / (PI * sqr(R * R))) * (1.0 - 1.0/t)); };
1702
1703 //M4
1704 Point2D zeroVec{ 0.0, 0.0 };
1705 auto W = [](double xi, double R) {double t = xi / R; return (t > 1 ? 0.0 : 40.0 / (7.0 * PI * R * R) * (t > 0.5 ? 2.0 * cubPower(1.0 - t) : 1.0 - 6.0 * sqr(t) * (1.0 - t))); };
1706 auto WW = [zeroVec](const Point2D& v, double R) {double t = v.length() / R; return (t > 1 ? zeroVec : v * (240.0 / (7.0 * PI * sqr(sqr(R))) * (t > 0.5 ? -sqr(1.0 - t) / t : -2.0 + 3.0 * t))); };
1707
1708 //Poly6
1709 //auto W = [](double xi, double R) {double t = xi / R; return (t > 1 ? 0.0 : 4.0 / (PI * R * R) * cubPower(1.0 - t * t)); };
1710 //auto gW = [](double xi, double R) {double t = xi / R; return (t > 1 ? 0.0 : -24.0 / (PI * sqr(R * R)) * sqr(1.0 - t * t)); };
1711
1712 //Poly6 + grad Spicky
1713 //auto W = [](double xi, double R) {double t = xi / R; return (t > 1 ? 0.0 : 4.0 / (PI * R * R) * cubPower(1.0 - t * t)); };
1714 //auto gW = [](double xi, double R) {double t = xi / R; return (t > 1 ? 0.0 : -30.0 / (PI * sqr(R * R)) * sqr(1.0 - t) / t); };
1715
1716 //WendlandC6
1717 /*
1718 Point2D zeroVec{ 0.0, 0.0 };
1719 auto W = [](double xi, double R) {double t = xi / R;
1720 return (t > 1 ? 0.0 : 78.0 / (7.0 * PI * sqr(R)) * sqr(sqr(sqr((1.0 - t)))) * (32.0 * cubPower(t)+ 25.0 * sqr(t) + 8.0*t + 1.0)); };
1721 auto WW = [zeroVec](const Point2D& v, double R) -> Point2D {double t = v.length() / R;
1722 return (t > 1 ? zeroVec : v * (-1716.0 / (7.0 * PI * sqr(sqr(R))) * sqr(cubPower(1.0 - t)) * (1.0 - t) * (16.0 * sqr(t) + 7.0 * t + 1.0))); };
1723 */
1724
1725 //fp5
1726 /*
1727 auto W = [](double xi, double R) {
1728 double t = xi / R;
1729 if (t >= 1) return 0.0;
1730 if (t >= 2.0 / 3.0)
1731 return 1701.0 / (478.0 * PI) * sqr(sqr(1.0 - t)) * (1.0 - t);
1732 if (t >= 1.0 / 3.0)
1733 return 1701.0 / (478.0 * PI) * (sqr(sqr(1.0 - t)) * (1.0 - t) - 6.0 * sqr(sqr((2.0 / 3.0 - t))) * (2.0 / 3.0 - t));
1734
1735 return 1701.0 / (478.0 * PI) * (sqr(sqr(1.0 - t)) * (1.0 - t) - 6.0 * sqr(sqr((2.0 / 3.0 - t))) * (2.0 / 3.0 - t) + 15.0 * sqr(sqr((1.0 / 3.0 - t))) * (1.0 / 3.0 - t));
1736 };
1737
1738 auto gW = [](double xi, double R) {
1739 double t = xi / R;
1740 if (t >= 1) return 0.0;
1741 if (t >= 2.0 / 3.0)
1742 return -8505.0 / (478.0 * PI * R * R) * sqr(sqr(1.0 - t)) / t;
1743 if (t >= 1.0 / 3.0)
1744 return -8505.0 / (478.0 * PI * R * R) * (sqr(sqr(1.0 - t)) - 6.0 * sqr(sqr((2.0 / 3.0 - t)))) / t;
1745
1746 return -8505.0 / (478.0 * PI * R * R) * (sqr(sqr(1.0 - t)) - 6.0 * sqr(sqr((2.0 / 3.0 - t))) + 15.0 * sqr(sqr((1.0 / 3.0 - t)))) / t;
1747 };
1748 */
1749
1750
1751 std::vector<double> OIP(wake->vtx.size(), 0.0);
1752 std::vector<double> VIP(wake->vtx.size(), 0.0);
1753 std::vector<Point2D> GIP(wake->vtx.size(), { 0.0, 0.0 });
1754 std::vector<Point2D> DIFFV(wake->vtx.size(), { 0.0, 0.0 });
1755
1756
1757 const auto& vtx = wake->vtx;
1758 const auto& vel = velocity->wakeVortexesParams.convVelo;
1759
1760
1761//#ifdef TURB
1762// std::vector<Point2D> grNu(wake->vtx.size(), { 0.0, 0.0 });
1763//
1764// //std::vector<Point2D> grVx(wake->vtx.size(), { 0.0, 0.0 });
1765// //std::vector<Point2D> grVy(wake->vtx.size(), { 0.0, 0.0 });
1766// std::vector<nummatrix<double,2,2>> grV(wake->vtx.size());
1767// std::vector<Point2D> TP(wake->vtx.size(), { 0.0, 0.0 });
1768// std::vector<double> RIP(wake->vtx.size(), 0.0);
1769// std::vector<double> DELTAG(wake->vtx.size(), 0.0);
1770//#endif //TURB
1771
1772 std::vector<nummatrix<double, 2, 2>> mtrL(wake->vtx.size(), { {0.0, 0.0}, {0.0, 0.0} });
1773 std::vector<std::vector<double>> weight(wake->vtx.size());
1774
1775
1776 std::vector<Point2D> sumDIFFV(wake->vtx.size(), {0.0, 0.0});
1777 std::vector<double> sumWeight(wake->vtx.size(), 0.0);
1778
1779#pragma omp parallel for schedule(dynamic, 100)
1780 for (int i = 0; i < (int)vtx.size(); ++i)
1781 {
1782 const double hati = c * eps[i];
1783
1784 double resultOIP = 0.0;
1785 //double resultIVIP = 0.0;
1786
1787 const Point2D myPos = vtx[i].r();
1788
1789 double I1 = 0.0, I0 = 1.0;
1790
1791
1792 weight[i].reserve(neib[i].size());
1793
1794 for (auto& nbr : neib[i])
1795 {
1796 double dist2 = (myPos - vtx[nbr].r()).length2();
1797 double dist = sqrt(dist2);
1798 double w = W(dist, hati);
1799 I1 += vtx[nbr].g() * w;
1800 weight[i].push_back(w);
1801 }
1802
1803 OIP[i] = I1 / I0;
1804 }
1805
1806#pragma omp parallel for schedule(dynamic, 100)
1807 for (int i = 0; i < (int)vtx.size(); ++i)
1808 {
1809 const Point2D myPos = vtx[i].r();
1810 const double hati = c * eps[i];
1811
1812 nummatrix<double, 2, 2> M = { {0.0, 0.0}, {0.0, 0.0} };
1813 GIP[i].toZero();
1814
1815 for (auto& nbr : neib[i])
1816 {
1817 Point2D dr = myPos - vtx[nbr].r();
1818 Point2D grweight = WW(dr, hati);
1819 double vol = (vtx[nbr].g() / OIP[nbr]);
1820 if (vol != vol)
1821 vol = 0.0;
1822
1823 M += (dr | grweight) * vol;
1824 GIP[i] -= grweight * ((OIP[nbr] - OIP[i]) * vol);
1825 }
1826
1827 double detM = M[0][0] * M[1][1] - M[1][0] * M[0][1];
1828 nummatrix<double, 2, 2> L{ {0.0, 0.0}, {0.0, 0.0} };
1829 if (fabs(detM) > 1e-2)
1830 L = nummatrix<double, 2, 2>{ { M[1][1], -M[0][1] }, { -M[1][0], M[0][0] } } *(1.0 / detM);
1831
1832 GIP[i] = (L & GIP[i]);
1833 DIFFV[i] = GIP[i] * (1.0 / OIP[i]);
1834 //GIP[i] = -GIP[i];
1835 }
1836
1837 //осредняем
1838 //*
1839//#pragma omp parallel for schedule(dynamic, 100)
1840 for (int i = 0; i < (int)vtx.size(); ++i)
1841 for (int j = 0; j < neib[i].size(); ++j)
1842 if ((vtx[i].r() - vtx[neib[i][j]].r()).length() <= 1.0 * eps[i])
1843 {
1844 sumDIFFV[i] += weight[i][j] * DIFFV[neib[i][j]];
1845 sumWeight[i] += weight[i][j];
1846 }
1847
1848 //#pragma omp parallel for schedule(dynamic, 100)
1849 for (int i = 0; i < (int)vtx.size(); ++i)
1850 {
1851 DIFFV[i] = sumDIFFV[i] * (1.0 / sumWeight[i]);
1852 }
1853 //*/
1854
1855//#ifdef TURB
1856//#pragma omp parallel for schedule(dynamic, 100)
1857// for (int i = 0; i < (int)vtx.size(); ++i)
1858// {
1859// Point2D myPos = vtx[i].r();
1860// Point2D resultGradNu = { 0.0, 0.0 };
1861// Point2D resultGradVx = { 0.0, 0.0 };
1862// Point2D resultGradVy = { 0.0, 0.0 };
1863//
1864// //if (i == 0)
1865// //{
1866// // std::cout << "h = " << h << std::endl;
1867// // std::cout << "VIP = " << VIP[0] << std::endl;
1868// // std::cout << "my_coord = " << vtx[i].r() << std::endl;
1869// // std::cout << "mtrC = " << mtrC[i] << std::endl;
1870// //}
1871//
1872// for (auto& nbr : neib[i])
1873// {
1874// //if (i == 0)
1875// // std::cout << "nb_" << nbr << "_coord = " << vtx[nbr].r() << std::endl;
1876//
1877// Point2D dr = myPos - vtx[nbr].r();
1878// double dist = dr.length();
1879// double gweight = gW(dist, h);
1880//
1881// if (nbr != i)
1882// {
1883// double nutNbr = (*nutPtr)[nbr];
1884// double nutI = (*nutPtr)[i];
1885// //double nutNbr = vtx[nbr].r() & Point2D { 1.0, 1.0 };
1886// //double nutSlf = vtx[i].r() & Point2D { 1.0, 1.0 };
1887//
1888// resultGradNu += (nutNbr - nutI) * (mtrL[i] & dr) * (gweight * /*vtx[nbr].g() / OIP[nbr]*/ VIP[nbr]);
1889// resultGradVx += (vel[nbr][0] - vel[i][0]) * (mtrL[i] & dr) * (gweight * /*vtx[nbr].g() / OIP[nbr]*/ VIP[nbr]);
1890// resultGradVy += (vel[nbr][1] - vel[i][1]) * (mtrL[i] & dr) * (gweight * /*vtx[nbr].g() / OIP[nbr]*/ VIP[nbr]);
1891// }
1892// }
1893//
1894// grNu[i] = resultGradNu;
1895// grV[i][0] = resultGradVx;
1896// grV[i][1] = resultGradVy;
1897//
1898// nummatrix<double, 2, 2> regGrV = grV[i];
1899// regGrV[0][0] -= grV[i][1][1];
1900// regGrV[0][1] += grV[i][1][0];
1901// regGrV[1][0] += grV[i][0][1];
1902// regGrV[1][1] -= grV[i][0][0];
1903//
1904// regGrV *= 0.5;
1905//
1906// regGrV[0][1] += 0.5 * OIP[i];
1907// regGrV[1][0] -= 0.5 * OIP[i];
1908//
1909// TP[i] = (regGrV & grNu[i]);
1910// }//for i
1911//#endif //TURB
1912
1913
1914//#ifdef TURB
1915//
1916//#pragma omp parallel for schedule(dynamic, 100)
1917// for (int i = 0; i < (int)vtx.size(); ++i)
1918// {
1919// Point2D myPos = vtx[i].r();
1920//
1921// Point2D resultGradTPx = { 0.0, 0.0 };
1922// Point2D resultGradTPy = { 0.0, 0.0 };
1923//
1924// for (auto& nbr : neib[i])
1925// {
1926// Point2D dr = myPos - vtx[nbr].r();
1927// double dist = dr.length();
1928// double gweight = gW(dist, h);
1929//
1930// if (nbr != i)
1931// {
1932// resultGradTPx += (TP[nbr][0] - TP[i][0]) * (mtrL[i] & dr) * (gweight * /*vtx[nbr].g() / OIP[nbr]*/ VIP[nbr]);
1933// resultGradTPy += (TP[nbr][1] - TP[i][1]) * (mtrL[i] & dr) * (gweight * /*vtx[nbr].g() / OIP[nbr]*/ VIP[nbr]);
1934// }
1935// }
1936//
1937// RIP[i] = resultGradTPy[0] - resultGradTPx[1];
1939// double dG = RIP[i] * VIP[i] * getPassport().timeDiscretizationProperties.dt;
1940// //if (i == 0)
1941// // std::cout << "nVirtVortex = " << nVirtVortex << std::endl;
1942// DELTAG[i] = 0.0;//dG;// (i < (wake->vtx.size() - nVirtVortex) ? dG : 0.0);
1943//
1944// //if (fabs(dG / getWake().vtx[i].g()) <= 0.25)
1945// getNonConstWake().vtx[i].g() += DELTAG[i];
1946// //else
1947// //{
1948// // if (dG * getWake().vtx[i].g() > 0)
1949// // getNonConstWake().vtx[i].g() *= 1.25;
1950// // else
1951// // getNonConstWake().vtx[i].g() /= 1.25;
1952// //}
1953//
1954// getNonConstWake().vtx[i].g() = std::clamp(getWake().vtx[i].g(), -1.5 * getPassport().wakeDiscretizationProperties.maxGamma, 1.5 * getPassport().wakeDiscretizationProperties.maxGamma);
1955// }//for i
1956//
1957// wake->SaveScalarFields("SPH", VIP, OIP, *nutPtr, grNu, RIP, DELTAG);
1958//#endif //TURB
1959
1960#endif //SPH
1961
1962
1963
1964 //newPos.clear();
1965 newPos.resize(nvt);
1966
1967
1968 // 1. Инициализация генератора случайных чисел (ПСЧГ)
1969 //std::random_device rd; // Источник энтропии для инициализации
1970 //std::mt19937 gen(rd()); // Mersenne Twister, инициализированный случайным значением
1971
1972 // 2. Определение параметров нормального распределения
1973 // μ (среднее) = 0.0, σ (стандартное отклонение) = 1.0
1974 //std::normal_distribution<> d(0.0, sqrt(2.0 * getPassport().physicalProperties.nu * getPassport().timeDiscretizationProperties.dt));
1975
1976
1977 //std::ofstream checkVel (passport.dir + "/dbg/checkVel" + std::to_string(getCurrentStep()) + ".txt");
1978 //std::ofstream checkVelDyn(passport.dir + "/dbg/checkVelDyn" + std::to_string(getCurrentStep()) + ".txt");
1979
1980 //checkVel << "i x y epsast Vx Vy Wx Wy corrWx corrWy Om gOmx gOmy\n";
1981 //checkVelDyn << "i x y epsast Vx Vy Wx Wy corrWx corrWy Om gOmx gOmy\n";
1982
1983//#pragma omp parallel for
1984 for (int i = 0; i < (int)wake->vtx.size(); ++i)
1985 {
1986#ifdef SPH
1987 //Point2D W = -(passport.physicalProperties.nu / OIP[i]) * GIP[i];
1988 Point2D W = -passport.physicalProperties.nu * DIFFV[i];
1989
1990 checkVel << i << " " << wake->vtx[i].r()[0] << " " << wake->vtx[i].r()[1] << " " << velocity->wakeVortexesParams.epsastWake[i] << " " \
1991 << velocity->wakeVortexesParams.convVelo[i][0] << " " << velocity->wakeVortexesParams.convVelo[i][1] << " " \
1992 << W[0] << " " << W[1];
1993
1994 if (W.length() > 1.5 * passport.physicalProperties.vRef)
1995 {
1996 std::cout << "i = " << i << ", W was " << W << std::endl;
1997 W.toZero();
1998 //W.normalize(1.5 * passport.physicalProperties.vRef);
1999 }
2000
2001 checkVel << " " << W[0] << " " << W[1] << " " << OIP[i] << " " << GIP[i][0] << " " << GIP[i][1] << "\n";
2002
2003#else
2004 Point2D W = velocity->wakeVortexesParams.diffVelo[i] * (nutPtr ? (1.0 + (*nutPtr)[i] / passport.physicalProperties.nu) : 1.0);
2005
2006 const auto& diff = velocity->wakeVortexesParams;
2007 Point2D grad = diff.I2[i] * (1.0 / (diff.epsastWake[i] * diff.I0[i])) - diff.I3[i] * (diff.I1[i] / sqr(diff.I0[i]));
2008
2009 //checkVelDyn << i << " " << wake->vtx[i].r()[0] << " " << wake->vtx[i].r()[1] << " " << velocity->wakeVortexesParams.epsastWake[i] << " " \
2010 // << velocity->wakeVortexesParams.convVelo[i][0] << " " << velocity->wakeVortexesParams.convVelo[i][1] << " " \
2011 // << W[0] << " " << W[1] << " " << W[0] << " " << W[1] << " " << diff.I1[i]/diff.I0[i] << " " << grad[0] << " " << grad[1] << "\n";
2012#endif
2013
2014 newPos[i] = wake->vtx[i].r() + (velocity->wakeVortexesParams.convVelo[i] + W + getV0()) * passport.timeDiscretizationProperties.dt;
2015
2016 //Chorin Random Walk method
2017 //newPos[i] = wake->vtx[i].r() + (velocity->wakeVortexesParams.convVelo[i] + getV0()) * passport.timeDiscretizationProperties.dt + Point2D{ d(gen), d(gen) };
2018 }
2019 //checkVel.close();
2020 //checkVelDyn.close();
2021
2022
2023 //for (int i = 0; i < (int)wake->vtx.size(); ++i)
2024 //{
2025 // std::cout << i << " " << wake->vtx[i].r() << " " << \
2026 // velocity->wakeVortexesParams.convVelo[i] << " " << \
2027 // velocity->wakeVortexesParams.diffVelo[i] << " " << \
2028 // getV0() << "\n";
2029 //}
2030
2031
2032
2033
2034 //getTimers().stop("Move");
2035}//MoveVortexes(...)
const double PI
Число .
Definition defs.h:76
Point2D getV0() const
Возврат текущей скорости набегающего потока
Definition World2D.h:148
Шаблонный класс, определяющий матрицу фиксированного размера Фактически представляет собой массив,...
Definition nummatrix.h:66
nummatrix< T, n, m > & toZero(T val=0.0)
Definition nummatrix.h:300
numvector< T, n > & toZero(P val=0)
Установка всех компонент вектора в константу (по умолчанию — нуль)
Definition numvector.h:528
size_t size() const
Definition numvector.h:114
P length() const
Вычисление 2-нормы (длины) вектора
Definition numvector.h:374
R dist(const numvector< T, n > &x, const numvector< P, n > &y)
Вычисление расстояния между двумя точками
Definition numvector.h:852
T cubPower(T x)
Возведение числа в куб
Definition defs.h:463
T sqr(T x)
Возведение числа в квадрат
Definition defs.h:455
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:836
double abs(const Vector3< T > &vec)
Definition utils.h:122
double vRef
Референсная скорость
Definition Passport2D.h:81
double nu
Коэффициент кинематической вязкости среды
Definition Passport2D.h:99
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReserveMemoryForMatrixAndRhs()

void World2D::ReserveMemoryForMatrixAndRhs ( )

Вычисляем размер матрицы и резервируем память под нее и под правую часть

Вызывается в Step()

Definition at line 1375 of file World2D.cpp.

1376{
1377 //getTimers().start("Mem");
1378
1379 if (currentStep == 0)
1380 {
1381 dispBoundaryInSystem.resize(boundary.size());
1382 dispBoundaryInSystem[0] = 0;
1383
1384 for (size_t i = 1; i < boundary.size(); ++i)
1385 {
1386 dispBoundaryInSystem[i] = dispBoundaryInSystem[i - 1] + boundary[i - 1]->GetUnknownsSize() + 1;
1387 }
1388
1389 size_t matrSize = boundary.size();
1390 size_t matrSkosSize = 0;
1391
1392 for (auto it = boundary.begin(); it != boundary.end(); ++it)
1393 {
1394 matrSize += (*it)->GetUnknownsSize();
1395 matrSkosSize += (*it)->GetUnknownsSize();
1396 }
1397
1398 if ((getPassport().numericalSchemes.linearSystemSolver.second == 0 || getPassport().numericalSchemes.linearSystemSolver.second == 1 || (getPassport().numericalSchemes.linearSystemSolver.second == 2 && isAnyMovableOrDeformable())))
1399 {
1400 //matr.resize(matrSize, matrSize);
1401 matrReord.resize(matrSize, matrSize);
1402 //matrSkos.resize(matrSkosSize, matrSkosSize);
1403
1404 //matr.setZero();
1405 matrReord.setZero();
1406 //matrSkos.setZero();
1407
1408
1409 for (size_t i = 0; i < getNumberOfAirfoil(); ++i)
1410 {
1411 size_t nVari = boundary[i]->GetUnknownsSize();
1412 for (size_t j = 0; j < getNumberOfAirfoil(); ++j)
1413 {
1414 size_t nVarj = boundary[j]->GetUnknownsSize();
1415 IQ[i][j].first.resize(nVari, nVarj);
1416 IQ[i][j].second.resize(nVari, nVarj);
1417 }
1418 }
1419 }
1420
1421 //rhs.resize(matrSize);
1422 rhsReord.resize(matrSize);
1423 //rhsSkos.resize(matrSkosSize);
1424 }
1425 //rhs.setZero();
1426 rhsReord.setZero();
1427 //rhsSkos.setZero();
1428
1429 //getTimers().stop("Mem");
1430}//ReserveMemoryForMatrixAndRhs()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SolveLinearSystem()

void World2D::SolveLinearSystem ( )

Решение системы линейных алгебраических уравнений

Вызывается в Step()

Definition at line 980 of file World2D.cpp.

981{
982 getTimers().start("Solve");
983/*
984 if (currentStep == 0)
985 {
986 invMatr = matr;
987 std::ifstream fileMatrix("matrix.txt");
988 int nx, ny;
989 fileMatrix >> nx;
990 fileMatrix >> ny;
991 for (int i = 0; i < matr.rows(); ++i)
992 {
993 for (int j = 0; j < matr.cols(); ++j)
994 {
995 fileMatrix >> matr(i, j);
996 }
997 }
998 fileMatrix.close();
999 }
1000*/
1001
1002//*
1003 //if (currentStep == 0)
1004 //{
1005 // std::ofstream fileMatrix(passport.dir + "/dbg/matrix.txt");
1006 // //int nx, ny;
1007 // //fileMatrix >> nx;
1008 // //fileMatrix >> ny;
1009 // fileMatrix.precision(16);
1010 // for (int i = 0; i < matrReord.rows(); ++i)
1011 // {
1012 // for (int j = 0; j < matrReord.cols(); ++j)
1013 // {
1014 // fileMatrix << matrReord(i, j) << " ";
1015 // }
1016 // fileMatrix << std::endl;
1017 // }
1018 // fileMatrix.close();
1019 //}
1020
1021
1022
1023 //{
1024 // std::ofstream fileMatrix(passport.dir + "/dbg/rhs"+std::to_string(currentStep)+".txt");
1025 // //int nx, ny;
1026 // //fileMatrix >> nx;
1027 // //fileMatrix >> ny;
1028 // fileMatrix.precision(16);
1029 // for (int i = 0; i < rhsReord.size(); ++i)
1030 // {
1031 // fileMatrix << rhsReord(i) << std::endl;
1032 // }
1033 // fileMatrix.close();
1034 //}//*/
1035
1036 //exit(-100500);
1037
1039 const int linSystemScheme = passport.numericalSchemes.linearSystemSolver.second;
1040
1041 if (linSystemScheme == 0) // Gaussian elimination
1042 {
1043 double t1 = -omp_get_wtime();
1044 if (useInverseMatrix && (currentStep == 0))
1045 {
1046 info('t') << "Inverting matrix... ";
1047
1048#if (defined(USE_CUDA))
1049 invMatr.resize(matrReord.rows(), matrReord.cols());
1050 for (int i = 0; i < (int)matrReord.rows(); ++i)
1051 for (int j = 0; j < (int)matrReord.cols(); ++j)
1052 invMatr(i, j) = (i == j) ? 1.0 : 0.0;
1053 cuInverseMatrix((int)matrReord.rows(), matrReord.data(), invMatr.data());
1054#else
1055 invMatr = matrReord.inverse();
1056#endif
1057 info('t') << "done" << std::endl;
1058 }
1059
1060 if (currentStep == 0)
1061 info('t') << "Solving system at step #0... ";
1062
1063 if (useInverseMatrix)
1064 {
1065 /*
1066 std::cout << "Solution via invMatrix" << std::endl;
1067 for (int i = 0; i < invMatr.rows(); ++i)
1068 for (int j = 0; j < invMatr.cols(); ++j)
1069 if (fabs(invMatr(i, j)) > 1e+5)
1070 std::cout << "invMatrixError: " << "invA(" << i << ", " << j << ") = " << invMatr(i, j) << std::endl;
1071
1072 for (int i = 0; i < rhsReord.size(); ++i)
1073 if (fabs(rhsReord(i)) > 1e+5)
1074 std::cout << "rhsReordError: " << "rhsReord(" << i << ") = " << rhsReord(i) << std::endl;
1075 */
1078 sol = invMatr * rhsReord;
1080 }
1081 else
1082 {
1085 sol = matrReord.partialPivLu().solve(rhsReord);
1087 }
1088
1089 if (currentStep == 0)
1090 info('t') << "done" << std::endl;
1091
1092 t1 += omp_get_wtime();
1093
1094 //std::cout << " Time in Gauss = " << t1 << std::endl;
1095/*
1096 std::ofstream solFile(getPassport().dir + "/sol" + std::to_string(currentStep) + "-Gauss.txt");
1097 solFile.precision(16);
1098 for (int i = 0; i < sol.size(); ++i)
1099 solFile << sol(i) << std::endl;
1100 solFile.close();
1101 exit(10101);
1102//*/
1103 }//Gauss
1104
1105/*
1106 if (currentStep == 0)
1107 { N
1108 invMatr = matr;
1109 std::ifstream fileMatrix("invMatrix.txt");
1110 int nx, ny;
1111 fileMatrix >> nx;
1112 fileMatrix >> ny;
1113 for (int i = 0; i < invMatr.rows(); ++i)
1114 {
1115 for (int j = 0; j < invMatr.cols(); ++j)
1116 {
1117 fileMatrix >> invMatr(i, j);
1118 }
1119 }
1120 fileMatrix.close();
1121 }
1122*/
1123
1124/*
1125 if (currentStep == 0)
1126 {
1127 Eigen::MatrixXd mmul = matr * invMatr;
1128 for (int i = 0; i < invMatr.rows(); ++i)
1129 mmul(i,i) -= 1.0;
1130
1131 double maxElem = 0.0;
1132 for (int i = 0; i < mmul.rows(); ++i)
1133 for (int j = 0; j < mmul.cols(); ++j)
1134 if (fabs(mmul(i,j)) > maxElem )
1135 maxElem = mmul(i,j);
1136
1137 std::cout << "A*A^-1: MAX ELEMENT = " << maxElem << std::endl;
1138 }
1139*/
1140
1141/*
1142 if (currentStep == 0)
1143 {
1144 std::ofstream fileMatrix("invMatrix4x3200.txt");
1145 fileMatrix << invMatr.rows() << " " << invMatr.cols() << std::endl;
1146 fileMatrix.precision(18);
1147 for (int i = 0; i < invMatr.rows(); ++i)
1148 {
1149 for (int j = 0; j < invMatr.cols(); ++j)
1150 {
1151 fileMatrix << invMatr(i, j) << " ";
1152 }
1153 fileMatrix << std::endl;
1154 }
1155 fileMatrix.close();
1156 }
1157*/
1158
1159
1160
1161 if ((linSystemScheme == 1 || linSystemScheme == 2)) // GMRES
1162 {
1163 int nFullVars = (int)getNumberOfBoundary();
1164 for (int i = 0; i < getNumberOfBoundary(); ++i)
1165 nFullVars += (int)(boundary[i]->GetUnknownsSize());
1166
1167 std::vector<std::vector<double>> Ggam(getNumberOfBoundary());
1168 for (int i = 0; i < getNumberOfBoundary(); ++i)
1169 Ggam[i].resize(boundary[i]->GetUnknownsSize());
1170
1171 std::vector<double> GR(getNumberOfBoundary());
1172
1173#ifndef USE_CUDA
1174 std::vector<double> Grhs(rhsReord.size());
1175 for (int i = 0; i < rhsReord.size(); ++i)
1176 Grhs[i] = rhsReord(i);
1177
1178 std::vector<int> Gpos(getNumberOfBoundary(), 0);
1179 for (int i = 1; i < getNumberOfBoundary(); ++i)
1180 Gpos[i] = Gpos[i - 1] + (int)(boundary[i - 1]->GetUnknownsSize());
1181
1182 std::vector<int> Gvsize(getNumberOfBoundary());
1183 for (int i = 0; i < getNumberOfBoundary(); ++i)
1184 Gvsize[i] = (int)(boundary[i]->GetUnknownsSize());
1185
1187 {
1188 //for direct GMRES
1189 std::vector<double> Gmatr(nFullVars * nFullVars);
1190 for (size_t i = 0; i < nFullVars; ++i)
1191 for (size_t j = 0; j < nFullVars; ++j)
1192 Gmatr[i * nFullVars + j] = matrReord(i, j);
1193
1194 for (int i = 0; i < getNumberOfBoundary(); ++i)
1195 for (int j = 0; j < boundary[i]->GetUnknownsSize(); ++j)
1196 auto y_test = airfoil[i]->len[j % airfoil[i]->getNumberOfPanels()];
1197
1198 //Gmres->GMRES_Direct(*this, nFullVars, (int)getNumberOfBoundary(), Gmatr, Grhs, Gpos, Gvsize, Ggam, GR);
1199 std::cout << "GMRES_Direct should be modified!" << std::endl;
1200 exit(-100);
1201
1202
1203 sol.resize(nFullVars);
1204 int cntr = 0;
1205 for (int i = 0; i < getNumberOfBoundary(); ++i)
1206 for (int j = 0; j < boundary[i]->GetUnknownsSize(); ++j)
1207 sol(cntr++) = Ggam[i][j] /*/ airfoil[i]->len[j % airfoil[i]->getNumberOfPanels()]*/;
1208 for (int i = 0; i < getNumberOfBoundary(); ++i)
1209 sol(cntr++) = GR[i];
1210
1211 //std::ofstream solFile(getPassport().dir + "/dbg/sol-direct-gmres" + std::to_string(currentStep) + ".txt");
1212 //solFile.precision(16);
1213 //for (int i = 0; i < sol.size(); ++i)
1214 // solFile << sol(i) << std::endl;
1215 //solFile.close();
1216 }
1218 {
1219 getInfo('e') << "Fast GMRES without CUDA is not implemented" << std::endl;
1220 exit(-2);
1221 }
1222#else
1224 {
1225 getInfo('e') << "Direct GMRES for CUDA is not implemented" << std::endl;
1226 exit(-2);
1227 }
1228
1229 if ( (passport.numericalSchemes.linearSystemSolver.second == 2))
1230 {
1231 // for fast GMRES
1232 std::vector<std::vector<double>> GGrhs(getNumberOfBoundary());
1233 int cntrRhs = 0;
1234 for (int i = 0; i < getNumberOfBoundary(); ++i)
1235 GGrhs[i].resize(boundary[i]->GetUnknownsSize());
1236 for (int i = 0; i < getNumberOfBoundary(); ++i)
1237 for (int j = 0; j < boundary[i]->GetUnknownsSize(); ++j)
1238 GGrhs[i][j] = rhsReord(cntrRhs++);
1239
1240 std::vector<double> GrhsReg(getNumberOfBoundary());
1241 for (int i = 0; i < getNumberOfBoundary(); ++i)
1242 GrhsReg[i] = rhsReord[nFullVars - (getNumberOfBoundary() - i)];
1243
1244
1245 int niter;
1247
1248 double time_GMRES = -omp_get_wtime();
1249 getNonConstCuda().Gmres->GMRES(Ggam, GR, GGrhs, GrhsReg, niter);//, linScheme);
1250 time_GMRES += omp_get_wtime();
1251 //std::cout << "Time_GMRES = " << time_GMRES << std::endl;
1252
1253 sol.resize(nFullVars);
1254 int cntr = 0;
1255 for (int i = 0; i < getNumberOfBoundary(); ++i)
1256 for (int j = 0; j < boundary[i]->GetUnknownsSize(); ++j)
1257 sol(cntr++) = Ggam[i][j] / airfoil[i]->len[j % airfoil[i]->getNumberOfPanels()];
1258 for (int i = 0; i < getNumberOfBoundary(); ++i)
1259 sol(cntr++) = GR[i];
1260
1261 /*
1262 std::ofstream solFile(getPassport().dir + "/sol-fast-new-gmres" + std::to_string(currentStep) + ".txt");
1263 solFile.precision(16);
1264 for (int i = 0; i < sol.size(); ++i)
1265 solFile << sol(i) << std::endl;
1266 solFile.close();
1267 exit(1010110);
1268 //*/
1269 }
1270#endif
1271 }
1272
1273 getTimers().stop("Solve");
1274}//SolveLinearSystem()
Eigen::MatrixXd invMatr
Обратная матрица
Definition World2D.h:128
VMlib::vmTimer timerSlaeSolve
Definition World2D.h:369
VMlib::LogStream & getInfo() const
Возврат ссылки на объект LogStream Используется в техничеcких целях для организации вывода
Definition WorldGen.h:82
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Step()

void World2D::Step ( )
overridevirtual

Функция выполнения предварительного шага

Основная функция выполнения одного шага по времени

Implements VMlib::WorldGen.

Definition at line 269 of file World2D.cpp.

270{
271 //try {
272 //Очистка статистики
274
275#ifdef USE_CUDA
276 cuSetCurrentStep((int)currentStep, 1);
277#endif // USE_CUDA
278
279
280 //Засечка времени в начале шага
281 getTimers().start("Step");
282
283 //Обновление параметров паспорта
285 {
286 std::unique_ptr<Passport> revisePspPtr;
287 revisePspPtr.reset(new VM2D::Passport(info, passport.dir, passport.problemNumber,
290
292
293 }
294
295
297
298 size_t countStrongCoupling = 0;
299 for (size_t m = 0; m < mechanics.size(); ++m)
300 {
301 MechanicsRigidOscillPart* mechVar = dynamic_cast<MechanicsRigidOscillPart*>(mechanics[m].get());
302 if (mechVar && getPassport().airfoilParams[m].addedMass.length2() > 0)
303 {
304 mechVar->getStrongCoupling() = true;
305 ++countStrongCoupling;
306 }
307 }
308
309 bool semiImplicitStrategy = ((countStrongCoupling == mechanics.size()) && (mechanics.size() > 0));
310 if ((currentStep == 0) && (semiImplicitStrategy))
311 info('i') << "Strong (semi-implicit) coupling strategy" << std::endl;
312
313//НЕПОДВИЖНЫЕ ТЕЛА
314//*
315 int nTotPan = 0;
316 for (size_t s = 0; s < getNumberOfAirfoil(); ++s)
317 nTotPan += (int)getAirfoil(s).getNumberOfPanels();
318
319
320 if (!semiImplicitStrategy)
321 {
323
326 if (getPassport().numericalSchemes.velocityComputation.second == 0 && getPassport().numericalSchemes.linearSystemSolver.second == 2)
327 {
328#ifdef USE_CUDA
329 cuda.RefreshAfls(3);
330 if (nTotPan > 0)
331 {
332 auto& afl = getAirfoil(0);
333 auto& treePnlVrt = *getCuda().inflTreePnlVortex;
334 if (getCurrentStep() == 0)
335 treePnlVrt.MemoryAllocate((int)getCuda().n_CUDA_pnls);
336
338 {
339 //Построение дерева для влияющих панелей (вихревых слоев)
340 treePnlVrt.UpdatePanelGeometry(nTotPan, (double4*)afl.devRPtr);
341 treePnlVrt.Build();
342 }
343
344 treePnlVrt.UpdatePanelAttachedVortexIntensity(afl.devAttachedVortexSheetPtr, afl.devAttachedVortexSheetLinPtr);
345 treePnlVrt.UpwardTraversal(getPassport().numericalSchemes.gmresMultipoleOrder);
346 }
347#endif
348 }
349
350 if (getPassport().numericalSchemes.velocityComputation.second == 1)
351 {
352#ifdef USE_CUDA
353 cuda.RefreshWake(3);
354 cuda.RefreshAfls(3);
355
356 //Построение дерева для вихрей
357 auto& treeWake = *getCuda().inflTreeWake;
358 treeWake.MemoryAllocate((int)getCuda().n_CUDA_wake);
359 treeWake.Update((int)getWake().vtx.size(), getWake().devVtxPtr);
360 treeWake.Build();
361 treeWake.UpwardTraversal(getPassport().numericalSchemes.nbodyMultipoleOrder);
362
363 if (nTotPan > 0)
364 {
365 auto& afl = getAirfoil(0);
366 auto& treePnl = *getCuda().cntrTreePnl;
367 auto& treePnlVrt = *getCuda().inflTreePnlVortex;
368 auto& treePnlSrc = *getCuda().inflTreePnlSource;
369 auto& treePnlAux = *getCuda().auxTreePnl;
370
371 if (getCurrentStep() == 0)
372 {
373 treePnl.MemoryAllocate((int)getCuda().n_CUDA_pnls);
374 treePnlAux.MemoryAllocate((int)getCuda().n_CUDA_pnls);
375 treePnlVrt.MemoryAllocate((int)getCuda().n_CUDA_pnls);
377 treePnlSrc.MemoryAllocate((int)getCuda().n_CUDA_pnls);
378 }
379
381 {
382 //Построение дерева для влияющих панелей (вихревых слоев)
383 treePnlVrt.UpdatePanelGeometry(nTotPan, (double4*)afl.devRPtr);
384 treePnlVrt.Build();
385
386 //Построение контрольного дерева панелей
387 treePnl.UpdatePanelGeometry((int)nTotPan, (double4*)afl.devRPtr);
388 treePnl.Build();
389
390 //Построение дерева для влияющих панелей (источников)
392 {
393 treePnlSrc.UpdatePanelGeometry(nTotPan, (double4*)afl.devRPtr);
394 treePnlSrc.UpdatePanelAttachedSourceIntensity(afl.devAttachedSourceSheetPtr, afl.devAttachedSourceSheetLinPtr);
395 treePnlSrc.Build();
396 treePnlSrc.UpwardTraversal(getPassport().numericalSchemes.nbodyMultipoleOrder);
397 }
398 }
399
400 treePnlVrt.UpdatePanelAttachedVortexIntensity(afl.devAttachedVortexSheetPtr, afl.devAttachedVortexSheetLinPtr);
401 treePnlVrt.UpwardTraversal(getPassport().numericalSchemes.nbodyMultipoleOrder);
402 }
403#else
404 if (getWake().vtx.size() > 0)
405 {
406 inflTreeWake->Update(getWake().vtx);
407 inflTreeWake->Build();
408 inflTreeWake->UpwardTraversal(getPassport().numericalSchemes.nbodyMultipoleOrder);
409 }
410 std::vector<std::pair<Point2D, Point2D>> panels;
411
412 for (size_t bou = 0; bou < getNumberOfAirfoil(); ++bou)
413 {
414 const auto& afl = getAirfoil(bou);
415
416 for (size_t i = 0; i < afl.getNumberOfPanels(); ++i)
417 panels.push_back({ afl.getR(i), afl.getR(i + 1) });
418 }
419 if (panels.size() > 0)
420 {
421 cntrTreePnl->UpdatePanelGeometry(panels, std::max(4, (int)(log2(panels.size())) - 2));
422 cntrTreePnl->Build();
423 cntrTreePnl->UpwardTraversal(getPassport().numericalSchemes.nbodyMultipoleOrder);
424 }
425#endif
426 }
428
429 measureVP->Initialization();
431
432 //added masses
433 if (getPassport().physicalProperties.typeAccel.second == 3)
434 {
435 std::vector<Point2D> lambdaAdd(getNumberOfAirfoil(), {0.0, 0.0});
436 std::vector<double> muAdd(getNumberOfAirfoil());
437 for (size_t bou = 0; bou < getNumberOfAirfoil(); ++bou)
438 {
439 if (dynamic_cast<MechanicsRigidGivenLaw*>(&getNonConstMechanics(bou)))
440 {
441 for (size_t pnl = 0; pnl < getAirfoil(bou).getNumberOfPanels(); ++pnl)
442 {
443 double sumGam = getBoundary(bou).sheets.freeVortexSheet(pnl, 0) + getBoundary(bou).sheets.attachedVortexSheet(pnl, 0);
444 Point2D rpnl = 0.5 * (getAirfoil(bou).getR(pnl) + getAirfoil(bou).getR(pnl + 1));
445 lambdaAdd[bou] += rpnl.kcross() * sumGam * getAirfoil(bou).len[pnl];
446 muAdd[bou] += (rpnl - getAirfoil(bou).rcm).length2() * sumGam * getAirfoil(bou).len[pnl];
447 }
448 lambdaAdd[bou] *= getPassport().physicalProperties.rho;
449 muAdd[bou] *= 0.5 * getPassport().physicalProperties.rho;
450 info('i') << "Added Masses for airfoil #" << bou << " = { " << lambdaAdd[bou][0] << ", " << lambdaAdd[bou][1] << ", " << muAdd[bou] << " }" << std::endl;
451
452 char direction;
453 switch ((int)(getPassport().physicalProperties.timeAccel))
454 {
455 case 0:
456 direction = 'x';
457 break;
458 case 1:
459 direction = 'y';
460 break;
461 case 2:
462 direction = 'w';
463 break;
464 default:
465 direction = '?';
466 info('e') << "Wrong dirfection is specified!" << std::endl;
467 exit(1);
468 }
469
470 std::string addMassFileName = getPassport().dir + "addMass-" + std::to_string(getAirfoil(bou).numberInPassport);
471 std::ofstream addMassFile;
472 if (!VMlib::fileExistTest(addMassFileName, info) || getPassport().physicalProperties.timeAccel == 0)
473 {
474 addMassFile.open(addMassFileName);
475 addMassFile << "Added Masses for airfoil:" << std::endl;
476 }
477 else
478 addMassFile.open(addMassFileName, std::ios_base::app);
479
480 addMassFile << direction << "-direction: " << lambdaAdd[bou][0] << " " << lambdaAdd[bou][1] << " " << muAdd[bou] << std::endl;
481
482 addMassFile.close();
483 }
484 }
486 }
487
489 if (nTotPan > 0 && getPassport().numericalSchemes.velocityComputation.second == 1)
490 {
491 auto& afl = getAirfoil(0);
492#ifdef USE_CUDA
493 getCuda().inflTreePnlVortex->UpdatePanelFreeAndAttachedVortexIntensity(afl.devFreeVortexSheetPtr, afl.devFreeVortexSheetLinPtr, afl.devAttachedVortexSheetPtr, afl.devAttachedVortexSheetLinPtr);
494 getCuda().inflTreePnlVortex->UpwardTraversal(getPassport().numericalSchemes.nbodyMultipoleOrder);
495#endif
496 }
498
499 //Вычисление скоростей вихрей: для тех, которые в следе, и виртуальных, а также в точках wakeVP
501
502
503#ifdef TURB
504 getTimers().start("Nut");
505 std::vector<double> nut;
506 CalcVeloDifference(nut);
507 getTimers().stop("Nut");
508
509 for (size_t q = 0; q < getWake().vtx.size(); ++q)
510 getNonConstWake().vtx[q].sigma() = 4.48364 * sqrt(passport.timeDiscretizationProperties.dt * (passport.physicalProperties.nu + nut[q]));
511#endif
512
513
514//#include "gammaCirc.h"
515
516 //Расчет и сохранение поля давления
518
519#ifdef OPTIMIZER
520 if ((getCurrentStep() >= OPTIMIZER_START_STEP && getCurrentStep() <= OPTIMIZER_STOP_STEP) || getCurrentStep()==0) //2026-03-28
521#endif
522 {
523 const double& vRef = getPassport().physicalProperties.vRef;
524 //scaleV = 1.0 / vRef;
525 double scaleP = 1.0 / (0.5 * getPassport().physicalProperties.rho * sqr(vRef));
526
527#ifdef USE_CUDA
528 measureVP->GPUCalcPressure();
529#else
530 measureVP->CalcPressure();
531#endif
532
533 if (mechanics.size()>0)
534 {
535 //std::cout << "presForces are calculated\n";
536 //MechanicsDeformable* ptr = dynamic_cast<MechanicsDeformable*>(mechanics[0].get());
537 Mechanics* ptr = mechanics[0].get();
538
539 if (measureVP->getTotalNumberOfRealPoints() > 0)
540 measureVP->SaveVP();
541
542 //if (ptr && !ptr->beam->fsi)
543
544 //сохранение главного вектора силы, вычисленного как интеграл от давления
545 //*
546 if (measureVP->elasticPoints.size() > 0)
547 {
548 std::ofstream presForcesFile;
549 if (currentStep == 0)
550 {
551 presForcesFile.open(getPassport().dir + "presForcesFile.csv");
552 presForcesFile << "time,Fx,Fy,Py" << std::endl;
553 }
554 else
555 presForcesFile.open(getPassport().dir + "presForcesFile.csv", std::ios_base::app);
556
557 auto r = measureVP->GetVPinElasticPoints();
558 Point2D presForce = { 0.0, 0.0 };
559 double yPower = 0.0;
560
561 for (int q = 0; q < r.size(); ++q)
562 {
563 presForce -= r[q].second * getAirfoil(0).len[q] * getAirfoil(0).nrm[q];
564 yPower -= (r[q].second * getAirfoil(0).len[q] * getAirfoil(0).nrm[q])[1] * (0.5 * (getAirfoil(0).getV(q) + getAirfoil(0).getV(q + 1))[1]);
565 }
566
567 presForcesFile << currentTime << "," << scaleP * presForce[0] << "," << scaleP * presForce[1] << "," << scaleP * yPower << std::endl;
568 presForcesFile.close();
569 }
570 }
571 //*/
572
573 if (mechanics.size() > 0)
574 {
575 //Коэффициенты разложения силы по балочным функциям
576 MechanicsDeformable* ptr = dynamic_cast<MechanicsDeformable*>(mechanics[0].get());
577 if (ptr && ptr->beam->fsi)
578 {
579 auto r = measureVP->GetVPinElasticPoints();
580
581 /*
582 std::ofstream elastPresFile;
583 elastPresFile.open(getPassport().dir + "elastPresFile-" + std::to_string(currentStep) + ".txt");
584 //if (currentStep == 0)
585 // elastPresFile.open(getPassport().dir + "elastPresFile.txt");
586 //else
587 // elastPresFile.open(getPassport().dir + "elastPresFile.txt", std::ios_base::app);
588 //elastPresFile << currentStep << " ";
589
590 for (size_t q = 0; q < r.size(); ++q)
591 elastPresFile << measureVP->elasticPoints[q][0] << " " << measureVP->elasticPoints[q][1] << " " << r[q].second << std::endl;
592 //elastPresFile << std::endl;
593 elastPresFile.close();
594 */
595
596 //Сохраняем давление на последних nLastSteps шагах по дисциплине очереди
597 std::vector<double> currentPres(ptr->chord.size());
598 for (size_t j = 0; j < ptr->chord.size(); ++j)
599 {
600 //currentPres[j] = -(ptr->beam->rho * 2 * ptr->beam->F); // gravity force for g = 2.0;
601 currentPres[j] = -(r[2 * j + 0].second - r[2 * j + 1].second);
602 }
603
604 if (ptr->beam->presLastSteps.size() < ptr->beam->nLastSteps)
605 ptr->beam->presLastSteps.push_back(currentPres);
606 else
607 {
608 for (int w = 1; w < ptr->beam->nLastSteps; ++w)
609 ptr->beam->presLastSteps[w - 1] = std::move(ptr->beam->presLastSteps[w]);
610 ptr->beam->presLastSteps.back() = currentPres;
611 }
612
613 for (int q = 0; q < ptr->beam->R; ++q)
614 {
615 ptr->beam->qCoeff[q] = 0;
616
617 if (ptr->beam->presLastSteps.size() == ptr->beam->nLastSteps)
618 {
619 for (size_t j = 0; j < ptr->chord.size(); ++j)
620 {
621 double averpres = 0.0;
622
623 //осредняем давление
624 for (int i = 0; i < ptr->beam->nLastSteps; ++i)
625 averpres += ptr->beam->presLastSteps[i][j];
626 averpres /= ptr->beam->nLastSteps;
627
628 ptr->beam->qCoeff[q] += -averpres * (ptr->initialChord[j].beg - ptr->initialChord[j].end).length() * ptr->beam->shape(q, 0.5 * (ptr->initialChord[j].beg + ptr->initialChord[j].end)[0]);
629 }
630 ptr->beam->qCoeff[q] /= (ptr->beam->intSqUnitShape * ptr->beam->L);
631 }
632
633 //std::cout << "q[" << q << "] = " << ptr->beam->qCoeff[q] << std::endl;
634 }
635
636 std::ofstream phiFile;
637 if (currentStep == 0)
638 {
639 phiFile.open(getPassport().dir + "phiFile.csv");
640 phiFile << "time";
641 for (int p = 0; p < ptr->beam->R; ++p)
642 phiFile << ",phi-" << std::to_string(p + 1);
643 for (int p = 0; p < ptr->beam->R; ++p)
644 phiFile << ",q-" << std::to_string(p + 1);
645 phiFile << std::endl;
646 }
647 else
648 phiFile.open(getPassport().dir + "phiFile.csv", std::ios_base::app);
649
650 phiFile << currentTime;
651 for (int p = 0; p < ptr->beam->R; ++p)
652 phiFile << "," << ptr->beam->phi(p, 0);
653 for (int p = 0; p < ptr->beam->R; ++p)
654 phiFile << "," << ptr->beam->qCoeff[p];
655
656 phiFile << std::endl;
657
658 phiFile.close();
659 }
660 }
661//*/
662 //getInfo('e') << "Deformable airfoils are not supported now!";
663 }
664
665 //Вычисление сил, действующих на профиль и сохранение в файл
666 for (auto& mech : mechanics)
667 {
668 mech->GetHydroDynamForce();
669 mech->GenerateForcesString();
670 mech->GeneratePositionString();
671 }
672
673 //Движение вихрей (сброс вихрей + передвижение пелены)
674#ifdef TURB
675 WakeAndAirfoilsMotion(true, &nut);
676
677
678#else
680#endif
681 wake->Restruct();
682 wake->SaveKadrVtk();
683
684 //std::string fname = getPassport().dir + "/airfoil-" + std::to_string(getAirfoil(0).numberInPassport) + "-" + std::to_string(currentStep) + ".pfl";
686 //{
687 // std::ofstream of(fname);
688 // for (size_t i = 0; i < getAirfoil(0).getNumberOfPanels(); ++i)
689 // of << getAirfoil(0).getR(i)[0] << " " << getAirfoil(0).getR(i)[1] << std::endl;
690 // of.close();
691 //}
692
693 }//if (!semiImplicitStrategy)
694
695
696//СОПРЯЖЕННАЯ ПОСТАНОВКА
697 if (semiImplicitStrategy)
698 {
700 measureVP->Initialization();
701
703
704 //Вычисление скоростей вихрей: для тех, которые в следе, и виртуальных, а также в точках wakeVP
706
707 //for (size_t s = 0; s < mechanics.size(); ++s) {// проверка: вычисление полной силы по циркуляциям новых вихрей
708 // mechanics[s]->GetHydroDynamForce();
709 // mechanics[s]->GenerateForcesString();
710 //}
711
712 //Расчет и сохранение поля давления
714 {
715 measureVP->CalcPressure();
716 measureVP->SaveVP();
717 }
718
719 WakeAndAirfoilsMotion(false); //профиль - кинематически, здесь Vold := V;
720 wake->Restruct();
721
724
725 //Вычисление сил, действующих на профиль и сохранение в файл
726
727 for (size_t m = 0; m < mechanics.size(); ++m)
728 {
729 mechanics[m]->GetHydroDynamForce();
730
731 MechanicsRigidOscillPart* mechVar = dynamic_cast<MechanicsRigidOscillPart*>(mechanics[m].get());
732 if (mechVar)
733 {
734 if (getPassport().airfoilParams[m].addedMass.length2() == 0)
735 {
736 getInfo('e') << "Added mass of the airfoil should be non-zero!" << std::endl;
737 exit(1);
738 }
739 mechVar->MoveOnlyVelo();
740 Point2D accel = (mechVar->getV() - mechVar->getVOld()) * (1.0 / getPassport().timeDiscretizationProperties.dt);
741 mechVar->hydroDynamForce -=
742 Point2D{ accel[0] * getPassport().airfoilParams[m].addedMass[0],
743 accel[1] * getPassport().airfoilParams[m].addedMass[1] };
744 mechVar->GenerateForcesString();
745 mechVar->GeneratePositionString();
746 }
747 else
748 exit(3333);
749 }
750 }
751
752
753 wake->SaveKadrVtk();
754//*/
756
757
758 //Засечка времени в конце шага
759 getTimers().stop("Step");
760 /*
761 std::cout << "nvt = " << nVtxBeforeMerging << std::endl;
762 std::cout << "tIBT = " << timerInitialBuild.duration() << std::endl;
763 std::cout << "tRHS = " << timerRhs.duration() << std::endl;
764 std::cout << "tFIL = " << timerFillMatrix.duration() << std::endl;
765 std::cout << "tLIN = " << timerSlaeSolve.duration() << std::endl;
766 std::cout << "tVEL = " << timerConvVelo.duration() << std::endl;
767 std::cout << "tINS = " << timerInside.duration() << std::endl;
768 std::cout << "tMRG = " << timerMerging.duration() << std::endl;
769 */
770
771 info('i') << "Step = " << getCurrentStep() \
772 << " PhysTime = " << getCurrentTime() \
773 << std::setprecision(3) \
774 << " StepTime = " << getTimers().durationStep() \
775 << std::setprecision(6) \
776 << std::endl;
777
779
781 currentStep += 1;
782 //}
783 //catch (...)
784 //{
785 // info('e') << "!!! Exception from unknown source !!!" << std::endl;
786 // exit(-1);
787 //}
788}//Step()
const Point2D & getR(size_t q) const
Возврат константной ссылки на вершину профиля
Definition Airfoil2D.h:113
std::vector< Point2D > nrm
Нормали к панелям профиля
Definition Airfoil2D.h:81
Point2D rcm
Положение центра масс профиля
Definition Airfoil2D.h:97
Sheet sheets
Слои на профиле
Definition Boundary2D.h:96
std::vector< ChordPanel > initialChord
std::vector< ChordPanel > chord
std::unique_ptr< Beam > beam
Абстрактный класс, определяющий вид механической системы
Definition Mechanics2D.h:72
Point2D hydroDynamForce
Вектор гидродинамической силы и момент, действующие на профиль
void GeneratePositionString()
Сохранение строки со статистикой в файл нагрузок
void GenerateForcesString()
Сохранение строки со статистикой в файл нагрузок
Point2D & getV()
текущая скорость профиля
std::string defaultsFileFullName
Definition Passport2D.h:281
std::vector< std::string > varLine
Definition Passport2D.h:283
std::string switchersFileFullName
Definition Passport2D.h:282
std::string mechanicsFileFullName
Definition Passport2D.h:280
std::string fileFullName
Имена файлов
Definition Passport2D.h:279
void GetReviseParamsFromParser(const Passport &newPassport, const std::vector< std::string > paramList)
Считывание измененных параметров
const double & attachedVortexSheet(size_t n, size_t moment) const
Definition Sheet2D.h:105
const double & freeVortexSheet(size_t n, size_t moment) const
Definition Sheet2D.h:100
std::vector< Vortex2D > vtx
Список вихревых элементов
void WakeAndAirfoilsMotion(bool dynamics, std::vector< double > *nutPtr=nullptr)
Перемещение вихрей и профилей на шаге
Definition World2D.cpp:2234
VMlib::vmTimer timerInitialBuild
Definition World2D.h:366
void CalcPanelsVeloAndAttachedSheets()
Вычисление скоростей панелей и интенсивностей присоединенных слоев вихрей и источников
Definition World2D.cpp:1616
void CalcVortexVelo()
Вычисление скоростей (и конвективных, и диффузионных) вихрей (в пелене и виртуальных),...
Definition World2D.cpp:1435
void CalcAndSolveLinearSystem()
Набор матрицы, правой части и решение СЛАУ
Definition World2D.cpp:2087
const Boundary & getBoundary(size_t i) const
Возврат константной ссылки на объект граничного условия
Definition World2D.h:186
bool ifDivisible(int val) const
Definition World2D.h:290
Mechanics & getNonConstMechanics(size_t i) const
Возврат неконстантной ссылки на объект механики
Definition World2D.h:225
Wake & getNonConstWake() const
Возврат неконстантной ссылки на вихревой след
Definition World2D.h:237
void GenerateStatString(size_t stepNo, double curTime, size_t N)
Формирование очередной строки файла временной статистики
Definition TimesGen.cpp:111
void resetAll()
Сброс всех счетчиков
Definition TimesGen.cpp:81
double durationStep() const
Вывод счетчика всего шага в секундах
Definition TimesGen.h:184
size_t getCurrentStep() const
Возврат константной ссылки на параметры распараллеливания по MPI.
Definition WorldGen.h:99
numvector< T, 2 > kcross() const
Геометрический поворот двумерного вектора на 90 градусов
Definition numvector.h:511
bool fileExistTest(std::string &fileName, LogStream &info, bool exitKey=false, const std::list< std::string > &extList={})
Проверка существования файла
Definition defs.h:340
double rho
Плотность потока
Definition Passport2D.h:75
std::vector< std::string > reviseParameters
Список перечитываемых параметров
Definition PassportGen.h:73
int revisePassportStep
Шаг перечитывания паспорта
Definition PassportGen.h:70
Here is the call graph for this function:

◆ WakeAndAirfoilsMotion()

void World2D::WakeAndAirfoilsMotion ( bool  dynamics,
std::vector< double > *  nutPtr = nullptr 
)

Перемещение вихрей и профилей на шаге

Вызывается в Step()

Definition at line 2234 of file World2D.cpp.

2235{
2236 std::vector<Point2D> newPos;
2237
2238 MoveVortexes(newPos, nutPtr);
2239
2240//#ifdef BRIDGE
2241// double totalForce = 0;
2242// for (size_t afl = 0; afl < airfoil.size(); ++afl)
2243// {
2244// totalForce += mechanics[afl]->hydroDynamForce[1];
2245// }
2246// totalForce *= 1.2;
2247//
2248// mechanics[0]->hydroDynamForce[1] = totalForce;
2249//#endif
2250
2251 oldAirfoil.resize(0);
2252 for (auto& afl : airfoil)
2253 {
2254 if (dynamic_cast<AirfoilRigid*>(afl.get()))
2255 oldAirfoil.emplace_back(new AirfoilGeometry(*afl));
2256
2257 if (dynamic_cast<AirfoilDeformable*>(afl.get()))
2258 oldAirfoil.emplace_back(new AirfoilGeometry(*afl));
2259
2260
2261#ifdef BRIDGE
2262 if (dynamics)
2263 {
2264 if (afl->numberInPassport == 0)
2265 {
2266 mechanics[afl->numberInPassport]->Move();
2267 }
2268 else
2269 {
2270 MechanicsRigidOscillPart* mechTest = dynamic_cast<MechanicsRigidOscillPart*>(mechanics[afl->numberInPassport].get());
2271 if (mechTest != nullptr)
2272 {
2273 Mechanics& mechGen = *mechanics[0];
2274 MechanicsRigidOscillPart& mech0 = dynamic_cast<MechanicsRigidOscillPart&>(mechGen);
2275
2276 Point2D dr = mech0.getR() - mech0.getROld();
2277 Point2D dv = mech0.getV() - mech0.getVOld();
2278
2279 double dphi = mech0.getPhi() - mech0.getPhiOld();
2280 double dw = mech0.getW() - mech0.getWOld();
2281
2282 Mechanics& mechGenI = *mechanics[afl->numberInPassport];
2283 MechanicsRigidOscillPart& mechI = dynamic_cast<MechanicsRigidOscillPart&>(mechGenI);
2284
2285 mechI.getROld() = mechI.getR();
2286 mechI.getVOld() = mechI.getV();
2287 mechI.getPhiOld() = mechI.getPhi();
2288 mechI.getWOld() = mechI.getW();
2289
2290 //std::cout << "afl = " << afl << ", dy = " << dy << std::endl;
2291
2292 airfoil[afl->numberInPassport]->Move(dr);
2293 airfoil[afl->numberInPassport]->Rotate(dphi);
2294
2295 mechI.getR() += dr;
2296 mechI.getV() += dv;
2297
2298 mechI.getPhi() += dphi;
2299 mechI.getW() += dw;
2300 }
2301 }
2302 }
2303#endif
2304
2305#ifdef INITIAL
2306 if (dynamics)
2307 mechanics[afl->numberInPassport]->Move();
2308 else
2309 {
2310 MechanicsRigidOscillPart* mech = dynamic_cast<MechanicsRigidOscillPart*>(mechanics[afl->numberInPassport].get());
2311 if (mech)
2312 mech->MoveKinematic();
2313 else
2314 exit(2222);
2315 }
2316#endif
2317 }//for
2318
2319#if defined(__CUDACC__) || defined(USE_CUDA)
2320 cuda.RefreshAfls(2);
2321#endif
2322
2323 for (auto& bou : boundary)
2324 bou->virtualWake.vtx.clear();
2325
2326
2327 CheckInside(newPos, oldAirfoil);
2328
2329
2330 //передача новых положений вихрей в пелену
2331 for (size_t i = 0; i < wake->vtx.size(); ++i)
2332 {
2333 wake->vtx[i].r() = newPos[i];
2334 //wake->vtx[i].sigma() = getPassport().wakeDiscretizationProperties.sigma0;
2335 }
2336
2337// getWake().SaveKadrVtk();
2338
2339}//WakeAndAirfoilsMotion()
Класс, определяющий форму профиля
Definition Airfoil2D.h:66
Point2D & getR()
текущее отклонение профиля
double & getPhi()
текущий угол поворота профиля
double & getW()
текущая угловая скорость профиля
void MoveVortexes(std::vector< Point2D > &newPos, std::vector< double > *nutPtr=nullptr)
Вычисляем новые положения вихрей (в пелене и виртуальных)
Definition World2D.cpp:1634
void CheckInside(std::vector< Point2D > &newPos, const std::vector< std::unique_ptr< AirfoilGeometry > > &oldAirfoil)
Проверка проникновения вихрей внутрь профиля
Definition World2D.cpp:792
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ airfoil

std::vector<std::unique_ptr<Airfoil> > VM2D::World2D::airfoil
private

Список умных указателей на обтекаемые профили

Definition at line 80 of file World2D.h.

◆ auxTreePnl

std::unique_ptr<CpuTreeInfo> VM2D::World2D::auxTreePnl

Definition at line 119 of file World2D.h.

◆ boundary

std::vector<std::unique_ptr<Boundary> > VM2D::World2D::boundary
private

Список умных указателей на формирователи граничных условий на профилях

Definition at line 86 of file World2D.h.

◆ check01

int VM2D::World2D::check01
mutable

Definition at line 108 of file World2D.h.

◆ check02

int VM2D::World2D::check02
mutable

Definition at line 109 of file World2D.h.

◆ checkPan

int VM2D::World2D::checkPan
mutable

Definition at line 110 of file World2D.h.

◆ cntrTreePnl

std::unique_ptr<CpuTreeInfo> VM2D::World2D::cntrTreePnl

Definition at line 116 of file World2D.h.

◆ cntrTreeVP

std::unique_ptr<CpuTreeInfo> VM2D::World2D::cntrTreeVP

Definition at line 115 of file World2D.h.

◆ cntrTreeWake

std::unique_ptr<CpuTreeInfo> VM2D::World2D::cntrTreeWake

Definition at line 114 of file World2D.h.

◆ cuda

Gpu VM2D::World2D::cuda
mutableprivate

Объект, управляющий графическим ускорителем

Definition at line 143 of file World2D.h.

◆ currentStep

size_t VMlib::WorldGen::currentStep
protectedinherited

Текущий номер шага в решаемой задаче

Definition at line 69 of file WorldGen.h.

◆ currentTime

double VMlib::WorldGen::currentTime
protectedinherited

Текущее время в решаемой задаче

Definition at line 72 of file WorldGen.h.

◆ dispBoundaryInSystem

std::vector<size_t> VM2D::World2D::dispBoundaryInSystem
private

Список номеров, с которых начинаются элементы правой части (или матрицы) системы для профилей

Definition at line 89 of file World2D.h.

◆ gabb

int VM2D::World2D::gabb
mutable

Definition at line 107 of file World2D.h.

◆ inflTreeWake

std::unique_ptr<CpuTreeInfo> VM2D::World2D::inflTreeWake

Деревья для быстрого метода

Definition at line 113 of file World2D.h.

◆ info

LogStream VMlib::WorldGen::info
mutableprotectedinherited

Поток для вывода логов и сообщений об ошибках

Definition at line 60 of file WorldGen.h.

◆ invMatr

Eigen::MatrixXd VM2D::World2D::invMatr
private

Обратная матрица

Definition at line 128 of file World2D.h.

◆ IQ

std::vector<std::vector<std::pair<Eigen::MatrixXd, Eigen::MatrixXd> > > VM2D::World2D::IQ
private

Матрица, состоящая из пар матриц, в которых хранятся касательные и нормальные компоненты интегралов от ядра

Definition at line 125 of file World2D.h.

◆ matrReord

Eigen::MatrixXd VM2D::World2D::matrReord
private

Матрица системы

Definition at line 122 of file World2D.h.

◆ measureVP

std::unique_ptr<MeasureVP> VM2D::World2D::measureVP
private

Умный указатель на алгоритм вычисления полей скоростей и давления (для сохранения в файл)

Definition at line 104 of file World2D.h.

◆ mechanics

std::vector<std::unique_ptr<Mechanics> > VM2D::World2D::mechanics
private

Список умных указателей на типы механической системы для каждого профиля

Definition at line 92 of file World2D.h.

◆ nVtxBeforeMerging

size_t VMlib::WorldGen::nVtxBeforeMerging
inherited

Definition at line 76 of file WorldGen.h.

◆ oldAirfoil

std::vector<std::unique_ptr<AirfoilGeometry> > VM2D::World2D::oldAirfoil
private

Список умных указателей на обтекаемые профили для сохранения старого положения

Definition at line 83 of file World2D.h.

◆ passport

const Passport& VM2D::World2D::passport
private

Константная ссылка на паспорт конкретного расчета

Definition at line 140 of file World2D.h.

◆ passportGen

const PassportGen& VMlib::WorldGen::passportGen
protectedinherited

Константная ссылка на паспорт конкретного расчета

Definition at line 63 of file WorldGen.h.

◆ rhsReord

Eigen::VectorXd VM2D::World2D::rhsReord
private

Правая часть системы

Definition at line 134 of file World2D.h.

◆ sol

Eigen::VectorXd VM2D::World2D::sol
private

Решение системы

Definition at line 137 of file World2D.h.

◆ source

std::unique_ptr<WakeDataBase> VM2D::World2D::source
private

Умный указатель на источники

Definition at line 101 of file World2D.h.

◆ timerConvVelo

VMlib::vmTimer VM2D::World2D::timerConvVelo

Definition at line 371 of file World2D.h.

◆ timerFillMatrix

VMlib::vmTimer VM2D::World2D::timerFillMatrix

Definition at line 368 of file World2D.h.

◆ timerInitialBuild

VMlib::vmTimer VM2D::World2D::timerInitialBuild

Definition at line 366 of file World2D.h.

◆ timerInside

VMlib::vmTimer VM2D::World2D::timerInside

Definition at line 372 of file World2D.h.

◆ timerMerging

VMlib::vmTimer VM2D::World2D::timerMerging

Definition at line 373 of file World2D.h.

◆ timerRhs

VMlib::vmTimer VM2D::World2D::timerRhs

Definition at line 367 of file World2D.h.

◆ timers

std::unique_ptr<TimersGen> VMlib::WorldGen::timers
protectedinherited

Сведения о временах выполнения основных операций

Definition at line 66 of file WorldGen.h.

◆ timerSlaeSolve

VMlib::vmTimer VM2D::World2D::timerSlaeSolve

Definition at line 369 of file World2D.h.

◆ useInverseMatrix

bool VM2D::World2D::useInverseMatrix
private

Признак использования обратной матрицы

Definition at line 131 of file World2D.h.

◆ velocity

std::unique_ptr<Velocity> VM2D::World2D::velocity
private

Умный укзатель на объект, определяющий методику вычисления скоростей

Definition at line 95 of file World2D.h.

◆ wake

std::unique_ptr<Wake> VM2D::World2D::wake
private

Умный указатель на вихревой след

Definition at line 98 of file World2D.h.


The documentation for this class was generated from the following files: