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

Класс, определяющий способ вычисления скоростей More...

#include <Velocity2DBiotSavart.h>

Inheritance diagram for VM2D::VelocityBiotSavart:
Collaboration diagram for VM2D::VelocityBiotSavart:

Public Member Functions

 VelocityBiotSavart (const World2D &W_)
 Конструктор
 
virtual ~VelocityBiotSavart ()
 Деструктор
 
virtual float CalcConvVeloToSetOfPointsFromWake (const WakeDataBase &pointsDb, std::vector< Point2D > &velo, std::vector< double > &domainRadius, bool calcVelo, bool calcRadius) override
 Вычисление конвективных скоростей и радиусов вихревых доменов в заданном наборе точек от следа
 
void CalcConvVelo ()
 Вычисление конвективных скоростей вихрей и виртуальных вихрей в вихревом следе, а также в точках wakeVP.
 
virtual void CalcConvVPVeloToSetOfPointsFromWake (const WakeDataBase &pointsDb, std::vector< Point2D > &velo, std::vector< double > &domainRadius, bool calcVelo, bool calcRadius)
 
virtual void CalcVeloToWakeVP ()
 Вычисление скоростей в точках wakeVP.
 
void CalcDiffVeloI1I2ToSetOfPointsFromWake (const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const WakeDataBase &vorticesDb, std::vector< double > &I1, std::vector< Point2D > &I2)
 Вычисление числителей и знаменателей диффузионных скоростей в заданном наборе точек
 
void CalcDiffVeloI1I2ToSetOfPointsFromSheets (const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const Boundary &bnd, std::vector< double > &I1, std::vector< Point2D > &I2)
 
void CalcDiffVeloI1I2ToWakeFromSheets (const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const Boundary &bnd, std::vector< double > &I1, std::vector< Point2D > &I2)
 
void CalcDiffVeloI1I2ToWakeFromWake (const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const WakeDataBase &vorticesDb, std::vector< double > &I1, std::vector< Point2D > &I2)
 
void CalcDiffVeloI1I2 ()
 Вычисление диффузионных скоростей вихрей и виртуальных вихрей в вихревом следе
 
void CalcDiffVeloI0I3 ()
 
void LimitDiffVelo (std::vector< Point2D > &diffVel)
 Контроль больших значений диффузионных скоростей
 
void CalcDiffVelo ()
 Вычисление диффузионных скоростей
 
void ResizeAndZero ()
 Очистка старых массивов под хранение скоростей, выделение новой памяти и обнуление
 
void SaveVisStress ()
 Сохранение вязких напряжений
 
void GetWakeInfluenceToRhs (const Airfoil &afl, std::vector< double > &wakeRhs) const
 Генерация вектора влияния вихревого следа на профиль
 
void CPUGetFASTWakeInfluenceToRhs (std::vector< double > &wakeRhs, std::vector< double > &wakeRhsLin) const
 
void FillRhs (Eigen::VectorXd &rhsReord) const
 

Public Attributes

VortexesParams wakeVortexesParams
 Струтура, определяющая параметры вихрей в следе
 
std::vector< VortexesParamsvirtualVortexesParams
 Вектор струтур, определяющий параметры виртуальных вихрей для профилей
 
OptimizedVelocity optimizedVelocity
 

Protected Attributes

const World2DW
 Константная ссылка на решаемую задачу
 

Detailed Description

Класс, определяющий способ вычисления скоростей

Способ вычисления скоростей

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

Definition at line 64 of file Velocity2DBiotSavart.h.

Constructor & Destructor Documentation

◆ VelocityBiotSavart()

VelocityBiotSavart::VelocityBiotSavart ( const World2D W_)

Конструктор

Parameters
[in]W_константная ссылка на решаемую задачу

Definition at line 54 of file Velocity2DBiotSavart.cpp.

54 :
55 Velocity(W_)
56{
57};
Абстрактный класс, определяющий способ вычисления скоростей
Definition Velocity2D.h:105

◆ ~VelocityBiotSavart()

VelocityBiotSavart::~VelocityBiotSavart ( )
virtual

Деструктор

Definition at line 60 of file Velocity2DBiotSavart.cpp.

61{
62};

Member Function Documentation

◆ CalcConvVelo()

void Velocity::CalcConvVelo ( )
inherited

Вычисление конвективных скоростей вихрей и виртуальных вихрей в вихревом следе, а также в точках wakeVP.

Warning
скорости приплюсовываются к уже имеющимся

FMM ///

Definition at line 952 of file Velocity2D.cpp.

