MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
fvstg.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#include "fvstg.h"
8
9using namespace std;
10
11template <class base_iterator, class SolverType>
14 return p->m_solver->a_reconstructionNeighborId(p->m_stgToCellId[*(*this)], dir);
15}
16
17
18template <class base_iterator, class SolverType>
21 return p->m_stgToCellId[*(*this)];
22}
23
24
25template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
27 MInt bcId,
28 const MPI_Comm commStg,
29 MInt* sortedBndryCellIds,
30 MInt noStgLCells,
31 MInt stgFaceNormalDir,
32 MInt stgDir,
33 MInt stgWallNormalDir,
34 MInt wallDir,
35 MBool cutOff)
36
37 : m_solver(solver),
38 m_solverId(solver->m_solverId),
39 m_bcId(bcId),
40 m_sutherlandConstant(solver->m_sutherlandConstant),
41 m_sutherlandPlusOne(solver->m_sutherlandPlusOne),
42 m_commStg(commStg),
43 m_noStgLCells(noStgLCells),
44 m_stgFaceNormalDir(stgFaceNormalDir),
45 m_stgWallNormalDir(stgWallNormalDir),
46 m_stgDir(stgDir),
47 m_wallDir(wallDir),
48 m_cutOff(cutOff),
49 a(new Accessor(sortedBndryCellIds, noStgLCells, m_solver, commStg, cutOff)) {
50 TRACE();
51
52 IF_CONSTEXPR(nDim == 2) mTerm(1, AT_, "Only implemented for 3D!");
53
54 for(MInt i = 0; i < nDim; i++) {
55 if(i != m_stgDir && i != m_wallDir) {
56 m_periodicDir = i;
57 }
58 }
59
60 m_stgLocal = (noStgLCells > 0);
61
63
64 // Allocate m_stgVariables
65 mAlloc(m_stgLVariables, STG::noStgVars, a->sizeStg(), "m_stgLVariables", F0, AT_);
66
67 if(m_newStgMethod) {
68 mAlloc(m_stgEddieCoverage, 2, a->sizeStg(), "m_stgEddieCoverage", F0, AT_);
69 }
70}
71
72
73/*
74 * random number generator
75 * @author Marian Albers
76 * @date 01.01.1010
77 *
78 */
79template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
81 std::uniform_real_distribution<MFloat> randRealDistNumber(0, 1);
82 return randRealDistNumber(randomEddyPosGenerator());
83 // return rand() / double(RAND_MAX);
84}
85
95template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
97 std::uniform_real_distribution<MFloat> randRealDistNumber(0, 1);
98 return pow(randRealDistNumber(randomEddyPosGenerator()), m_stgEddieDistribution);
99 // return pow((rand() / double(RAND_MAX)), m_stgEddieDistribution);
100}
101
102template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
104 return 15.0 * pow((rand() / double(RAND_MAX)) - 0.35, F3) + F1;
105}
106
107
108template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
110 MFloat angle = atan(z / y);
111 if(y < 0) {
112 if(z >= 0) {
113 angle += PI;
114 } else {
115 angle -= PI;
116 }
117 }
118 return angle;
119}
120
121template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
123 TRACE();
124 m_stgInitialStartup = false;
125 m_stgRootRank = false;
126
127 if(m_stgLocal) {
128 MPI_Comm_rank(m_commStg, &m_commStgMyRank);
129 } else {
130 m_commStgMyRank = -1;
131 }
132
133 //
134 std::string prop_name;
135
136 // default error message
137 std::stringstream errorMsg;
138 errorMsg << ": This property is not allowed to exist without an assignment to a BC" << std::endl;
139
140 // STG seed
141 prop_name = "bc" + std::to_string(m_bcId) + "STGSeed";
142 if(Context::propertyExists(prop_name, m_solverId)) {
143 m_randomEddySeed = Context::getSolverProperty<MInt>(prop_name, m_solverId, AT_, &m_randomEddySeed);
144 m_PRNGEddy.seed(m_randomEddySeed);
145 }
146
147 m_zonal = m_solver->m_zonal;
148
149 prop_name = "bc" + std::to_string(m_bcId) + "preliminary";
150 m_preliminary = Context::getSolverProperty<MBool>(prop_name, m_solverId, AT_, &m_preliminary);
151
152 prop_name = "bc" + std::to_string(m_bcId) + "preliminaryRans2D";
153 m_preliminaryRans2D = Context::getSolverProperty<MBool>(prop_name, m_solverId, AT_, &m_preliminary);
154
155 if(m_preliminaryRans2D) m_preliminary = true;
156
157 prop_name = "bc" + std::to_string(m_bcId) + "newStgMethod";
158 m_newStgMethod = Context::getSolverProperty<MBool>(prop_name, m_solverId, AT_, &m_newStgMethod);
159
160 prop_name = "bc" + std::to_string(m_bcId) + "stgCylinderTransformation";
161 m_cylinderTransformation = Context::getSolverProperty<MBool>(prop_name, m_solverId, AT_, &m_cylinderTransformation);
162
163 // isotropicTurbulence
164 if(Context::propertyExists("isotropicTurbulence", m_solverId)) {
165 m_isotropicTurbulence =
166 Context::getSolverProperty<MBool>("isotropicTurbulence", m_solverId, AT_, &m_isotropicTurbulence);
167 }
168
169 // freeStreamTurbulence
170 m_uuFS = F0;
171 m_vvFS = F0;
172 m_wwFS = F0;
173 m_SijSijFS = F0;
174 m_BLEddieFraction = F1;
175 m_freeStreamTurbulence = false;
176 if(Context::propertyExists("freeStreamTurbulence", m_solverId)) {
177 m_freeStreamTurbulence =
178 Context::getSolverProperty<MBool>("freeStreamTurbulence", m_solverId, AT_, &m_freeStreamTurbulence);
179 m_uuFS = Context::getSolverProperty<MFloat>("uuFS", m_solverId, AT_, &m_uuFS);
180 m_vvFS = Context::getSolverProperty<MFloat>("vvFS", m_solverId, AT_, &m_vvFS);
181 m_wwFS = Context::getSolverProperty<MFloat>("wwFS", m_solverId, AT_, &m_wwFS);
182 m_SijSijFS = Context::getSolverProperty<MFloat>("SijSijFS", m_solverId, AT_, &m_SijSijFS);
183 m_BLEddieFraction = Context::getSolverProperty<MFloat>("BLEddieFraction", m_solverId, AT_, &m_BLEddieFraction);
184 }
185
198 if(Context::propertyExists("stgSubSup", m_solverId)) mTerm(1, AT_, "stgSubSup" + errorMsg.str());
199 prop_name = "bc" + std::to_string(m_bcId) + "stgSubSup";
200 m_stgSubSup = false;
201 if(Context::propertyExists(prop_name, m_solverId)) {
202 m_stgSubSup = Context::getSolverProperty<MBool>(prop_name, m_solverId, AT_, &m_stgSubSup);
203 }
204
216 if(Context::propertyExists("stgSupersonic", m_solverId)) mTerm(1, AT_, "stgSupersonic" + errorMsg.str());
217 prop_name = "bc" + std::to_string(m_bcId) + "stgSupersonic";
218 m_stgSupersonic = false;
219 if(Context::propertyExists(prop_name, m_solverId)) {
220 m_stgSupersonic = Context::getSolverProperty<MBool>(prop_name, m_solverId, AT_, &m_stgSupersonic);
221
222 if(m_stgSupersonic && m_stgSubSup) {
223 m_stgSubSup = false;
224 if(m_solver->domainId() == 0) {
225 std::cout << "WARNING: You activated conflicting properties stgSubSup "
226 << "and stgSupersonic, thus only the pure supersonic formulation will be used. "
227 << "Switch off stgSupersonic to get the mixed formulation" << std::endl;
228 }
229 }
230 }
231
245 if(Context::propertyExists("BLT1", m_solverId)) mTerm(1, AT_, "BLT1" + errorMsg.str());
246 prop_name = "bc" + std::to_string(m_bcId) + "BLT1";
247 m_stgBLT1 = 1.0;
248 m_stgBLT1 = Context::getSolverProperty<MFloat>(prop_name, m_solverId, AT_, &m_stgBLT1);
249
263 if(Context::propertyExists("BLT2", m_solverId)) mTerm(1, AT_, "BLT2" + errorMsg.str());
264 prop_name = "bc" + std::to_string(m_bcId) + "BLT2";
265 m_stgBLT2 = 1.1;
266 m_stgBLT2 = Context::getSolverProperty<MFloat>(prop_name, m_solverId, AT_, &m_stgBLT2);
267
281 if(Context::propertyExists("BLT3", m_solverId)) mTerm(1, AT_, "BLT3" + errorMsg.str());
282 prop_name = "bc" + std::to_string(m_bcId) + "BLT3";
283 m_stgBLT3 = 1.0;
284 m_stgBLT3 = Context::getSolverProperty<MFloat>(prop_name, m_solverId, AT_, &m_stgBLT3);
285
286 mAlloc(m_stgLengthFactors, 3, "m_stgLengthFactors", F0, AT_);
287 m_stgLengthFactors[0] = 1.0;
288 m_stgLengthFactors[1] = 0.6;
289 m_stgLengthFactors[2] = 1.5;
290
305 if(Context::propertyExists("stgLengthFactors", m_solverId)) mTerm(1, AT_, "stgLengthFactors" + errorMsg.str());
306 prop_name = "bc" + std::to_string(m_bcId) + "stgLengthFactors";
307 if(Context::propertyExists(prop_name, m_solverId)) {
308 for(MInt i = 0; i < 3; i++) {
309 m_stgLengthFactors[i] = Context::getSolverProperty<MFloat>(prop_name, m_solverId, AT_, &m_stgLengthFactors[i], i);
310 }
311 }
312
313 mAlloc(m_stgRSTFactors, 3, "m_stgRSTFactors", F0, AT_);
314 m_stgRSTFactors[0] = 1.0;
315 m_stgRSTFactors[1] = 0.4;
316 m_stgRSTFactors[2] = 0.5;
317
332 if(Context::propertyExists("stgRSTFactors", m_solverId)) mTerm(1, AT_, "stgRSTFactors" + errorMsg.str());
333 prop_name = "bc" + std::to_string(m_bcId) + "stgRSTFactors";
334 if(Context::propertyExists(prop_name, m_solverId)) {
335 for(MInt i = 0; i < 3; i++) {
336 m_stgRSTFactors[i] = Context::getSolverProperty<MFloat>(prop_name, m_solverId, AT_, &m_stgRSTFactors[i], i);
337 }
338 }
339
351 if(Context::propertyExists("stgMaxNoEddies", m_solverId)) mTerm(1, AT_, "stgMaxNoEddies" + errorMsg.str());
352 prop_name = "bc" + std::to_string(m_bcId) + "stgMaxNoEddies";
353 m_stgMaxNoEddies = 200;
354 m_stgMaxNoEddies = Context::getSolverProperty<MInt>(prop_name, m_solverId, AT_, &m_stgMaxNoEddies);
355
367 if(Context::propertyExists("stgExple", m_solverId)) mTerm(1, AT_, "stgExple" + errorMsg.str());
368 prop_name = "bc" + std::to_string(m_bcId) + "stgExple";
369 m_stgExple = 0.5;
370 m_stgExple = Context::getSolverProperty<MFloat>(prop_name, m_solverId, AT_, &m_stgExple);
371
384 if(Context::propertyExists("stgEddieDistribution", m_solverId))
385 mTerm(1, AT_, "stgEddieDistribution" + errorMsg.str());
386 prop_name = "bc" + std::to_string(m_bcId) + "stgEddieDistribution";
387 m_stgEddieDistribution = 1.0;
388 if(Context::propertyExists(prop_name, m_solverId)) {
389 m_stgEddieDistribution = Context::getSolverProperty<MFloat>(prop_name, m_solverId, AT_, &m_stgEddieDistribution);
390 }
391
404 if(Context::propertyExists("stgCreateNewEddies", m_solverId)) mTerm(1, AT_, "stgCreateNewEddies" + errorMsg.str());
405 prop_name = "bc" + std::to_string(m_bcId) + "stgCreateNewEddies";
406 m_stgCreateNewEddies = false;
407 if(Context::propertyExists(prop_name, m_solverId)) {
408 m_stgCreateNewEddies = Context::getSolverProperty<MBool>(prop_name, m_solverId, AT_, &m_stgCreateNewEddies);
409 }
410
422 if(Context::propertyExists("stgInitialStartup", m_solverId)) mTerm(1, AT_, "stgInitialStartup" + errorMsg.str());
423 prop_name = "bc" + std::to_string(m_bcId) + "stgInitialStartup";
424 m_stgInitialStartup = false;
425 m_stgInitialStartup = Context::getSolverProperty<MBool>(prop_name, m_solverId, AT_, &m_stgInitialStartup);
426
438 if(Context::propertyExists("stgEddieLengthScales", m_solverId))
439 mTerm(1, AT_, "stgEddieLengthScales" + errorMsg.str());
440 prop_name = "bc" + std::to_string(m_bcId) + "stgEddieLengthScales";
441 m_stgEddieLengthScales = false;
442 if(Context::propertyExists(prop_name, m_solverId)) {
443 m_stgEddieLengthScales = Context::getSolverProperty<MBool>(prop_name, m_solverId, AT_, &m_stgEddieLengthScales);
444 }
445
457 if(Context::propertyExists("stgShapeFunction", m_solverId)) mTerm(1, AT_, "stgShapeFunction" + errorMsg.str());
458 prop_name = "bc" + std::to_string(m_bcId) + "stgShapeFunction";
459 m_stgShapeFunction = 4;
460 if(Context::propertyExists(prop_name, m_solverId)) {
461 m_stgShapeFunction = Context::getSolverProperty<MInt>(prop_name, m_solverId, AT_, &m_stgShapeFunction);
462 }
463
464 // TODO
465 /* if(m_stgInitialStartup) {
466 //activate the nut FQ field
467 FQ->neededFQVariables[FQ->NU_T] = 1;
468 }*/
469
470 m_stgNoEddieProperties = 6;
471 if(m_stgEddieLengthScales) {
472 m_stgNoEddieProperties = 9;
473 }
474 mAlloc(m_stgEddies, m_stgMaxNoEddies, m_stgNoEddieProperties, "m_solver->m_stgEddies", -F1, AT_);
475
476 // JANNIK:new method
477 mAlloc(m_stgEddyStrength, m_stgMaxNoEddies, "m_solver->m_stgEddyStrength", F1, AT_);
478
479 m_log << "===========================================================" << std::endl
480 << " STG PROPERTIES " << std::endl
481 << "===========================================================" << std::endl
482 << "Initial Start: " << m_stgInitialStartup << std::endl
483 << "SubSup (Mixed subsonic/supersonic bc): " << m_stgSubSup << std::endl
484 << "Supersonic BC: " << m_stgSupersonic << std::endl
485 << "BLT 1,2,3: " << m_stgBLT1 << ", " << m_stgBLT2 << ", " << m_stgBLT3 << std::endl
486 << "Length factors: " << m_stgLengthFactors[0] << ", " << m_stgLengthFactors[1] << ", " << m_stgLengthFactors[2]
487 << std::endl
488 << "Number of eddies: " << m_stgMaxNoEddies << std::endl
489 << "Length scale exponent: " << m_stgExple << std::endl
490 << "Eddie distribution: " << m_stgEddieDistribution << std::endl
491 << "Create new eddies: " << m_stgCreateNewEddies << std::endl
492 << "Eddie lengthscales: " << m_stgEddieLengthScales << std::endl
493 << "Shape function: " << m_stgShapeFunction << std::endl
494 << "Number of eddie properties: " << m_stgNoEddieProperties << std::endl
495 << "Number of stg variables: " << STG::noStgVars << std::endl
496 << "===========================================================" << std::endl;
497}
498
499
504template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
506 TRACE();
507
508 MPI_Comm_rank(m_commStg, &m_stgMyRank);
509 m_commStgRoot = commStgRoot;
510
511 mAlloc(m_stgMaxVel, m_nDim, "m_stgMaxVel", 0.0, AT_);
512 mAlloc(m_stgVbStart, m_nDim, "m_stgVbStart", 0.0, AT_);
513 mAlloc(m_stgVbEnd, m_nDim, "m_stgVbEnd", 0.0, AT_);
514
515#ifndef NDEBUG
516 if(m_stgMyRank == m_commStgRoot) {
517 std::cout << globalTimeStep << " Initializing BC " + std::to_string(m_bcId) << std::endl;
518 }
519#endif
520
521 readRANSProfileStg();
522
523 if(m_solver->m_resetInitialCondition) {
524 m_stgDelta99Inflow = 0.0;
525 m_initialRange = true;
526 } else {
527 getBoundaryLayerThickness();
528 }
529
530 // Compute size of the Box, take inflow as middle x-coordinate
531 mAlloc(m_inflowStart, m_nDim, "m_inflowStart", AT_);
532 mAlloc(m_inflowEnd, m_nDim, "m_inflowEnd", AT_);
533 getInflowStartEnd(m_inflowStart, m_inflowEnd);
534 setVb(m_inflowStart, m_inflowEnd);
535
536 if(m_newStgMethod) {
537 // determinePeriodicCells();
538 }
539
540 // TODO: check if this is the right place
541 if((globalTimeStep == m_solver->m_restartTimeStep && globalTimeStep > m_solver->m_stgStartTimeStep
542 && !m_stgCreateNewEddies)
543 || (m_solver->m_wasAdapted) || (m_solver->m_wasBalancedZonal)) {
544 loadStg();
545 } else {
546 // // create new eddies if it's an initial start or the createNewEddie flag is set
547 MFloatScratchSpace bcast_eddies(m_stgMaxNoEddies * 6, AT_, "bcast_eddies");
548 MFloatScratchSpace bcast_eddyStrength(m_stgMaxNoEddies, AT_, "bcast_eddyStrength");
549
550 if(m_stgMyRank == m_commStgRoot) {
551#ifndef NDEBUG
552 std::cerr << "-------Creating new Eddies inside Virtual Box------" << std::endl;
553#endif
554 MFloat xk[m_nDim];
555 MFloat epsi[m_nDim];
556 for(MInt n = 0; n < m_stgMaxNoEddies; n++) {
557 generateNewEddies(xk, epsi);
558
559 bcast_eddies[n + m_stgMaxNoEddies * 0] = xk[0];
560 bcast_eddies[n + m_stgMaxNoEddies * 1] = xk[1];
561 bcast_eddies[n + m_stgMaxNoEddies * 2] = xk[2];
562 bcast_eddies[n + m_stgMaxNoEddies * 3] = epsi[0];
563 bcast_eddies[n + m_stgMaxNoEddies * 4] = epsi[1];
564 bcast_eddies[n + m_stgMaxNoEddies * 5] = epsi[2];
565
566 bcast_eddyStrength[n] = F1;
567 if(m_newStgMethod) {
568 bcast_eddyStrength[n] = generate_rand_normalDist();
569 }
570 }
571 }
572
573 // Broadcast the new/updated eddies to all relevant processes
574 MPI_Bcast(bcast_eddies.begin(), 6 * m_stgMaxNoEddies, MPI_DOUBLE, m_commStgRoot, m_commStg, AT_,
575 "bcast_eddies.begin()");
576 MPI_Bcast(bcast_eddyStrength.begin(), m_stgMaxNoEddies, MPI_DOUBLE, m_commStgRoot, m_commStg, AT_,
577 "bcast_eddyStrength.begin()");
578 // Copy data into m_FQeddie vector
579 for(MInt n = 0; n < m_stgMaxNoEddies; n++) {
580 m_stgEddies[n][0] = bcast_eddies[n + m_stgMaxNoEddies * 0];
581 m_stgEddies[n][1] = bcast_eddies[n + m_stgMaxNoEddies * 1];
582 m_stgEddies[n][2] = bcast_eddies[n + m_stgMaxNoEddies * 2];
583 m_stgEddies[n][3] = bcast_eddies[n + m_stgMaxNoEddies * 3];
584 m_stgEddies[n][4] = bcast_eddies[n + m_stgMaxNoEddies * 4];
585 m_stgEddies[n][5] = bcast_eddies[n + m_stgMaxNoEddies * 5];
586
587 m_stgEddyStrength[n] = bcast_eddyStrength[n];
588 }
589 }
590}
591
592
593template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
595 TRACE();
596
597 MInt noStgBcCells = 0;
598 MInt noBcStgLocations = 0;
599 MFloat periodicL = 0;
600 MBool first = true;
601 m_stgWallNormalLocations.clear();
602
603 // ======================================================
604 // 1) Determine local locations in wall-normal direction for spanwise average
605 // ======================================================
606 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
607 const MInt cellId = a->getCellId(it);
608
609 MFloat halfCellLength = m_solver->grid().halfCellLength(cellId);
610 if(first) {
611 periodicL = m_solver->a_coordinate(cellId, m_periodicDir) - F1B3 * halfCellLength;
612 first = false;
613 }
614 if(abs(m_solver->a_coordinate(cellId, m_periodicDir) + halfCellLength - eps - periodicL) < halfCellLength) {
615 m_stgWallNormalLocations.push_back(m_solver->a_coordinate(cellId, m_wallDir));
616 noBcStgLocations++;
617 }
618 noStgBcCells++;
619 }
621 // ======================================================
622 // 2) Create communicator
623 // ======================================================
624 MInt comm_size;
625 MPI_Comm_size(m_commStg, &comm_size);
626
627 // ======================================================
628 // 3) Determine global locations in wall-normal direction for spanwise average
629 // ======================================================
630 MInt globalNoBcStgLocations = 0;
631 MPI_Allreduce(&noBcStgLocations, &globalNoBcStgLocations, 1, MPI_INT, MPI_SUM, m_commStg, AT_, "noBcStgLocations",
632 "globalNoBcStgLocations");
633
634 ScratchSpace<MFloat> globalBcStgLocations(globalNoBcStgLocations, "globalBcStgLocations", FUN_);
635 ScratchSpace<MInt> recvbuf(comm_size, "recvbuf", FUN_);
636 ScratchSpace<MInt> displs(comm_size, "displspos", FUN_);
637
638 recvbuf.fill(0);
639
640 MPI_Gather(&noBcStgLocations, 1, MPI_INT, &recvbuf[0], 1, MPI_INT, 0, m_commStg, AT_, "noBcStgLocations", "recvbuf");
642 if(m_stgMyRank == m_commStgRoot) {
643 MInt offset = 0;
644 for(MInt dom = 0; dom < comm_size; dom++) {
645 displs[dom] = offset;
646 offset += recvbuf[dom];
649
650 MPI_Gatherv(&m_stgWallNormalLocations[0], noBcStgLocations, MPI_DOUBLE, &globalBcStgLocations[0],
651 &recvbuf[m_stgMyRank], &displs[m_stgMyRank], MPI_DOUBLE, 0, m_commStg, AT_, "m_StgwallNormalLocations",
652 "globalBcStgLocations");
653
654 MPI_Bcast(&globalBcStgLocations[0], globalNoBcStgLocations, MPI_DOUBLE, 0, m_commStg, AT_, "globalBcStgLocations");
656 m_stgGlobalWallNormalLocations.clear();
657
658 for(MInt i = 0; i < globalNoBcStgLocations; i++) {
659 MFloat L = globalBcStgLocations[i];
660 if(std::find(m_stgGlobalWallNormalLocations.begin(), m_stgGlobalWallNormalLocations.end(), L)
661 == m_stgGlobalWallNormalLocations.end()) {
662 m_stgGlobalWallNormalLocations.push_back(L);
663 }
664 }
666
667 m_stgGlobalNoWallNormalLocations = (MInt)m_stgGlobalWallNormalLocations.size();
668
669 std::sort(m_stgGlobalWallNormalLocations.begin(), m_stgGlobalWallNormalLocations.end());
670
671 // ======================================================
672 // 4) Determine local cells in periodic locations of global wall-normal locations
673 // ======================================================
674 mAlloc(m_stgPeriodicCellId, m_stgGlobalNoWallNormalLocations, "m_stgPeriodicCellIndex", FUN_);
675 mAlloc(m_stgGlobalNoPeriodicLocations, m_stgGlobalNoWallNormalLocations, "m_stgGlobalNoPeriodicLocations", 0, FUN_);
676
677 for(MInt i = 0; i < m_stgGlobalNoWallNormalLocations; i++) {
678 m_stgPeriodicCellId[i].clear();
679 }
680
681 mAlloc(m_stgPeriodicIndex, noStgBcCells, "m_stgPeriodicIndex", -1, FUN_);
682
683 vector<MInt> noPeriodicLocations(m_stgGlobalNoWallNormalLocations, F0);
684
685 for(MInt i = 0; i < m_stgGlobalNoWallNormalLocations; i++) {
686 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
687 const MInt cellId = a->getCellId(it);
688 const MInt IBC = a->getStgId(it);
689 if(abs(m_solver->a_coordinate(cellId, m_wallDir) - m_stgGlobalWallNormalLocations[i]) < eps) {
690 m_stgPeriodicIndex[IBC] = i;
691 if(!m_solver->a_isHalo(cellId)) {
692 m_stgPeriodicCellId[i].push_back(IBC);
693 ++noPeriodicLocations[i];
694 }
695 }
696 }
697 }
698
699 MPI_Allreduce(&noPeriodicLocations[0], &m_stgGlobalNoPeriodicLocations[0], m_stgGlobalNoWallNormalLocations, MPI_INT,
700 MPI_SUM, m_commStg, AT_, "noPeriodicLocations", "m_stgGlobalNoPeriodicLocations");
701}
702
703template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
705 TRACE();
706
707 using namespace maia::parallel_io;
708 std::stringstream filename;
709 filename << m_solver->outputDir() << "stg" << std::to_string(m_bcId) << "RestartNew_" << globalTimeStep
710 << ParallelIo::fileExt();
711
712 m_log << "Writing restart file " << filename.str() << " ..." << std::endl;
713#ifndef NDEBUG
714 if(m_stgMyRank == m_commStgRoot) {
715 cerr << "Writing restart file " << filename.str() << " ..." << std::endl;
716 }
717#endif
718
719 std::stringstream stgPrefix_;
720 stgPrefix_ << "stgVar" << m_bcId << "_";
721 MString stgPrefix = stgPrefix_.str();
722
723 ParallelIo parallelIo((filename.str()).c_str(), PIO_REPLACE, m_commStg);
724 parallelIo.setAttributes(&(m_stgMaxNoEddies), (stgPrefix + "stgMaxNoEddies").c_str(), 1);
725
726 parallelIo.defineArray(PIO_FLOAT, (stgPrefix + "FQeddies").c_str(), m_stgMaxNoEddies * m_stgNoEddieProperties);
727
728 parallelIo.defineArray(PIO_FLOAT, (stgPrefix + "FQeddyStrength").c_str(), m_stgMaxNoEddies);
729
730 parallelIo.setAttribute("FQeddies", "name", (stgPrefix + "FQeddies").c_str());
731 parallelIo.setOffset(m_stgMaxNoEddies * m_stgNoEddieProperties, 0);
732 parallelIo.writeArray(&(m_stgEddies[0][0]), (stgPrefix + "FQeddies").c_str());
733
734 parallelIo.setAttribute("FQeddyStrength", "name", (stgPrefix + "FQeddyStrength").c_str());
735 parallelIo.setOffset(m_stgMaxNoEddies, 0);
736 parallelIo.writeArray(&(m_stgEddyStrength[0]), (stgPrefix + "FQeddyStrength").c_str());
737}
738
739template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
741 TRACE();
742
743 using namespace maia::parallel_io;
744 std::stringstream filename;
745 filename << m_solver->restartDir() << "stg" << std::to_string(m_bcId) << "RestartNew_" << globalTimeStep
746 << ParallelIo::fileExt();
747
748 m_log << "Loading restart file " << filename.str() << " ..." << std::endl;
749#ifndef NDEBUG
750 if(m_stgMyRank == m_commStgRoot) {
751 cerr << "Loading restart file " << filename.str() << " ..." << std::endl;
752 }
753#endif
754
755 std::stringstream stgPrefix_;
756 stgPrefix_ << "stgVar" << m_bcId << "_";
757 MString stgPrefix = stgPrefix_.str();
758
759 // All stg ranks read m_stgMaxNoEddies & m_stgEddies
760 {
761 ParallelIo parallelIo((filename.str()).c_str(), PIO_READ, m_commStg);
762 MInt stgMaxNoEddies;
763 parallelIo.getAttribute(&stgMaxNoEddies, (stgPrefix + "stgMaxNoEddies").c_str());
764 if(stgMaxNoEddies != m_stgMaxNoEddies && !m_stgCreateNewEddies)
765 TERMM(-1, "bc" + std::to_string(m_bcId) + ": Number of eddies has changed!");
766 ParallelIo::size_type stgEddies_ = parallelIo.getArraySize((stgPrefix + "FQeddies").c_str());
767 if(stgEddies_ != stgMaxNoEddies * m_stgNoEddieProperties) TERMM(-1, "");
768 ParallelIo::size_type stgEddyStrength_ = parallelIo.getArraySize((stgPrefix + "FQeddyStrength").c_str());
769 if(stgEddyStrength_ != stgMaxNoEddies) TERMM(-1, "");
770
771 parallelIo.setOffset(stgEddies_, 0);
772 parallelIo.readArray(&(m_stgEddies[0][0]), (stgPrefix + "FQeddies").c_str()); // TODO: check this
773
774 parallelIo.setOffset(stgEddyStrength_, 0);
775 parallelIo.readArray(&(m_stgEddyStrength[0]), (stgPrefix + "FQeddyStrength").c_str()); // TODO: check this
776 }
777}
778
787template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
789 if((globalTimeStep != m_solver->m_restartTimeStep) && !m_solver->m_wasAdapted
790 && globalTimeStep % m_solver->m_restartInterval == 0 && m_solver->m_RKStep == 0) {
791 saveStg();
792 }
793
794 if(m_solver->m_RKStep == 0) {
795 if(m_zonal
796 && (globalTimeStep % m_solver->m_zonalTransferInterval == 0 || globalTimeStep == m_solver->m_restartTimeStep
797 || m_solver->m_wasAdapted)) {
798 readRANSProfileStg();
799
800 getBoundaryLayerThickness();
801 getInflowStartEnd(m_inflowStart, m_inflowEnd);
802 setVb(m_inflowStart, m_inflowEnd);
803
804 calcStrainRate();
805 calcReynoldsStressConvVelLengthScale();
806 }
807
808 if(!m_zonal && (globalTimeStep == m_solver->m_restartTimeStep || globalTimeStep <= 1)) {
809 calcStrainRate();
810 calcReynoldsStressConvVelLengthScale();
811 }
812
813 /*********************** J *****************/
814 // The virtual box part - executed by Master Solver at the inflow
815 /*********************** J *****************/
816
817 if(!m_solver->m_wasAdapted) {
818 advanceEddies();
819 }
820
821#ifndef NDEBUG
822 // Summary of synth turb parameters
823 // printSTGSummary();
824#endif
825 /*********************** L *****************/
826 // Calculation of the fluctuation induced by all eddies on each cell
827 /*********************** L *****************/
828 calcTotalFluctuationCholesky();
829
830 if(m_newStgMethod) {
831 // calcEddieCoverage();
832 }
833
834 } // RKStep end if
835
839 // Now comes the BC stuff that we need to do every RK step
840 apply();
841}
842
843
844template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
845template <class _, std::enable_if_t<SolverTypeL == MAIA_FINITE_VOLUME, _*>>
847 TRACE();
848
849 std::stringstream errorMsg;
850 std::string prop_name;
851 errorMsg << ": This property is not allowed to exist without an assignment to a BC" << std::endl;
852
853 m_stgDelta99Inflow = -1.0;
854
855 MInt factor = (m_stgWallNormalDir % 2 == 0) ? -1 : 1;
856
857 if(!m_zonal) {
858 prop_name = "bc" + std::to_string(m_bcId) + "deltaIn";
859 if(!Context::propertyExists(prop_name, m_solverId)) {
860 mTerm(1, AT_, "deltaIn" + errorMsg.str());
861 }
862 m_stgDelta99Inflow = Context::getSolverProperty<MFloat>(prop_name, m_solverId, AT_, &m_stgDelta99Inflow);
863 } else {
864 MFloat maxVel = F0;
865 MFloat maxVelPos = std::numeric_limits<MFloat>::max();
866 MFloat minPos = std::numeric_limits<MFloat>::max();
867 MFloat maxPos = std::numeric_limits<MFloat>::lowest();
868 MFloat halfCellLength = F0;
869 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
870 const MInt IBC = a->getStgId(it);
871 const MInt cellId = a->getCellId(it);
872 MFloat y = LES->a_coordinate(cellId, m_wallDir);
873 MFloat z = LES->a_coordinate(cellId, m_periodicDir);
874 MFloat r = sqrt(y * y + z * z);
875 if(m_stgLVariables[m_stgDir][IBC] >= maxVel) {
876 maxVel = m_stgLVariables[m_stgDir][IBC];
877 if(m_cylinderTransformation) {
878 maxVelPos = r;
879 } else {
880 maxVelPos = m_solver->a_coordinate(cellId, m_wallDir);
881 }
882 }
883 if(m_cylinderTransformation) {
884 if(r < minPos) {
885 minPos = r;
886 }
887 if(r > maxPos) {
888 maxPos = r;
889 }
890 } else {
891 if(m_solver->a_coordinate(cellId, m_wallDir) < minPos) {
892 minPos = m_solver->a_coordinate(cellId, m_wallDir);
893 halfCellLength = m_solver->grid().halfCellLength(cellId);
894 }
895 if(m_solver->a_coordinate(cellId, m_wallDir) > maxPos) {
896 maxPos = m_solver->a_coordinate(cellId, m_wallDir);
897 }
898 }
899 }
900
901 MPI_Allreduce(MPI_IN_PLACE, &maxVel, 1, MPI_DOUBLE, MPI_MAX, m_commStg, AT_, "maxVel", "1");
902 MPI_Allreduce(MPI_IN_PLACE, &maxVelPos, 1, MPI_DOUBLE, MPI_MIN, m_commStg, AT_, "maxVelPos", "1");
903 MPI_Allreduce(MPI_IN_PLACE, &minPos, 1, MPI_DOUBLE, MPI_MIN, m_commStg, AT_, "minPos", "1");
904 MPI_Allreduce(MPI_IN_PLACE, &maxPos, 1, MPI_DOUBLE, MPI_MAX, m_commStg, AT_, "maxPos", "1");
905
906 if(maxVel < 0.9 * m_solver->m_UInfinity) {
907 m_initialRange = true;
908 m_stgDelta99Inflow = 2 * halfCellLength;
909 }
910
911 if(!m_initialRange) {
912 MFloat delta0 = std::numeric_limits<MFloat>::max();
913 MFloat delta0_1 = minPos;
914 MFloat delta0_2 = maxPos;
915 MFloat delta0_u1 = std::numeric_limits<MFloat>::max();
916 MFloat delta0_u2 = std::numeric_limits<MFloat>::lowest();
917 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
918 const MInt cellId = a->getCellId(it);
919 const MInt IBC = a->getStgId(it);
920 MFloat pos = m_solver->a_coordinate(cellId, m_wallDir);
921 if(m_cylinderTransformation) {
922 MFloat y = LES->a_coordinate(cellId, m_wallDir);
923 MFloat z = LES->a_coordinate(cellId, m_periodicDir);
924 pos = sqrt(y * y + z * z);
925 }
926
927 if(m_solver->a_isHalo(cellId)) continue;
928
929 if(factor * m_stgLVariables[m_stgDir][IBC] > factor * 0.99 * maxVel && pos < delta0_2 && pos < maxVelPos) {
930 delta0_2 = pos;
931 delta0_u2 = m_stgLVariables[m_stgDir][IBC];
932 }
933
934 if(factor * m_stgLVariables[m_stgDir][IBC] < factor * 0.99 * maxVel && pos > delta0_1 && pos < maxVelPos) {
935 delta0_1 = pos;
936 delta0_u1 = m_stgLVariables[m_stgDir][IBC];
937 }
938 }
939
940 MFloat deltaOffset = (factor == 1) ? minPos : maxPos;
941 delta0 =
942 factor
943 * (delta0_1 + (delta0_2 - delta0_1) / (delta0_u2 - delta0_u1) * (0.99 * maxVel - delta0_u1) - deltaOffset);
944
945 if(delta0 < 1e-16) delta0 = std::numeric_limits<MFloat>::max();
946
947 MPI_Allreduce(&delta0, &m_stgDelta99Inflow, 1, MPI_DOUBLE, MPI_MIN, m_commStg, AT_, "m_stgDelta99Inflow",
948 "delta0");
949 }
950 }
951
952#ifndef NDEBUG
953 if(m_stgMyRank == m_commStgRoot) {
954 std::cerr << "---------- Boundary layer thickness (" << globalTimeStep << "," << m_bcId << "): ----------"
955 << std::endl;
956 std::cerr << m_stgDelta99Inflow << std::endl;
957 }
958#endif
959}
960
961
962template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
963template <class _, std::enable_if_t<SolverTypeL == MAIA_STRUCTURED, _*>>
964void MSTG<nDim, SolverTypeR, SolverTypeL>::getBoundaryLayerThickness(/*SolverTraits<nDim, MAIA_STRUCTURED>**/) {
965 MInt bndryLayerIndex = 0;
966 MFloat u99_0 = F0, u99_1 = F0;
967 MInt start_[] = {0, a->start(1) + a->m_noGhostLayers, 2};
968 MInt end_[] = {1, a->end(1) - a->m_noGhostLayers, 3};
969 for(typename Accessor::nDim_citerator it = a->nDim_citerator_begin(start_, end_); it != a->nDim_citerator_end();
970 ++it) {
971 const MInt IBC = a->getStgId(it);
972 const MInt IJMK = a->getNghbrStg(it, 2);
973 if(m_stgLVariables[PV->U][IBC] >= 0.99 * LES->UInfinity()
974 && m_stgLVariables[PV->U][IJMK] < 0.99 * LES->UInfinity()) {
975 u99_0 = m_stgLVariables[PV->U][IJMK];
976 u99_1 = m_stgLVariables[PV->U][IBC];
977 bndryLayerIndex = it->getijk(1) - 1;
978 break;
979 }
980 }
981 MFloat bndryLayerThicknessLocal = 0.0;
982 MFloat bndryLayerThicknessGlobal = 0.0;
983
984 if(bndryLayerIndex > 0) {
985 bndryLayerThicknessLocal = LES->a_coordinate(a->cellIndex(0, bndryLayerIndex, 2), 1)
986 + (0.99 * LES->UInfinity() - u99_0) / (u99_1 - u99_0)
987 * (LES->a_coordinate(a->cellIndex(0, bndryLayerIndex + 1, 2), 1)
988 - LES->a_coordinate(a->cellIndex(0, bndryLayerIndex, 2), 1));
989 }
990 MPI_Allreduce(&bndryLayerThicknessLocal, &bndryLayerThicknessGlobal, 1, MPI_DOUBLE, MPI_MAX, m_commStg, AT_,
991 "bndryLayerThicknessLocal", "bndryLayerThicknessGlobal");
992 if(m_stgMyRank == m_commStgRoot) {
993 std::cout << "Boundary Layer thickness delta99: " << bndryLayerThicknessGlobal << std::endl;
994 }
995}
996
997
998template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
999template <class _, std::enable_if_t<SolverTypeL == MAIA_FINITE_VOLUME, _*>>
1001 TRACE();
1002
1003 MFloat inflowStartLocal[] = {std::numeric_limits<MFloat>::max(), std::numeric_limits<MFloat>::max(),
1004 std::numeric_limits<MFloat>::max()};
1005 MFloat inflowEndlocal[] = {-std::numeric_limits<MFloat>::max(), -std::numeric_limits<MFloat>::max(),
1006 -std::numeric_limits<MFloat>::max()};
1007 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
1008 MInt cellId = a->getCellId(it);
1009 if(m_solver->a_isHalo(cellId)) continue;
1010
1011 if(m_cylinderTransformation) {
1012 MFloat y = LES->a_coordinate(cellId, m_wallDir);
1013 MFloat z = LES->a_coordinate(cellId, m_periodicDir);
1014 MFloat alpha = get_angle(y, z);
1015 MFloat r = sqrt(y * y + z * z);
1016 if(inflowStartLocal[0] > LES->a_coordinate(cellId, 0)) inflowStartLocal[0] = LES->a_coordinate(cellId, 0);
1017 if(inflowEndlocal[0] < LES->a_coordinate(cellId, 0)) inflowEndlocal[0] = LES->a_coordinate(cellId, 0);
1018 if(inflowStartLocal[1] > r) inflowStartLocal[1] = r;
1019 if(inflowEndlocal[1] < r) inflowEndlocal[1] = r;
1020 if(inflowStartLocal[2] > alpha) inflowStartLocal[2] = alpha;
1021 if(inflowEndlocal[2] < alpha) inflowEndlocal[2] = alpha;
1022
1023 } else {
1024 for(MInt d = 0; d < nDim; ++d) {
1025 if(inflowStartLocal[d] > LES->a_coordinate(cellId, d)) inflowStartLocal[d] = LES->a_coordinate(cellId, d);
1026 if(inflowEndlocal[d] < LES->a_coordinate(cellId, d)) inflowEndlocal[d] = LES->a_coordinate(cellId, d);
1027 }
1028 }
1029 }
1030
1031 std::fill(inflowStart, inflowStart + nDim, 9999999);
1032 std::fill(inflowEnd, inflowEnd + nDim, -9999999);
1033 MPI_Allreduce(inflowStartLocal, inflowStart, nDim, MPI_DOUBLE, MPI_MIN, m_commStg, AT_, "inflowStartLocal",
1034 "inflowStart");
1035 MPI_Allreduce(inflowEndlocal, inflowEnd, nDim, MPI_DOUBLE, MPI_MAX, m_commStg, AT_, "inflowEndlocal", "inflowEnd");
1036
1037 if(m_stgWallNormalDir % 2 == 0) {
1038 MFloat temp = inflowStart[m_wallDir];
1039 inflowStart[m_wallDir] = inflowEnd[m_wallDir];
1040 inflowEnd[m_wallDir] = temp;
1041 }
1042
1043#ifndef NDEBUG
1044 if(m_stgMyRank == m_commStgRoot) {
1045 std::cerr << "inflowStartEnd(" << m_bcId << "): " << inflowStart[0] << " " << inflowStart[1] << " "
1046 << inflowStart[2] << " " << inflowEnd[0] << " " << inflowEnd[1] << " " << inflowEnd[2] << std::endl;
1047 }
1048#endif
1049}
1050
1051
1052template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1053template <class _, std::enable_if_t<SolverTypeL == MAIA_STRUCTURED, _*>>
1055 MInt minIndex = getPointIdFromCell(a->m_noGhostLayers, a->m_noGhostLayers, a->m_noGhostLayers);
1056 MInt maxIndex =
1057 getPointIdFromCell(a->m_noGhostLayers, a->m_noGhostLayers, a->m_noGhostLayers + m_solver->m_nActiveCells[0]);
1058 MFloat inflowStartLocal[3] = {LES->a_coordinates(minIndex, 0), LES->a_coordinates(minIndex, 1),
1059 LES->a_coordinates(minIndex, 2)};
1060 MFloat inflowEndlocal[3] = {LES->a_coordinates(maxIndex, 0), LES->a_coordinates(maxIndex, 1),
1061 LES->a_coordinates(maxIndex, 2)};
1062 std::fill(inflowStart, inflowStart + nDim, 99999.9);
1063 std::fill(inflowEnd, inflowEnd + nDim, F0);
1064 MPI_Allreduce(inflowStartLocal, inflowStart, nDim, MPI_DOUBLE, MPI_MIN, m_commStg, AT_, "inflowStartLocal",
1065 "inflowStart");
1066 MPI_Allreduce(inflowEndlocal, inflowEnd, nDim, MPI_DOUBLE, MPI_MAX, m_commStg, AT_, "inflowEndlocal", "inflowEnd");
1067}
1068
1069
1070template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1072 MFloatScratchSpace bcast_vb(6, AT_, "bcast_vb");
1073
1074
1075 const MFloat vbDepth = (inflowEnd[m_periodicDir] - inflowStart[m_periodicDir]) * m_stgBLT3;
1076 const MFloat offset = F1B2 * (inflowEnd[m_periodicDir] - inflowStart[m_periodicDir]) * (m_stgBLT3 - F1);
1077
1078 if(m_stgMyRank == m_commStgRoot) {
1079 m_stgRootRank = true;
1080
1081 // Get the coordinate of the inflow
1082 // Points in stgDir
1083 MInt factor = (m_stgFaceNormalDir % 2 == 0) ? 1 : -1;
1084 bcast_vb[m_stgDir] = inflowStart[m_stgDir] - factor * m_stgBLT1 * m_stgDelta99Inflow * F1B2;
1085 bcast_vb[m_stgDir + 3] = inflowStart[m_stgDir] + factor * m_stgBLT1 * m_stgDelta99Inflow * F1B2;
1086
1087 // Points in wallDir
1088 factor = (m_stgWallNormalDir % 2 != 0) ? 1 : -1;
1089 bcast_vb[m_wallDir] = inflowStart[m_wallDir];
1090 bcast_vb[m_wallDir + 3] = inflowStart[m_wallDir] + factor * m_stgBLT2 * m_stgDelta99Inflow;
1091
1092 if(m_freeStreamTurbulence) {
1093 m_stgWallEnd = inflowStart[m_wallDir] + factor * m_stgBLT2 * m_stgDelta99Inflow;
1094 bcast_vb[m_wallDir + 3] = inflowEnd[m_wallDir];
1095 }
1096
1097 if(m_isotropicTurbulence) {
1098 m_stgWallEnd = inflowStart[m_wallDir];
1099 bcast_vb[m_wallDir + 3] = inflowEnd[m_wallDir];
1100 }
1101
1102 // Points in periodicDir
1103 bcast_vb[m_periodicDir] = inflowStart[m_periodicDir] - offset;
1104 bcast_vb[m_periodicDir + 3] = inflowStart[m_periodicDir] - offset + vbDepth;
1105 }
1106
1107 MPI_Bcast(bcast_vb.begin(), 6, MPI_DOUBLE, m_commStgRoot, m_commStg, AT_, "bcast_vb.begin()");
1108
1109 if(m_freeStreamTurbulence) {
1110 MPI_Bcast(&m_stgWallEnd, 1, MPI_DOUBLE, m_commStgRoot, m_commStg, AT_, "m_stgWallEnd");
1111 }
1112
1113 m_stgVbStart[0] = bcast_vb[0];
1114 m_stgVbStart[1] = bcast_vb[1];
1115 m_stgVbStart[2] = bcast_vb[2];
1116 m_stgVbEnd[0] = bcast_vb[3];
1117 m_stgVbEnd[1] = bcast_vb[4];
1118 m_stgVbEnd[2] = bcast_vb[5];
1119
1120#ifndef NDEBUG
1121 if(m_stgMyRank == m_commStgRoot) {
1122 std::cout << "setVbStart(" << m_bcId << "): " << m_stgVbStart[0] << " " << m_stgVbStart[1] << " " << m_stgVbStart[2]
1123 << std::endl;
1124 std::cout << "setVbEnd(" << m_bcId << "): " << m_stgVbEnd[0] << " " << m_stgVbEnd[1] << " " << m_stgVbEnd[2]
1125 << std::endl;
1126 if(m_freeStreamTurbulence) {
1127 std::cout << "setVbEndFS(" << m_bcId << "): " << m_stgWallEnd << endl;
1128 }
1129 }
1130#endif
1131}
1132
1133
1137template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1138template <class _, std::enable_if_t<SolverTypeR == MAIA_FINITE_VOLUME, _*>,
1139 std::enable_if_t<SolverTypeL == MAIA_FINITE_VOLUME, _*>>
1141 TRACE();
1142
1143 if(m_zonal && !m_preliminary) {
1144 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
1145 const MInt IBC = a->getStgId(it);
1146 const MInt cellId = a->m_stgToCellId[IBC];
1147
1148 // Debugging
1149 for(MInt varId = 0; varId < (MInt)m_solver->m_noRANSVariables; varId++) {
1150 ASSERT(cellId < (MInt)m_solver->m_RANSValues[varId].size(),
1151 "Trying to access data [" + std::to_string(cellId) + "] in RANSValues with length "
1152 + std::to_string(m_solver->m_RANSValues[varId].size())
1153 + ", domainId: " + std::to_string(m_solver->domainId()));
1154 }
1155
1156 m_stgLVariables[STG::AVG_RHO][IBC] = m_solver->m_RANSValues[PV->RHO][cellId];
1157 m_stgLVariables[STG::AVG_U][IBC] = m_solver->m_RANSValues[PV->U][cellId];
1158 m_stgLVariables[STG::AVG_V][IBC] = m_solver->m_RANSValues[PV->V][cellId];
1159 m_stgLVariables[STG::AVG_W][IBC] = m_solver->m_RANSValues[PV->W][cellId];
1160 m_stgLVariables[STG::AVG_P][IBC] = m_solver->m_RANSValues[PV->P][cellId];
1161 // JANNIK: generalize this for other RANS models
1162 m_stgLVariables[STG::NU_T][IBC] = m_solver->m_RANSValues[PV->N][cellId];
1163
1164 for(MInt d = 0; d < m_nDim; d++) {
1165 m_stgLVariables[STG::AVG_UU[d]][IBC] = m_solver->m_RANSValues[PV->VV[d]][cellId];
1166 }
1167
1168 // reconstruct fluc values since not saved anymore
1169 // (for timsm function in calcTotalFluctuationCholesky)
1170 if(globalTimeStep == m_solver->m_restartTimeStep) {
1171 m_stgLVariables[STG::FLUC_U][IBC] =
1172 m_solver->a_pvariable(cellId, PV->U) - m_solver->m_RANSValues[PV->U][cellId];
1173 m_stgLVariables[STG::FLUC_V][IBC] =
1174 m_solver->a_pvariable(cellId, PV->V) - m_solver->m_RANSValues[PV->V][cellId];
1175 m_stgLVariables[STG::FLUC_W][IBC] =
1176 m_solver->a_pvariable(cellId, PV->W) - m_solver->m_RANSValues[PV->W][cellId];
1177 }
1178 }
1179 } else {
1180 // read in text-file with
1181 if(m_preliminaryRans2D) {
1182 stringstream fn;
1183 fn.clear();
1184 MString prop_name = "bc" + std::to_string(m_bcId);
1185 fn << prop_name << "preliminaryDataRans2D.txt";
1186 MString fname = fn.str();
1187 if(m_stgMyRank == m_commStgRoot) cerr << "loading STG preliminary data from " << fname << "...";
1188
1189 ifstream preliminaryData;
1190 preliminaryData.open(fname);
1191
1192 vector<MFloat> data;
1193 MFloat num;
1194 string line;
1195
1196 while(preliminaryData >> num) {
1197 data.push_back(num);
1198 }
1199
1200 // MInt count = 0;
1201 prop_name = "bc" + std::to_string(m_bcId) + "preliminaryRansDataCount";
1202 MInt preliminaryDataVarCount =
1203 Context::getSolverProperty<MInt>(prop_name, m_solverId, AT_, &preliminaryDataVarCount);
1204
1205 MInt dataCount = data.size() / preliminaryDataVarCount;
1206
1207 vector<vector<MFloat>> preData(dataCount, vector<MFloat>(preliminaryDataVarCount, 0));
1208
1209 MInt index = 0;
1210 for(MInt d = 0; d < dataCount; d++) {
1211 for(MInt dd = 0; dd < preliminaryDataVarCount; dd++) {
1212 index = preliminaryDataVarCount * d + dd;
1213 preData[d][dd] = data[index];
1214 }
1215 }
1216
1217 preliminaryData.close();
1218
1219 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
1220 const MInt IBC = a->getStgId(it);
1221 const MInt cellId = a->m_stgToCellId[IBC];
1222 MFloat pos = m_solver->a_coordinate(cellId, m_wallDir);
1223 // interpolate data
1224 for(MInt d = 0; d < dataCount - 1; d++) {
1225 if(pos >= preData[d][0] && pos < preData[d + 1][0]) {
1226 MInt var = 1;
1227 m_stgLVariables[STG::AVG_U][IBC] =
1228 preData[d][var]
1229 + (preData[d + 1][var] - preData[d][var]) * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1230 var = 2;
1231 m_stgLVariables[STG::AVG_V][IBC] =
1232 preData[d][var]
1233 + (preData[d + 1][var] - preData[d][var]) * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1234 var = 3;
1235 m_stgLVariables[STG::AVG_RHO][IBC] =
1236 preData[d][var]
1237 + (preData[d + 1][var] - preData[d][var]) * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1238 var = 4;
1239 m_stgLVariables[STG::AVG_P][IBC] =
1240 preData[d][var]
1241 + (preData[d + 1][var] - preData[d][var]) * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1242 var = 5;
1243 m_stgLVariables[STG::NU_T][IBC] =
1244 preData[d][var]
1245 + (preData[d + 1][var] - preData[d][var]) * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1246 var = 6;
1247 m_stgLVariables[STG::S11][IBC] =
1248 preData[d][var]
1249 + (preData[d + 1][var] - preData[d][var]) * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1250 var = 7;
1251 m_stgLVariables[STG::S12][IBC] =
1252 preData[d][var]
1253 + (preData[d + 1][var] - preData[d][var]) * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1254 var = 8;
1255 m_stgLVariables[STG::S22][IBC] =
1256 preData[d][var]
1257 + (preData[d + 1][var] - preData[d][var]) * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1258 var = 9;
1259 m_stgLVariables[STG::SIJSIJ][IBC] =
1260 preData[d][var]
1261 + (preData[d + 1][var] - preData[d][var]) * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1262 m_stgLVariables[STG::AVG_W][IBC] = F0;
1263 m_stgLVariables[STG::S13][IBC] = F0;
1264 m_stgLVariables[STG::S23][IBC] = F0;
1265 m_stgLVariables[STG::S33][IBC] = F0;
1266 }
1267 }
1268 }
1269 }
1270
1271 if(m_preliminary && !m_preliminaryRans2D) {
1272 stringstream fn;
1273 fn.clear();
1274 MString prop_name = "bc" + std::to_string(m_bcId);
1275 fn << prop_name << "preliminaryData.txt";
1276
1277 MString fname = fn.str();
1278
1279 if(m_stgMyRank == m_commStgRoot) cerr << "loading STG preliminary data from " << fname << "...";
1280
1281 ifstream preliminaryData;
1282 preliminaryData.open(fname);
1283
1284 vector<MFloat> data;
1285 MFloat num;
1286
1287 while(preliminaryData >> num) {
1288 data.push_back(num);
1289 }
1290
1291 // MInt count = 0;
1292 MInt preliminaryDataVarCount = 1 + m_solver->noVariables() + 8; // y + primVars + rms + p'p' + SijSij
1293 MInt dataCount = data.size() / preliminaryDataVarCount;
1294
1295 vector<vector<MFloat>> preData(dataCount, vector<MFloat>(preliminaryDataVarCount, 0));
1296
1297 MInt index = 0;
1298 for(MInt d = 0; d < dataCount; d++) {
1299 for(MInt dd = 0; dd < preliminaryDataVarCount; dd++) {
1300 index = preliminaryDataVarCount * d + dd;
1301 preData[d][dd] = data[index];
1302 }
1303 }
1304
1305 preliminaryData.close();
1306
1307 if(m_stgMyRank == m_commStgRoot) cerr << "ok" << endl;
1308
1309 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
1310 const MInt IBC = a->getStgId(it);
1311 const MInt cellId = a->m_stgToCellId[IBC];
1312
1313 MFloat pos = m_solver->a_coordinate(cellId, m_wallDir);
1314 if(m_cylinderTransformation) {
1315 MFloat y = m_solver->a_coordinate(cellId, m_wallDir);
1316 MFloat z = m_solver->a_coordinate(cellId, m_periodicDir);
1317 pos = sqrt(y * y + z * z);
1318 }
1319
1320 for(MInt d = 0; d < dataCount; d++) {
1321 if(abs(pos - preData[d][0]) / pos < 0.001) {
1322 // no interpolation needed
1323 for(MInt var = 0; var < nDim + 2; var++) {
1324 m_stgLVariables[var][IBC] = preData[d][var + 1];
1325 if(var < nDim) {
1326 m_stgLVariables[STG::AVG_UU[var]][IBC] = m_stgLVariables[var][IBC];
1327 }
1328 }
1329 MInt v = 6;
1330 for(MInt fluc = STG::FLUC_UU; fluc < STG::FLUC_WW + 1; fluc++) {
1331 m_stgLVariables[fluc][IBC] = preData[d][v];
1332 v++;
1333 }
1334 MInt index_ = preliminaryDataVarCount - 1;
1335 m_stgLVariables[STG::SIJSIJ][IBC] = preData[d][index_];
1336 } else {
1337 if(d == dataCount - 1) continue; // this is necessary for interpolation
1338 // interpolation
1339 if(pos >= preData[d][0] && pos < preData[d + 1][0]) {
1340 for(MInt var = 0; var < nDim + 2; var++) {
1341 m_stgLVariables[var][IBC] = preData[d][var + 1]
1342 + (preData[d + 1][var + 1] - preData[d][var + 1]) * (pos - preData[d][0])
1343 / (preData[d + 1][0] - preData[d][0]);
1344
1345 if(var < nDim) {
1346 m_stgLVariables[STG::AVG_UU[var]][IBC] = m_stgLVariables[var][IBC];
1347 }
1348 }
1349 MInt v = 6;
1350 for(MInt fluc = STG::FLUC_UU; fluc < STG::FLUC_WW + 1; fluc++) {
1351 m_stgLVariables[fluc][IBC] =
1352 preData[d][v]
1353 + (preData[d + 1][v] - preData[d][v]) * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1354
1355 v++;
1356 }
1357
1358 MInt index_ = preliminaryDataVarCount - 1;
1359 m_stgLVariables[STG::SIJSIJ][IBC] = preData[d][index_]
1360 + (preData[d + 1][index_] - preData[d][index_])
1361 * (pos - preData[d][0]) / (preData[d + 1][0] - preData[d][0]);
1362 }
1363 }
1364 }
1365 }
1366 }
1367 }
1368}
1369
1370
1374template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1375template <class _, std::enable_if_t<SolverTypeR == MAIA_STRUCTURED, _*>,
1376 std::enable_if_t<SolverTypeL == MAIA_FINITE_VOLUME, _*>>
1378 // Sut: if it is not a zonal run, fill a_pvariable of ghost cells with RANS values
1379 // and if it is a m_stgInitialStartup, than also fill m_stgLVariables with RANS values
1380 if(m_stgInitialStartup) {
1381 // Reading in RANS Profile for BC
1382 // Iterate over all stg cells for gradient calculations
1383
1384 // ScratchSpace<MFloat> stgCoords(m_nDim, a->sizeStg(), AT_, "stgCoords" );
1385 std::vector<std::vector<MFloat>> stgCoords(m_nDim);
1386 for(MInt d = 0; d < m_nDim; ++d)
1387 stgCoords[d].resize(a->sizeStg());
1388
1389 // loop over all stg cells
1390 for(typename Accessor::nDim_citerator it = a->iterateAll(); it != a->iterateAll_nDim_citerator_end(); ++it) {
1391 const MInt stgId = a->getStgId(it);
1392 const MInt cellId = a->getCellId(it);
1393 stgCoords[0][stgId] = LES->a_coordinate(cellId, 0);
1394 stgCoords[1][stgId] = LES->a_coordinate(cellId, 1);
1395 stgCoords[2][stgId] = LES->a_coordinate(cellId, 2);
1396 }
1397
1398 // hack
1399 MInt c = 0;
1400 std::vector<MFloat*> stgCoords_ptr(m_nDim);
1401 for(auto& s_ptr : stgCoords) {
1402 stgCoords_ptr[c++] = s_ptr.data();
1403 }
1404 // MInt* temp = new MInt[a->sizeStg()];
1405 MInt temp2[] = {a->sizeStg(), 1, 1};
1406
1407 auto* structuredInterpolation = new StructuredInterpolation<3>(m_commStg);
1408 // TODO: check this later
1409 // structuredInterpolation->prepareInterpolation(a->sizeStg(), stgCoords_ptr.data(), temp);
1410 structuredInterpolation->prepareInterpolationField(&temp2[0], stgCoords_ptr.data());
1411 std::array<MString, m_nDim + 2> pvariableNames;
1412 /* pvariableNames[PV->U] = "u";
1413 pvariableNames[PV->V] = "v";
1414 if (nDim==3)
1415 pvariableNames[PV->W] = "w";
1416 pvariableNames[PV->P] = "p";
1417 pvariableNames[PV->RHO] = "rho";*/
1418 pvariableNames[STG::AVG_U] = "u";
1419 pvariableNames[STG::AVG_V] = "v";
1420 IF_CONSTEXPR(nDim == 3) { pvariableNames[STG::AVG_W] = "w"; }
1421 pvariableNames[STG::AVG_P] = "p";
1422 pvariableNames[STG::AVG_RHO] = "rho";
1423 const MInt noVars = nDim + 2;
1424 for(MInt var = 0; var < noVars; var++) {
1425 // BE CAREFUL WITH THE ORDER OF THE VARIABLES
1426 structuredInterpolation->interpolateField(pvariableNames[var], m_stgLVariables[var]);
1427 }
1428 // TODO "nu_t" is hardcoded
1429 structuredInterpolation->interpolateField("nu_t", m_stgLVariables[STG::NU_T]);
1430
1431 // SANITY CHECK
1432 MInt cnt = 0;
1433 for(MInt var = 0; var < noVars; var++) {
1434 MFloat minVar = std::numeric_limits<MFloat>::max();
1435 MFloat maxVar = -std::numeric_limits<MFloat>::max();
1436 for(typename Accessor::nDim_citerator it = a->iterateAll(); it != a->iterateAll_nDim_citerator_end(); ++it) {
1437 cnt++;
1438 const MInt stgId = a->getStgId(it);
1439 MFloat variable = m_stgLVariables[var][stgId];
1440 if(std::isnan(variable)) TERMM(1, "NAN");
1441 if(variable > maxVar) maxVar = variable;
1442 if(variable < minVar) minVar = variable;
1443 }
1444 MFloat minVarGlobal;
1445 MFloat maxVarGlobal;
1446 MPI_Reduce(&minVar, &minVarGlobal, 1, MPI_DOUBLE, MPI_MIN, m_commStgRoot, m_commStg, AT_, "MPI_IN_PLACE",
1447 "minVar");
1448 MPI_Reduce(&maxVar, &maxVarGlobal, 1, MPI_DOUBLE, MPI_MAX, m_commStgRoot, m_commStg, AT_, "MPI_IN_PLACE",
1449 "maxVar");
1450 if(m_stgMyRank == m_commStgRoot)
1451 std::cout << " CHECK after readRANSProfileStg of rank=" << m_solver->domainId() << ":var=" << var
1452 << std::scientific << ": minVar=" << minVarGlobal << "; maxVar=" << maxVarGlobal << "; " << cnt
1453 << std::endl;
1454 }
1455 // SANITY CHECK ENDS
1456
1457 } else {
1458 // TODO: check if it should be B1 or Ghost cells
1459 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
1460 const MInt cellId = a->getCellId(it);
1461 const MInt IBC = a->getStgId(it);
1462 for(int var = 0; var < PV->noVariables; var++) {
1463 LES->a_pvariable(cellId, var) = m_stgLVariables[var][IBC];
1464 }
1465 }
1466 }
1467}
1468
1469
1470template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1471template <class _, std::enable_if_t<SolverTypeL == MAIA_FINITE_VOLUME, _*>>
1473 TRACE();
1474
1475 if(!m_preliminary) {
1476 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
1477 const MInt cellId = a->getCellId(it);
1478 const MInt recData = m_solver->a_reconstructionData(cellId);
1479 MFloat du[nDim][nDim]{{F0, F0, F0}, {F0, F0, F0}, {F0, F0, F0}};
1480 const MFloat u[nDim] = {m_stgLVariables[STG::AVG_U][a->getStgId(it)],
1481 m_stgLVariables[STG::AVG_V][a->getStgId(it)],
1482 m_stgLVariables[STG::AVG_W][a->getStgId(it)]};
1483
1484 for(MInt nghbr = 0; nghbr < m_solver->a_noReconstructionNeighbors(cellId); nghbr++) {
1485 const MInt recNghbrId = m_solver->a_reconstructionNeighborId(cellId, nghbr);
1486 const MInt nghbrStgId = a->getNghbrMapping(a->getStgId(it), nghbr);
1487
1488 const MFloat recConst_x = m_solver->m_reconstructionConstants[nDim * (recData + nghbr) + 0];
1489 const MFloat recConst_y = m_solver->m_reconstructionConstants[nDim * (recData + nghbr) + 1];
1490 const MFloat recConst_z = m_solver->m_reconstructionConstants[nDim * (recData + nghbr) + 2];
1491
1492 MFloat delta_u = F0;
1493 for(MInt d = 0; d < nDim; ++d) {
1494 if(m_cutOff) {
1495 if(recNghbrId > 0 && recNghbrId < m_solver->c_noCells()) {
1496 delta_u = m_solver->m_RANSValues[d][recNghbrId] - u[d];
1497 }
1498 } else {
1499 if(nghbrStgId > 0) delta_u = m_stgLVariables[STG::AVG_UU[d]][nghbrStgId] - u[d];
1500 }
1501 du[d][0] += recConst_x * delta_u;
1502 du[d][1] += recConst_y * delta_u;
1503 du[d][2] += recConst_z * delta_u;
1504 }
1505 }
1506 if(m_solver->m_reConstSVDWeightMode == 3) {
1507 if(!m_solver->a_hasProperty(cellId, /*SolverCell*/ FvCell::HasCoarseNghbr)) {
1508 continue;
1509 }
1510 std::array<MBool, nDim> dirsJmp = {};
1511 for(MInt d = 0; d < nDim; ++d) {
1512 if(m_solver->m_cells.nghbrInterface(cellId, 2 * d) == 3
1513 || m_solver->m_cells.nghbrInterface(cellId, 2 * d + 1) == 3) {
1514 dirsJmp[d] = true;
1515 } else {
1516 dirsJmp[d] = false;
1517 }
1518 }
1519
1520 for(MUint d = 0; d < nDim; ++d) {
1521 for(MInt dd = 0; dd < nDim; ++dd) {
1522 if(dirsJmp[dd]) {
1523 du[d][dd] = 0.0;
1524 }
1525 }
1526 }
1527
1528 for(MInt nghbr = 0; nghbr < m_solver->a_noReconstructionNeighbors(cellId); nghbr++) {
1529 const MInt nghbrStgId = a->getNghbrMapping(a->getStgId(it), nghbr);
1530 const MInt nghbrId = m_solver->a_reconstructionNeighborId(cellId, nghbr);
1531
1532 for(MUint d = 0; d < nDim; ++d) {
1533 MFloat tmp = m_stgLVariables[STG::AVG_UU[d]][nghbrStgId] - u[d];
1534 for(MInt dd = 0; dd < nDim; ++dd) {
1535 if(!dirsJmp[dd]) {
1536 const MFloat dx = LES->a_coordinate(nghbrId, dd) - LES->a_coordinate(cellId, dd);
1537 tmp -= du[d][dd] * dx;
1538 }
1539 }
1540 for(MInt dd = 0; dd < nDim; ++dd) {
1541 if(dirsJmp[dd]) {
1542 du[d][dd] += m_solver->m_reconstructionConstants[nDim * (recData + nghbr) + dd] * tmp;
1543 }
1544 }
1545 }
1546 }
1547 }
1548
1549 const MFloat s11 = 2.0 * du[0][0];
1550 const MFloat s22 = 2.0 * du[1][1];
1551 const MFloat s33 = 2.0 * du[2][2];
1552
1553 const MFloat s12 = du[1][0] + du[0][1];
1554 const MFloat s13 = du[2][0] + du[0][2];
1555 const MFloat s23 = du[2][1] + du[1][2];
1556
1557 const MFloat s21 = s12;
1558 const MFloat s31 = s13;
1559 const MFloat s32 = s23;
1560
1561 // Strain tensor
1562 const MFloat SijSij =
1563 F1B4
1564 * (s11 * s11 + s12 * s12 + s13 * s13 + s21 * s21 + s22 * s22 + s23 * s23 + s31 * s31 + s32 * s32 + s33 * s33);
1565
1566 m_stgLVariables[STG::S11][a->getStgId(it)] = s11;
1567 m_stgLVariables[STG::S22][a->getStgId(it)] = s22;
1568 m_stgLVariables[STG::S33][a->getStgId(it)] = s33;
1569
1570 m_stgLVariables[STG::S12][a->getStgId(it)] = s12;
1571 m_stgLVariables[STG::S13][a->getStgId(it)] = s13;
1572 m_stgLVariables[STG::S23][a->getStgId(it)] = s23;
1573
1574 m_stgLVariables[STG::SIJSIJ][a->getStgId(it)] = SijSij;
1575 }
1576 }
1577}
1578
1579
1580#if 0
1581template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1582template <class _, std::enable_if_t<SolverTypeL == MAIA_STRUCTURED, _*>>
1584
1585 const MInt ii = 1;
1586
1587 for(MInt k = start[2]+1; k < end[2]-1; k++) {
1588 for(MInt j = start[1]+1; j < end[1]-1; j++) {
1589 /*********************** C *****************/
1590 //This is the metrics / strain tensor / max shear part
1591 /*********************** C *****************/
1592
1593 MInt IPJK, IMJK, IJPK, IJMK, IJKP, IJKM;
1594
1595 I = cellIndex(ii,j,k);
1596 IPJK = cellIndex(ii+1,j,k);
1597 IMJK = cellIndex(ii-1,j,k);
1598 IJPK = cellIndex(ii,j+1,k);
1599 IJMK = cellIndex(ii,j-1,k);
1600 IJKP = cellIndex(ii,j,k+1);
1601 IJKM = cellIndex(ii,j,k-1);
1602
1603
1604 const MFloat dxdi = F1B2 * (m_cells->coordinates[0][IPJK] - m_cells->coordinates[0][IMJK]);
1605 const MFloat dxdj = F1B2 * (m_cells->coordinates[0][IJPK] - m_cells->coordinates[0][IJMK]);
1606 const MFloat dxdk = F1B2 * (m_cells->coordinates[0][IJKP] - m_cells->coordinates[0][IJKM]);
1607 const MFloat dydi = F1B2 * (m_cells->coordinates[1][IPJK] - m_cells->coordinates[1][IMJK]);
1608 const MFloat dydj = F1B2 * (m_cells->coordinates[1][IJPK] - m_cells->coordinates[1][IJMK]);
1609 const MFloat dydk = F1B2 * (m_cells->coordinates[1][IJKP] - m_cells->coordinates[1][IJKM]);
1610 const MFloat dzdi = F1B2 * (m_cells->coordinates[2][IPJK] - m_cells->coordinates[2][IMJK]);
1611 const MFloat dzdj = F1B2 * (m_cells->coordinates[2][IJPK] - m_cells->coordinates[2][IJMK]);
1612 const MFloat dzdk = F1B2 * (m_cells->coordinates[2][IJKP] - m_cells->coordinates[2][IJKM]);
1613
1614 const MFloat dxl = sqrt(dxdi*dxdi + dydi*dydi + dzdi*dzdi);
1615 const MFloat dyl = sqrt(dxdj*dxdj + dydj*dydj + dzdj*dzdj);
1616 const MFloat dzl = sqrt(dxdk*dxdk + dydk*dydk + dzdk*dzdk);
1617
1618 const MFloat dxidx = (1./std::max(m_cells->cellJac[I], epss))*m_cells->cellMetrics[I][0];
1619 const MFloat dxidy = (1./std::max(m_cells->cellJac[I], epss))*m_cells->cellMetrics[I][1];
1620 const MFloat dxidz = (1./std::max(m_cells->cellJac[I], epss))*m_cells->cellMetrics[I][2];
1621
1622 const MFloat detadx = (1./std::max(m_cells->cellJac[I], epss))*m_cells->cellMetrics[I][3 + 0];
1623 const MFloat detady = (1./std::max(m_cells->cellJac[I], epss))*m_cells->cellMetrics[I][3 + 1];
1624 const MFloat detadz = (1./std::max(m_cells->cellJac[I], epss))*m_cells->cellMetrics[I][3 + 2];
1625
1626 const MFloat dzetadx = (1./std::max(m_cells->cellJac[I], epss))*m_cells->cellMetrics[I][6 + 0];
1627 const MFloat dzetady = (1./std::max(m_cells->cellJac[I], epss))*m_cells->cellMetrics[I][6 + 1];
1628 const MFloat dzetadz = (1./std::max(m_cells->cellJac[I], epss))*m_cells->cellMetrics[I][6 + 2];
1629
1630 IBC = cellIndexBC(ii,j,k);
1631 IPJK = cellIndexBC(ii+1,j,k);
1632 IMJK = cellIndexBC(ii-1,j,k);
1633 IJPK = cellIndexBC(ii,j+1,k);
1634 IJMK = cellIndexBC(ii,j-1,k);
1635 IJKP = cellIndexBC(ii,j,k+1);
1636 IJKM = cellIndexBC(ii,j,k-1);
1637
1638 const MFloat frho = 1.0 / m_stgVariables[STG::AVG_RHO][IBC];
1639
1640 //dud?
1641 const MFloat dudxi = F1B2*(m_stgVariables[STG::AVG_U][IPJK] - m_stgVariables[STG::AVG_U][IMJK]);
1642 const MFloat dudeta = F1B2*(m_stgVariables[STG::AVG_U][IJPK] - m_stgVariables[STG::AVG_U][IJMK]);
1643 const MFloat dudzeta = F1B2*(m_stgVariables[STG::AVG_U][IJKP] - m_stgVariables[STG::AVG_U][IJKM]);
1644
1645 //dvd?
1646 const MFloat dvdxi = F1B2*(m_stgVariables[STG::AVG_V][IPJK] - m_stgVariables[STG::AVG_V][IMJK]);
1647 const MFloat dvdeta = F1B2*(m_stgVariables[STG::AVG_V][IJPK] - m_stgVariables[STG::AVG_V][IJMK]);
1648 const MFloat dvdzeta = F1B2*(m_stgVariables[STG::AVG_V][IJKP] - m_stgVariables[STG::AVG_V][IJKM]);
1649
1650 //dwd?
1651 const MFloat dwdxi = F1B2*(m_stgVariables[STG::AVG_W][IPJK] - m_stgVariables[STG::AVG_W][IMJK]);
1652 const MFloat dwdeta = F1B2*(m_stgVariables[STG::AVG_W][IJPK] - m_stgVariables[STG::AVG_W][IJMK]);
1653 const MFloat dwdzeta = F1B2*(m_stgVariables[STG::AVG_W][IJKP] - m_stgVariables[STG::AVG_W][IJKM]);
1654
1655 const MFloat dudx = dudxi*dxidx + dudeta*detadx + dudzeta*dzetadx;
1656 const MFloat dudy = dudxi*dxidy + dudeta*detady + dudzeta*dzetady;
1657 const MFloat dudz = dudxi*dxidz + dudeta*detadz + dudzeta*dzetadz;
1658
1659 const MFloat dvdx = dvdxi*dxidx + dvdeta*detadx + dvdzeta*dzetadx;
1660 const MFloat dvdy = dvdxi*dxidy + dvdeta*detady + dvdzeta*dzetady;
1661 const MFloat dvdz = dvdxi*dxidz + dvdeta*detadz + dvdzeta*dzetadz;
1662
1663 const MFloat dwdx = dwdxi*dxidx + dwdeta*detadx + dwdzeta*dzetadx;
1664 const MFloat dwdy = dwdxi*dxidy + dwdeta*detady + dwdzeta*dzetady;
1665 const MFloat dwdz = dwdxi*dxidz + dwdeta*detadz + dwdzeta*dzetadz;
1666
1667
1668 m_stgVariables[STG::S11][cellIndexBC(ii,j,k)] = 2.0*dudx;
1669 m_stgVariables[STG::S22][cellIndexBC(ii,j,k)] = 2.0*dvdy;
1670 m_stgVariables[STG::S33][cellIndexBC(ii,j,k)] = 2.0*dwdz;
1671
1672 m_stgVariables[STG::S12][cellIndexBC(ii,j,k)] = dvdx+dudy;
1673 m_stgVariables[STG::S13][cellIndexBC(ii,j,k)] = dwdx+dudz;
1674 m_stgVariables[STG::S23][cellIndexBC(ii,j,k)] = dwdy+dvdz;
1675 }
1676 }
1677}
1678#endif
1679
1680
1681template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1683 // Arrays for MPI operations
1684 MFloatScratchSpace maxValsLocal(3, AT_, "maxValsLocal");
1685 MInt size;
1686 MPI_Comm_size(m_commStg, &size);
1687 MFloatScratchSpace maxValsGlobal(3 * size, AT_, "maxValsGlobal");
1688 maxValsLocal.fill(F0);
1689 maxValsGlobal.fill(F0);
1690
1691 const MFloat fre = 1.0 / m_solver->sysEqn().m_Re0;
1692
1693 const MFloat delta_in = m_stgDelta99Inflow;
1694
1695 // Initialize max values
1696 MFloat utaumax = F0, umax = F0, vmax = F0, wmax = F0, minLengthLocal = F0;
1697
1698 for(typename Accessor::nDim_citerator it = a->iterateSlopes(); it != a->iterateSlopes_nDim_citerator_end(); ++it) {
1699 const MInt id = a->getStgId(it);
1700 const MInt cellId = a->getCellId(it);
1701
1702 const MFloat frho = 1.0 / m_stgLVariables[STG::AVG_RHO][id];
1703
1704 MFloat SijSij = m_stgLVariables[STG::SIJSIJ][id];
1705
1706 if(!m_preliminary || m_preliminaryRans2D) {
1707 // Strain tensor
1708 // const MFloat s11 = m_stgLVariables[STG::S11][id];
1709 // const MFloat s22 = m_stgLVariables[STG::S22][id];
1710 // const MFloat s33 = m_stgLVariables[STG::S33][id];
1711 const MFloat s12 = m_stgLVariables[STG::S12][id];
1712 const MFloat s23 = m_stgLVariables[STG::S23][id];
1713 const MFloat s13 = m_stgLVariables[STG::S13][id];
1714 const MFloat s21 = s12;
1715 const MFloat s32 = s23;
1716 const MFloat s31 = s13;
1717
1718 if(m_freeStreamTurbulence) {
1719 MFloat SijSij_ = SijSij;
1720 MFloat tmp = LES->a_coordinate(cellId, m_wallDir);
1721 if(m_cylinderTransformation) {
1722 MFloat y = LES->a_coordinate(cellId, m_wallDir);
1723 MFloat z = LES->a_coordinate(cellId, m_periodicDir);
1724 tmp = sqrt(y * y + z * z);
1725 }
1726 if(tmp > m_stgWallEnd) {
1727 SijSij_ = m_SijSijFS;
1728 }
1729 SijSij = SijSij_;
1730 m_stgLVariables[STG::SIJSIJ][id] = SijSij;
1731 }
1732
1733 //>marian: in TFS code this isn't SQRT
1734 // m_stgLVariables[STG::SIJSIJ][id] = SijSij;
1735
1736 // Assume a one-, or two equation turbulence model
1737 // Assume a simplified directivity:
1738 // Read from RANS profile
1739
1740 MFloat nu_t = m_stgLVariables[STG::NU_T][id];
1741
1742 const MFloat sr1 = (s12 + s21) * (s12 + s21);
1743 const MFloat sr2 = (s23 + s32) * (s23 + s32);
1744 const MFloat sr3 = (s13 + s31) * (s13 + s31);
1745 const MFloat srt = std::max(sqrt(sr1 + sr2 + sr3), epsl);
1746
1747 const MFloat rr1 = sqrt(sr1) / srt;
1748 const MFloat rr2 = sqrt(sr2) / srt;
1749 const MFloat rr3 = sqrt(sr3) / srt;
1750
1751 const MFloat uv = -sqrt(2.0 * SijSij) * rr1 * nu_t * fre;
1752 const MFloat vw = -sqrt(2.0 * SijSij) * rr2 * nu_t * fre;
1753 const MFloat uw = -sqrt(2.0 * SijSij) * rr3 * nu_t * fre;
1754 const MFloat uu = a1 * std::abs(uv) * m_stgRSTFactors[0];
1755 const MFloat vv = a1 * std::abs(uv) * m_stgRSTFactors[1];
1756 const MFloat ww = a1 * std::abs(uv) * m_stgRSTFactors[2];
1757
1758 m_stgLVariables[STG::FLUC_UU][id] = uu;
1759 m_stgLVariables[STG::FLUC_UV][id] = uv;
1760 m_stgLVariables[STG::FLUC_VV][id] = vv;
1761 m_stgLVariables[STG::FLUC_WW][id] = ww;
1762 m_stgLVariables[STG::FLUC_VW][id] = vw;
1763 m_stgLVariables[STG::FLUC_UW][id] = uw;
1764 }
1765 else {
1766 MFloat uv = m_stgLVariables[STG::FLUC_UV][id];
1767 m_stgLVariables[STG::FLUC_UU][id] = a1 * std::abs(uv) * m_stgRSTFactors[0];
1768 m_stgLVariables[STG::FLUC_VV][id] = a1 * std::abs(uv) * m_stgRSTFactors[1];
1769 m_stgLVariables[STG::FLUC_WW][id] = a1 * std::abs(uv) * m_stgRSTFactors[2];
1770 m_stgLVariables[STG::FLUC_VW][id] = 0;
1771 m_stgLVariables[STG::FLUC_UW][id] = 0;
1772 }
1773
1774 if(m_freeStreamTurbulence) {
1775 m_stgLVariables[STG::FLUC_UU][id] = m_uuFS;
1776 m_stgLVariables[STG::FLUC_UV][id] = 0;
1777 m_stgLVariables[STG::FLUC_VV][id] = m_vvFS;
1778 m_stgLVariables[STG::FLUC_WW][id] = m_wwFS;
1779 m_stgLVariables[STG::FLUC_VW][id] = 0;
1780 m_stgLVariables[STG::FLUC_UW][id] = 0;
1781 }
1782
1783 // TODO: this is different from the implementation in the Structured solver
1784 MFloat rhoRANSI1 = m_stgLVariables[PV->RHO][id];
1785 MFloat pressure1 = m_stgLVariables[PV->P][id];
1786
1787 const MFloat temp = m_solver->m_gamma * pressure1 / rhoRANSI1;
1788 const MFloat xmu = SUTHERLANDLAW(temp);
1789
1790 // Get utau using laminar viscosity
1791 MFloat utau2_ = sqrt(fre * sqrt(2.0 * SijSij) * xmu * frho);
1792
1793 const MFloat utau2 = utau2_;
1794
1795 // TODO: check the following
1796 const MFloat dV = getCellSize(it);
1797
1798 // Save values if they are the new maximum
1799 if(utau2 >= utaumax) {
1800 minLengthLocal = pow(dV, 0.33);
1801 utaumax = std::max(utau2, utaumax);
1802 }
1803
1804 // In which direction aims the maximum averaged velocity?
1805 // TODO: think if RANS or LES velocity?
1806 const MFloat u = m_stgLVariables[STG::AVG_U][id];
1807 const MFloat v = m_stgLVariables[STG::AVG_V][id];
1808 const MFloat w = m_stgLVariables[STG::AVG_W][id];
1809
1810 // TODO: check the following
1811 umax = (fabs(u) > fabs(umax)) ? u : umax; // std::max(u, umax);
1812 vmax = (fabs(v) > fabs(vmax)) ? v : vmax; // std::max(v, vmax);
1813 wmax = (fabs(w) > fabs(wmax)) ? w : wmax; // std::max(w, wmax);
1814
1815 // We need a global length scale to compare
1816 m_stgLVariables[STG::LENGTH_SCALE][id] = pow(sqrt(std::max(2.0 * SijSij, epss)), -m_stgExple);
1817
1818 // TODO: next section only for Structured:
1819 // Zero gradient extrapolation of boundary values
1820 // extrapolateToBoundary(it);
1821
1822 // Save max direction vector and max tau
1823 maxValsLocal[0] = umax;
1824 maxValsLocal[1] = vmax;
1825 maxValsLocal[2] = wmax;
1826
1827 if(std::isnan(utaumax) || std::isinf(utaumax)) utaumax = F0;
1828 }
1829
1830 // Communication: Exchange min and max values
1831 MFloat minLengthGlobal = 0.0;
1832 MFloat utaux;
1833 MPI_Allgather(maxValsLocal.begin(), 3, MPI_DOUBLE, maxValsGlobal.begin(), 3, MPI_DOUBLE, m_commStg, AT_,
1834 "maxValsLocal.begin()", "maxValsGlobal.begin()");
1835 MPI_Allreduce(&utaumax, &utaux, 1, MPI_DOUBLE, MPI_MAX, m_commStg, AT_, "utaumax", "utaux");
1836
1837 MPI_Allreduce(&minLengthLocal, &minLengthGlobal, 1, MPI_DOUBLE, MPI_MIN, m_commStg, AT_, "minLengthLocal",
1838 "minLengthGlobal");
1839
1840 // Maximum convection velocities at inflow
1841 std::fill_n(&m_stgMaxVel[0], 3, 0.0);
1842 for(MInt d = 0; d < size; ++d) {
1843 m_stgMaxVel[0] = (fabs(m_stgMaxVel[0]) > fabs(maxValsGlobal[3 * d])) ? m_stgMaxVel[0] : maxValsGlobal[3 * d];
1844 m_stgMaxVel[1] =
1845 (fabs(m_stgMaxVel[1]) > fabs(maxValsGlobal[3 * d + 1])) ? m_stgMaxVel[1] : maxValsGlobal[3 * d + 1];
1846 m_stgMaxVel[2] =
1847 (fabs(m_stgMaxVel[2]) > fabs(maxValsGlobal[3 * d + 2])) ? m_stgMaxVel[2] : maxValsGlobal[3 * d + 2];
1848 }
1849
1850#ifndef NDEBUG
1851 if(m_stgMyRank == m_commStgRoot) {
1852 cerr << "m_stgMaxVel: " << utaux << " " << m_stgMaxVel[0] << " " << m_stgMaxVel[1] << " " << m_stgMaxVel[2] << endl;
1853 }
1854#endif
1855
1856 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
1857 const MInt IBC = it.getStgId();
1858 // const MInt cellId = a->getCellId(it);
1859
1860 MFloat maxLength = delta_in;
1861
1862 // Length scale in main flow direction
1863 const MFloat xlength = std::max(
1864 std::min(
1865 m_stgLengthFactors[0]
1866 * std::max(m_stgLVariables[STG::LENGTH_SCALE][IBC] * delta_in * pow(utaux / delta_in, m_stgExple), eps),
1867 maxLength * 1.0),
1868 minLengthGlobal);
1869
1870 // Length scale in the direction of main shear
1871 const MFloat ylength = std::max(
1872 std::min(
1873 m_stgLengthFactors[1]
1874 * std::max(m_stgLVariables[STG::LENGTH_SCALE][IBC] * delta_in * pow(utaux / delta_in, m_stgExple), eps),
1875 maxLength * 0.66),
1876 minLengthGlobal);
1877
1878 // Length scale in the direction perpendicular of x and y
1879 const MFloat zlength = std::max(
1880 std::min(
1881 m_stgLengthFactors[2]
1882 * std::max(m_stgLVariables[STG::LENGTH_SCALE][IBC] * delta_in * pow(utaux / delta_in, m_stgExple), eps),
1883 maxLength * 1.0),
1884 minLengthGlobal);
1885
1886 m_stgLVariables[STG::LENGTH_X][IBC] = xlength;
1887 m_stgLVariables[STG::LENGTH_Y][IBC] = ylength;
1888 m_stgLVariables[STG::LENGTH_Z][IBC] = zlength;
1889 }
1890}
1891
1892
1893template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1894template <class _, std::enable_if_t<SolverTypeL == MAIA_FINITE_VOLUME, _*>>
1896 return m_solver->a_cellVolume(a->getCellId(it));
1897}
1898
1899
1900template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1901template <class _, std::enable_if_t<SolverTypeL == MAIA_STRUCTURED, _*>>
1903 const MInt IPJK = a->getNghbr(it, 1);
1904 const MInt IMJK = a->getNghbr(it, 0);
1905 const MInt IJPK = a->getNghbr(it, 3);
1906 const MInt IJMK = a->getNghbr(it, 2);
1907 const MInt IJKP = a->getNghbr(it, 5);
1908 const MInt IJKM = a->getNghbr(it, 4);
1909
1910 const MFloat dxdi = F1B2 * (LES->a_coordinate(IPJK, 0) - LES->a_coordinate(IMJK, 0));
1911 const MFloat dxdj = F1B2 * (LES->a_coordinate(IJPK, 0) - LES->a_coordinate(IJMK, 0));
1912 const MFloat dxdk = F1B2 * (LES->a_coordinate(IJKP, 0) - LES->a_coordinate(IJKM, 0));
1913 const MFloat dydi = F1B2 * (LES->a_coordinate(IPJK, 1) - LES->a_coordinate(IMJK, 1));
1914 const MFloat dydj = F1B2 * (LES->a_coordinate(IJPK, 1) - LES->a_coordinate(IJMK, 1));
1915 const MFloat dydk = F1B2 * (LES->a_coordinate(IJKP, 1) - LES->a_coordinate(IJKM, 1));
1916 const MFloat dzdi = F1B2 * (LES->a_coordinate(IPJK, 2) - LES->a_coordinate(IMJK, 2));
1917 const MFloat dzdj = F1B2 * (LES->a_coordinate(IJPK, 2) - LES->a_coordinate(IJMK, 2));
1918 const MFloat dzdk = F1B2 * (LES->a_coordinate(IJKP, 2) - LES->a_coordinate(IJKM, 2));
1919
1920 const MFloat dxl = sqrt(dxdi * dxdi + dydi * dydi + dzdi * dzdi);
1921 const MFloat dyl = sqrt(dxdj * dxdj + dydj * dydj + dzdj * dzdj);
1922 const MFloat dzl = sqrt(dxdk * dxdk + dydk * dydk + dzdk * dzdk);
1923
1924 return dxl * dyl * dzl;
1925}
1926
1927
1928template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1930 xk[m_stgDir] = m_stgVbStart[m_stgDir] + generate_rand() * (m_stgVbEnd[m_stgDir] - m_stgVbStart[m_stgDir]);
1931 xk[m_periodicDir] =
1932 m_stgVbStart[m_periodicDir] + generate_rand() * (m_stgVbEnd[m_periodicDir] - m_stgVbStart[m_periodicDir]);
1933 xk[m_wallDir] =
1934 m_stgVbStart[m_wallDir] + generate_rand_weighted() * (m_stgVbEnd[m_wallDir] - m_stgVbStart[m_wallDir]);
1935
1936 if(m_isotropicTurbulence) {
1937 xk[m_wallDir] = m_stgVbStart[m_wallDir] + generate_rand() * (m_stgVbEnd[m_wallDir] - m_stgVbStart[m_wallDir]);
1938 }
1939
1940 if(m_cylinderTransformation) {
1941 xk[m_wallDir] = m_stgVbStart[m_wallDir] + generate_rand() * (m_stgVbEnd[m_wallDir] - m_stgVbStart[m_wallDir]);
1942 }
1943
1944 if(m_freeStreamTurbulence) {
1945 if(generate_rand() < m_BLEddieFraction) {
1946 // generate new eddie in BL
1947 xk[m_wallDir] = m_stgVbStart[m_wallDir] + generate_rand_weighted() * (m_stgWallEnd - m_stgVbStart[m_wallDir]);
1948 } else {
1949 // generate new eddie in FS
1950 xk[m_wallDir] = m_stgWallEnd + generate_rand() * (m_stgVbEnd[m_wallDir] - m_stgWallEnd);
1951 }
1952 }
1953
1954 epsi[m_stgDir] = 2.0 * generate_rand() - 1.0;
1955 epsi[m_stgDir] = epsi[m_stgDir] / std::max(std::abs(epsi[m_stgDir]), eps);
1956 epsi[m_wallDir] = 2.0 * generate_rand() - 1.0;
1957 epsi[m_wallDir] = epsi[m_wallDir] / std::max(std::abs(epsi[m_wallDir]), eps);
1958 epsi[m_periodicDir] = 2.0 * generate_rand() - 1.0;
1959 epsi[m_periodicDir] = epsi[m_periodicDir] / std::max(std::abs(epsi[m_periodicDir]), eps);
1960}
1961
1962
1963template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
1965 // Array for MPI operation
1966 MFloatScratchSpace eddyBcastBuffer(m_stgMaxNoEddies * m_stgNoEddieProperties, AT_, "eddyBcastBuffer");
1967 eddyBcastBuffer.fill(F0);
1968
1969 MFloatScratchSpace eddyBcastStrength(m_stgMaxNoEddies, AT_, "eddyBcastStrength");
1970 eddyBcastStrength.fill(F0);
1971
1972
1973 MFloat xk[3];
1974 MFloat epsi[3];
1975 if(m_stgMyRank == m_commStgRoot) {
1976 for(MInt n = 0; n < m_stgMaxNoEddies; n++) {
1977 xk[0] = m_stgEddies[n][0];
1978 xk[1] = m_stgEddies[n][1];
1979 xk[2] = m_stgEddies[n][2];
1980
1981 eddyBcastStrength[n] = m_stgEddyStrength[n];
1982
1983 // Check if the eddie has left the Virtual Box
1984 if(xk[0] > m_stgVbEnd[0] || xk[0] < m_stgVbStart[0] || xk[1] > m_stgVbEnd[1] || xk[1] < m_stgVbStart[1]
1985 || xk[2] > m_stgVbEnd[2] || xk[2] < m_stgVbStart[2]) {
1986 generateNewEddies(xk, epsi);
1987
1988 eddyBcastStrength[n] = F1;
1989 if(m_newStgMethod) {
1990 eddyBcastStrength[n] = generate_rand_normalDist();
1991 }
1992
1993 } else {
1994 xk[0] = m_stgMaxVel[0] * m_solver->m_timeStep + m_stgEddies[n][0];
1995 xk[1] = m_stgMaxVel[1] * m_solver->m_timeStep + m_stgEddies[n][1];
1996 xk[2] = m_stgMaxVel[2] * m_solver->m_timeStep + m_stgEddies[n][2];
1997
1998 epsi[0] = m_stgEddies[n][3];
1999 epsi[1] = m_stgEddies[n][4];
2000 epsi[2] = m_stgEddies[n][5];
2001 }
2002
2003 eddyBcastBuffer[n + m_stgMaxNoEddies * 0] = xk[0];
2004 eddyBcastBuffer[n + m_stgMaxNoEddies * 1] = xk[1];
2005 eddyBcastBuffer[n + m_stgMaxNoEddies * 2] = xk[2];
2006 eddyBcastBuffer[n + m_stgMaxNoEddies * 3] = epsi[0];
2007 eddyBcastBuffer[n + m_stgMaxNoEddies * 4] = epsi[1];
2008 eddyBcastBuffer[n + m_stgMaxNoEddies * 5] = epsi[2];
2009 }
2010 }
2011
2012 // Broadcast the new/updated eddies to all relevant processes
2013 MPI_Bcast(eddyBcastBuffer.begin(), m_stgMaxNoEddies * m_stgNoEddieProperties, MPI_DOUBLE, m_commStgRoot, m_commStg,
2014 AT_, "eddyBcastBuffer.begin()");
2015
2016 MPI_Bcast(eddyBcastStrength.begin(), m_stgMaxNoEddies, MPI_DOUBLE, m_commStgRoot, m_commStg, AT_,
2017 "eddyBcastStrength.begin()");
2018
2019 // Copy data into m_FQeddie vector
2020 for(MInt n = 0; n < m_stgMaxNoEddies; n++) {
2021 for(MInt p = 0; p < m_stgNoEddieProperties; p++) {
2022 m_stgEddies[n][p] = eddyBcastBuffer[n + m_stgMaxNoEddies * p];
2023 }
2024 m_stgEddyStrength[n] = eddyBcastStrength[n];
2025 }
2026}
2027
2028template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
2030 const MFloat BLT3 = std::abs(m_stgVbEnd[m_periodicDir] - m_stgVbStart[m_periodicDir]);
2031 const MFloat Vb = m_stgBLT2 * BLT3 * m_stgBLT1 * POW2(m_stgDelta99Inflow);
2032
2033 // Summary of synth turb parameters
2034 if(m_stgMyRank == m_commStgRoot && globalTimeStep == m_solver->m_restartTimeStep) {
2035 std::cout << "**************************" << std::endl
2036 << "Synthetic turbulence (bcId=" << m_bcId << "):" << std::endl
2037 << "zones: 1" << std::endl
2038 << "Dir: " << m_stgFaceNormalDir << " / " << m_stgWallNormalDir << " / " << m_stgDir << " / " << m_wallDir
2039 << std::endl
2040 << "nr. eddies: " << m_stgMaxNoEddies << std::endl
2041 << "conv. vel: " << sqrt(POW2(m_stgMaxVel[0]) + POW2(m_stgMaxVel[1]) + POW2(m_stgMaxVel[2])) << std::endl
2042 << "umax = " << m_stgMaxVel[0] << std::endl
2043 << "vmax = " << m_stgMaxVel[1] << std::endl
2044 << "wmax = " << m_stgMaxVel[2] << std::endl
2045 << "virtual box volume: " << Vb << std::endl
2046 << "Vb/stgMaxNoEddies = " << Vb / m_stgMaxNoEddies << std::endl
2047 << "**************************" << std::endl;
2048 }
2049}
2050
2051
2052template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
2054 TRACE();
2055
2056 const MFloat BLT3 = std::abs(m_stgVbEnd[m_periodicDir] - m_stgVbStart[m_periodicDir]);
2057 MFloat Vb = m_stgBLT1 * m_stgBLT2 * POW2(m_stgDelta99Inflow) * BLT3;
2058 if(m_freeStreamTurbulence || m_isotropicTurbulence) {
2059 const MFloat BLT2 = std::abs(m_stgVbEnd[m_wallDir] - m_stgVbStart[m_wallDir]);
2060 Vb = m_stgBLT1 * m_stgDelta99Inflow * BLT2 * BLT3;
2061 }
2062 // const MFloat Vb = m_stgBLT1 * m_stgBLT2 * POW2(m_stgDelta99Inflow) * BLT3;
2063 const MFloat vbFactor = sqrt(Vb / m_stgMaxNoEddies);
2064
2065 const MFloat umax = m_stgMaxVel[0];
2066 const MFloat vmax = m_stgMaxVel[1];
2067 const MFloat wmax = m_stgMaxVel[2];
2068
2069 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
2070 const MInt cellIdBC = a->getStgId(it);
2071 const MInt cellIdBCFirst = cellIdBC;
2072 const MInt cellId = a->getCellId(it);
2073
2074 MFloat help1 = F0, help2 = F0, help3 = F0, help4 = F0, help5 = F0, help6 = F0;
2075
2076 const MFloat uu = m_stgLVariables[STG::FLUC_UU][cellIdBCFirst];
2077 const MFloat vv = m_stgLVariables[STG::FLUC_VV][cellIdBCFirst];
2078 const MFloat ww = m_stgLVariables[STG::FLUC_WW][cellIdBCFirst];
2079 const MFloat uv = m_stgLVariables[STG::FLUC_UV][cellIdBCFirst];
2080 const MFloat vw = m_stgLVariables[STG::FLUC_VW][cellIdBCFirst];
2081 const MFloat uw = m_stgLVariables[STG::FLUC_UW][cellIdBCFirst];
2082
2083 // Cholesky decomposition of the Reynolds stress tensor
2084 const MFloat a11 = sqrt(std::max(uu, epsl));
2085 const MFloat a21 = uv / a11;
2086 const MFloat a31 = uw / a11;
2087 const MFloat a22 = sqrt(std::max((vv - a21 * a21), epsl));
2088 const MFloat a32 = (vw - a21 * a31) / a22;
2089 const MFloat a33 = sqrt(std::max((ww - a31 * a31 - a32 * a32), epsl));
2090
2091 for(MInt n = 0; n < m_stgMaxNoEddies; n++) {
2092 // Tent function to determine the symmetric function to model the
2093 // decay of the fluctuations
2094 const MFloat xk1t = m_stgEddies[n][0];
2095 const MFloat xk2t = m_stgEddies[n][1];
2096 const MFloat xk3t = m_stgEddies[n][2];
2097
2098 MFloat distX = LES->a_coordinate(cellId, 0) - xk1t;
2099 MFloat distY = LES->a_coordinate(cellId, 1) - xk2t;
2100 MFloat distZ = LES->a_coordinate(cellId, 2) - xk3t;
2101
2102 if(m_cylinderTransformation) {
2103 MFloat y = LES->a_coordinate(cellId, m_wallDir);
2104 MFloat z = LES->a_coordinate(cellId, m_periodicDir);
2105 MFloat r = sqrt(y * y + z * z);
2106 MFloat alpha = get_angle(y, z);
2107 distY = r - xk2t;
2108 distZ = std::fmod(r * (alpha - xk3t), 2 * r * PI); // Distance of 2*PI means zero distance
2109 }
2110
2111 // if(m_newStgMethod){
2112 const MFloat xLb1 = m_stgLVariables[STG::LENGTH_X][cellIdBCFirst] * m_stgEddyStrength[n];
2113 const MFloat xLb2 = m_stgLVariables[STG::LENGTH_Y][cellIdBCFirst] * m_stgEddyStrength[n];
2114 const MFloat xLb3 = m_stgLVariables[STG::LENGTH_Z][cellIdBCFirst] * m_stgEddyStrength[n];
2115 //}
2116
2117 const MFloat fxLb1 = 1.0 / xLb1;
2118 const MFloat fxLb2 = 1.0 / xLb2;
2119 const MFloat fxLb3 = 1.0 / xLb3;
2120
2121 const MFloat fsqrtxLb1 = 1.0 / sqrt(xLb1);
2122 const MFloat fsqrtxLb2 = 1.0 / sqrt(xLb2);
2123 const MFloat fsqrtxLb3 = 1.0 / sqrt(xLb3);
2124
2125 const MFloat fsqrtPixLb1 = 1.0 / sqrt(3.141 * xLb1);
2126 const MFloat fsqrtPixLb2 = 1.0 / sqrt(3.141 * xLb2);
2127 const MFloat fsqrtPixLb3 = 1.0 / sqrt(3.141 * xLb3);
2128
2129 const MFloat aDistX = fabs(distX);
2130 const MFloat aDistY = fabs(distY);
2131 const MFloat aDistZ = fabs(distZ);
2132
2133 // only compute contribution if eddie is in vicinity, i.e.,
2134 // if it is within 4 eddy lengthscales
2135 if(aDistX < 4.0 * xLb1 && aDistY < 4.0 * xLb2 && aDistZ < 4.0 * xLb3) {
2136 const MFloat zacfq1 = distX / aDistX;
2137 const MFloat rol1H = zacfq1 * std::min(aDistX * fxLb1, 1.0);
2138
2139 const MFloat zacfq2 = distY / aDistY;
2140 const MFloat rol2H = zacfq2 * std::min(aDistY * fxLb2, 1.0);
2141
2142 const MFloat zacfq3 = distZ / aDistZ;
2143 const MFloat rol3H = zacfq3 * std::min(aDistZ * fxLb3, 1.0);
2144
2145 const MFloat fl1 = 2.0 * fsqrtPixLb1 * exp(-((distX)*2 * fxLb1) * ((distX)*2 * fxLb1));
2146 const MFloat fl2 = 2.0 * fsqrtPixLb2 * exp(-((distY)*2 * fxLb2) * ((distY)*2 * fxLb2));
2147 const MFloat fl3 = 2.0 * fsqrtPixLb3 * exp(-((distZ)*2 * fxLb3) * ((distZ)*2 * fxLb3));
2148
2149 // Normalization factor cannot be chosen as Pamies did... or we...
2150 MFloat fH1 = (F1 - cos(2.0 * 3.141 * rol1H)) / (2.0 * 3.141 * rol1H * 0.44);
2151 MFloat fH2 = (F1 - cos(2.0 * 3.141 * rol2H)) / (2.0 * 3.141 * rol2H * 0.44);
2152 MFloat fH3 = (F1 - cos(2.0 * 3.141 * rol3H)) / (2.0 * 3.141 * rol3H * 0.44);
2153
2154 fH1 = aniso * fH1 * fsqrtxLb1 + fabs(aniso - 1.0) * fl1;
2155 fH2 = aniso * fH2 * fsqrtxLb2 + fabs(aniso - 1.0) * fl2;
2156 fH3 = aniso * fH3 * fsqrtxLb3 + fabs(aniso - 1.0) * fl3;
2157
2158 const MFloat epsik1 = m_stgEddies[n][3];
2159 const MFloat epsik2 = m_stgEddies[n][4];
2160 const MFloat epsik3 = m_stgEddies[n][5];
2161
2162 help4 += vbFactor * epsik1 * fl1 * fl2 * fH3;
2163 help5 += vbFactor * epsik2 * fl1 * fl2 * fH3;
2164 help6 += vbFactor * epsik3 * fl1 * fH2 * fl3;
2165
2166 // if(m_newStgMethod){
2167 // MFloat coverage = POW2(fl1 * fl2 * fH3);
2168 // MFloat T = 2 * m_stgLVariables[STG::LENGTH_X][cellIdBC] / m_stgMaxVel[m_stgDir];
2169 // MFloat alpha = m_solver->timeStep() / T;
2170 // m_stgEddieCoverage[0][cellIdBC] = alpha * coverage + (1 - alpha) * m_stgEddieCoverage[0][cellIdBC];
2171
2172 // //transfer
2173 // m_solver->m_stgEddieCoverage[0][cellId] = m_stgEddieCoverage[0][cellIdBC];
2174 // }
2175 }
2176 }
2177
2178 help1 = help4 * a11; // Fluctuation u'
2179 help2 = help4 * a21 + help5 * a22; // Fluctuation v'
2180 help3 = help4 * a31 + help5 * a32 + help6 * a33; // Fluctuation w'
2181
2182 const MFloat velmax = sqrt(umax * umax + vmax * vmax + wmax * wmax);
2183
2184 MFloat ufluc = std::min(std::max(help1, -0.3 * velmax), 0.3 * velmax);
2185 MFloat vfluc = std::min(std::max(help2, -0.3 * velmax), 0.3 * velmax);
2186 MFloat wfluc = std::min(std::max(help3, -0.3 * velmax), 0.3 * velmax);
2187
2188 if(m_cylinderTransformation) {
2189 MFloat y = m_solver->a_coordinate(cellId, m_wallDir);
2190 MFloat z = m_solver->a_coordinate(cellId, m_periodicDir);
2191 MFloat alpha = get_angle(y, z);
2192 MFloat vtemp = vfluc;
2193 MFloat wtemp = wfluc;
2194 vfluc = vtemp * cos(alpha) + wtemp * sin(alpha);
2195 wfluc = vtemp * sin(alpha) - wtemp * cos(alpha);
2196 }
2197
2198 m_stgLVariables[STG::FLUC_U][cellIdBC] += timsm * (ufluc - m_stgLVariables[STG::FLUC_U][cellIdBC]);
2199 m_stgLVariables[STG::FLUC_V][cellIdBC] += timsm * (vfluc - m_stgLVariables[STG::FLUC_V][cellIdBC]);
2200 m_stgLVariables[STG::FLUC_W][cellIdBC] += timsm * (wfluc - m_stgLVariables[STG::FLUC_W][cellIdBC]);
2201 }
2202}
2203
2204
2205template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
2207 TRACE();
2208
2209 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
2210 const MInt IBC = a->getStgId(it);
2211
2212 m_stgEddieCoverage[1][IBC] = F0;
2213 }
2214
2215 std::vector<MFloat> eddieCoverage(m_stgGlobalNoWallNormalLocations, F0);
2216
2217 for(MInt i = 0; i < m_stgGlobalNoWallNormalLocations; i++) {
2218 for(MInt p = 0; p < (MInt)m_stgPeriodicCellId[i].size(); p++) {
2219 MInt id = m_stgPeriodicCellId[i][p];
2220 eddieCoverage[i] += m_stgEddieCoverage[0][id] / m_stgGlobalNoPeriodicLocations[i];
2221 }
2222 }
2223
2224 MPI_Allreduce(MPI_IN_PLACE, &eddieCoverage[0], m_stgGlobalNoWallNormalLocations, MPI_DOUBLE, MPI_SUM, m_commStg, AT_,
2225 "MPI_IN_PLACE", "m_LESPeriodicAverage");
2226
2227 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
2228 const MInt IBC = a->getStgId(it);
2229 const MInt cellId = a->getCellId(it);
2230
2231 MFloat index = m_stgPeriodicIndex[IBC];
2232 m_stgEddieCoverage[1][IBC] = eddieCoverage[index];
2233
2234 m_solver->m_stgEddieCoverage[1][cellId] = m_stgEddieCoverage[1][IBC];
2235 m_solver->m_stgEddieCoverage[2][cellId] = m_stgEddieCoverage[1][IBC] - m_stgEddieCoverage[0][IBC];
2236 }
2237}
2238
2239
2240template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
2241template <class _, std::enable_if_t<SolverTypeL == MAIA_STRUCTURED, _*>>
2243 const MInt noSTGVariables = STG::noSTGVars - PV->noVariables;
2244
2245 const MInt k = it.getijk(2);
2246 if(k == a->start(2) + 1) {
2247 // 1st layer
2248 for(MInt var = PV->noVariables; var < noSTGVariables; ++var) {
2249 m_stgLVariables[var][it.getNghbrStg(4)] = m_stgLVariables[var][it.getStgId()];
2250 }
2251 } else if(k == a->end(2) - a->m_noGhostLayers) {
2252 // 1st layer
2253 for(MInt var = PV->noVariables; var < noSTGVariables; ++var) {
2254 m_stgLVariables[var][it.getNghbrStg(5)] = m_stgLVariables[var][it.getStgId()];
2255 }
2256 }
2257
2258 const MInt j = it.getijk(1);
2259 if(j == a->start(1) + 1) {
2260 for(MInt var = PV->noVariables; var < noSTGVariables; ++var) {
2261 m_stgLVariables[var][it.getNghbrStg(2)] = m_stgLVariables[var][it.getStgId()];
2262 }
2263 } else if(j == a->end(1) - a->m_noGhostLayers) {
2264 for(MInt var = PV->noVariables; var < noSTGVariables; ++var) {
2265 m_stgLVariables[var][it.getNghbrStg(3)] = m_stgLVariables[var][it.getStgId()];
2266 }
2267 }
2268}
2269
2270
2271template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
2272template <class _, std::enable_if_t<SolverTypeL == MAIA_STRUCTURED, _*>>
2274 const MInt cellIdG1 = a->getCellId(it);
2275 const MInt cellIdA1 = a->getNghbr(it, 1); // express this by means of face
2276 const MInt cellIdG2 = a->getNghbr(it, 0);
2277 // const MInt cellIdG2 = cellIndex(0,j,k);
2278 // extrapolate into second ghost cell
2279 for(MInt var = 0; var < PV->noVariables; var++) {
2280 LES->a_pvariable(cellIdG2, var) = F2 * LES->a_pvariable(cellIdG1, var) - LES->a_pvariable(cellIdA1, var);
2281 }
2282}
2283
2284
2285template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
2286template <class _, std::enable_if_t<SolverTypeL == MAIA_FINITE_VOLUME, _*>>
2288 TRACE();
2289
2290 const MFloat gamma = m_solver->m_gamma;
2291 const MFloat gammaMinusOne = gamma - 1.0;
2292
2293 if(m_initialRange || globalTimeStep < m_solver->m_stgStartTimeStep) {
2294 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
2295 const MInt cellIdG1 = a->getCellId(it);
2296 const MInt IBC = a->getStgId(it);
2297
2298 if(m_cutOff) {
2299 LES->a_pvariable(cellIdG1, PV->RHO) = m_stgLVariables[STG::AVG_RHO][IBC];
2300 LES->a_pvariable(cellIdG1, PV->U) = m_stgLVariables[STG::AVG_U][IBC];
2301 LES->a_pvariable(cellIdG1, PV->V) = m_stgLVariables[STG::AVG_V][IBC];
2302 LES->a_pvariable(cellIdG1, PV->W) = m_stgLVariables[STG::AVG_W][IBC];
2303 } else {
2304 const MInt ghostCellId = a->getGhostIdFromStgId(IBC);
2305 // Density
2306 LES->a_pvariable(ghostCellId, PV->RHO) =
2307 2.0 * m_stgLVariables[STG::AVG_RHO][IBC] - LES->a_pvariable(cellIdG1, PV->RHO);
2308 // Velocitiy
2309 LES->a_pvariable(ghostCellId, PV->U) =
2310 2.0 * m_stgLVariables[STG::AVG_U][IBC] - LES->a_pvariable(cellIdG1, PV->U);
2311 LES->a_pvariable(ghostCellId, PV->V) =
2312 2.0 * m_stgLVariables[STG::AVG_V][IBC] - LES->a_pvariable(cellIdG1, PV->V);
2313 LES->a_pvariable(ghostCellId, PV->W) =
2314 2.0 * m_stgLVariables[STG::AVG_W][IBC] - LES->a_pvariable(cellIdG1, PV->W);
2315 // Pressure
2316 LES->a_pvariable(ghostCellId, PV->P) =
2317 2.0 * m_stgLVariables[STG::AVG_P][IBC] - LES->a_pvariable(cellIdG1, PV->P);
2318 }
2319 }
2320
2321 } else {
2322 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
2323 const MInt cellIdG1 = a->getCellId(it);
2324 const MInt IBC = a->getStgId(it);
2325 // TODO: CHECK THIS LATER
2326 const MInt cellIdA1 = cellIdG1;
2327 // if(m_cutOff) {
2328 // const MInt cellIdA1 = a->getNghbr(it, 1); // cellIdG1; // a->getNghbr(it, 1); //express this by means of face
2329 // }
2330
2331 // TODO: especially check if this is true if stg is applied at +x
2332 MFloat dxidx = 1;
2333 MFloat dxidy = 0;
2334 MFloat dxidz = 0;
2335
2336 MFloat gradxi = -F1 / sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz);
2337
2338 MFloat dxHelp = dxidx * gradxi;
2339 MFloat dyHelp = dxidy * gradxi;
2340 MFloat dzHelp = dxidz * gradxi;
2341
2342 // compute Mach number perpendicular to inlet
2343 const MFloat rhoBC = LES->a_pvariable(cellIdG1, PV->RHO);
2344 const MFloat pBC = LES->a_pvariable(cellIdG1, PV->P);
2345 const MFloat fRhoBC = F1 / rhoBC;
2346 const MFloat aBC = sqrt(gamma * pBC * fRhoBC);
2347 const MFloat uBC = LES->a_pvariable(cellIdG1, PV->U);
2348 const MFloat vBC = LES->a_pvariable(cellIdG1, PV->V);
2349 const MFloat wBC = LES->a_pvariable(cellIdG1, PV->W);
2350
2351 const MFloat maBC = (dxHelp * uBC + dyHelp * vBC + dzHelp * wBC) / aBC;
2353
2356 // get mean values from the rans
2357 const MFloat rhoRANS = m_stgLVariables[STG::AVG_RHO][IBC];
2358 const MFloat uRANS = m_stgLVariables[STG::AVG_U][IBC];
2359 const MFloat vRANS = m_stgLVariables[STG::AVG_V][IBC];
2360 const MFloat wRANS = m_stgLVariables[STG::AVG_W][IBC];
2361 const MFloat pRANS = m_stgLVariables[STG::AVG_P][IBC];
2362
2363 // fluctuation values from the STG
2364 const MFloat u_prime = m_stgLVariables[STG::FLUC_U][IBC];
2365 const MFloat v_prime = m_stgLVariables[STG::FLUC_V][IBC];
2366 const MFloat w_prime = m_stgLVariables[STG::FLUC_W][IBC];
2367
2368 // superpose onto mean RANS variables
2369 const MFloat uSTG = std::max(uRANS + u_prime, epsl);
2370 const MFloat vSTG = vRANS + v_prime;
2371 const MFloat wSTG = wRANS + w_prime;
2372
2373 // compute correct density
2374 const MFloat u9a = LES->UInfinity();
2375 const MFloat u9ff = u_prime;
2376 const MFloat alok = sqrt(gamma * LES->PInfinity() / LES->rhoInfinity());
2377 const MFloat flucc =
2378 u9ff / u9a * POW2((LES->UInfinity() / alok)) * gammaMinusOne * m_stgLVariables[STG::AVG_RHO][IBC];
2379 const MFloat zdir = flucc / std::max(fabs(flucc), 0.0000001);
2380 const MFloat rhoSTG = rhoRANS + zdir * std::min(fabs(flucc), 0.1 * rhoRANS);
2381
2382 // get field values inside the integration domain
2383 const MFloat pField = LES->a_pvariable(cellIdA1, PV->P);
2384 const MFloat rhoField = LES->a_pvariable(cellIdA1, PV->RHO);
2385 const MFloat uField = LES->a_pvariable(cellIdA1, PV->U);
2386 const MFloat vField = LES->a_pvariable(cellIdA1, PV->V);
2387 const MFloat wField = LES->a_pvariable(cellIdA1, PV->W);
2388 const MFloat aField = sqrt(gamma * pField / rhoField);
2389
2393 const MFloat pSub =
2394 F1B2
2395 * (pField + pRANS
2396 + rhoField * aField * (+dxHelp * (uField - uSTG) + dyHelp * (vField - vSTG) + dzHelp * (wField - wSTG)));
2397 const MFloat rhoSub = rhoSTG + (pSub - pRANS) / (POW2(aField));
2398 const MFloat rhoSubHelp = (pSub - pRANS) / (rhoField * aField);
2399
2400 // Multiply velocities with density
2401 const MFloat uSub = uSTG + dxHelp * rhoSubHelp;
2402 const MFloat vSub = vSTG + dyHelp * rhoSubHelp;
2403 const MFloat wSub = wSTG + dzHelp * rhoSubHelp;
2404
2408 const MFloat rhoSup = rhoSTG;
2409 const MFloat uSup = uSTG;
2410 const MFloat vSup = vSTG;
2411 const MFloat wSup = wSTG;
2412 const MFloat pSup = pRANS;
2413
2417
2418 // by default the subsonic formulation is used
2419 // switch on "stgSubSup" to get the mixed formulation
2420 // or "stgSupersonic" to use the pure supersonic formulation
2421 MFloat xSub = F1;
2422 MFloat xSup = F0;
2423
2424 if(m_stgSubSup) {
2425 const MFloat maBCAbs = fabs(maBC);
2426 const MFloat alpha = 14.0;
2427 const MFloat b = 0.95;
2428 const MFloat count = alpha * (maBCAbs - b);
2429 const MFloat denom = (F1 - 0.99 * b) * maBCAbs + b;
2430 const MFloat ratio = count / denom;
2431 const MFloat wfun = F1B2 * (F1 + tanh(ratio) / tanh(alpha));
2432
2433 xSub = fabs(wfun - F1);
2434 xSup = fabs(wfun);
2435 } else if(m_stgSupersonic) {
2436 xSub = F0;
2437 xSup = F1;
2438 }
2439
2440 const MFloat rho_target = rhoSub * xSub + rhoSup * xSup;
2441 const MFloat u_target = uSub * xSub + uSup * xSup;
2442 const MFloat v_target = vSub * xSub + vSup * xSup;
2443 const MFloat w_target = wSub * xSub + wSup * xSup;
2444 const MFloat p_target = pSub * xSub + pSup * xSup;
2445
2446 if(m_cutOff) {
2447 LES->a_pvariable(cellIdG1, PV->RHO) = rho_target;
2448 LES->a_pvariable(cellIdG1, PV->U) = u_target;
2449 LES->a_pvariable(cellIdG1, PV->V) = v_target;
2450 LES->a_pvariable(cellIdG1, PV->W) = w_target;
2451 } else {
2452 const MInt ghostCellId = a->getGhostIdFromStgId(IBC);
2453 LES->a_pvariable(ghostCellId, PV->RHO) = 2.0 * rho_target - LES->a_pvariable(cellIdG1, PV->RHO);
2454 LES->a_pvariable(ghostCellId, PV->U) = 2.0 * u_target - LES->a_pvariable(cellIdG1, PV->U);
2455 LES->a_pvariable(ghostCellId, PV->V) = 2.0 * v_target - LES->a_pvariable(cellIdG1, PV->V);
2456 LES->a_pvariable(ghostCellId, PV->W) = 2.0 * w_target - LES->a_pvariable(cellIdG1, PV->W);
2457 LES->a_pvariable(ghostCellId, PV->P) = 2.0 * p_target - LES->a_pvariable(cellIdG1, PV->P);
2458 }
2459 }
2460 }
2461}
2462
2463
2464template <MInt nDim, SolverType SolverTypeR, SolverType SolverTypeL>
2465template <class _, std::enable_if_t<SolverTypeL == MAIA_STRUCTURED, _*>>
2467 const MFloat gamma = m_solver->m_gamma;
2468 const MFloat gammaMinusOne = gamma - 1.0;
2469
2470 for(typename Accessor::nDim_citerator it = a->iterateB1(); it != a->iterateB1_nDim_citerator_end(); ++it) {
2471 const MInt cellIdG1 = a->getCellId(it);
2472 const MInt IBC = a->getStgId(it);
2473 const MInt cellIdA1 = a->getNghbr(it, 1); // express this by means of face
2474
2475
2476 MFloat dxidx = m_solver->m_cells->cellMetrics[cellIdA1][0];
2477 MFloat dxidy = m_solver->m_cells->cellMetrics[cellIdA1][1];
2478 MFloat dxidz = m_solver->m_cells->cellMetrics[cellIdA1][2];
2479
2480 MFloat gradxi = -F1 / sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz);
2481
2482 MFloat dxHelp = dxidx * gradxi;
2483 MFloat dyHelp = dxidy * gradxi;
2484 MFloat dzHelp = dxidz * gradxi;
2485
2486 // compute Mach number perpendicular to inlet
2487 const MFloat rhoBC = LES->a_pvariable(cellIdG1, PV->RHO);
2488 const MFloat pBC = LES->a_pvariable(cellIdG1, PV->P);
2489 const MFloat fRhoBC = F1 / rhoBC;
2490 const MFloat aBC = sqrt(gamma * pBC * fRhoBC);
2491 const MFloat uBC = LES->a_pvariable(cellIdG1, PV->U);
2492 const MFloat vBC = LES->a_pvariable(cellIdG1, PV->V);
2493 const MFloat wBC = LES->a_pvariable(cellIdG1, PV->W);
2494
2495 const MFloat maBC = (dxHelp * uBC + dyHelp * vBC + dzHelp * wBC) / aBC;
2497
2500 // get mean values from the rans
2501 const MFloat rhoRANS = m_stgLVariables[STG::AVG_RHO][IBC];
2502 const MFloat uRANS = m_stgLVariables[STG::AVG_U][IBC];
2503 const MFloat vRANS = m_stgLVariables[STG::AVG_V][IBC];
2504 const MFloat wRANS = m_stgLVariables[STG::AVG_W][IBC];
2505 const MFloat pRANS = m_stgLVariables[STG::AVG_P][IBC];
2506
2507 // fluctuation values from the STG
2508 const MFloat u_prime = m_stgLVariables[STG::FLUC_U][IBC];
2509 const MFloat v_prime = m_stgLVariables[STG::FLUC_V][IBC];
2510 const MFloat w_prime = m_stgLVariables[STG::FLUC_W][IBC];
2511
2512 // superpose onto mean RANS variables
2513 const MFloat uSTG = std::max(uRANS + u_prime, epsl);
2514 const MFloat vSTG = vRANS + v_prime;
2515 const MFloat wSTG = wRANS + w_prime;
2516
2517 // compute correct density
2518 const MFloat u9a = LES->UInfinity();
2519 const MFloat u9ff = u_prime;
2520 const MFloat alok = sqrt(gamma * LES->PInfinity() / LES->rhoInfinity());
2521 const MFloat flucc =
2522 u9ff / u9a * POW2((LES->UInfinity() / alok)) * gammaMinusOne * m_stgLVariables[STG::AVG_RHO][IBC];
2523 const MFloat zdir = flucc / std::max(fabs(flucc), 0.0000001);
2524 const MFloat rhoSTG = rhoRANS + zdir * std::min(fabs(flucc), 0.1 * rhoRANS);
2525
2526 // get field values inside the integration domain
2527 const MFloat pField = LES->a_pvariable(cellIdA1, PV->P);
2528 const MFloat rhoField = LES->a_pvariable(cellIdA1, PV->RHO);
2529 const MFloat uField = LES->a_pvariable(cellIdA1, PV->U);
2530 const MFloat vField = LES->a_pvariable(cellIdA1, PV->V);
2531 const MFloat wField = LES->a_pvariable(cellIdA1, PV->W);
2532 const MFloat aField = sqrt(gamma * pField / rhoField);
2533
2537 const MFloat pSub =
2538 F1B2
2539 * (pField + pRANS
2540 + rhoField * aField * (+dxHelp * (uField - uSTG) + dyHelp * (vField - vSTG) + dzHelp * (wField - wSTG)));
2541 const MFloat rhoSub = rhoSTG + (pSub - pRANS) / (POW2(aField));
2542 const MFloat rhoSubHelp = (pSub - pRANS) / (rhoField * aField);
2543
2544 // Multiply velocities with density
2545 const MFloat uSub = uSTG + dxHelp * rhoSubHelp;
2546 const MFloat vSub = vSTG + dyHelp * rhoSubHelp;
2547 const MFloat wSub = wSTG + dzHelp * rhoSubHelp;
2548
2552 const MFloat rhoSup = rhoSTG;
2553 const MFloat uSup = uSTG;
2554 const MFloat vSup = vSTG;
2555 const MFloat wSup = wSTG;
2556 const MFloat pSup = pRANS;
2557
2561
2562 // by default the subsonic formulation is used
2563 // switch on "stgSubSup" to get the mixed formulation
2564 // or "stgSupersonic" to use the pure supersonic formulation
2565 MFloat xSub = F1;
2566 MFloat xSup = F0;
2567
2568 if(m_stgSubSup) {
2569 const MFloat maBCAbs = fabs(maBC);
2570 const MFloat alpha = 14.0;
2571 const MFloat b = 0.95;
2572 const MFloat count = alpha * (maBCAbs - b);
2573 const MFloat denom = (F1 - 0.99 * b) * maBCAbs + b;
2574 const MFloat ratio = count / denom;
2575 const MFloat wfun = F1B2 * (F1 + tanh(ratio) / tanh(alpha));
2576
2577 xSub = fabs(wfun - F1);
2578 xSup = fabs(wfun);
2579 } else if(m_stgSupersonic) {
2580 xSub = F0;
2581 xSup = F1;
2582 }
2583
2584 LES->a_pvariable(cellIdG1, PV->RHO) = rhoSub * xSub + rhoSup * xSup;
2585 LES->a_pvariable(cellIdG1, PV->U) = uSub * xSub + uSup * xSup;
2586 LES->a_pvariable(cellIdG1, PV->V) = vSub * xSub + vSup * xSup;
2587 LES->a_pvariable(cellIdG1, PV->W) = wSub * xSub + wSup * xSup;
2588 LES->a_pvariable(cellIdG1, PV->P) = pSub * xSub + pSup * xSup;
2589
2590
2594 extrapolateToGX(it);
2595 // }
2596 }
2597}
2598
2599
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
Definition: alloc.h:173
Definition: fvstg.h:88
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
Definition: context.cpp:494
Definition: fvstg.h:609
void getInflowStartEnd(MFloat *, MFloat *)
Definition: fvstg.cpp:1000
MFloat ** m_stgEddieCoverage
Definition: fvstg.h:768
MFloat getCellSize(typename Accessor::nDim_citerator it)
Definition: fvstg.cpp:1895
MBool m_newStgMethod
Definition: fvstg.h:766
void setVb(MFloat *, MFloat *)
Definition: fvstg.cpp:1071
void extrapolateToGX(typename Accessor::nDim_citerator)
Definition: fvstg.cpp:2273
MInt m_stgDir
Definition: fvstg.h:742
void calcTotalFluctuationCholesky()
Definition: fvstg.cpp:2053
MFloat generate_rand()
Definition: fvstg.cpp:80
void setSTGProperties()
void printSTGSummary()
Definition: fvstg.cpp:2029
void bc7909()
Reformulated Synthetic Turbulence Generation Synthetic Turbulence Generation Method Computes fluctuat...
Definition: fvstg.cpp:788
MFloat ** m_stgLVariables
Definition: fvstg.h:753
void calcReynoldsStressConvVelLengthScale()
Definition: fvstg.cpp:1682
void loadStg()
Definition: fvstg.cpp:740
MFloat generate_rand_normalDist()
Definition: fvstg.cpp:103
void advanceEddies()
Definition: fvstg.cpp:1964
MFloat get_angle(MFloat y, MFloat z)
Definition: fvstg.cpp:109
MFloat generate_rand_weighted()
Definition: fvstg.cpp:96
void getBoundaryLayerThickness()
Definition: fvstg.cpp:846
void determinePeriodicCells()
Definition: fvstg.cpp:594
friend void saveStg(std::map< MInt, self * >, SolverTypeL_ *)
void apply()
Definition: fvstg.cpp:2287
MInt m_wallDir
Definition: fvstg.h:743
MSTG(FvCartesianSolverXD< nDim, FvSysEqnNS< nDim > > *solver, MInt bcId, const MPI_Comm commStg, MInt *sortedBndryCellIds, MInt noStgLCells, MInt stgFaceNormalDir, MInt stgDir, MInt stgWallNormalDir, MInt wallDir, MBool cutOff)
Definition: fvstg.cpp:26
void readRANSProfileStg()
write RANSValues from solver to stgLVariables (fully coupled) /author Jannik Borgelt
Definition: fvstg.cpp:1140
void calcStrainRate()
Definition: fvstg.cpp:1472
void generateNewEddies(MFloat *, MFloat *)
Definition: fvstg.cpp:1929
MBool m_stgLocal
Definition: fvstg.h:734
MInt m_periodicDir
Definition: fvstg.h:744
void calcEddieCoverage()
Definition: fvstg.cpp:2206
void init(MInt commStgRoot)
Definition: fvstg.cpp:505
void extrapolateToBoundary(typename Accessor::nDim_citerator)
Definition: fvstg.cpp:2242
This class is a ScratchSpace.
Definition: scratch.h:758
void fill(T val)
fill the scratch with a given value
Definition: scratch.h:311
iterator begin()
Definition: scratch.h:273
value_type getStgId() const
Definition: fvstg.h:74
typename base_iterator::value_type value_type
Definition: fvstg.h:64
value_type getCellId() const
Definition: fvstg.cpp:20
value_type getNghbr(MInt dir) const
Definition: fvstg.cpp:13
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
constexpr Real POW2(const Real x)
Definition: functions.h:119
@ HasCoarseNghbr
cell has a coarse nghbr (only set for cells with IsNotGradient==false)
void saveStg(std::map< MInt, MSTG< nDim, SolverTypeR, SolverTypeL > * > stgBC, typename SolverTraits< nDim, SolverTypeL >::SolverType *solver)
MInt globalTimeStep
InfoOutFile m_log
int32_t MInt
Definition: maiatypes.h:62
uint32_t MUint
Definition: maiatypes.h:63
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
MInt id
Definition: maiatypes.h:71
int MPI_Gatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Gatherv
int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Reduce
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
int MPI_Gather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Gather
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather
void const MInt cellId
Definition: collector.h:239
PARALLELIO_DEFAULT_BACKEND ParallelIo
Definition: parallelio.h:292
static constexpr const MInt noStgVars
Definition: fvstg.h:834
Definition: contexttypes.h:19
define array structures