280{
281
282
284
285#ifdef USE_CUDA
287#endif
288
289
290
292
293
295 {
296 std::unique_ptr<Passport> revisePspPtr;
300
302
303 }
304
305
307
308 size_t countStrongCoupling = 0;
309 for (
size_t m = 0; m <
mechanics.size(); ++m)
310 {
313 {
315 ++countStrongCoupling;
316 }
317 }
318
319 bool semiImplicitStrategy = ((countStrongCoupling ==
mechanics.size()) && (
mechanics.size() > 0));
321 info(
'i') <<
"Strong (semi-implicit) coupling strategy" << std::endl;
322
323
324
325 int nTotPan = 0;
328
329
330 if (!semiImplicitStrategy)
331 {
333
336 if (
getPassport().numericalSchemes.velocityComputation.second == 0 &&
getPassport().numericalSchemes.linearSystemSolver.second == 2)
337 {
338#ifdef USE_CUDA
340 if (nTotPan > 0)
341 {
343 auto& treePnlVrt = *
getCuda().inflTreePnlVortex;
345 treePnlVrt.MemoryAllocate((
int)
getCuda().n_CUDA_pnls);
346
348 {
349
350 treePnlVrt.UpdatePanelGeometry(nTotPan, (double4*)afl.devRPtr);
351 treePnlVrt.Build();
352 }
353
354 treePnlVrt.UpdatePanelAttachedVortexIntensity(afl.devAttachedVortexSheetPtr, afl.devAttachedVortexSheetLinPtr);
355 treePnlVrt.UpwardTraversal(
getPassport().numericalSchemes.gmresMultipoleOrder);
356 }
357#endif
358 }
359
360 if (
getPassport().numericalSchemes.velocityComputation.second == 1)
361 {
362#ifdef USE_CUDA
365
366
367 auto& treeWake = *
getCuda().inflTreeWake;
368 treeWake.MemoryAllocate((
int)
getCuda().n_CUDA_wake);
370 treeWake.Build();
371 treeWake.UpwardTraversal(
getPassport().numericalSchemes.nbodyMultipoleOrder);
372
373 if (nTotPan > 0)
374 {
376 auto& treePnl = *
getCuda().cntrTreePnl;
377 auto& treePnlVrt = *
getCuda().inflTreePnlVortex;
378 auto& treePnlSrc = *
getCuda().inflTreePnlSource;
379 auto& treePnlAux = *
getCuda().auxTreePnl;
380
382 {
383 treePnl.MemoryAllocate((
int)
getCuda().n_CUDA_pnls);
384 treePnlAux.MemoryAllocate((
int)
getCuda().n_CUDA_pnls);
385 treePnlVrt.MemoryAllocate((
int)
getCuda().n_CUDA_pnls);
387 treePnlSrc.MemoryAllocate((
int)
getCuda().n_CUDA_pnls);
388 }
389
391 {
392
393 treePnlVrt.UpdatePanelGeometry(nTotPan, (double4*)afl.devRPtr);
394 treePnlVrt.Build();
395
396
397 treePnl.UpdatePanelGeometry((int)nTotPan, (double4*)afl.devRPtr);
398 treePnl.Build();
399
400
402 {
403 treePnlSrc.UpdatePanelGeometry(nTotPan, (double4*)afl.devRPtr);
404 treePnlSrc.UpdatePanelAttachedSourceIntensity(afl.devAttachedSourceSheetPtr, afl.devAttachedSourceSheetLinPtr);
405 treePnlSrc.Build();
406 treePnlSrc.UpwardTraversal(
getPassport().numericalSchemes.nbodyMultipoleOrder);
407 }
408 }
409
410 treePnlVrt.UpdatePanelAttachedVortexIntensity(afl.devAttachedVortexSheetPtr, afl.devAttachedVortexSheetLinPtr);
411 treePnlVrt.UpwardTraversal(
getPassport().numericalSchemes.nbodyMultipoleOrder);
412
413
414
415
416
417
418
419
420
421
422
423
424
425 }
426#else
428 {
432 }
433 std::vector<std::pair<Point2D, Point2D>> panels;
434
436 {
438
439 for (size_t i = 0; i < afl.getNumberOfPanels(); ++i)
440 panels.push_back({ afl.getR(i), afl.getR(i + 1) });
441 }
442 if (panels.size() > 0)
443 {
444 cntrTreePnl->UpdatePanelGeometry(panels, std::max(4, (
int)(log2(panels.size())) - 2));
447 }
448#endif
449 }
451
454
455
456 if (
getPassport().physicalProperties.typeAccel.second == 3)
457 {
461 {
463 {
465 {
470 }
473 info(
'i') <<
"Added Masses for airfoil #" << bou <<
" = { " << lambdaAdd[bou][0] <<
", " << lambdaAdd[bou][1] <<
", " << muAdd[bou] <<
" }" << std::endl;
474
475 char direction;
476 switch ((
int)(
getPassport().physicalProperties.timeAccel))
477 {
478 case 0:
479 direction = 'x';
480 break;
481 case 1:
482 direction = 'y';
483 break;
484 case 2:
485 direction = 'w';
486 break;
487 default:
488 direction = '?';
489 info(
'e') <<
"Wrong dirfection is specified!" << std::endl;
490 exit(1);
491 }
492
494 std::ofstream addMassFile;
496 {
497 addMassFile.open(addMassFileName);
498 addMassFile << "Added Masses for airfoil:" << std::endl;
499 }
500 else
501 addMassFile.open(addMassFileName, std::ios_base::app);
502
503 addMassFile << direction << "-direction: " << lambdaAdd[bou][0] << " " << lambdaAdd[bou][1] << " " << muAdd[bou] << std::endl;
504
505 addMassFile.close();
506 }
507 }
509 }
510
512 if (nTotPan > 0 &&
getPassport().numericalSchemes.velocityComputation.second == 1)
513 {
515#ifdef USE_CUDA
516 getCuda().inflTreePnlVortex->UpdatePanelFreeAndAttachedVortexIntensity(afl.devFreeVortexSheetPtr, afl.devFreeVortexSheetLinPtr, afl.devAttachedVortexSheetPtr, afl.devAttachedVortexSheetLinPtr);
517 getCuda().inflTreePnlVortex->UpwardTraversal(
getPassport().numericalSchemes.nbodyMultipoleOrder);
518#endif
519 }
521
522
524
525
526#ifdef TURB
528 std::vector<double> nut;
529 CalcVeloDifference(nut);
531
532 for (
size_t q = 0; q <
getWake().
vtx.size(); ++q)
534#endif
535
536
537
538
539
541
542#ifdef OPTIMIZER
544#endif
545 {
547
549
550#ifdef USE_CUDA
552#else
554#endif
555
557 {
558
559
561
562 if (
measureVP->getTotalNumberOfRealPoints() > 0)
564
565
566
567
568
570 {
571 std::ofstream presForcesFile;
573 {
575 presForcesFile << "time,Fx,Fy,Py" << std::endl;
576 }
577 else
578 presForcesFile.open(
getPassport().
dir +
"presForcesFile.csv", std::ios_base::app);
579
580 auto r =
measureVP->GetVPinElasticPoints();
581 Point2D presForce = { 0.0, 0.0 };
582 double yPower = 0.0;
583
584 for (int q = 0; q < r.size(); ++q)
585 {
588 }
589
590 presForcesFile <<
currentTime <<
"," << scaleP * presForce[0] <<
"," << scaleP * presForce[1] <<
"," << scaleP * yPower << std::endl;
591 presForcesFile.close();
592 }
593 }
594
595
597 {
598
600 if (ptr && ptr->
beam->fsi)
601 {
602 auto r =
measureVP->GetVPinElasticPoints();
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620 std::vector<double> currentPres(ptr->
chord.size());
621 for (
size_t j = 0; j < ptr->
chord.size(); ++j)
622 {
623
624 currentPres[j] = -(r[2 * j + 0].second - r[2 * j + 1].second);
625 }
626
627 if (ptr->
beam->presLastSteps.size() < ptr->
beam->nLastSteps)
628 ptr->
beam->presLastSteps.push_back(currentPres);
629 else
630 {
631 for (
int w = 1; w < ptr->
beam->nLastSteps; ++w)
632 ptr->
beam->presLastSteps[w - 1] = std::move(ptr->
beam->presLastSteps[w]);
633 ptr->
beam->presLastSteps.back() = currentPres;
634 }
635
636 for (
int q = 0; q < ptr->
beam->R; ++q)
637 {
638 ptr->
beam->qCoeff[q] = 0;
639
640 if (ptr->
beam->presLastSteps.size() == ptr->
beam->nLastSteps)
641 {
642 for (
size_t j = 0; j < ptr->
chord.size(); ++j)
643 {
644 double averpres = 0.0;
645
646
647 for (
int i = 0; i < ptr->
beam->nLastSteps; ++i)
648 averpres += ptr->
beam->presLastSteps[i][j];
649 averpres /= ptr->
beam->nLastSteps;
650
652 }
653 ptr->
beam->qCoeff[q] /= (ptr->
beam->intSqUnitShape * ptr->
beam->L);
654 }
655
656
657 }
658
659 std::ofstream phiFile;
661 {
663 phiFile << "time";
664 for (
int p = 0; p < ptr->
beam->R; ++p)
665 phiFile << ",phi-" << std::to_string(p + 1);
666 for (
int p = 0; p < ptr->
beam->R; ++p)
667 phiFile << ",q-" << std::to_string(p + 1);
668 phiFile << std::endl;
669 }
670 else
671 phiFile.open(
getPassport().
dir +
"phiFile.csv", std::ios_base::app);
672
674 for (
int p = 0; p < ptr->
beam->R; ++p)
675 phiFile <<
"," << ptr->
beam->phi(p, 0);
676 for (
int p = 0; p < ptr->
beam->R; ++p)
677 phiFile <<
"," << ptr->
beam->qCoeff[p];
678
679 phiFile << std::endl;
680
681 phiFile.close();
682 }
683 }
684
685
686 }
687
688
690 {
691 mech->GetHydroDynamForce();
692 mech->GenerateForcesString();
693 mech->GeneratePositionString();
694 }
695
696
697#ifdef TURB
699#else
701#endif
704
705
707
708
709
710
711
712
713
714 }
715
716
717
718 if (semiImplicitStrategy)
719 {
722
724
725
727
728
729
730
731
732
733
735 {
738 }
739
742
745
746
747
748 for (
size_t m = 0; m <
mechanics.size(); ++m)
749 {
751
753 if (mechVar)
754 {
756 {
757 getInfo(
'e') <<
"Added mass of the airfoil should be non-zero!" << std::endl;
758 exit(1);
759 }
767 }
768 else
769 exit(3333);
770 }
771 }
772
773
775
777
778
779
781
782
783
784
785
786
787
788
789
790
791
794 << std::setprecision(3) \
796 << std::setprecision(6) \
797 << std::endl;
798
800
803
804
805
806
807
808
809}
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()
std::string defaultsFileFullName
std::vector< std::string > varLine
std::string switchersFileFullName
std::string mechanicsFileFullName
std::string fileFullName
Имена файлов
void GetReviseParamsFromParser(const Passport &newPassport, const std::vector< std::string > paramList)
Считывание измененных параметров
const double & attachedVortexSheet(size_t n, size_t moment) const
const double & freeVortexSheet(size_t n, size_t moment) const
std::vector< Vortex2D > vtx
Список вихревых элементов
void WakeAndAirfoilsMotion(bool dynamics, std::vector< double > *nutPtr=nullptr)
Перемещение вихрей и профилей на шаге
VMlib::vmTimer timerInitialBuild
void CalcPanelsVeloAndAttachedSheets()
Вычисление скоростей панелей и интенсивностей присоединенных слоев вихрей и источников
void CalcVortexVelo()
Вычисление скоростей (и конвективных, и диффузионных) вихрей (в пелене и виртуальных),...
void CalcAndSolveLinearSystem()
Набор матрицы, правой части и решение СЛАУ
const Boundary & getBoundary(size_t i) const
Возврат константной ссылки на объект граничного условия
bool ifDivisible(int val) const
Mechanics & getNonConstMechanics(size_t i) const
Возврат неконстантной ссылки на объект механики
Wake & getNonConstWake() 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 градусов
double rho
Плотность потока
std::vector< std::string > reviseParameters
Список перечитываемых параметров
int revisePassportStep
Шаг перечитывания паспорта