953{
954 W.getTimers().start("ConvVel");
955
956 //Влияние следа на след
957#if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_CONV_TOWAKE))
958 //Вызов виртуальной функции
959
962
963 VMlib::vmTimer timerAgpu, timerBgpu;
964
965 std::unique_ptr<BHcu::CudaTreeInfo>& cntrTree = W.getNonConstCuda().cntrTreeWake;
966 auto& treeWake = *W.getNonConstCuda().inflTreeWake;
968 {
969 cntrTree->MemoryAllocate((int)W.getCuda().n_CUDA_wake);
970 cntrTree->Update((int)W.getWake().vtx.size(), W.getWake().devVtxPtr);
971 cntrTree->Build();
972
973 //Перестроение дерева для вихрей //todo //временно для корректного расчета epsast
974 treeWake.MemoryAllocate((int)W.getCuda().n_CUDA_wake);
975 treeWake.Update((int)W.getWake().vtx.size(), W.getWake().devVtxPtr);
976 timerAgpu.start();
977 treeWake.Build();
978 timerAgpu.stop();
979
980 timerBgpu.start();
981 treeWake.UpwardTraversal(W.getPassport().numericalSchemes.nbodyMultipoleOrder);
982 timerBgpu.stop();
983 }
984
985 double timerCgpuduration = GPUCalcConvVeloToSetOfPointsFromWake(W.getNonConstCuda().cntrTreeWake, W.getWake(), wakeVortexesParams.convVelo, wakeVortexesParams.epsastWake, true, true);
986
987
989
991 /*
992 std::vector<fmm::particle2d> sources(W.getWake().vtx.size());
993 #pragma omp parallel for
994 for (int i = 0; i < (int)sources.size(); ++i)
995 {
996 const auto& w = W.getWake().vtx[i];
997
998 sources[i].center = fmm::point2d(w.r()[0], w.r()[1]);
999 sources[i].q = w.g();
1000 sources[i].morton_code = 0;
1001 }
1002
1003 auto targets = sources;
1004 for (int i = 0; i < (int)sources.size(); ++i)
1005 targets[i].q = 0;
1006
1007 double t = omp_get_wtime();
1008 //fmm::ComputeExact<fmm::InteractionType::Potential2d>(sources, targets); // or fmm::gpu::ComputeExact... for gpu version
1009 fmm::ComputeExact<fmm::InteractionType::Force2d>(sources, targets); // or fmm::gpu::ComputeExact... for gpu version
1010 std::cout << "Compute exact time = " << omp_get_wtime() - t << std::endl;
1011
1012 t = omp_get_wtime();
1013
1014 fmm::FastMultipole fmm(sources, targets, 1.e-8, fmm::FMM_AUTO, fmm::FMM_AUTO); // or fmm::gpu::FastMultipole... for gpu version
1015 fmm::ReadError<fmm::InteractionType::Force2d>(fmm.forces);
1016 //fmm::ReadError<fmm::InteractionType::Potential2d>(fmm.potentials);
1017 std::cout << "Total time = " << omp_get_wtime() - t << std::endl;
1018 */
1019
1020
1021
1023 /*
1024 std::ofstream treeTimeFile;
1025 if (W.getCurrentStep() == 0)
1026 {
1027 treeTimeFile.open(W.getPassport().dir + "/dbg/treeTime.csv");
1028 treeTimeFile << "step,time,N,lev,averPoints,tBUI,tUPW,tDNW,tBUIgpu,tUPWgpu,tDNWgpu\n";
1029 }
1030 else
1031 treeTimeFile.open(W.getPassport().dir + "/dbg/treeTime.csv", std::ios::app);
1032
1033
1034 int estLevel = std::max(4, (int)(log2(W.getWake().vtx.size())));
1035
1036 for (int controlLevel = std::max(estLevel - 2, 1); controlLevel <= estLevel + 2; ++controlLevel)
1037 {
1038 VMlib::vmTimer timerA, timerB;
1039 if (W.getWake().vtx.size() > 0)
1040 {
1041 if (W.getPassport().numericalSchemes.velocityComputation.second == 1)
1042 {
1043 W.getInflTreeWake().Update(W.getWake().vtx, controlLevel);
1044 timerA.start();
1045 W.getInflTreeWake().Build();
1046 timerA.stop();
1047 timerB.start();
1048 W.getInflTreeWake().UpwardTraversal(W.getPassport().numericalSchemes.nbodyMultipoleOrder);
1049 timerB.stop();
1050
1051 W.getCntrTreeWake().Update(W.getWake().vtx, controlLevel);
1052 W.getCntrTreeWake().Build();
1053 W.getCntrTreeWake().UpwardTraversal(W.getPassport().numericalSchemes.nbodyMultipoleOrder);
1054 }
1055
1056 std::vector<Point2D> tempVelo(wakeVortexesParams.convVelo.size());
1057 std::vector<double> tempRadius(wakeVortexesParams.epsastWake.size());
1058
1059 //Вызов виртуальной функции
1060 double timerCduration = CalcConvVeloToSetOfPointsFromWake(W.getWake(), tempVelo, tempRadius, true, false);
1061
1062 int nObjInContr = 0;
1063 for (int c = 0; c < W.getCntrTreeWake().indexControlCells.size(); ++c)
1064 {
1065 const auto& idx = W.getCntrTreeWake().indexControlCells[c];
1066 if (idx > W.getCntrTreeWake().object.size())
1067 nObjInContr += 1;
1068 else
1069 {
1070 nObjInContr += W.getCntrTreeWake().range[idx].second - W.getCntrTreeWake().range[idx].first + 1;
1071 }
1072 }
1073
1074 treeTimeFile << W.getCurrentStep() << ',' << W.getCurrentTime() << ',' << W.getInflTreeWake().object.size() << ',' \
1075 << controlLevel << ',' << (double)nObjInContr / W.getCntrTreeWake().indexControlCells.size() << ',' \
1076 << timerA.duration() << ',' << timerB.duration() << ',' << timerCduration << ',' \
1077 << timerAgpu.duration() << ',' << timerBgpu.duration() << ',' << timerCgpuduration << '\n';
1078 }
1079 }
1080
1081 treeTimeFile.close();
1082 */
1083#else
1084 float timeUpd1=0, timeBld1=0, timeUpw1=0, timeUpd2=0, timeBld2=0, timeUpw2=0, timeDnw=0;
1087
1088 VMlib::vmTimer fullTimer;
1089 fullTimer.reset();
1090 fullTimer.start();
1091
1092 if (W.getWake().vtx.size() > 0)
1093 {
1095 {
1096 int estOptLevel = std::max(4, (int)(log2(W.getWake().vtx.size())) - 2);
1097
1098 timeUpd1 = W.getInflTreeWake().Update(W.getWake().vtx, estOptLevel);
1099 timeBld1 = W.getInflTreeWake().Build();
1101
1102 //timeUpd2 = W.getCntrTreeWake().Update(W.getWake().vtx, estOptLevel);
1103 //timeBld2 = W.getCntrTreeWake().Build();
1104 //timeUpw2 = W.getCntrTreeWake().UpwardTraversal(W.getPassport().numericalSchemes.nbodyMultipoleOrder);
1105
1106 //std::cout << "timeUpd = " << timeUpd1 << " " << timeUpd2 << '\n';
1107 //std::cout << "timeBld = " << timeBld1 << " " << timeBld2 << '\n';
1108 //std::cout << "timeUpw = " << timeUpw1 << " " << timeUpw2 << '\n';
1109
1110 }
1111
1112 //Вызов виртуальной функции
1113
1115
1116 //std::string vname = VMlib::fileNameStep("VeloBH", 0, wakeVortexesParams.convVelo.size(), "txt");
1117 //std::ofstream velofile;
1118 //velofile.open(W.getPassport().dir + vname);
1119
1120 //for (int i = 0; i < wakeVortexesParams.convVelo.size(); ++i)
1121 // velofile << wakeVortexesParams.convVelo[i][0] << " " << wakeVortexesParams.convVelo[i][1] << "\n";
1122 //velofile.close();
1123 //exit(-124);
1124
1125 //std::cout << "timeDnw = " << timeDnw << '\n';
1126 }
1127 fullTimer.stop();
1128
1130 //std::cout << "theta = " << W.getPassport().numericalSchemes.nbodyTheta << "\n";
1131
1133 /*
1134 VMlib::vmTimer timerExact;
1135
1136 if (W.getWake().vtx.size() > 0)
1137 {
1138 std::vector<fmm::particle2d> sources(W.getWake().vtx.size());
1139 #pragma omp parallel for
1140 for (int i = 0; i < (int)sources.size(); ++i)
1141 {
1142 const auto& w = W.getWake().vtx[i];
1143
1144 sources[i].center = fmm::point2d(w.r()[0], w.r()[1]);
1145 sources[i].q = w.g();
1146 sources[i].morton_code = 0;
1147 }
1148
1149 auto targets = sources;
1150 for (int i = 0; i < (int)sources.size(); ++i)
1151 targets[i].q = 0;
1152
1153 //double t = omp_get_wtime();
1154 //fmm::ComputeExact<fmm::InteractionType::Potential2d>(sources, targets); // or fmm::gpu::ComputeExact... for gpu version
1155 timerExact.start();
1156 fmm::ComputeExact<fmm::InteractionType::Force2d>(sources, targets); // or fmm::gpu::ComputeExact... for gpu version
1157 timerExact.stop();
1158 //std::cout << "Compute exact time = " << omp_get_wtime() - t << std::endl;
1159
1160 //t = omp_get_wtime();
1161
1162 fmm::FastMultipole fmm(sources, targets, 1.e-8, fmm::FMM_AUTO, fmm::FMM_AUTO); // or fmm::gpu::FastMultipole... for gpu version
1163 fmm::ReadError<fmm::InteractionType::Force2d>(fmm.forces);
1164 //fmm::ReadError<fmm::InteractionType::Potential2d>(fmm.potentials);
1165 //std::cout << "Total time = " << omp_get_wtime() - t << std::endl;
1166
1167 std::cout << "Hybrid time ConvVelo Wake = " << fullTimer.duration() <<
1168 //W.timerConvVelo.duration() <<
1169 " ( " << timeUpd1 + timeUpd2 + timeBld1 + timeBld2 + timeUpw1 + timeUpw2 + timeDnw << " )" << '\n';
1170
1171 fmm::ReadErrorHyb(*((std::vector<std::array<double, 2>>*) &wakeVortexesParams.convVelo));
1172 std::cout << "Exact time = " << timerExact.duration() << '\n';
1173 }
1174 //*/
1175
1176
1177
1178#endif
1179
1180 std::vector<Point2D> nullVector(0);
1181 //вычисление конвективных скоростей по закону Био-Савара от виртуальных вихрей (точнее, от слоев)
1182 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
1183 {
1184 //Влияние на след от панелей
1185#if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_CONVVIRT))
1186
1188 {
1189 case 0:
1190 W.getBoundary(bou).GPUCalcConvVelocityToSetOfPointsFromSheets(W.getWake(), wakeVortexesParams.convVelo);
1191 break;
1192 case 1:
1193 if (bou == 0)
1194 GPUCalcConvVelocityToSetOfPointsFromSheets(W.getNonConstCuda().cntrTreeWake, W.getWake(), wakeVortexesParams.convVelo);
1195 break;
1196 }
1197 //
1198
1199#else
1201#endif
1202 }
1203
1204 //Скорости только что рожденных вихрей
1205 {
1206 size_t nVirtVortices = 0;
1207 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
1208 nVirtVortices += W.getBoundary(bou).virtualWake.vtx.size();
1209
1210 size_t counter = wakeVortexesParams.convVelo.size() - nVirtVortices;
1211
1212 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
1213 for (size_t v = 0; v < W.getBoundary(bou).virtualWake.vtx.size(); ++v)
1214 {
1217 - W.getV0();
1218 ++counter;
1219 }
1220 }
1221
1222 //Заполнение структур данных виртуальных вихрей
1223 {
1224 size_t nVirtVortices = 0;
1225 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
1226 nVirtVortices += W.getBoundary(bou).virtualWake.vtx.size();
1227
1228 size_t counter = wakeVortexesParams.convVelo.size() - nVirtVortices;
1229
1230 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
1231 for (size_t v = 0; v < W.getBoundary(bou).virtualWake.vtx.size(); ++v)
1232 {
1233 virtualVortexesParams[bou].convVelo[v] = wakeVortexesParams.convVelo[counter];
1234 virtualVortexesParams[bou].epsastWake[v] = wakeVortexesParams.epsastWake[counter];
1235 ++counter;
1236 }
1237 }
1238
1239 W.getTimers().stop("ConvVel");
1240 W.getTimers().start("VelPres");
1241
1242 //вычисление скоростей в заданных точках только на соответствующем шаге по времени
1244#ifdef OPTIMIZER
1245 if ((W.getCurrentStep() >= OPTIMIZER_START_STEP && W.getCurrentStep() <= OPTIMIZER_STOP_STEP) || W.getCurrentStep() == 0)
1247#else
1248
1249 //t1 = -omp_get_wtime();
1251 //t1 += omp_get_wtime();
1252 //std::cout << "time ConvVelo VP = " << t1 << std::endl;
1253#endif
1254
1256 /*if ((W.getPassport().timeDiscretizationProperties.saveVPstep > 0) && (!(W.getCurrentStep() % W.getPassport().timeDiscretizationProperties.saveVPstep)))
1257 {
1258 int currentStep = W.getCurrentStep();
1259 if (currentStep >= 1100 && currentStep <= 1300)
1260 {
1261 CalcVeloToWakeVP();
1262 optimizedVelocity.AddVelocities(W.getNonConstMeasureVP().getNonConstVelocity());
1263 }
1264
1265 if (currentStep == 1200)
1266 {
1267 optimizedVelocity.PerformAveragingVelo(W.getPassport().dir);
1268 }
1269 }*/
1271
1272 W.getTimers().stop("VelPres");
1273}//CalcConvVelo()
const Point2D & getV(size_t q) const
Возврат константной ссылки на скорость вершины профиля
Definition Airfoil2D.h:137
const Airfoil & afl
Definition Boundary2D.h:77
VirtualWake virtualWake
Виртуальный вихревой след конкретного профиля
Definition Boundary2D.h:86
virtual void CalcConvVelocityToSetOfPointsFromSheets(const WakeDataBase &pointsDb, std::vector< Point2D > &velo) const =0
Вычисление конвективных скоростей в наборе точек, вызываемых наличием слоев вихрей и источников на пр...
float Update(const std::vector< Vortex2D > &vtx, int cntrLev=0)
float UpwardTraversal(int order)
NumericalSchemes numericalSchemes
Структура с используемыми численными схемами
Definition Passport2D.h:307
virtual float CalcConvVeloToSetOfPointsFromWake(const WakeDataBase &pointsDb, std::vector< Point2D > &velo, std::vector< double > &domainRadius, bool calcVelo, bool calcRadius)=0
Вычисление конвективных скоростей и радиусов вихревых доменов в заданном наборе точек от следа
std::vector< VortexesParams > virtualVortexesParams
Вектор струтур, определяющий параметры виртуальных вихрей для профилей
Definition Velocity2D.h:115
VortexesParams wakeVortexesParams
Струтура, определяющая параметры вихрей в следе
Definition Velocity2D.h:112
virtual void CalcVeloToWakeVP()
Вычисление скоростей в точках wakeVP.
const World2D & W
Константная ссылка на решаемую задачу
Definition Velocity2D.h:108
std::vector< Point2D > vecHalfGamma
Скорость вихрей виртуального следа конкретного профиля (равна Gamma/2) используется для расчета давле...
std::vector< std::pair< size_t, size_t > > aflPan
Пара чисел: номер профиля и номер панели, на которой рожден виртуальный вихрь
std::vector< Vortex2D > vtx
Список вихревых элементов
VMlib::vmTimer timerConvVelo
Definition World2D.h:371
const Wake & getWake() const
Возврат константной ссылки на вихревой след
Definition World2D.h:232
Gpu & getNonConstCuda() const
Возврат неконстантной ссылки на объект, связанный с видеокартой (GPU)
Definition World2D.h:278
VMlib::TimersGen & getTimers() const
Возврат ссылки на временную статистику выполнения шага расчета по времени
Definition World2D.h:288
Point2D getV0() const
Возврат текущей скорости набегающего потока
Definition World2D.h:148
const Gpu & getCuda() const
Возврат константной ссылки на объект, связанный с видеокартой (GPU)
Definition World2D.h:273
const Passport & getPassport() const
Возврат константной ссылки на паспорт
Definition World2D.h:263
const Boundary & getBoundary(size_t i) const
Возврат константной ссылки на объект граничного условия
Definition World2D.h:186
size_t getNumberOfBoundary() const
Возврат количества граничных условий в задаче
Definition World2D.h:197
CpuTreeInfo & getInflTreeWake() const
Definition World2D.h:239
TimeDiscretizationProperties timeDiscretizationProperties
Структура с параметрами процесса интегрирования по времени
void stop(const std::string &timerLabel)
Останов счетчика
Definition TimesGen.cpp:68
void start(const std::string &timerLabel)
Запуск счетчика
Definition TimesGen.cpp:55
size_t getCurrentStep() const
Возврат константной ссылки на параметры распараллеливания по MPI.
Definition WorldGen.h:99
Класс засекания времени
Definition TimesGen.h:59
const vmTimer & stop() const
Останов работающего счетчика времени
Definition TimesGen.h:125
const vmTimer & start() const
Запуск (первый или повторный) счетчика времени
Definition TimesGen.h:109
const vmTimer & reset() const
Сброс счетчика времени
Definition TimesGen.h:101
std::pair< std::string, int > velocityComputation
Definition Passport2D.h:180
std::vector< Point2D > convVelo
Вектор конвективных скоростей вихрей
Definition Velocity2D.h:72
std::vector< double > epsastWake
Вектор характерных радиусов вихревых доменов (eps*)
Definition Velocity2D.h:90
int saveVPstep
Шаг вычисления и сохранения скорости и давления
Definition PassportGen.h:86
Here is the call graph for this function:

