MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
couplerlbfveemultiphase.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
8#include "LB/lbconstants.h"
9#include "couplerlbfv.h"
10#include "coupling.h"
11
12template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
13class CouplerLbFv;
14
15template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
18 : Coupling(couplerId), CouplerLbFv<nDim, nDist, SysEqnLb, SysEqnFv>(couplerId, lb, fv) {
19 initData();
21 initAlpha();
22}
23
24template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
26 if(m_alphaConvergenceCheck > 0) {
27 lbSolver().storeOldDistributions();
28 if(m_updateAfterPropagation) lbSolver().storeOldVariables();
29 }
30}
31
32template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
35 if(!fvSolver().m_EEGas.depthCorrection) {
36 mAlloc(m_depthCorrectionValues, fvSolver().maxNoGridCells(), "m_depthCorrectionValues", F0, AT_);
37 initDepthcorrection();
38 }
39}
40
41template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
43 if(!fvSolver().m_EEGas.depthCorrection) {
44 initDepthcorrection();
45 }
46 transferUFv2Lb();
47}
48
49template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
51 if(!fvSolver().m_EEGas.depthCorrection) {
52 TERMM(1, "not implemented for in-coupler depthCorrection!");
53 }
54}
55
56template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
58 std::vector<MBool>& solverCompleted) {
59 static MInt noAlphaIterations = 0;
60
61 if(m_redistributeAlpha && !m_disableSubstepAlphaRedist
62 && !(solverCompleted[a_lbSolverId()] && solverCompleted[a_fvSolverId()]))
63 correctInvalidAlpha();
64
65 if(solverCompleted[a_lbSolverId()] && solverCompleted[a_fvSolverId()]) {
66 if(m_redistributeAlpha) correctInvalidAlpha();
67 // both Solvers completed -> check for convergence of alpha
68 MBool alphaConverged = true;
69 if(noAlphaIterations < m_maxNoAlphaIterations) alphaConverged = checkAlphaConverged();
70 if(alphaConverged) {
71 transferAlphaFv2Lb();
72 transferUFv2Lb();
73
74#ifndef NDEBUG
75 if(fvSolver().domainId() == 0 && m_alphaConvergenceCheck != 0 && noAlphaIterations > 3) {
76 if(noAlphaIterations < m_maxNoAlphaIterations)
77 std::cerr << "Globaltimestep: " << globalTimeStep << " alpha Converged after " << noAlphaIterations
78 << " Iterations!" << std::endl;
79 else
80 std::cerr << "Globaltimestep: " << globalTimeStep
81 << " max number of alphaIterations reached: " << noAlphaIterations << std::endl;
82 }
83#endif
84
85 noAlphaIterations = 0;
86 return;
87 } else {
88 transferAlphaFv2Lb();
89 revertLb();
90 revertFv();
91 noAlphaIterations++;
92 solverCompleted[a_lbSolverId()] = false;
93 solverCompleted[a_fvSolverId()] = false;
94 return;
95 }
96 } else if(solverCompleted[a_lbSolverId()]) {
97 // LB Solver completed -> transfer new liquid variables
98 transferPressureLb2Fv(fvSolver().m_RKalpha[fvSolver().m_RKStep], m_updateFVBC);
99 if(fvSolver().m_RKStep == 0)
100 transferULb2Fv<true>(fvSolver().m_RKalpha[fvSolver().m_RKStep]);
101 else
102 transferULb2Fv<false>(fvSolver().m_RKalpha[fvSolver().m_RKStep]);
103 transferNuLb2Fv(fvSolver().m_RKalpha[fvSolver().m_RKStep]);
104 fvSolver().exchange();
105 return;
106 } else if(solverCompleted[a_fvSolverId()]) {
107 mTerm(1, AT_, "Fv Solver cant be completed before Lb Solver is completed in LB-FV-Euler-Euler-Multiphase!");
108 }
109}
110
111template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
113 transferPressureLb2Fv(1.0, false);
114}
115
116template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
118
119template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
121 switch(m_initAlphaMethod) {
122 case 0: // initialize alphaGas to be zero everywhere
123 {
124 for(MInt lbCellId = 0; lbCellId < a_noLbCells(); lbCellId++) {
125 lbSolver().a_alphaGas(lbCellId) = 0.0;
126 }
127 for(MInt fvCellId = 0; fvCellId < a_noFvCells(); fvCellId++) {
128 fvSolver().a_alphaGas(fvCellId) = 0.0;
129 }
130 break;
131 } // case 0
132
133 case 1: // initialize alphaGas to a constant value given in m_initialAlpha
134 {
135 const MFloat alpha = m_initialAlpha;
136 for(MInt lbCellId = 0; lbCellId < a_noLbCells(); lbCellId++) {
137 lbSolver().a_alphaGas(lbCellId) = alpha;
138 }
139 for(MInt fvCellId = 0; fvCellId < a_noFvCells(); fvCellId++) {
140 fvSolver().a_alphaGas(fvCellId) = alpha;
141 }
142 break;
143 } // case 1
144
145 case 2: // initialize alphaGas to a constant value given in m_initialAlpha in a sphere with radius 0.5 around the
146 // origin, else m_alphaInf
147 {
148 const MFloat alpha = m_initialAlpha;
149 for(MInt i = 0; i < a_noLbCells(); i++) {
150 MFloat xcoord = lbSolver().a_coordinate(i, 0);
151 MFloat ycoord = lbSolver().a_coordinate(i, 1);
152 MFloat zcoord = lbSolver().a_coordinate(i, 2);
153 if(xcoord * xcoord + ycoord * ycoord + zcoord * zcoord < 0.5) {
154 lbSolver().a_alphaGas(i) = alpha;
155 } else {
156 lbSolver().a_alphaGas(i) = m_alphaInf;
157 }
158 }
159 for(MInt i = 0; i < a_noFvCells(); i++) {
160 MFloat xcoord = fvSolver().a_coordinate(i, 0);
161 MFloat ycoord = fvSolver().a_coordinate(i, 1);
162 MFloat zcoord = fvSolver().a_coordinate(i, 2);
163 if(xcoord * xcoord + ycoord * ycoord + zcoord * zcoord < 0.5) {
164 fvSolver().a_alphaGas(i) = alpha;
165 } else {
166 fvSolver().a_alphaGas(i) = m_alphaInf;
167 }
168 }
169 break;
170 } // case 2
171
172 case 3: // initialize alphaGas to a constant value given in m_initialAlpha below the z value of 0, else m_alphaInf
173 {
174 const MFloat alpha = m_initialAlpha;
175 for(MInt i = 0; i < a_noLbCells(); i++) {
176 MFloat zcoord = lbSolver().a_coordinate(i, 2);
177 if(zcoord < 0.0) {
178 lbSolver().a_alphaGas(i) = alpha;
179 } else {
180 lbSolver().a_alphaGas(i) = m_alphaInf;
181 }
182 }
183 for(MInt i = 0; i < a_noFvCells(); i++) {
184 MFloat zcoord = fvSolver().a_coordinate(i, 2);
185 if(zcoord < 0.0) {
186 fvSolver().a_alphaGas(i) = alpha;
187 } else {
188 fvSolver().a_alphaGas(i) = m_alphaInf;
189 }
190 }
191 break;
192 }
193
194 case 4: // alpha Gradient in z direction with initial alpha at 0, alphaInf at 1 and (2 initial alpha - alphaInf) at
195 // -1
196 {
197 const MFloat delAlpha = m_initialAlpha - m_alphaInf;
198 for(MInt i = 0; i < a_noLbCells(); i++) {
199 MFloat zcoord = lbSolver().a_coordinate(i, 2);
200 if(zcoord < -1.0) {
201 lbSolver().a_alphaGas(i) = m_initialAlpha + delAlpha;
202 } else if(zcoord > 1.0) {
203 lbSolver().a_alphaGas(i) = m_initialAlpha - delAlpha;
204 } else {
205 lbSolver().a_alphaGas(i) = m_initialAlpha - zcoord * delAlpha;
206 }
207 }
208 for(MInt i = 0; i < a_noFvCells(); i++) {
209 MFloat zcoord = fvSolver().a_coordinate(i, 2);
210 if(zcoord < -1.0) {
211 fvSolver().a_alphaGas(i) = m_initialAlpha + delAlpha;
212 } else if(zcoord > 1.0) {
213 fvSolver().a_alphaGas(i) = m_initialAlpha - delAlpha;
214 } else {
215 fvSolver().a_alphaGas(i) = m_initialAlpha - zcoord * delAlpha;
216 }
217 }
218 break;
219 }
220
221 default: {
222 mTerm(1, AT_, "initAlphaMethod not matching any case!");
223 break;
224 } // default
225
226 } // switch (m_initAlphaMethod)
227}
228
229template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
240 m_alphaConvergenceCheck = 0;
241 if(Context::propertyExists("alphaConvergenceCheck", 0)) {
242 m_alphaConvergenceCheck = Context::getBasicProperty<MInt>("alphaConvergenceCheck", AT_, &m_alphaConvergenceCheck);
243 }
244
252 m_maxNoAlphaIterations = 4;
253 if(Context::propertyExists("maxNoAlphaIterations", 0)) {
254 m_maxNoAlphaIterations = Context::getBasicProperty<MInt>("maxNoAlphaIterations", AT_, &m_maxNoAlphaIterations);
255 }
256
264 m_epsAlpha = 1.0e-6;
265 if(Context::propertyExists("epsAlpha", 0)) {
266 m_epsAlpha = Context::getBasicProperty<MFloat>("epsAlpha", AT_, &m_epsAlpha);
267 }
268
276 m_alphaFloor = 0.0;
277 m_alphaFloor = Context::getBasicProperty<MFloat>("alphaFloor", AT_, &m_alphaFloor);
278
286 m_alphaCeil = 1.0;
287 m_alphaCeil = Context::getBasicProperty<MFloat>("alphaCeil", AT_, &m_alphaCeil);
288
300 m_initAlphaMethod = 0;
301 if(Context::propertyExists("initAlphaMethod", 0)) {
302 m_initAlphaMethod = Context::getBasicProperty<MInt>("initAlphaMethod", AT_, &m_initAlphaMethod);
303 }
304
312 m_initialAlpha = 0.0;
313 if(Context::propertyExists("initialAlpha", 0)) {
314 m_initialAlpha = Context::getBasicProperty<MFloat>("initialAlpha", AT_, &m_initialAlpha);
315 }
316
324 m_alphaInf = m_initialAlpha;
325 m_alphaInf = Context::getBasicProperty<MFloat>("alphaInf", AT_, &m_alphaInf);
326
334 m_redistributeAlpha = true;
335 m_redistributeAlpha = Context::getBasicProperty<MBool>("redistributeAlpha", AT_, &m_redistributeAlpha);
336
344 m_disableSubstepAlphaRedist = true;
345 m_disableSubstepAlphaRedist =
346 Context::getBasicProperty<MBool>("disableSubstepAlphaRedist", AT_, &m_disableSubstepAlphaRedist);
347
355 m_updateAfterPropagation = true;
356 m_updateAfterPropagation =
357 Context::getSolverProperty<MBool>("updateAfterPropagation", 1, AT_, &m_updateAfterPropagation);
358
367 m_interpolationFactor = 0.5;
368 m_interpolationFactor =
369 Context::getSolverProperty<MFloat>("EEMultiphaseInterpolationFactor", 1, AT_, &m_interpolationFactor);
370
378 m_updateFVBC = false;
379 m_updateFVBC = Context::getSolverProperty<MBool>("EEMultiphaseUpdateFVBC", 1, AT_, &m_updateFVBC);
380
381 if(Context::propertyExists("gravityRefCoords", 0) && Context::propertyExists("depthCorrectionCoefficients", 0)) {
382 for(MInt i = 0; i < 3; i++) {
389 m_gravityRefCoords[i] = Context::getSolverProperty<MFloat>("gravityRefCoords", 0, AT_, i);
390
400 m_depthCorrectionCoefficients[i] = Context::getSolverProperty<MFloat>("depthCorrectionCoefficients", 0, AT_, i);
401 }
402 } else {
403 mTerm(1, AT_, "gravityRefCoords and depthCorrectionCoefficients are required for Euler-Euler multiphase!");
404 }
405}
406
407template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
409 MFloat TInf = fvSolver().m_TInfinity;
410 if(std::isnan(TInf)) {
411 TInf = fvSolver().m_initialCondition == 465 || fvSolver().m_initialCondition == 9465
412 ? 1.0
413 : 1.0 / (1.0 + 0.5 * (fvSolver().m_gamma - 1.0) * POW2(fvSolver().m_Ma));
414 }
415 for(MInt fvCellId = 0; fvCellId < a_noFvCells(); fvCellId++) {
416 MFloat depthCorrectionValue = 0.0;
417 for(MInt i = 0; i < nDim; i++) {
418 const MFloat deltaH = fvSolver().a_coordinate(fvCellId, i) - m_gravityRefCoords[i];
419 depthCorrectionValue +=
420 fvSolver().m_EEGas.liquidDensity * m_depthCorrectionCoefficients[i] * deltaH * TInf / fvSolver().m_gamma;
421 }
422 m_depthCorrectionValues[fvCellId] = depthCorrectionValue;
423 }
424}
425
426template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
428 const MBool update) {
429 // conversion factor for pressure from LB to FV: 3 / (1 + (gamma-1)/2 * Ma_inf^2)^(gamma/(gamma-1))
430 // = 3 * T_inf ^ (gamma/(gamma-1))
431 // conversion factor LB RHO to P: p = rho / (3 * gamma)
432 // total conversion factor: T_inf ^ (gamma/(gamma-1)) / gamma
433
434 for(MInt lbCellId = 0; lbCellId < a_noLbCells(); lbCellId++) {
435 const MInt lvlDiff = lbSolver().maxLevel() - lbSolver().a_level(lbCellId);
436 const MInt tsSinceUpdate = globalTimeStep % IPOW2(lvlDiff);
437 const MFloat dt =
438 m_interpolationFactor > 0.0 ? (rkAlpha * m_interpolationFactor - 1.0 + tsSinceUpdate) * FFPOW2(lvlDiff) : 0.0;
439 MInt fvCellId = lb2fvId(lbCellId);
440 if(fvCellId < 0) continue;
441
442 if(!fvSolver().m_EEGas.depthCorrection) {
443 fvSolver().a_pvariable(fvCellId, fvSolver().PV->P) =
444 conversionLbFv.pressure * lbSolver().a_interpolatedVariable(lbCellId, lbSolver().PV->RHO, dt)
445 / fvSolver().m_gamma
446 + m_depthCorrectionValues[fvCellId];
447 } else {
448 fvSolver().a_pvariable(fvCellId, fvSolver().PV->P) =
449 conversionLbFv.pressure * lbSolver().a_interpolatedVariable(lbCellId, lbSolver().PV->RHO, dt)
450 / fvSolver().m_gamma;
451 }
452 }
453 for(MInt bndIndex = 0; bndIndex < (MInt)(lbBndCnd().m_bndCndIds.size()); bndIndex++) {
454 for(MInt bndId = lbBndCnd().m_bndCndOffsets[bndIndex]; bndId < lbBndCnd().m_bndCndOffsets[bndIndex + 1]; bndId++) {
455 if(lbBndCnd().m_bndCells[bndId].m_isFluid) continue; // extrapolate only solid boundary cells from flow field
456 const MInt lbCellId = lbBndCnd().m_bndCells[bndId].m_cellId;
457 const MInt fvCellId = lb2fvId(lbCellId);
458 if(fvCellId < 0) continue;
459 for(MInt i = 0; i < 26; i++) { // look in all directions, including diagonals
460 if(!lbSolver().a_hasNeighbor(lbCellId, i)) {
461 MInt lbOppNId = lbSolver().c_neighborId(lbCellId, oppositeDirGrid[i]);
462 if(lbOppNId >= 0 && !lbSolver().a_isBndryCell(lbOppNId)) {
463 MInt fvOppNId = lb2fvId(lbOppNId);
464 if(fvOppNId >= a_noFvCells() || fvOppNId < 0) {
465 break;
466 }
467 if(!fvSolver().m_EEGas.depthCorrection) {
468 fvSolver().a_pvariable(fvCellId, fvSolver().PV->P) = fvSolver().a_pvariable(fvOppNId, fvSolver().PV->P)
469 - m_depthCorrectionValues[fvOppNId]
470 + m_depthCorrectionValues[fvCellId];
471 } else {
472 fvSolver().a_pvariable(fvCellId, fvSolver().PV->P) = fvSolver().a_pvariable(fvOppNId, fvSolver().PV->P);
473 }
474 break;
475 }
476 }
477 }
478 }
479 }
480
481 if(update) {
483 fvSolver().exchange();
485
486 // apply von Neumann boundary conditions
488 }
489}
490
491template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
492template <MBool updateGradients>
494 static MBool firstCall = true;
495
496 // conversion factor for velocity from LB to FV: sqrt(3 / (1 + (gamma-1)/2 * Ma_inf^2))
497 const MFloat ufactor = conversionLbFv.velocity;
498
499 // derivatives need an additional conversion factor
500 const MFloat dufactor = conversionLbFv.length;
501
502 // swap the pointers instead of copying all values from m_EEGas.uOtherPhase to m_EEGas.uOtherPhaseOld
503 MFloat** tempPointer = fvSolver().m_EEGas.uOtherPhaseOld;
505 fvSolver().m_EEGas.uOtherPhase = tempPointer;
506
507 lbSolver().exchange();
508
509 // update the velocity arrays
510 const MBool interpolate = m_interpolationFactor > 0.0;
511 for(MInt lbCellId = 0; lbCellId < a_noLbCells(); lbCellId++) {
512 MInt fvCellId = lb2fvId(lbCellId);
513 if(fvCellId < 0) continue;
514
515 if(interpolate) {
516 const MInt lvlDiff = lbSolver().maxLevel() - lbSolver().a_level(lbCellId);
517 const MInt tsSinceUpdate = globalTimeStep % IPOW2(lvlDiff);
518 const MFloat dt = (rkAlpha * m_interpolationFactor - 1.0 + tsSinceUpdate) * FFPOW2(lvlDiff);
519 // since the gradients are not updated for each RK step, they are interpolated for the whole timestep
520 for(MInt i = 0; i < nDim; i++) {
521 fvSolver().a_uOtherPhase(fvCellId, i) = ufactor * lbSolver().a_interpolatedVariable(lbCellId, i, dt);
522 IF_CONSTEXPR(updateGradients) {
523 const MFloat dtGrad = (m_interpolationFactor - 1.0 + tsSinceUpdate) * FFPOW2(lvlDiff);
524 for(MInt j = 0; j < nDim; j++) {
525 fvSolver().a_gradUOtherPhase(fvCellId, i, j) =
526 ufactor * dufactor * lbSolver().calculateInterpolatedDerivative(lbCellId, i, j, dtGrad);
527 }
528 }
529 }
530 } else {
531 for(MInt i = 0; i < nDim; i++) {
532 fvSolver().a_uOtherPhase(fvCellId, i) = ufactor * lbSolver().a_variable(lbCellId, i);
533 IF_CONSTEXPR(updateGradients) {
534 for(MInt j = 0; j < nDim; j++) {
535 fvSolver().a_gradUOtherPhase(fvCellId, i, j) =
536 ufactor * dufactor * lbSolver().calculateDerivative(lbCellId, i, j);
537 }
538 }
539 }
540 }
541 IF_CONSTEXPR(updateGradients) {
542 fvSolver().a_vortOtherPhase(fvCellId, 0) =
543 fvSolver().a_gradUOtherPhase(fvCellId, 2, 1) - fvSolver().a_gradUOtherPhase(fvCellId, 1, 2);
544 fvSolver().a_vortOtherPhase(fvCellId, 1) =
545 fvSolver().a_gradUOtherPhase(fvCellId, 0, 2) - fvSolver().a_gradUOtherPhase(fvCellId, 2, 0);
546 fvSolver().a_vortOtherPhase(fvCellId, 2) =
547 fvSolver().a_gradUOtherPhase(fvCellId, 1, 0) - fvSolver().a_gradUOtherPhase(fvCellId, 0, 1);
548 }
549 }
550 if(firstCall) {
551 for(MInt lbCellId = 0; lbCellId < a_noLbCells(); lbCellId++) {
552 MInt fvCellId = lb2fvId(lbCellId);
553 if(fvCellId < 0) continue;
554 for(MInt i = 0; i < 3; i++) {
555 fvSolver().a_uOtherPhaseOld(fvCellId, i) = fvSolver().a_uOtherPhase(fvCellId, i);
556 }
557 }
558 firstCall = false;
559 }
560}
561
562template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
564 // conversion factor for velocity from LB to FV: sqrt((1 + (gamma-1)/2 * Ma_inf^2) / 3)
565
566 for(MInt fvCellId = 0; fvCellId < a_noFvCells(); fvCellId++) {
567 MInt lbCellId = fv2lbId(fvCellId);
568 if(lbCellId < 0) continue;
569
570 lbSolver().a_uOtherPhase(lbCellId, 0) =
571 conversionFvLb.velocity * fvSolver().a_pvariable(fvCellId, fvSolver().PV->U);
572 lbSolver().a_uOtherPhase(lbCellId, 1) =
573 conversionFvLb.velocity * fvSolver().a_pvariable(fvCellId, fvSolver().PV->V);
574 lbSolver().a_uOtherPhase(lbCellId, 2) =
575 conversionFvLb.velocity * fvSolver().a_pvariable(fvCellId, fvSolver().PV->W);
576 }
577}
578
579template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
581 for(MInt lbCellId = 0; lbCellId < a_noLbCells(); lbCellId++) {
582 const MInt lvlDiff = lbSolver().maxLevel() - lbSolver().a_level(lbCellId);
583 const MInt tsSinceUpdate = globalTimeStep % IPOW2(lvlDiff);
584 const MFloat dt =
585 m_interpolationFactor > 0.0 ? (rkAlpha * m_interpolationFactor - 1.0 + tsSinceUpdate) * FFPOW2(lvlDiff) : 0.0;
586 const MInt fvCellId = lb2fvId(lbCellId);
587 if(fvCellId < 0) continue;
588 if(fvSolver().a_isBndryGhostCell(fvCellId)) continue;
589
590 fvSolver().a_nuEffOtherPhase(fvCellId) =
591 ((1.0 + dt) * lbSolver().a_nu(lbCellId) - dt * lbSolver().a_oldNu(lbCellId)) * conversionLbFv.viscosity;
592 fvSolver().a_nuTOtherPhase(fvCellId) =
593 ((1.0 + dt) * lbSolver().a_nuT(lbCellId) - dt * lbSolver().a_oldNuT(lbCellId)) * conversionLbFv.viscosity;
594 }
595}
596
597template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
599 for(MInt fvCellId = 0; fvCellId < a_noFvCells(); fvCellId++) {
600 const MInt lbCellId = fv2lbId(fvCellId);
601 if(lbCellId < 0) continue;
602
603 lbSolver().a_alphaGas(lbCellId) = fvSolver().a_alphaGas(fvCellId);
604 }
605}
606
607template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
609 for(MInt cellId = 0; cellId < a_noLbCells(); cellId++) {
610 lbSolver().a_variable(cellId, lbSolver().PV->RHO) = lbSolver().a_oldVariable(cellId, lbSolver().PV->RHO);
611 lbSolver().a_variable(cellId, lbSolver().PV->U) = lbSolver().a_oldVariable(cellId, lbSolver().PV->U);
612 lbSolver().a_variable(cellId, lbSolver().PV->V) = lbSolver().a_oldVariable(cellId, lbSolver().PV->V);
613 lbSolver().a_variable(cellId, lbSolver().PV->W) = lbSolver().a_oldVariable(cellId, lbSolver().PV->W);
614 }
615}
616
617template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
619 for(MInt cellId = 0; cellId < a_noLbCells(); cellId++) {
620 for(MInt distr = 0; distr < lbSolver().m_noDistributions; distr++) {
621 lbSolver().a_oldDistribution(cellId, distr) = lbSolver().a_previousDistribution(cellId, distr);
622 }
623 }
624}
625
626template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
628 for(MInt cellId = 0; cellId < a_noLbCells(); cellId++) {
629 lbSolver().a_oldVariable(cellId, lbSolver().PV->RHO) = lbSolver().a_previousVariable(cellId, lbSolver().PV->RHO);
630 lbSolver().a_oldVariable(cellId, lbSolver().PV->U) = lbSolver().a_previousVariable(cellId, lbSolver().PV->U);
631 lbSolver().a_oldVariable(cellId, lbSolver().PV->V) = lbSolver().a_previousVariable(cellId, lbSolver().PV->V);
632 lbSolver().a_oldVariable(cellId, lbSolver().PV->W) = lbSolver().a_previousVariable(cellId, lbSolver().PV->W);
633 }
634}
635
636template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
638 if(m_alphaConvergenceCheck <= 0) {
639 mTerm(1, AT_, "Didn't store the variables to revert the LB solver!");
640 }
641 revertLbVariables();
642 revertLbDistributions();
643 if(m_updateAfterPropagation) revertLbOldVariables();
644 if(lbSolver().noDomains() > 1) {
645 lbSolver().exchange();
646 lbSolver().exchangeOldDistributions();
647 }
648}
649
650template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
652 for(MInt cellId = 0; cellId < a_noFvCells(); cellId++) {
653 for(MInt varId = 0; varId < fvSolver().noVariables(); varId++) {
654 fvSolver().a_variable(cellId, varId) = fvSolver().a_oldVariable(cellId, varId);
655 }
656 }
658}
659
660template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
662 revertFvVariables();
664 fvSolver().exchange();
665}
666
667template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
669 MBool converged = false;
670 switch(m_alphaConvergenceCheck) {
671 case 0:
672 converged = true;
673 break;
674
675 case 1:
676 converged = true;
677 for(MInt cellId = 0; cellId < a_noFvCells(); cellId++) {
678 if(fv2lbId(cellId) < 0) continue;
679 if(m_epsAlpha < std::abs(fvSolver().a_alphaGas(cellId) - lbSolver().a_alphaGas(fv2lbId(cellId)))) {
680 converged = false;
681 break;
682 }
683 }
684 MPI_Allreduce(MPI_IN_PLACE, &converged, 1, maia::type_traits<MBool>::mpiType(), MPI_LAND, fvSolver().mpiComm(),
685 AT_, "MPI_IN_PLACE", "converged");
686 break;
687
688 default:
689 mTerm(1, AT_, "not a valid alphaConvergenceCheck!");
690 break;
691 }
692 return converged;
693}
694
700template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
702 const MInt noCVars = fvSolver().CV->noVariables;
703
705 fvSolver().exchange();
706
707 // Request conservative variables of halo cells
708 // modified from smallcellcorrection()
709 {
710 MIntScratchSpace sendBufferCnts(mMax(1, fvSolver().noNeighborDomains()), AT_, "sendBufferCnts");
711 MIntScratchSpace recvBufferCnts(mMax(1, fvSolver().noNeighborDomains()), AT_, "recvBufferCnts");
712 ScratchSpace<MPI_Request> sendReq(mMax(1, fvSolver().noNeighborDomains()), AT_, "sendReq");
713 ScratchSpace<MPI_Request> recvReq(mMax(1, fvSolver().noNeighborDomains()), AT_, "recvReq");
714 sendReq.fill(MPI_REQUEST_NULL);
715 recvReq.fill(MPI_REQUEST_NULL);
716 sendBufferCnts.fill(0);
717 recvBufferCnts.fill(0);
718 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
719 sendBufferCnts(i) = noCVars * fvSolver().m_noMaxLevelWindowCells[i];
720 recvBufferCnts(i) = noCVars * fvSolver().m_noMaxLevelHaloCells[i];
721 MInt sendBufferCounter = 0;
722 for(MInt j = 0; j < fvSolver().m_noMaxLevelWindowCells[i]; j++) {
723 MInt cellId = fvSolver().m_maxLevelWindowCells[i][j];
724 for(MInt v = 0; v < noCVars; v++) {
725 fvSolver().m_sendBuffers[i][sendBufferCounter] = fvSolver().a_variable(cellId, v);
726 sendBufferCounter++;
727 }
728 }
729 }
730 MInt sendCnt = 0;
731 MInt recvCnt = 0;
732 if(fvSolver().m_nonBlockingComm) {
733 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
734 if(sendBufferCnts(i) == 0) continue;
735 ASSERT(sendBufferCnts(i) <= fvSolver().m_noMaxLevelWindowCells[i] * fvSolver().m_dataBlockSize, "");
736 MPI_Isend(fvSolver().m_sendBuffers[i], sendBufferCnts(i), MPI_DOUBLE, fvSolver().neighborDomain(i), 12,
737 fvSolver().mpiComm(), &sendReq[sendCnt], AT_, "m_sendBuffers[" + std::to_string(i) + "],0");
738 sendCnt++;
739 }
740 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
741 if(recvBufferCnts(i) == 0) continue;
742 ASSERT(recvBufferCnts(i) <= fvSolver().m_noMaxLevelHaloCells[i] * fvSolver().m_dataBlockSize, "");
743 MPI_Irecv(fvSolver().m_receiveBuffers[i], recvBufferCnts(i), MPI_DOUBLE, fvSolver().neighborDomain(i), 12,
744 fvSolver().mpiComm(), &recvReq[recvCnt], AT_, "m_receiveBuffers[" + std::to_string(i) + "],0");
745 recvCnt++;
746 }
747 if(recvCnt > 0) MPI_Waitall(recvCnt, &recvReq[0], MPI_STATUSES_IGNORE, AT_);
748 } else {
749 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
750 if(sendBufferCnts(i) == 0) continue;
751 ASSERT(sendBufferCnts(i) <= fvSolver().m_noMaxLevelWindowCells[i] * fvSolver().m_dataBlockSize, "");
752 MPI_Issend(fvSolver().m_sendBuffers[i], sendBufferCnts(i), MPI_DOUBLE, fvSolver().neighborDomain(i), 12,
753 fvSolver().mpiComm(), &sendReq[sendCnt], AT_, "m_sendBuffers[" + std::to_string(i) + "],0");
754 sendCnt++;
755 }
756 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
757 if(recvBufferCnts(i) == 0) continue;
758 ASSERT(recvBufferCnts(i) <= fvSolver().m_noMaxLevelHaloCells[i] * fvSolver().m_dataBlockSize, "");
759 MPI_Recv(fvSolver().m_receiveBuffers[i], recvBufferCnts(i), MPI_DOUBLE, fvSolver().neighborDomain(i), 12,
760 fvSolver().mpiComm(), MPI_STATUS_IGNORE, AT_, "m_receiveBuffers[" + std::to_string(i) + "],0");
761 recvCnt++;
762 }
763 }
764 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
765 MInt recvBufferCounter = 0;
766 for(MInt j = 0; j < fvSolver().m_noMaxLevelHaloCells[i]; j++) {
767 MInt cellId = fvSolver().m_maxLevelHaloCells[i][j];
768 for(MInt v = 0; v < noCVars; v++) {
769 fvSolver().a_variable(cellId, v) = fvSolver().m_receiveBuffers[i][recvBufferCounter];
770 recvBufferCounter++;
771 }
772 }
773 }
774 if(sendCnt > 0) MPI_Waitall(sendCnt, &sendReq[0], MPI_STATUSES_IGNORE, AT_);
775 }
776
777 // find cells with invalid alpha values and redistribute mass and momentum from/to them
778 // TODO labels:COUPLER,toenhance replace struct by std::vector or something else
779 struct transferCV {
780 MFloat rhoAlpha;
781 MFloat rhoUAlpha;
782 MFloat rhoVAlpha;
783 MFloat rhoWAlpha;
784 };
785 constexpr MInt noTransferCV = 4;
786 std::map<MInt, transferCV>
787 haloCorrections; // save which Halo cells are altered to communicate the changes to their domains
788 for(MInt cellId = 0; cellId < fvSolver().m_bndryGhostCellsOffset; cellId++) {
789 if(fvSolver().a_isHalo(cellId)) continue;
790 if(!fvSolver().c_isLeafCell(cellId)) continue;
791
792 const MFloat origAlpha = fvSolver().a_pvariable(cellId, fvSolver().PV->A);
793
794 if(origAlpha < (m_alphaFloor - 1.0e-8)) {
795 const MFloat origMass = fvSolver().a_variable(cellId, fvSolver().CV->A_RHO) * fvSolver().a_cellVolume(cellId);
796 const MFloat deltaMass = 0.0 - origMass;
797 const std::vector<MInt> neighbors = findRedistCells(cellId, true, 0.0);
798 std::vector<MInt> redistNeighbors = neighbors;
799 MInt noRedistNbs = 0;
800 MFloat massNeedPerCell = 0.0;
801 while(true) {
802 MBool change = false;
803 noRedistNbs = redistNeighbors.size();
804 massNeedPerCell = deltaMass / noRedistNbs;
805 for(auto it = redistNeighbors.begin(); it != redistNeighbors.end(); ++it) {
806 const MInt candidateId = *it;
807 if(fvSolver().a_variable(candidateId, fvSolver().CV->A_RHO) * fvSolver().a_cellVolume(candidateId)
808 < massNeedPerCell) {
809 change = true;
810 redistNeighbors.erase(it);
811 break;
812 }
813 }
814 if(change) continue;
815 break;
816 }
817 MFloat momentumTransfer[3] = {0.0, 0.0, 0.0};
818 if(!redistNeighbors.empty()) {
819 for(auto redistId : redistNeighbors) {
820 const MFloat delRho = massNeedPerCell / fvSolver().a_cellVolume(redistId);
821 const MFloat delRhoVV[3] = {delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[0]),
822 delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[1]),
823 delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[2])};
824 fvSolver().a_variable(redistId, fvSolver().CV->A_RHO) -= delRho;
825 for(MInt dir = 0; dir < 3; dir++) {
826 fvSolver().a_variable(redistId, fvSolver().CV->A_RHO_VV[dir]) -= delRhoVV[dir];
827 momentumTransfer[dir] += delRhoVV[dir] * fvSolver().a_cellVolume(redistId);
828 }
829 fvSolver().setPrimitiveVariables(redistId);
830
831 if(fvSolver().a_isHalo(redistId)) {
832 const transferCV delCV = {
833 -delRho,
834 -delRhoVV[0],
835 -delRhoVV[1],
836 -delRhoVV[2],
837 };
838 auto success = haloCorrections.insert(std::pair<MInt, transferCV>(redistId, delCV));
839 if(!success.second) { // redistId already in map
840 success.first->second.rhoAlpha += delCV.rhoAlpha;
841 success.first->second.rhoUAlpha += delCV.rhoUAlpha;
842 success.first->second.rhoVAlpha += delCV.rhoVAlpha;
843 success.first->second.rhoWAlpha += delCV.rhoWAlpha;
844 }
845 }
846 }
847 fvSolver().a_variable(cellId, fvSolver().CV->A_RHO) +=
848 massNeedPerCell * noRedistNbs / fvSolver().a_cellVolume(cellId);
849 for(MInt dir = 0; dir < 3; dir++) {
850 fvSolver().a_variable(cellId, fvSolver().CV->A_RHO_VV[dir]) +=
851 momentumTransfer[dir] / fvSolver().a_cellVolume(cellId);
852 }
853 fvSolver().setPrimitiveVariables(cellId);
854 } else {
855 // if there is not enough mass in any cell to get the negative cell to 0, take as much, as you can from cells
856 redistNeighbors = neighbors;
857
858 MFloat massTransfer = 0.0;
859 for(auto redistId : redistNeighbors) {
860 const MFloat massAvail =
861 fvSolver().a_variable(redistId, fvSolver().CV->A_RHO) * fvSolver().a_cellVolume(redistId);
862 const MFloat delRho = massAvail / fvSolver().a_cellVolume(redistId);
863 const MFloat delRhoVV[3] = {delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[0]),
864 delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[1]),
865 delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[2])};
866 massTransfer += massAvail;
867 fvSolver().a_variable(redistId, fvSolver().CV->A_RHO) -= delRho;
868 for(MInt dir = 0; dir < 3; dir++) {
869 fvSolver().a_variable(redistId, fvSolver().CV->A_RHO_VV[dir]) -= delRhoVV[dir];
870 momentumTransfer[dir] += delRhoVV[dir] * fvSolver().a_cellVolume(redistId);
871 }
872 fvSolver().setPrimitiveVariables(redistId);
873
874 if(fvSolver().a_isHalo(redistId)) {
875 const transferCV delCV = {
876 -delRho,
877 -delRhoVV[0],
878 -delRhoVV[1],
879 -delRhoVV[2],
880 };
881 auto success = haloCorrections.insert(std::pair<MInt, transferCV>(redistId, delCV));
882 if(!success.second) { // redistId already in map
883 success.first->second.rhoAlpha += delCV.rhoAlpha;
884 success.first->second.rhoUAlpha += delCV.rhoUAlpha;
885 success.first->second.rhoVAlpha += delCV.rhoVAlpha;
886 success.first->second.rhoWAlpha += delCV.rhoWAlpha;
887 }
888 }
889 }
890 fvSolver().a_variable(cellId, fvSolver().CV->A_RHO) += massTransfer / fvSolver().a_cellVolume(cellId);
891 for(MInt dir = 0; dir < 3; dir++) {
892 fvSolver().a_variable(cellId, fvSolver().CV->A_RHO_VV[dir]) +=
893 momentumTransfer[dir] / fvSolver().a_cellVolume(cellId);
894 }
895 fvSolver().setPrimitiveVariables(cellId);
896 }
897 } else if(origAlpha > (m_alphaCeil + 1.0e-8)) {
898 const MFloat origMass = fvSolver().a_variable(cellId, fvSolver().CV->A_RHO) * fvSolver().a_cellVolume(cellId);
899 const MFloat deltaMass =
900 m_alphaCeil * fvSolver().a_pvariable(cellId, fvSolver().PV->RHO) * fvSolver().a_cellVolume(cellId) - origMass;
901 std::vector<MInt> neighbors = findRedistCells(cellId, false, m_alphaCeil);
902 MBool isOutlet = false;
903
904 if(fvSolver().a_bndryId(cellId) >= 0) {
905 const MInt bndryId = fvSolver().a_bndryId(cellId);
906 for(MInt srfc = 0; srfc < fvSolver().m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
907 const MInt bndrCndId = fvSolver().m_fvBndryCnd->m_bndryCell[bndryId].m_srfcs[srfc]->m_bndryCndId;
908 if(bndrCndId == 1002) {
909 isOutlet = true;
910 break;
911 }
912 }
913 }
914 if(isOutlet) {
915 for(MUint dir = 0; dir < 26; dir++) { // loop over ALL the directions!
916 const MInt neighborId = fvSolver().grid().neighborList(cellId, dir);
917 if(fvSolver().a_isBndryGhostCell(neighborId)) {
918 neighbors.push_back(neighborId);
919 }
920 }
921 }
922 std::vector<MInt> redistNeighbors = neighbors;
923
924 MInt noRedistNbs = 0;
925 MFloat massExcessPerCell = 0.0;
926 while(true) {
927 MBool change = false;
928 noRedistNbs = redistNeighbors.size();
929 massExcessPerCell = -deltaMass / noRedistNbs;
930 for(auto it = redistNeighbors.begin(); it != redistNeighbors.end(); ++it) {
931 const MInt candidateId = *it;
932 if(!fvSolver().a_isBndryGhostCell(candidateId)
933 && ((fvSolver().a_variable(candidateId, fvSolver().CV->A_RHO)
934 + massExcessPerCell / fvSolver().a_cellVolume(candidateId))
935 > fvSolver().a_pvariable(candidateId, fvSolver().PV->RHO) * m_alphaCeil)) {
936 change = true;
937 redistNeighbors.erase(it);
938 break;
939 }
940 }
941 if(change) continue;
942 break;
943 }
944 MFloat momentumTransfer[3] = {0.0, 0.0, 0.0};
945 if(!redistNeighbors.empty() || isOutlet) {
946 if(redistNeighbors.empty()) {
947 noRedistNbs = 1;
948 massExcessPerCell = -deltaMass / noRedistNbs;
949 for(MInt dir = 0; dir < 3; dir++) {
950 momentumTransfer[dir] += massExcessPerCell * fvSolver().a_pvariable(cellId, fvSolver().PV->VV[dir]);
951 }
952 }
953 for(auto redistId : redistNeighbors) {
954 if(fvSolver().a_isBndryGhostCell(redistId)) continue;
955 const MFloat delRho = massExcessPerCell / fvSolver().a_cellVolume(redistId);
956 const MFloat delRhoVV[3] = {delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[0]),
957 delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[1]),
958 delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[2])};
959 fvSolver().a_variable(redistId, fvSolver().CV->A_RHO) += delRho;
960 for(MInt dir = 0; dir < 3; dir++) {
961 fvSolver().a_variable(redistId, fvSolver().CV->A_RHO_VV[dir]) += delRhoVV[dir];
962 momentumTransfer[dir] += delRhoVV[dir] * fvSolver().a_cellVolume(redistId);
963 }
964 fvSolver().setPrimitiveVariables(redistId);
965
966 if(fvSolver().a_isHalo(redistId)) {
967 const transferCV delCV = {
968 delRho,
969 delRhoVV[0],
970 delRhoVV[1],
971 delRhoVV[2],
972 };
973 auto success = haloCorrections.insert(std::pair<MInt, transferCV>(redistId, delCV));
974 if(!success.second) { // redistId already in map
975 success.first->second.rhoAlpha += delCV.rhoAlpha;
976 success.first->second.rhoUAlpha += delCV.rhoUAlpha;
977 success.first->second.rhoVAlpha += delCV.rhoVAlpha;
978 success.first->second.rhoWAlpha += delCV.rhoWAlpha;
979 }
980 }
981 }
982 fvSolver().a_variable(cellId, fvSolver().CV->A_RHO) -=
983 massExcessPerCell / fvSolver().a_cellVolume(cellId) * noRedistNbs;
984 for(MInt dir = 0; dir < 3; dir++) {
985 fvSolver().a_variable(cellId, fvSolver().CV->A_RHO_VV[dir]) -=
986 momentumTransfer[dir] / fvSolver().a_cellVolume(cellId);
987 }
988 fvSolver().setPrimitiveVariables(cellId);
989 } else {
990 // if no neighbor can take enough mass to bring our cell under alphaCeil, give them as much as they can take
991 redistNeighbors = neighbors;
992 if(redistNeighbors.empty()) {
993 redistNeighbors = findRedistCells(cellId, false, std::numeric_limits<MFloat>::max());
994 }
995 MFloat massTransfer = 0.0;
996 for(auto redistId : redistNeighbors) {
997 const MFloat massCapacityAvail = (fvSolver().a_pvariable(redistId, fvSolver().PV->RHO) * m_alphaCeil
998 - fvSolver().a_variable(redistId, fvSolver().CV->A_RHO))
999 * fvSolver().a_cellVolume(redistId);
1000 if(massCapacityAvail < 0.0) continue;
1001 const MFloat delRho = massCapacityAvail / fvSolver().a_cellVolume(redistId);
1002 const MFloat delRhoVV[3] = {delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[0]),
1003 delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[1]),
1004 delRho * fvSolver().a_pvariable(redistId, fvSolver().PV->VV[2])};
1005 massTransfer += massCapacityAvail;
1006 fvSolver().a_variable(redistId, fvSolver().CV->A_RHO) += delRho;
1007 for(MInt dir = 0; dir < 3; dir++) {
1008 fvSolver().a_variable(redistId, fvSolver().CV->A_RHO_VV[dir]) += delRhoVV[dir];
1009 momentumTransfer[dir] += delRhoVV[dir] * fvSolver().a_cellVolume(redistId);
1010 }
1011 fvSolver().setPrimitiveVariables(redistId);
1012
1013 if(fvSolver().a_isHalo(redistId)) {
1014 const transferCV delCV = {
1015 delRho,
1016 delRhoVV[0],
1017 delRhoVV[1],
1018 delRhoVV[2],
1019 };
1020 auto success = haloCorrections.insert(std::pair<MInt, transferCV>(redistId, delCV));
1021 if(!success.second) { // redistId already in map
1022 success.first->second.rhoAlpha += delCV.rhoAlpha;
1023 success.first->second.rhoUAlpha += delCV.rhoUAlpha;
1024 success.first->second.rhoVAlpha += delCV.rhoVAlpha;
1025 success.first->second.rhoWAlpha += delCV.rhoWAlpha;
1026 }
1027 }
1028 }
1029 fvSolver().a_variable(cellId, fvSolver().CV->A_RHO) -= massTransfer / fvSolver().a_cellVolume(cellId);
1030 for(MInt dir = 0; dir < 3; dir++) {
1031 fvSolver().a_variable(cellId, fvSolver().CV->A_RHO_VV[dir]) -=
1032 momentumTransfer[dir] / fvSolver().a_cellVolume(cellId);
1033 }
1034 fvSolver().setPrimitiveVariables(cellId);
1035 }
1036 }
1037 }
1038
1039 // Communicate the changes in the CVs to the neighboring domains
1040 // Since this function changed the CV in the halo cells, m_send- and m_receiveBuffer are swapped in this communication
1041 {
1042 if(noTransferCV > fvSolver().m_dataBlockSize)
1043 mTerm(1, AT_, "The send- and receive Buffers are too small for this communication!");
1044 // gather
1045 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
1046 MInt receiveBufferCounter = 0;
1047 for(MInt j = 0; j < fvSolver().m_noMaxLevelHaloCells[i]; j++) {
1048 auto it = haloCorrections.find(fvSolver().m_maxLevelHaloCells[i][j]);
1049 if(it != haloCorrections.end()) {
1050 fvSolver().m_receiveBuffers[i][receiveBufferCounter + fvSolver().CV->A_RHO] = it->second.rhoAlpha;
1051 fvSolver().m_receiveBuffers[i][receiveBufferCounter + fvSolver().CV->A_RHO_U] = it->second.rhoUAlpha;
1052 fvSolver().m_receiveBuffers[i][receiveBufferCounter + fvSolver().CV->A_RHO_V] = it->second.rhoVAlpha;
1053 fvSolver().m_receiveBuffers[i][receiveBufferCounter + fvSolver().CV->A_RHO_W] = it->second.rhoWAlpha;
1054 } else {
1055 fvSolver().m_receiveBuffers[i][receiveBufferCounter + fvSolver().CV->A_RHO] = 0.0;
1056 fvSolver().m_receiveBuffers[i][receiveBufferCounter + fvSolver().CV->A_RHO_U] = 0.0;
1057 fvSolver().m_receiveBuffers[i][receiveBufferCounter + fvSolver().CV->A_RHO_V] = 0.0;
1058 fvSolver().m_receiveBuffers[i][receiveBufferCounter + fvSolver().CV->A_RHO_W] = 0.0;
1059 }
1060 receiveBufferCounter += noTransferCV;
1061 }
1062 }
1063
1064 // send
1065 MInt bufSize = 0;
1066 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
1067 bufSize = fvSolver().m_noMaxLevelHaloCells[i] * noTransferCV;
1068 MPI_Issend(fvSolver().m_receiveBuffers[i], bufSize, MPI_DOUBLE, fvSolver().neighborDomain(i), 0,
1069 fvSolver().mpiComm(), &fvSolver().m_mpi_request[i], AT_,
1070 "m_receiveBuffers[" + std::to_string(i) + "],1");
1071 }
1072
1073 // receive
1074 MPI_Status status;
1075 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
1076 bufSize = fvSolver().m_noMaxLevelWindowCells[i] * noTransferCV;
1077 MPI_Recv(fvSolver().m_sendBuffers[i], bufSize, MPI_DOUBLE, fvSolver().neighborDomain(i), 0, fvSolver().mpiComm(),
1078 &status, AT_, "m_sendBuffers[" + std::to_string(i) + "],1");
1079 }
1080 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
1081 MPI_Wait(&fvSolver().m_mpi_request[i], &status, AT_);
1082 }
1083
1084 // scatter
1085 MInt sendBufferCounter = 0;
1086 for(MInt i = 0; i < fvSolver().noNeighborDomains(); i++) {
1087 sendBufferCounter = 0;
1088 for(MInt j = 0; j < fvSolver().m_noMaxLevelWindowCells[i]; j++) {
1089 fvSolver().a_variable(fvSolver().m_maxLevelWindowCells[i][j], fvSolver().CV->A_RHO) +=
1090 fvSolver().m_sendBuffers[i][sendBufferCounter + fvSolver().CV->A_RHO];
1091 for(MInt dir = 0; dir < nDim; dir++) {
1092 fvSolver().a_variable(fvSolver().m_maxLevelWindowCells[i][j], fvSolver().CV->A_RHO_VV[dir]) +=
1093 fvSolver().m_sendBuffers[i][sendBufferCounter + fvSolver().CV->A_RHO_VV[dir]];
1094 }
1095 sendBufferCounter += noTransferCV;
1096 }
1097 }
1098 }
1099 fvSolver().computePV();
1100 fvSolver().exchange();
1101}
1102
1112template <MInt nDim, MInt nDist, class SysEqnLb, class SysEqnFv>
1114 const MBool searchUp,
1115 const MFloat limit) {
1116 std::vector<MInt> redistNeighbors;
1117 redistNeighbors.reserve(56);
1118
1119 MIntScratchSpace adjacentLeafCells(56, AT_, "adjacentLeafCells");
1120 MIntScratchSpace layers(56, AT_, "layers");
1121 const MInt noLeafCells = fvSolver().getAdjacentLeafCells_d2(cellId, 1, adjacentLeafCells, layers);
1122
1123 for(MInt i = 0; i < noLeafCells; i++) {
1124 const MInt neighborId = adjacentLeafCells[i];
1125 const MFloat alpha = fvSolver().a_pvariable(neighborId, fvSolver().PV->A);
1126 if(searchUp && alpha < limit) continue;
1127 if(!searchUp && alpha > limit) continue;
1128 redistNeighbors.push_back(neighborId);
1129 }
1130 return redistNeighbors;
1131}
1132
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
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
Definition: context.cpp:494
void subCouple(MInt, MInt, std::vector< MBool > &solverCompleted) override
CouplerLbFvEEMultiphase(const MInt couplerId, LbSolver *lb, FvCartesianSolver *fv)
void transferNuLb2Fv(const MFloat rkAlpha)
std::vector< MInt > findRedistCells(const MInt cellId, const MBool searchUp, const MFloat limit)
find neighbor Cells to cellId, that are candidates for alpha corrections
void correctInvalidAlpha()
find cells with invalid alpha values and redistribute mass from/to neighboring cells to raise/lower a...
void transferULb2Fv(const MFloat rkAlpha)
void transferPressureLb2Fv(const MFloat rkAlpha, const MBool update)
void finalizeSubCoupleInit(MInt) override
void balancePre() override
Load balancing.
virtual void initConversionFactors()
Definition: couplerlbfv.cpp:31
MInt a_lbSolverId() const
Definition: couplerlbfv.h:121
MInt lb2fvId(const MInt lbId) const
Definition: couplerlbfv.h:116
ConversionFactors conversionLbFv
Definition: couplerlbfv.h:103
ConversionFactors conversionFvLb
Definition: couplerlbfv.h:104
MInt a_fvSolverId() const
Definition: couplerlbfv.h:120
MInt fv2lbId(const MInt fvId) const
Definition: couplerlbfv.h:115
solverType & fvSolver(const MInt solverId=0) const
Definition: coupling.h:386
MInt couplerId() const
Definition: coupling.h:67
solverType & lbSolver(const MInt solverId=0) const
Definition: coupling.h:454
LbBndCnd & lbBndCnd(const MInt id=0)
Definition: coupling.h:461
MInt a_noLbCells(const MInt id=0) const
Definition: coupling.h:470
MFloat a_nuEffOtherPhase(const MInt cellId) const
FvBndryCndXD< nDim_, SysEqn > * m_fvBndryCnd
struct FvCartesianSolverXD::@8 m_EEGas
MFloat & a_oldVariable(const MInt cellId, const MInt varId)
Returns oldVariablesv of the cell cellId variables varId.
MFloat & a_variable(const MInt cellId, const MInt varId)
Returns conservative variable v of the cell cellId for variables varId.
SysEqn::ConservativeVariables * CV
MFloat a_alphaGas(const MInt cellId) const
MFloat a_gradUOtherPhase(const MInt cellId, const MInt uDir, const MInt gradDir) const
MFloat & a_coordinate(const MInt cellId, const MInt dir)
Returns the coordinate of the cell from the fvcellcollector cellId for dimension dir.
MFloat a_vortOtherPhase(const MInt cellId, const MInt dir) const
MInt noVariables() const override
Return the number of primitive variables.
MFloat a_nuTOtherPhase(const MInt cellId) const
MFloat a_uOtherPhase(const MInt cellId, const MInt dir) const
MFloat & a_pvariable(const MInt cellId, const MInt varId)
Returns primitive variable v of the cell cellId for variables varId.
MFloat a_uOtherPhaseOld(const MInt cellId, const MInt dir) const
std::vector< LbGridBoundaryCell< nDim > > m_bndCells
Definition: lbbndcnd.h:130
std::vector< MInt > m_bndCndOffsets
Definition: lbbndcnd.h:159
This class represents all LB models.
Definition: lbsolverdxqy.h:29
static constexpr MInt m_noDistributions
Definition: lbsolverdxqy.h:180
This class is a ScratchSpace.
Definition: scratch.h:758
void fill(T val)
fill the scratch with a given value
Definition: scratch.h:311
MFloat m_Ma
the Mach number
Definition: solver.h:71
MInt noNeighborDomains() const
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
constexpr T mMax(const T &x, const T &y)
Definition: functions.h:94
MInt globalTimeStep
constexpr MLong IPOW2(MInt x)
constexpr MFloat FFPOW2(MInt x)
int32_t MInt
Definition: maiatypes.h:62
uint32_t MUint
Definition: maiatypes.h:63
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status, const MString &name, const MString &varname)
same as MPI_Recv
int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Isend
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Irecv
int MPI_Issend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Issend
int MPI_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait
int MPI_Waitall(int count, MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Waitall
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