261{
262
263
265
266#ifdef USE_CUDA
268#endif
269
270
271
273
275
276 size_t countStrongCoupling = 0;
277 for (
size_t m = 0; m <
mechanics.size(); ++m)
278 {
281 {
283 ++countStrongCoupling;
284 }
285 }
286
287 bool semiImplicitStrategy = ((countStrongCoupling ==
mechanics.size()) && (
mechanics.size() > 0));
289 info(
'i') <<
"Strong (semi-implicit) coupling strategy" << std::endl;
290
291
292
293 int nTotPan = 0;
296
297 if (!semiImplicitStrategy)
298 {
300
303 if (
getPassport().numericalSchemes.velocityComputation.second == 0 &&
getPassport().numericalSchemes.linearSystemSolver.second == 2)
304 {
305#ifdef USE_CUDA
307 if (nTotPan > 0)
308 {
310 auto& treePnlVrt = *
getCuda().inflTreePnlVortex;
312 treePnlVrt.MemoryAllocate((
int)
getCuda().n_CUDA_pnls);
313
315 {
316
317 treePnlVrt.UpdatePanelGeometry(nTotPan, (double4*)afl.devRPtr);
318 treePnlVrt.Build();
319 }
320
321 treePnlVrt.UpdatePanelAttachedVortexIntensity(afl.devAttachedVortexSheetPtr, afl.devAttachedVortexSheetLinPtr);
323 }
324#endif
325 }
326
327 if (
getPassport().numericalSchemes.velocityComputation.second == 1)
328 {
329#ifdef USE_CUDA
332
333
334 auto& treeWake = *
getCuda().inflTreeWake;
335 treeWake.MemoryAllocate((
int)
getCuda().n_CUDA_wake);
337 treeWake.Build();
338 treeWake.UpwardTraversal(
getPassport().numericalSchemes.nbodyMultipoleOrder);
339
340 if (nTotPan > 0)
341 {
343 auto& treePnl = *
getCuda().cntrTreePnl;
344 auto& treePnlVrt = *
getCuda().inflTreePnlVortex;
345 auto& treePnlSrc = *
getCuda().inflTreePnlSource;
346 auto& treePnlAux = *
getCuda().auxTreePnl;
347
349 {
350 treePnl.MemoryAllocate((
int)
getCuda().n_CUDA_pnls);
351 treePnlAux.MemoryAllocate((
int)
getCuda().n_CUDA_pnls);
352 treePnlVrt.MemoryAllocate((
int)
getCuda().n_CUDA_pnls);
354 treePnlSrc.MemoryAllocate((
int)
getCuda().n_CUDA_pnls);
355 }
356
358 {
359
360 treePnlVrt.UpdatePanelGeometry(nTotPan, (double4*)afl.devRPtr);
361 treePnlVrt.Build();
362
363
364 treePnl.UpdatePanelGeometry((int)nTotPan, (double4*)afl.devRPtr);
365 treePnl.Build();
366
367
369 {
370 treePnlSrc.UpdatePanelGeometry(nTotPan, (double4*)afl.devRPtr);
371 treePnlSrc.UpdatePanelAttachedSourceIntensity(afl.devAttachedSourceSheetPtr, afl.devAttachedSourceSheetLinPtr);
372 treePnlSrc.Build();
374 }
375 }
376
377 treePnlVrt.UpdatePanelAttachedVortexIntensity(afl.devAttachedVortexSheetPtr, afl.devAttachedVortexSheetLinPtr);
379 }
380#endif
381 }
383
386
387
388 if (
getPassport().physicalProperties.typeAccel.second == 3)
389 {
393 {
395 {
397 {
402 }
405 info(
'i') <<
"Added Masses for airfoil #" << bou <<
" = { " << lambdaAdd[bou][0] <<
", " << lambdaAdd[bou][1] <<
", " << muAdd[bou] <<
" }" << std::endl;
406
407 char direction;
408 switch ((
int)(
getPassport().physicalProperties.timeAccel))
409 {
410 case 0:
411 direction = 'x';
412 break;
413 case 1:
414 direction = 'y';
415 break;
416 case 2:
417 direction = 'w';
418 break;
419 default:
420 direction = '?';
421 info(
'e') <<
"Wrong dirfection is specified!" << std::endl;
422 exit(1);
423 }
424
426 std::ofstream addMassFile;
428 {
429 addMassFile.open(addMassFileName);
430 addMassFile << "Added Masses for airfoil:" << std::endl;
431 }
432 else
433 addMassFile.open(addMassFileName, std::ios_base::app);
434
435 addMassFile << direction << "-direction: " << lambdaAdd[bou][0] << " " << lambdaAdd[bou][1] << " " << muAdd[bou] << std::endl;
436
437 addMassFile.close();
438 }
439 }
440
441
443 }
444
446 if (nTotPan > 0 &&
getPassport().numericalSchemes.velocityComputation.second == 1)
447 {
449#if USE_CUDA
450 getCuda().inflTreePnlVortex->UpdatePanelFreeAndAttachedVortexIntensity(afl.devFreeVortexSheetPtr, afl.devFreeVortexSheetLinPtr, afl.devAttachedVortexSheetPtr, afl.devAttachedVortexSheetLinPtr);
452#endif
453 }
455
456
458
459
460
461
463
464
465 {
467
469
471
472 {
474 if (
measureVP->getTotalNumberOfRealPoints() > 0)
476
477 if (ptr && !ptr->
beam->fsi)
478
479
480
482 {
483 std::ofstream presForcesFile;
485 {
487 presForcesFile << "time,Fx,Fy,Py" << std::endl;
488 }
489 else
490 presForcesFile.open(
getPassport().
dir +
"presForcesFile.csv", std::ios_base::app);
491
492 auto r =
measureVP->GetVPinElasticPoints();
493 Point2D presForce = { 0.0, 0.0 };
494 double yPower = 0.0;
495
496 for (int q = 0; q < r.size(); ++q)
497 {
500 }
501
502 presForcesFile <<
currentTime <<
"," << scaleP * presForce[0] <<
"," << scaleP * presForce[1] <<
"," << scaleP * yPower << std::endl;
503 presForcesFile.close();
504 }
505 }
506
507
508
510 if (ptr && ptr->
beam->fsi)
511 {
512 auto r =
measureVP->GetVPinElasticPoints();
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530 std::vector<double> currentPres(ptr->
chord.size());
531 for (
size_t j = 0; j < ptr->
chord.size(); ++j)
532 {
533
534 currentPres[j] = -(r[2 * j + 0].second - r[2 * j + 1].second);
535 }
536
537 if (ptr->
beam->presLastSteps.size() < ptr->
beam->nLastSteps)
538 ptr->
beam->presLastSteps.push_back(currentPres);
539 else
540 {
541 for (
int w = 1; w < ptr->
beam->nLastSteps; ++w)
542 ptr->
beam->presLastSteps[w - 1] = std::move(ptr->
beam->presLastSteps[w]);
543 ptr->
beam->presLastSteps.back() = currentPres;
544 }
545
546 for (
int q = 0; q < ptr->
beam->R; ++q)
547 {
548 ptr->
beam->qCoeff[q] = 0;
549
550 if (ptr->
beam->presLastSteps.size() == ptr->
beam->nLastSteps)
551 {
552 for (
size_t j = 0; j < ptr->
chord.size(); ++j)
553 {
554 double averpres = 0.0;
555
556
557 for (
int i = 0; i < ptr->
beam->nLastSteps; ++i)
558 averpres += ptr->
beam->presLastSteps[i][j];
559 averpres /= ptr->
beam->nLastSteps;
560
562 }
563 ptr->
beam->qCoeff[q] /= (ptr->
beam->intSqUnitShape * ptr->
beam->L);
564 }
565
566
567 }
568
569 std::ofstream phiFile;
571 {
573 phiFile << "time";
574 for (
int p = 0; p < ptr->
beam->R; ++p)
575 phiFile << ",phi-" << std::to_string(p + 1);
576 phiFile << std::endl;
577 }
578 else
579 phiFile.open(
getPassport().
dir +
"phiFile.csv", std::ios_base::app);
580
582 for (
int p = 0; p < ptr->
beam->R; ++p)
583 phiFile <<
"," << ptr->
beam->phi(p, 0);
584 phiFile << std::endl;
585
586 phiFile.close();
587 }
588
589
590 }
591
592
594 {
595 mech->GetHydroDynamForce();
596 mech->GenerateForcesString();
597 mech->GeneratePositionString();
598 }
599
600
604
605
607
608
609
610
611
612
613
614 }
615
616
617
618 if (semiImplicitStrategy)
619 {
622
624
625
627
628
629
630
631
632
633
635 {
638 }
639
642
645
646
647
648 for (
size_t m = 0; m <
mechanics.size(); ++m)
649 {
651
653 if (mechVar)
654 {
656 {
657 getInfo(
'e') <<
"Added mass of the airfoil should be non-zero!" << std::endl;
658 exit(1);
659 }
667 }
668 else
669 exit(3333);
670 }
671 }
672
673
675
677
678
679
681
682
683
684
685
686
687
688
689
690
691
694 << std::setprecision(3) \
696 << std::setprecision(6) \
697 << std::endl;
698
700
703
704
705
706
707
708
709}
const Point2D & getR(size_t q) const
Возврат константной ссылки на вершину профиля
std::vector< Point2D > nrm
Нормали к панелям профиля
Point2D rcm
Положение центра масс профиля
Sheet sheets
Слои на профиле
Point2D hydroDynamForce
Вектор гидродинамической силы и момент, действующие на профиль
void GeneratePositionString()
Сохранение строки со статистикой в файл нагрузок
void GenerateForcesString()
Сохранение строки со статистикой в файл нагрузок
Point2D & getV()
текущая скорость профиля
bool & getStrongCoupling()
const double & attachedVortexSheet(size_t n, size_t moment) const
const double & freeVortexSheet(size_t n, size_t moment) const
VMlib::vmTimer timerInitialBuild
void CalcPanelsVeloAndAttachedSheets()
Вычисление скоростей панелей и интенсивностей присоединенных слоев вихрей и источников
void CalcVortexVelo()
Вычисление скоростей (и конвективных, и диффузионных) вихрей (в пелене и виртуальных),...
void CalcAndSolveLinearSystem()
Набор матрицы, правой части и решение СЛАУ
void WakeAndAirfoilsMotion(bool dynamics)
Перемещение вихрей и профилей на шаге
const Boundary & getBoundary(size_t i) const
Возврат константной ссылки на объект граничного условия
bool ifDivisible(int val) const
Mechanics & getNonConstMechanics(size_t i) const
Возврат неконстантной ссылки на объект механики
void GenerateStatString(size_t stepNo, double curTime, size_t N)
Формирование очередной строки файла временной статистики
void resetAll()
Сброс всех счетчиков
double durationStep() const
Вывод счетчика всего шага в секундах
size_t getCurrentStep() const
Возврат константной ссылки на параметры распараллеливания по MPI.
numvector< T, 2 > kcross() const
Геометрический поворот двумерного вектора на 90 градусов
T sqr(T x)
Умножение a на комплексно сопряженноe к b.
bool fileExistTest(std::string &fileName, LogStream &info, bool exitKey=false, const std::list< std::string > &extList={})
Проверка существования файла
double vRef
Референсная скорость
double rho
Плотность потока