◆ CalcConvVeloToSetOfPointsFromWake()

float VelocityBiotSavart::CalcConvVeloToSetOfPointsFromWake ( const WakeDataBase pointsDb,
std::vector< Point2D > &  velo,
std::vector< double > &  domainRadius,
bool  calcVelo,
bool  calcRadius 
)
overridevirtual

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

Parameters
[in]pointsDbконстантная ссылка на базу данных пелены из вихрей, в которых надо сосчитать конвективные скорости
[out]veloссылка на вектор скоростей в требуемых точках
[out]domainRadiusссылка на вектор радиусов вихревых доменов
[in]calcVeloпризнак вычисления скоростей в точках
[in]calcRadiusпризнак вычисления радиусов доменов

TESTONLYVELO

Implements VM2D::Velocity.

Definition at line 92 of file Velocity2DBiotSavart.cpp.

93{
94 std::vector<Point2D> selfVelo(pointsDb.vtx.size());
95 domainRadius.resize(pointsDb.vtx.size());
96
97 double cft = IDPI;
98
99#pragma warning (push)
100#pragma warning (disable: 4101)
101 //Локальные переменные для цикла
102 Point2D velI;
103 Point2D tempVel;
104 double dst2eps, dst2;
105#pragma warning (pop)
106
107 VMlib::vmTimer timer;
108 timer.start();
109
110 if (calcVelo)
111 {
112#pragma omp parallel for default(none) shared(selfVelo, cft, calcVelo, calcRadius, pointsDb, domainRadius) private(tempVel, velI, dst2, dst2eps) schedule(dynamic, DYN_SCHEDULE)
113 for (int i = 0; i < pointsDb.vtx.size(); ++i)
114 {
115 double ee2[3] = { 10000.0, 10000.0, 10000.0 };
116
117 velI.toZero();
118
119 const Point2D& posI = pointsDb.vtx[i].r();
120
121 for (size_t j = 0; j < W.getWake().vtx.size(); ++j)
122 {
123 const Point2D& posJ = W.getWake().vtx[j].r();
124
125 dst2 = (posI - posJ).length2();
126
127 //Модифицируем массив квадратов расстояний до ближайших вихрей из wake
128#ifndef TESTONLYVELO
129 if (calcRadius)
130 VMlib::ModifyE2(ee2, dst2);
131#endif
132
133 const double& gamJ = W.getWake().vtx[j].g();
134 const double sigmaJ2 = sqr(W.getWake().vtx[j].sigma());
135
136 tempVel.toZero();
137 dst2eps = VMlib::boundDenom(dst2, sigmaJ2); //Сглаживать надо!!!
138
139 tempVel = { -posI[1] + posJ[1], posI[0] - posJ[0] };
140 tempVel *= (gamJ / dst2eps);
141 velI += tempVel;
142 }
143
144 for (size_t j = 0; j < W.getSource().vtx.size(); ++j)
145 {
146 const Point2D& posJ = W.getSource().vtx[j].r();
147 const double& gamJ = W.getPassport().physicalProperties.accelCft(W.getCurrentTime()) * W.getSource().vtx[j].g();
148 const double sigmaJ2 = sqr(W.getSource().vtx[j].sigma());
149
150 tempVel.toZero();
151
152 dst2 = dist2(posI, posJ);
153 dst2eps = VMlib::boundDenom(dst2, sigmaJ2); //Сглаживать надо!!!
154
155 tempVel = { posI[0] - posJ[0], posI[1] - posJ[1] };
156 tempVel *= (gamJ / dst2eps);
157 velI += tempVel;
158 }
159#ifndef TESTONLYVELO
160 if (calcRadius)
161 {
162 for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
163 {
164 const auto& bou = W.getBoundary(s);
165 //Модифицируем массив квадратов расстояний до ближайших вихрей из virtualWake
166 for (size_t j = 0; j < bou.virtualWake.vtx.size(); ++j)
167 ModifyE2(ee2, dist2(posI, bou.virtualWake.vtx[j].r()));
168 }
169 }
170#endif
171
172 velI *= cft;
173 selfVelo[i] = velI;
174
175#ifndef TESTONLYVELO
176 if (calcRadius)
177 domainRadius[i] = 1.0 * sqrt((ee2[0] + ee2[1] + ee2[2]) / 3.0);
178#endif
179 }
180 }
181 else if (calcRadius)
182 {
183#pragma omp parallel for default(none) shared(selfVelo, cft, calcVelo, calcRadius, pointsDb, domainRadius) private(tempVel, velI, dst2) schedule(dynamic, DYN_SCHEDULE)
184 for (int i = 0; i < pointsDb.vtx.size(); ++i)
185 {
186 double ee2[3] = { 10000.0, 10000.0, 10000.0 };
187
188 velI.toZero();
189
190 const Point2D& posI = pointsDb.vtx[i].r();
191
192 for (size_t j = 0; j < W.getWake().vtx.size(); ++j)
193 {
194 const Point2D& posJ = W.getWake().vtx[j].r();
195
196 dst2 = dist2(posI, posJ);
197
198 //Модифицируем массив квадратов расстояний до ближайших вихрей из wake
199 VMlib::ModifyE2(ee2, dst2);
200 }
201
202 for (size_t s = 0; s < W.getNumberOfBoundary(); ++s)
203 {
204 for (size_t j = 0; j < W.getBoundary(s).virtualWake.vtx.size(); ++j)
205 {
206 const Point2D& posJ = W.getBoundary(s).virtualWake.vtx[j].r();
207 dst2 = dist2(posI, posJ);
208
209 //Модифицируем массив квадратов расстояний до ближайших вихрей из virtualWake
210 ModifyE2(ee2, dst2);
211 }
212 }
213
214 domainRadius[i] = 1.0 * sqrt((ee2[0] + ee2[1] + ee2[2]) / 3.0);
215 }
216 } //else
217
218
219 timer.stop();
220
221 if (calcVelo)
222 for (size_t i = 0; i < velo.size(); ++i)
223 velo[i] += selfVelo[i];
224
225#ifdef USE_CUDA
226 if (calcVelo)
227 W.getCuda().CopyMemToDev<double, 2>(velo.size(), (double*)velo.data(), pointsDb.devVelPtr);
228 if (calcRadius)
229 W.getCuda().CopyMemToDev<double, 1>(domainRadius.size(), domainRadius.data(), pointsDb.devRadPtr);
230#endif
231 return (float)timer.duration();
232}//CalcConvVeloToSetOfPointsFromWake(...)
const double IDPI
Число .
Definition defs.h:79
void ModifyE2(double *ee2, double dst2)
PhysicalProperties physicalProperties
Структура с физическими свойствами задачи
Definition Passport2D.h:301
const WakeDataBase & getSource() const
Возврат константной ссылки на источники в области течения
Definition World2D.h:248
double getCurrentTime() const
Definition WorldGen.h:100
numvector< T, n > & toZero(P val=0)
Установка всех компонент вектора в константу (по умолчанию — нуль)
Definition numvector.h:528
double duration() const
Definition TimesGen.h:143
void ModifyE2(double *ee2, double dst2)
Модифицирует массив квадратов расстояний до ближайших вихрей из wake.
Definition defs.cpp:236
T sqr(T x)
Возведение числа в квадрат
Definition defs.h:455
double boundDenom(double r2, double eps2)
Способ сглаживания скорости вихря (вихрь Рэнкина или вихрь Ламба)
Definition defs.h:569
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 accelCft(double currentTime) const
Функция-множитель, позволяющая моделировать разгон
Here is the call graph for this function:

◆ CalcConvVPVeloToSetOfPointsFromWake()

virtual void VM2D::Velocity::CalcConvVPVeloToSetOfPointsFromWake ( const WakeDataBase pointsDb,
std::vector< Point2D > &  velo,
std::vector< double > &  domainRadius,
bool  calcVelo,
bool  calcRadius 
)
inlinevirtualinherited

Reimplemented in VM2D::VelocityBarnesHut.

Definition at line 141 of file Velocity2D.h.

141{};

◆ CalcDiffVelo()

void Velocity::CalcDiffVelo ( )
inherited

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

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

Definition at line 155 of file Velocity2D.cpp.

156{
157 W.getTimers().start("DiffVel");
158
159 double t12start, t12finish;
160 double t03start, t03finish;
161 double tOtherstart, tOtherfinish;
162
164 {
165 t12start = omp_get_wtime();
167 t12finish = omp_get_wtime();
168
169 t03start = omp_get_wtime();
171 t03finish = omp_get_wtime();
172
173 tOtherstart = omp_get_wtime();
174 for (Point2D& diffV : wakeVortexesParams.diffVelo)
175 diffV *= W.getPassport().physicalProperties.nu;
176
177 //контроль застрелов диффузионной скорости
179
180 for (size_t afl = 0; afl < W.getNumberOfAirfoil(); ++afl)
181 for (size_t i = 0; i < W.getAirfoil(afl).viscousStress.size(); ++i)
183
184 //SaveVisStress();
185
186
187 //Заполнение структуры данных виртуальных вихрей
188 size_t nVirtVortices = 0;
189 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
190 nVirtVortices += W.getBoundary(bou).virtualWake.vtx.size();
191
192 size_t counter = wakeVortexesParams.convVelo.size() - nVirtVortices;
193
194 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
195 for (size_t v = 0; v < W.getBoundary(bou).virtualWake.vtx.size(); ++v)
196 {
197 virtualVortexesParams[bou].diffVelo[v] = wakeVortexesParams.diffVelo[counter];
198 virtualVortexesParams[bou].I0[v] = wakeVortexesParams.I0[counter];
199 virtualVortexesParams[bou].I1[v] = wakeVortexesParams.I1[counter];
200 virtualVortexesParams[bou].I2[v] = wakeVortexesParams.I2[counter];
201 virtualVortexesParams[bou].I3[v] = wakeVortexesParams.I3[counter];
202 ++counter;
203 }
204
205 tOtherfinish = omp_get_wtime();
206 }
207 W.getTimers().stop("DiffVel");
208
209}// CalcDiffVelo()
std::vector< double > viscousStress
Нейросеть для коэффициентов I0 и I3 диффузионной скорости
Definition Airfoil2D.h:268
void LimitDiffVelo(std::vector< Point2D > &diffVel)
Контроль больших значений диффузионных скоростей
void CalcDiffVeloI0I3()
void CalcDiffVeloI1I2()
Вычисление диффузионных скоростей вихрей и виртуальных вихрей в вихревом следе
size_t getNumberOfAirfoil() const
Возврат количества профилей в задаче
Definition World2D.h:180
const Airfoil & getAirfoil(size_t i) const
Возврат константной ссылки на объект профиля
Definition World2D.h:163
Airfoil & getNonConstAirfoil(size_t i) const
Возврат неконстантной ссылки на объект профиля
Definition World2D.h:175
double nu
Коэффициент кинематической вязкости среды
Definition Passport2D.h:99
std::vector< Point2D > I2
Вектор числителей (I2) диффузионных скоростей вихрей (обусловленных завихренностью)
Definition Velocity2D.h:84
std::vector< double > I0
Вектор знаменателей (I0) диффузионных скоростей вихрей (обусловленных профилем)
Definition Velocity2D.h:78
std::vector< Point2D > diffVelo
Вектор диффузионных скоростей вихрей
Definition Velocity2D.h:75
std::vector< Point2D > I3
Вектор числителей (I3) диффузионных скоростей вихрей (обусловленных профилем)
Definition Velocity2D.h:87
std::vector< double > I1
Вектор знаменателей (I1) диффузионных скоростей вихрей (обусловленных завихренностью)
Definition Velocity2D.h:81
Here is the call graph for this function:

◆ CalcDiffVeloI0I3()

void Velocity::CalcDiffVeloI0I3 ( )
inherited

Definition at line 106 of file Velocity2D.cpp.

107{
108 for (size_t afl = 0; afl < W.getNumberOfAirfoil(); ++afl)
109 {
110#if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_I0I3))
111 W.getNonConstAirfoil(afl).GPUGetDiffVelocityI0I3ToSetOfPointsAndViscousStresses(wakeVortexesParams.epsastWake, wakeVortexesParams.I0, wakeVortexesParams.I3);
112#else
114#endif
115 }
116
117
118 //влияние поверхности
119 Point2D I3;
120 double I0;
121
122 double domrad = 0.0;
123
124#pragma omp parallel for private(I0, I3, domrad)
125 for (int vt = 0; vt < (int)wakeVortexesParams.diffVelo.size(); ++vt)
126 {
128
129 wakeVortexesParams.I0[vt] *= domrad;
130 wakeVortexesParams.I0[vt] += DPI * sqr(domrad);
131
132
135
136
137 if (fabs(I0) > 1.e-8)
138 wakeVortexesParams.diffVelo[vt] += I3 * (1.0 / I0);
139 }
140}//CalcDiffVeloI0I3()
const double DPI
Число .
Definition defs.h:82
virtual void GetDiffVelocityI0I3ToSetOfPointsAndViscousStresses(const WakeDataBase &pointsDb, std::vector< double > &domainRadius, std::vector< double > &I0, std::vector< Point2D > &I3)
Вычисление числителей и знаменателей диффузионных скоростей в заданном наборе точек,...
WakeDiscretizationProperties wakeDiscretizationProperties
Структура с параметрами дискретизации вихревого следа
Definition Passport2D.h:304
void vt(const Vector3d &x, const Matrix3d *T, Matrix3d &M)
double getMinEpsAst() const
Функция минимально возможного значения для epsAst.
Definition Passport2D.h:153
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CalcDiffVeloI1I2()

void Velocity::CalcDiffVeloI1I2 ( )
inherited

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

Вызывает 4 раза функцию CalcDiffVeloToSetOfPoints

Warning
скорости приплюсовываются к уже имеющимся

Definition at line 62 of file Velocity2D.cpp.

63{
64 // !!! пелена на пелену
65#if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_I1I2))
67 GPUCalcDiffVeloI1I2ToSetOfPointsFromWake(W.getWake(), wakeVortexesParams.epsastWake, W.getWake(), wakeVortexesParams.I1, wakeVortexesParams.I2);
68 else
70#else
72#endif
73
74
75 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
76 {
77 //не нужно, т.к. сделано выше перед началом вычисления скоростей
78 //W.getNonConstBoundary(bou).virtualWake.WakeSynchronize();
79
80
81 //виртуальные на границе на след
82#if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_I1I2))
83 GPUCalcDiffVeloI1I2ToSetOfPointsFromSheets(W.getWake(), wakeVortexesParams.epsastWake, W.getBoundary(bou), wakeVortexesParams.I1, wakeVortexesParams.I2);
84#else
86#endif
87 } //for bou
88
89 Point2D I2;
90 double I1;
91
92#pragma omp parallel for private(I1, I2)
93 for (int vt = 0; vt < (int)wakeVortexesParams.diffVelo.size(); ++vt)
94 {
97
98 if (fabs(I1) < 1.e-8)
99 wakeVortexesParams.diffVelo[vt] = { 0.0, 0.0 };
100 else
102 }
103}//CalcDiffVeloI1I2()
void CalcDiffVeloI1I2ToWakeFromSheets(const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const Boundary &bnd, std::vector< double > &I1, std::vector< Point2D > &I2)
void CalcDiffVeloI1I2ToWakeFromWake(const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const WakeDataBase &vorticesDb, std::vector< double > &I1, std::vector< Point2D > &I2)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CalcDiffVeloI1I2ToSetOfPointsFromSheets()

void Velocity::CalcDiffVeloI1I2ToSetOfPointsFromSheets ( const WakeDataBase pointsDb,
const std::vector< double > &  domainRadius,
const Boundary bnd,
std::vector< double > &  I1,
std::vector< Point2D > &  I2 
)
inherited
Todo:
Понять природу магической константы 8.0 и синхронизировать с GPU
Todo:
Сделать переменной и синхронизировать с GPU
Todo:
Учитываем пока только нулевой момент решения

Definition at line 271 of file Velocity2D.cpp.

272{
273 double tCPUSTART, tCPUEND;
274
275 tCPUSTART = omp_get_wtime();
276
277 std::vector<double> selfI1(pointsDb.vtx.size(), 0.0);
278 std::vector<Point2D> selfI2(pointsDb.vtx.size(), { 0.0, 0.0 });
279
280#pragma warning (push)
281#pragma warning (disable: 4101)
282 //Локальные переменные для цикла
283 Point2D Rij;
284 double rij, expr;
285 double diffRadius;
286 double left;
287 double right;
288 double posJx;
289 double domRad;
290#pragma warning (pop)
291
292
293#pragma omp parallel for default(none) shared(selfI1, selfI2, domainRadius, bnd, pointsDb, std::cout) private(Rij, rij, expr, domRad, diffRadius, left, right, posJx)
294 for (int i = 0; i < pointsDb.vtx.size(); ++i)
295 {
296 const Vortex2D& vtxI = pointsDb.vtx[i];
297
298 domRad = std::max(domainRadius[i], W.getPassport().wakeDiscretizationProperties.getMinEpsAst());
299
301 diffRadius = 8.0 * domRad;
302
303 left = vtxI.r()[0] - diffRadius;
304 right = vtxI.r()[0] + diffRadius;
305
306 for (size_t j = 0; j < bnd.afl.getNumberOfPanels(); ++j)
307 {
309 const int nQuadPt = 3;
310
312 const double ptG = bnd.sheets.freeVortexSheet(j, 0) * bnd.afl.len[j] / nQuadPt;
313
314 for (int q = 0; q < nQuadPt; ++q)
315 {
316 const Point2D& ptJ = bnd.afl.getR(j) + bnd.afl.tau[j] * (q + 0.5) * bnd.afl.len[j] * (1.0 / nQuadPt); // vorticesDb.vtx[j];
317 posJx = ptJ[0];
318
319 if ((left < posJx) && (posJx < right))
320 {
321 Rij = vtxI.r() - ptJ;
322 rij = Rij.length();
323 if (rij < diffRadius && rij > 1.e-10)
324 {
325 expr = exp(-rij / domRad);
326 selfI2[i] += (ptG * expr / rij) * Rij;
327 selfI1[i] += ptG * expr;
328 }
329 }//if (rij>1e-6)
330 }
331 }//for j
332 } // for r
333
334 for (size_t i = 0; i < I1.size(); ++i)
335 {
336 I1[i] += selfI1[i];
337 I2[i] += selfI2[i];
338 }
339
340 tCPUEND = omp_get_wtime();
341 //W.getInfo('t') << "DIFF_CPU: " << tCPUEND - tCPUSTART << std::endl;
342}//CalcDiffVeloI1I2ToSetOfPointsFromSheets(...)
std::vector< double > len
Длины панелей профиля
Definition Airfoil2D.h:94
const Point2D & getR(size_t q) const
Возврат константной ссылки на вершину профиля
Definition Airfoil2D.h:113
std::vector< Point2D > tau
Касательные к панелям профиля
Definition Airfoil2D.h:91
size_t getNumberOfPanels() const
Возврат количества панелей на профиле
Definition Airfoil2D.h:163
Sheet sheets
Слои на профиле
Definition Boundary2D.h:96
const double & freeVortexSheet(size_t n, size_t moment) const
Definition Sheet2D.h:100
Класс, опеделяющий двумерный вихревой элемент
Definition Vortex2D.h:59
HD Point2D & r()
Функция для доступа к радиус-вектору вихря
Definition Vortex2D.h:92
P length() const
Вычисление 2-нормы (длины) вектора
Definition numvector.h:374
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CalcDiffVeloI1I2ToSetOfPointsFromWake()

void Velocity::CalcDiffVeloI1I2ToSetOfPointsFromWake ( const WakeDataBase pointsDb,
const std::vector< double > &  domainRadius,
const WakeDataBase vorticesDb,
std::vector< double > &  I1,
std::vector< Point2D > &  I2 
)
inherited

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

Parameters
[in]pointsDbконстантная ссылка на базу данных пелены из вихрей, в которых надо сосчитать диффузионные скорости
[in]domainRadiusконстантная ссылка на вектор радиусов вихревых доменов
[in]vorticesDbконстантная ссылка на на базу данных пелены из вихрей,от которых надо сосчитать влияния на points
[out]I1ссылка на вектор величин I1 (знаменателей в диффузионных скоростях) в требуемых точках
[out]I2ссылка на вектор величин I2 (числителей в диффузионных скоростях) в требуемых точках
Todo:
Понять природу магической константы 8.0 и синхронизировать с GPU

Definition at line 213 of file Velocity2D.cpp.

214{
215 std::vector<double> selfI1(pointsDb.vtx.size(), 0.0);
216 std::vector<Point2D> selfI2(pointsDb.vtx.size(), { 0.0, 0.0 });
217
218#pragma warning (push)
219#pragma warning (disable: 4101)
220 //Локальные переменные для цикла
221 Point2D Rij;
222 double rij, expr;
223 double diffRadius, domRad;
224 double left;
225 double right;
226 double posJx;
227#pragma warning (pop)
228
229#pragma omp parallel for default(none) shared(selfI1, selfI2, domainRadius, vorticesDb, pointsDb) private(Rij, rij, expr, diffRadius, domRad, left, right, posJx)
230 for (int i = 0; i < pointsDb.vtx.size(); ++i)
231 {
232 const Vortex2D& vtxI = pointsDb.vtx[i];
233
234 domRad = std::max(domainRadius[i], W.getPassport().wakeDiscretizationProperties.getMinEpsAst());
235
237 diffRadius = 8.0 * domRad;
238
239 left = vtxI.r()[0] - diffRadius;
240 right = vtxI.r()[0] + diffRadius;
241
242 for (size_t j = 0; j < vorticesDb.vtx.size(); ++j)
243 {
244 const Vortex2D& vtxJ = vorticesDb.vtx[j];
245 posJx = vtxJ.r()[0];
246
247 if ((left < posJx) && (posJx < right))
248 {
249 Rij = vtxI.r() - vtxJ.r();
250 rij = Rij.length();
251 if (rij < diffRadius && rij > 1.e-10)
252 {
253 expr = exp(-rij / domRad);
254 selfI2[i] += (vtxJ.g()* expr / rij) * Rij;
255 selfI1[i] += vtxJ.g()*expr;
256 }
257 }//if (rij>1e-6)
258 }//for j
259 } // for r
260
261
262 for (size_t i = 0; i < I1.size(); ++i)
263 {
264 I1[i] += selfI1[i];
265 I2[i] += selfI2[i];
266 }
267}//CalcDiffVeloI1I2ToSetOfPointsFromWake(...)
HD double & g()
Функция для доступа к циркуляции вихря
Definition Vortex2D.h:100
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CalcDiffVeloI1I2ToWakeFromSheets()

void Velocity::CalcDiffVeloI1I2ToWakeFromSheets ( const WakeDataBase pointsDb,
const std::vector< double > &  domainRadius,
const Boundary bnd,
std::vector< double > &  I1,
std::vector< Point2D > &  I2 
)
inherited

Definition at line 1372 of file Velocity2D.cpp.

1373{
1374 CalcDiffVeloI1I2ToSetOfPointsFromSheets(pointsDb, domainRadius, bnd, I1, I2);
1375}
void CalcDiffVeloI1I2ToSetOfPointsFromSheets(const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const Boundary &bnd, std::vector< double > &I1, std::vector< Point2D > &I2)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CalcDiffVeloI1I2ToWakeFromWake()

void Velocity::CalcDiffVeloI1I2ToWakeFromWake ( const WakeDataBase pointsDb,
const std::vector< double > &  domainRadius,
const WakeDataBase vorticesDb,
std::vector< double > &  I1,
std::vector< Point2D > &  I2 
)
inherited

Definition at line 1367 of file Velocity2D.cpp.

1368{
1369 CalcDiffVeloI1I2ToSetOfPointsFromWake(pointsDb, domainRadius, vorticesDb, I1, I2);
1370}//CalcDiffVeloI1I2ToWakeFromWake(...)
void CalcDiffVeloI1I2ToSetOfPointsFromWake(const WakeDataBase &pointsDb, const std::vector< double > &domainRadius, const WakeDataBase &vorticesDb, std::vector< double > &I1, std::vector< Point2D > &I2)
Вычисление числителей и знаменателей диффузионных скоростей в заданном наборе точек
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CalcVeloToWakeVP()

void Velocity::CalcVeloToWakeVP ( )
virtualinherited

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

Definition at line 1278 of file Velocity2D.cpp.

1279{
1280 std::vector<Point2D> velConvWake;
1281 std::vector<std::vector<Point2D>> velConvBou;
1282
1283 int addWSize = (int)W.getMeasureVP().getWakeVP().vtx.size();
1284
1285 velConvWake.resize(addWSize, { 0.0, 0.0 });
1286
1287 velConvBou.resize(W.getNumberOfBoundary());
1288 for (size_t i = 0; i < W.getNumberOfBoundary(); ++i)
1289 velConvBou[i].resize(addWSize, { 0.0, 0.0 });
1290
1291 std::vector<Point2D>& velocityRef = W.getNonConstMeasureVP().getNonConstVelocity();
1292 velocityRef.assign(addWSize, W.getV0());
1293
1294#if (defined(USE_CUDA))
1295 W.getNonConstCuda().RefreshVP();
1296#endif
1297
1298#if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_VP))
1299 std::unique_ptr<BHcu::CudaTreeInfo>& cntrTree = W.getNonConstCuda().cntrTreeVP;
1300
1302 {
1303 case 1:
1305 {
1306 cntrTree->MemoryAllocate((int)W.getCuda().n_CUDA_velVP);
1307 cntrTree->Update((int)W.getMeasureVP().getWakeVP().vtx.size(), W.getMeasureVP().getWakeVP().devVtxPtr);
1308 cntrTree->Build();
1309 GPUCalcConvVeloToSetOfPointsFromWake(cntrTree, W.getMeasureVP().getWakeVP(), velocityRef, W.getNonConstMeasureVP().getNonConstDomainRadius(), true, false);
1310 }
1311 break;
1312 case 0:
1313 GPUCalcConvVeloToSetOfPointsFromWake(cntrTree, W.getMeasureVP().getWakeVP(), velocityRef, W.getNonConstMeasureVP().getNonConstDomainRadius(), true, false);
1314 break;
1315 }
1316
1317
1318#else
1320 {
1321 case 0:
1323 break;
1324 case 1:
1326 double theta = W.getPassport().numericalSchemes.nbodyTheta;
1327
1329 W.getCntrTreeVP().Build();
1332 }
1333#endif
1334
1335
1336 for (size_t i = 0; i < W.getNumberOfBoundary(); ++i)
1337#if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_VP))
1339 {
1340 case 0:
1341 W.getNonConstBoundary(i).GPUCalcConvVelocityToSetOfPointsFromSheets(W.getMeasureVP().getWakeVP(), velConvBou[i]);
1342
1343 for (int s = 0; s < addWSize; ++s)
1344 velocityRef[s] += velConvWake[s];
1345
1346 for (size_t bou = 0; bou < velConvBou.size(); ++bou)
1347 for (int j = 0; j < addWSize; ++j)
1348 velocityRef[j] += velConvBou[bou][j];
1349 break;
1350 case 1:
1351 if (i == 0)
1352 GPUCalcConvVelocityToSetOfPointsFromSheets(cntrTree, W.getMeasureVP().getWakeVP(), velocityRef);
1353 break;
1354 }
1355#else
1357 for (int i = 0; i < addWSize; ++i)
1358 velocityRef[i] += velConvWake[i];
1359
1360 for (size_t bou = 0; bou < velConvBou.size(); ++bou)
1361 for (int j = 0; j < addWSize; ++j)
1362 velocityRef[j] += velConvBou[bou][j];
1363#endif
1364}// CalcVeloToWakeVP()
#define CU_VP
Definition Gpudefs.h:92
float DownwardTraversalVorticesToPoints(CpuTreeInfo &cntrTree, std::vector< Point2D > &vel, std::vector< double > &epsast, double theta, int order, bool calcRadius)
const WakeDataBase & getWakeVP() const
Возврат wakeVP.
std::vector< Point2D > & getNonConstVelocity()
Возврат velocity.
std::vector< double > & getNonConstDomainRadius()
Возврат domainRadius.
bool isAnyMovableOrDeformable() const
Возврат признака того, что хотя бы один из профилей подвижный или деформируемый
Definition World2D.cpp:2349
MeasureVP & getNonConstMeasureVP() const
Возврат неконстантной ссылки на measureVP.
Definition World2D.h:213
Boundary & getNonConstBoundary(size_t i) const
Возврат неконстантной ссылки на объект граничного условия
Definition World2D.h:192
CpuTreeInfo & getCntrTreeVP() const
Definition World2D.h:242
const MeasureVP & getMeasureVP() const
Возврат константной ссылки на measureVP.
Definition World2D.h:208
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CPUGetFASTWakeInfluenceToRhs()

void Velocity::CPUGetFASTWakeInfluenceToRhs ( std::vector< double > &  wakeRhs,
std::vector< double > &  wakeRhsLin 
) const
inherited

Definition at line 656 of file Velocity2D.cpp.

657{
658 const size_t nvt = W.getWake().vtx.size();
659
660
661 size_t nTotPan = 0;
662
663 for (size_t s = 0; s < W.getNumberOfAirfoil(); ++s)
664 nTotPan += W.getAirfoil(s).getNumberOfPanels();
665
666 wakeRhs.assign(nTotPan, 0.0);
667 wakeRhsLin.assign(nTotPan, 0.0);
668
669 if (nvt > 0)
670 {
671 auto& inflTree = W.getInflTreeWake();
672
673 auto& cntrTree = W.getCntrTreePnl();
674
676 cntrTree,
677 wakeRhs,
678 wakeRhsLin,
681 }
682}//CPUGetFASTWakeInfluenceToRhs(...)
float DownwardTraversalVorticesToPanels(CpuTreeInfo &cntrTree, std::vector< double > &rhs, std::vector< double > &rhsLin, double theta, int order)
CpuTreeInfo & getCntrTreePnl() const
Definition World2D.h:243
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FillRhs()

void Velocity::FillRhs ( Eigen::VectorXd &  rhsReord) const
inherited

!!!!!!!!!!влияние присоединенных слоев от самого себя и от других профилей

Definition at line 811 of file Velocity2D.cpp.

812{
813 Eigen::VectorXd locRhs;
814 std::vector<double> lastRhs(W.getNumberOfBoundary());
815
816 size_t currentRow = 0;
817 size_t currentSkosRow = 0;
818
819 size_t nAllVars = 0;
820 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
821 nAllVars += W.getBoundary(bou).GetUnknownsSize();
822
823 //Временные массивы для хранения правой части по быстрому методу (размеры задаются внутри CPUGetFASTWakeInfluenceToRhs)
824 std::vector<double> fastWakeRhs;
825 std::vector<double> fastWakeRhsLin;
826
827#ifndef USE_CUDA
828 if (W.getPassport().numericalSchemes.velocityComputation.second == 1) //Быстрый метод на CPU
829 CPUGetFASTWakeInfluenceToRhs(fastWakeRhs, fastWakeRhsLin);
830#endif
831 size_t curGlobPnl = 0;
832
833 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
834 {
835 const Airfoil& afl = W.getAirfoil(bou);
836 size_t np = afl.getNumberOfPanels();
837
838 size_t nVars;
839
840 nVars = W.getBoundary(bou).GetUnknownsSize();
841 locRhs.resize(nVars);
842
843 std::vector<double> wakeRhs;
844
845 double tt1 = omp_get_wtime();
846
847#if (defined(__CUDACC__) || defined(USE_CUDA)) && (defined(CU_RHS))
848 W.timerRhs.reset();
849 W.timerRhs.start();
851 GPUFASTGetWakeInfluenceToRhs(afl, wakeRhs);
852 else
853 GPUGetWakeInfluenceToRhs(afl, wakeRhs);
854 W.timerRhs.stop();
855#else
856 if (W.getPassport().numericalSchemes.velocityComputation.second == 1) //Собираем результат из быстрого метода
857 {
858 size_t shDim = W.getBoundary(afl.numberInPassport).sheetDim;
859
860 wakeRhs.assign(np * shDim, 0.0);
861
862 for (size_t i = 0; i < np; ++i)
863 {
864 wakeRhs[i] = fastWakeRhs[curGlobPnl + i];
865
866 if (shDim != 1)
867 wakeRhs[np + i] = fastWakeRhsLin[curGlobPnl + i];
868 }
869 curGlobPnl += np;
870 }
871 else
872 GetWakeInfluenceToRhs(afl, wakeRhs); //Прямой расчет
873
874 //std::string vname = VMlib::fileNameStep("rhsLinBH", 0, wakeRhs.size(), "txt");
875 //std::ofstream velofile;
876 //velofile.open(W.getPassport().dir + vname);
877
878 //for (int i = 0; i < wakeRhs.size(); ++i)
879 // velofile << wakeRhs[i] << "\n";
880 //velofile.close();
881 //exit(-124);
882#endif
883 std::vector<double> vInfRhs;
884 afl.GetInfluenceFromVInfToPanel(vInfRhs);
885
886#pragma omp parallel for \
887 default(none) \
888 shared(locRhs, afl, bou, wakeRhs, vInfRhs, np) \
889 schedule(dynamic, DYN_SCHEDULE)
890 for (int i = 0; i < (int)afl.getNumberOfPanels(); ++i)
891 {
892 locRhs(i) = -vInfRhs[i] - wakeRhs[i] + 0.25 * ((afl.getV(i) + afl.getV(i + 1)) & afl.tau[i]); //0.25 * (afl.getV(i) + afl.getV(i + 1))*afl.tau[i] - прямолинейные
893 if (W.getBoundary(bou).sheetDim > 1)
894 locRhs(np + i) = -vInfRhs[np + i] - wakeRhs[np + i];
895
897 //Если включен быстрый метод и есть подвижные тела, то пока что все равно вычисляем IQ
899 {
900 for (size_t q = 0; q < W.getNumberOfBoundary(); ++q)
901 {
902 const auto& sht = W.getBoundary(q).sheets;
903 const auto& iq = W.getIQ(bou, q);
904
905 const Airfoil& aflOther = W.getAirfoil(q);
906 if (W.getMechanics(q).isMoves)
907 {
908 for (size_t j = 0; j < aflOther.getNumberOfPanels(); ++j)
909 {
910 if ((i != j) || (bou != q))
911 {
912 locRhs(i) += -iq.first(i, j) * sht.attachedVortexSheet(j, 0);
913 locRhs(i) += -iq.second(i, j) * sht.attachedSourceSheet(j, 0);
914 }//if (i != j)
915
916 }//for j
917 }
918 }//for q
919 }
920 }//for i
921
922 lastRhs[bou] = 0.0;
923
924#pragma omp for
925 for (int q = 0; q < (int)afl.gammaThrough.size(); ++q)
926 lastRhs[bou] += afl.gammaThrough[q];
927
929
930 const double currT = W.getCurrentTime();
931 const double dt = W.getPassport().timeDiscretizationProperties.dt;
932
933 lastRhs[bou] += (W.getMechanics(bou).circulation - W.getMechanics(bou).circulationOld) * (W.getAirfoil(bou).inverse ? 1.0 : -1.0);
934
936
937 //размазываем правую часть
938 for (size_t i = 0; i < nVars; ++i)
939 rhsReord(i + currentSkosRow) = locRhs(i);
940
941 rhsReord(nAllVars + bou) = lastRhs[bou];
942
943 currentRow += nVars + 1;
944 currentSkosRow += nVars;
945 }// for bou
946}
bool inverse
Признак разворота нормалей (для расчета внутренних течений)
Definition Airfoil2D.h:76
Абстрактный класс, определяющий обтекаемый профиль
Definition Airfoil2D.h:182
std::vector< double > gammaThrough
Суммарные циркуляции вихрей, пересекших панели профиля на прошлом шаге
Definition Airfoil2D.h:276
virtual void GetInfluenceFromVInfToPanel(std::vector< double > &vInfRhs) const
Вычисление влияния набегающего потока на панель для правой части
const size_t numberInPassport
Номер профиля в паспорте
Definition Airfoil2D.h:188
size_t GetUnknownsSize() const
Возврат размерности вектора решения
size_t sheetDim
Размерность параметров каждого из слоев на каждой из панелей
Definition Boundary2D.h:93
const bool isMoves
Переменная, отвечающая за то, двигается профиль или нет
double circulationOld
Циркуляция скорости по границе профиля с предыдущего шага
double circulation
Текущая циркуляция скорости по границе профиля
void GetWakeInfluenceToRhs(const Airfoil &afl, std::vector< double > &wakeRhs) const
Генерация вектора влияния вихревого следа на профиль
void CPUGetFASTWakeInfluenceToRhs(std::vector< double > &wakeRhs, std::vector< double > &wakeRhsLin) const
const Mechanics & getMechanics(size_t i) const
Возврат константной ссылки на объект механики
Definition World2D.h:219
const std::pair< Eigen::MatrixXd, Eigen::MatrixXd > & getIQ(size_t i, size_t j) const
Возврат константной ссылки на объект, связанный с матрицей интегралов от (r-xi)/|r-xi|^2.
Definition World2D.h:283
VMlib::vmTimer timerRhs
Definition World2D.h:367
double dt
Шаг по времени
Definition PassportGen.h:67
Here is the call graph for this function:

◆ GetWakeInfluenceToRhs()

void Velocity::GetWakeInfluenceToRhs ( const Airfoil afl,
std::vector< double > &  wakeRhs 
) const
inherited

Генерация вектора влияния вихревого следа на профиль

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

Parameters
[in]aflконстантная ссылка на профиль, правая часть для которого вычисляется
[out]wakeRhsссылка на вектор влияния вихревого следа на ОДИН профиль

Definition at line 619 of file Velocity2D.cpp.

620{
621 size_t np = afl.getNumberOfPanels();
622 size_t shDim = W.getBoundary(afl.numberInPassport).sheetDim;
623
624 wakeRhs.resize(W.getBoundary(afl.numberInPassport).GetUnknownsSize());
625
626 //локальные переменные для цикла
627 std::vector<double> velI(shDim, 0.0);
628
629#pragma omp parallel for default(none) shared(shDim, afl, np, wakeRhs, IDPI) private(velI)
630 for (int i = 0; i < np; ++i)
631 {
632 velI.assign(shDim, 0.0);
633
634 if (W.getWake().vtx.size() > 0)
635 {
636 //Учет влияния следа
637 afl.GetInfluenceFromVorticesToPanel(i, W.getWake().vtx.data(), W.getWake().vtx.size(), velI);
638 }
639
640 if (W.getSource().vtx.size() > 0)
641 {
642 //Учет влияния источников
643 afl.GetInfluenceFromSourcesToPanel(i, W.getSource().vtx.data(), W.getSource().vtx.size(), velI);
644 }
645
646 for (size_t j = 0; j < shDim; ++j)
647 velI[j] *= IDPI / afl.len[i];
648
649 wakeRhs[i] = velI[0];
650
651 if (shDim != 1)
652 wakeRhs[np + i] = velI[1];
653 }//for i
654}//GetWakeInfluenceToRhs(...)
virtual void GetInfluenceFromSourcesToPanel(size_t panel, const Vortex2D *ptr, ptrdiff_t count, std::vector< double > &panelRhs) const
Вычисление влияния части подряд идущих источников из области течения на панель для правой части
virtual void GetInfluenceFromVorticesToPanel(size_t panel, const Vortex2D *ptr, ptrdiff_t count, std::vector< double > &panelRhs) const
Вычисление влияния части подряд идущих вихрей из вихревого следа на панель для правой части
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LimitDiffVelo()

void Velocity::LimitDiffVelo ( std::vector< Point2D > &  diffVel)
inherited

Контроль больших значений диффузионных скоростей

Parameters
[in,out]diffVelссылка на вектор диффузионных скоростей

Definition at line 143 of file Velocity2D.cpp.

144{
145 for (size_t i = 0; i < diffVel.size(); ++i)
146 {
147 Point2D& diffV = diffVel[i];
148
149 if (diffV.length() > 1.5 * W.getPassport().physicalProperties.vRef)
151 }
152}
void normalize(P newlen=1.0)
Нормирование вектора на заданную длину
Definition numvector.h:419
double vRef
Референсная скорость
Definition Passport2D.h:81
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ResizeAndZero()

void Velocity::ResizeAndZero ( )
inherited

Очистка старых массивов под хранение скоростей, выделение новой памяти и обнуление

Вызывается в CalcVortexVelo() на каждом шаге расчета перед непосредственно расчетом скоростей

Definition at line 523 of file Velocity2D.cpp.

524{
525 W.getTimers().start("ConvVel");
527 wakeVortexesParams.convVelo.resize(W.getWake().vtx.size(), { 0.0, 0.0 });
528 W.getTimers().stop("ConvVel");
529
530 W.getTimers().start("DiffVel");
531 wakeVortexesParams.I0.clear();
532 wakeVortexesParams.I0.resize(W.getWake().vtx.size(), 0.0);
533
534 wakeVortexesParams.I1.clear();
535 wakeVortexesParams.I1.resize(W.getWake().vtx.size(), 0.0);
536
537 wakeVortexesParams.I2.clear();
538 wakeVortexesParams.I2.resize(W.getWake().vtx.size(), { 0.0, 0.0 });
539
540 wakeVortexesParams.I3.clear();
541 wakeVortexesParams.I3.resize(W.getWake().vtx.size(), { 0.0, 0.0 });
542
544 wakeVortexesParams.diffVelo.resize(W.getWake().vtx.size(), { 0.0, 0.0 });
545
547 wakeVortexesParams.epsastWake.resize(W.getWake().vtx.size(), 0.0);
548 W.getTimers().stop("DiffVel");
549
550 //Создаем массивы под виртуальные вихри
551 W.getTimers().start("ConvVel");
552 virtualVortexesParams.clear();
554 W.getTimers().stop("ConvVel");
555
556 for (size_t bou = 0; bou < W.getNumberOfBoundary(); ++bou)
557 {
558 W.getTimers().start("ConvVel");
559 virtualVortexesParams[bou].convVelo.clear();
560 virtualVortexesParams[bou].convVelo.resize(W.getBoundary(bou).virtualWake.vtx.size(), { 0.0, 0.0 });
561 W.getTimers().stop("ConvVel");
562
563 W.getTimers().start("DiffVel");
564 virtualVortexesParams[bou].I0.clear();
565 virtualVortexesParams[bou].I0.resize(W.getBoundary(bou).virtualWake.vtx.size(), 0.0);
566
567 virtualVortexesParams[bou].I1.clear();
568 virtualVortexesParams[bou].I1.resize(W.getBoundary(bou).virtualWake.vtx.size(), 0.0);
569
570 virtualVortexesParams[bou].I2.clear();
571 virtualVortexesParams[bou].I2.resize(W.getBoundary(bou).virtualWake.vtx.size(), { 0.0, 0.0 });
572
573 virtualVortexesParams[bou].I3.clear();
574 virtualVortexesParams[bou].I3.resize(W.getBoundary(bou).virtualWake.vtx.size(), { 0.0, 0.0 });
575
576 virtualVortexesParams[bou].diffVelo.clear();
577 virtualVortexesParams[bou].diffVelo.resize(W.getBoundary(bou).virtualWake.vtx.size(), { 0.0, 0.0 });
578
579 virtualVortexesParams[bou].epsastWake.clear();
580 virtualVortexesParams[bou].epsastWake.resize(W.getBoundary(bou).virtualWake.vtx.size(), 0.0);
581
582 W.getTimers().stop("DiffVel");
583 }
584}//ResizeAndZero()
Here is the call graph for this function:

◆ SaveVisStress()

void Velocity::SaveVisStress ( )
inherited

Сохранение вязких напряжений

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

Definition at line 587 of file Velocity2D.cpp.

588{
590 // if ((W.getPassport().timeDiscretizationProperties.saveVTK > 0) && (W.ifDivisible(10)) && (W.getNumberOfAirfoil() > 0))
591 {
592 for (size_t q = 0; q < W.getNumberOfAirfoil(); ++q)
593 {
594 if (q == 0)
596
597 std::stringstream ss;
598 ss << "VisStress_" << q << "-";
600 std::ofstream outfile;
601 outfile.open(W.getPassport().dir + "visStress/" + fname);
602
603 outfile << W.getAirfoil(q).viscousStress.size() << std::endl; //Сохранение числа вихрей в пелене
604
605 for (size_t i = 0; i < W.getAirfoil(q).viscousStress.size(); ++i)
606 {
607 const Point2D& r = 0.5 * (W.getAirfoil(q).getR(i + 1) + W.getAirfoil(q).getR(i));
608 double gi = W.getAirfoil(q).viscousStress[i];
609 outfile << static_cast<int>(i) << " " << r[0] << " " << r[1] << " " << gi << std::endl;
610 }//for i
611 outfile.close();
612 }
613 }
614}//SaveVisStress()
bool ifDivisible(int val) const
Definition World2D.h:290
std::string dir
Рабочий каталог задачи
void CreateUserDirectory(const std::string &dir, const std::string &name)
Создание каталога
Definition defs.h:439
std::string fileNameStep(const std::string &name, int length, size_t number, const std::string &ext)
Формирование имени файла
Definition defs.h:379
int saveVtxStep
Шаг сохранения кадров в бинарные файлы
Definition PassportGen.h:81
int saveVisStress
Шаг вычисления и сохранения скорости и давления
Definition PassportGen.h:89
int nameLength
Число разрядов в имени файла
Definition PassportGen.h:76
Here is the call graph for this function:

Member Data Documentation

◆ optimizedVelocity

OptimizedVelocity VM2D::Velocity::optimizedVelocity
inherited

Definition at line 117 of file Velocity2D.h.

◆ virtualVortexesParams

std::vector<VortexesParams> VM2D::Velocity::virtualVortexesParams
inherited

Вектор струтур, определяющий параметры виртуальных вихрей для профилей

Definition at line 115 of file Velocity2D.h.

◆ W

const World2D& VM2D::Velocity::W
protectedinherited

Константная ссылка на решаемую задачу

Definition at line 108 of file Velocity2D.h.

◆ wakeVortexesParams

VortexesParams VM2D::Velocity::wakeVortexesParams
inherited

Струтура, определяющая параметры вихрей в следе

Definition at line 112 of file Velocity2D.h.


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