23template <MInt nDim,
class SysEqn>
26 m_log <<
"Create Zonal coupler for RANS Solver (" << RANSSolver().m_solverId <<
") and LES Solver ("
27 << LESSolver().m_solverId <<
")" << endl;
37 m_rntStartTimeStep = Context::getBasicProperty<MInt>(
"rntStartTimeStep", AT_, &m_rntStartTimeStep);
46 m_reconstructAverageFromNut =
false;
48 m_reconstructAverageFromNut =
49 Context::getBasicProperty<MBool>(
"reconstructAverageFromNut", AT_, &m_reconstructAverageFromNut);
59 m_reconstructNut =
false;
61 m_reconstructNut = Context::getBasicProperty<MBool>(
"reconstructNut", AT_, &m_reconstructNut);
74 m_turbulentIntensity = -1;
76 m_turbulentIntensity = Context::getBasicProperty<MFloat>(
"turbulentIntensity", AT_, &m_turbulentIntensity);
84 m_tuLengthScaleCorrection = F1;
86 m_tuLengthScaleCorrection =
87 Context::getBasicProperty<MFloat>(
"tuLengthScaleCorrection", AT_, &m_tuLengthScaleCorrection);
92template <MInt nDim,
class SysEqn>
96 m_RANSSolverId = RANSSolver().m_solverId;
97 m_LESSolverId = LESSolver().m_solverId;
99 LESSolver().m_LESNoVarAverage = LESVarAverageData::noAvgVars;
104 determineZonalPositions();
108template <MInt nDim,
class SysEqn>
112 m_7902faceNormalDir = -1;
113 m_7902Position = std::numeric_limits<MFloat>::infinity();
118 for(
MInt i = 0; i < propertyLength; i++) {
119 MInt bcId = Context::getSolverProperty<MFloat>(
"cutOffBndryIds", m_RANSSolverId, AT_, i);
120 if(bcId == 7902 || bcId == 7905) {
121 m_7902faceNormalDir = Context::getSolverProperty<MFloat>(
"cutOffDirections", m_RANSSolverId, AT_, i);
125 if(m_7902faceNormalDir != -1) {
126 m_7902faceNormalDir = (m_7902faceNormalDir % 2 == 0) ? m_7902faceNormalDir + 1 : m_7902faceNormalDir - 1;
131 m_7902periodicDir = 2;
134 m_7902wallDir = Context::getSolverProperty<MInt>(
"bc7902wallDir", m_RANSSolverId, AT_);
137 m_7902periodicDir = Context::getSolverProperty<MInt>(
"bc7902periodicDir", m_RANSSolverId, AT_);
140 for(
MInt bcId = 0; bcId < RANSSolver().m_fvBndryCnd->m_noCutOffBndryCndIds; bcId++) {
141 if(RANSSolver().m_fvBndryCnd->m_cutOffBndryCndIds[bcId] == 7902) {
148 MFloat tmpPos7902 = ((m_7902faceNormalDir + 1) % 2 > 0) ? -std::numeric_limits<MFloat>::infinity()
149 : std::numeric_limits<MFloat>::infinity();
150 MFloat compFactor7902 = ((m_7902faceNormalDir + 1) % 2 > 0) ? F1 : -F1;
152 if(LESSolver().grid().isActive()) {
153 for(
MInt cellId = 0; cellId < a_noFvGridCellsLES(); cellId++) {
156 MFloat pos = LESSolver().a_coordinate(cellId, 0);
157 if(compFactor7902 * pos > compFactor7902 * tmpPos7902) {
163 if(compFactor7902 > 0) {
164 MPI_Allreduce(MPI_IN_PLACE, &tmpPos7902, 1, MPI_DOUBLE, MPI_MAX, LESSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
167 MPI_Allreduce(MPI_IN_PLACE, &tmpPos7902, 1, MPI_DOUBLE, MPI_MIN, LESSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
170 m_7902Position = tmpPos7902;
173 if(RANSSolver().grid().isActive()) {
174 if(compFactor7902 > 0) {
175 MPI_Allreduce(MPI_IN_PLACE, &tmpPos7902, 1, MPI_DOUBLE, MPI_MAX, RANSSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
178 MPI_Allreduce(MPI_IN_PLACE, &tmpPos7902, 1, MPI_DOUBLE, MPI_MIN, RANSSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
182 if(m_7902faceNormalDir != -1) {
183 m_7902Position = tmpPos7902;
187 m_averagePos = m_7902Position;
188 m_averageDir = abs(m_7902wallDir + m_7902periodicDir - nDim);
189 m_averageFaceDir = m_7902faceNormalDir;
191 LESSolver().m_averagePos.push_back(m_averagePos);
192 LESSolver().m_averageDir.push_back(m_averageDir);
193 LESSolver().m_averageReconstructNut.push_back(m_reconstructNut);
197template <MInt nDim,
class SysEqn>
202 determineNutReconstructionCells();
205 reconstructNutilde();
208 transferSolverData();
212template <MInt nDim,
class SysEqn>
216 if(LESSolver().grid().isActive()) {
218 for(
MInt LESId = 0; LESId < a_noFvGridCellsLES(); LESId++) {
219 if(LESSolver().a_isHalo(LESId))
continue;
221 MFloat halfCellLength = LESSolver().grid().halfCellLength(LESId);
222 MFloat pos = LESSolver().a_coordinate(LESId, m_averageDir);
224 if(
approx(m_averagePos, pos, halfCellLength)) {
225 m_rntBcCells.push_back(LESId);
233template <MInt nDim,
class SysEqn>
237 if(LESSolver().grid().isActive()) {
239 std::vector<MFloat> LESAverageCells_OLD_L;
240 std::vector<std::vector<MFloat>> LESVarAverage_OLD;
241 std::vector<MInt> rntBcCells_OLD;
242 std::vector<MInt> LESAverageCells_OLD;
244 for(
MInt c = 0; c < (
MInt)LESSolver().m_LESAverageCells.size(); c++) {
245 LESAverageCells_OLD_L.push_back(LESSolver().m_LESAverageCells[c]);
248 for(
MInt cc = 0; cc < m_noRntBcCells; cc++) {
249 rntBcCells_OLD.push_back(m_rntBcCells[cc]);
254 reconstructNutilde();
257 transferSolverData();
261template <MInt nDim,
class SysEqn>
265 if(LESSolver().grid().isActive()) {
266 if(LESSolver().noNeighborDomains() > 0) {
267 LESSolver().exchangeData(&LESSolver().a_variable(0, 0), noLESVariables());
268 LESSolver().exchangeData(&LESSolver().a_oldVariable(0, 0), noLESVariables());
269 LESSolver().exchangeData(&LESSolver().a_pvariable(0, 0), noLESVariables());
273 if(RANSSolver().grid().isActive()) {
274 if(RANSSolver().noNeighborDomains() > 0) {
275 RANSSolver().exchangeData(&RANSSolver().a_variable(0, 0), noRANSVariables());
276 RANSSolver().exchangeData(&RANSSolver().a_oldVariable(0, 0), noRANSVariables());
277 RANSSolver().exchangeData(&RANSSolver().a_pvariable(0, 0), noRANSVariables());
283 reconstructNutilde();
285 transferSolverData();
290template <MInt nDim,
class SysEqn>
295 if(RANSSolver().grid().isActive()) {
296 for(
MInt var = 0; var < noRANSVariables(); var++) {
297 for(
MInt cellId = 0; cellId < a_noFvGridCellsRANS(); cellId++) {
300 ASSERT(cellId < (
MInt)RANSSolver().m_LESValues[var].size(),
301 "Trying to access data [" + to_string(var) +
"][" + to_string(cellId)
302 +
"] in LESSolver().m_LESVarAverage(RANS) with length "
303 + to_string(RANSSolver().m_LESValues[var].size())
304 +
", domainId: " + to_string(RANSSolver().domainId()));
307 vector<MInt>::iterator findAvgId =
308 find(LESSolver().m_LESAverageCells.begin(), LESSolver().m_LESAverageCells.end(), LESId);
309 if(findAvgId != LESSolver().m_LESAverageCells.end()) {
310 MInt avgId = distance(LESSolver().m_LESAverageCells.begin(), findAvgId);
313 RANSSolver().m_LESValues[var][cellId] = LESSolver().m_LESVarAverage[var_][avgId];
321 if(LESSolver().grid().isActive()) {
322 for(
MInt cellId = 0; cellId < a_noFvGridCellsLES(); cellId++) {
326 for(
MInt var = 0; var < noRANSVariables(); var++) {
327 ASSERT(cellId < (
MInt)LESSolver().m_RANSValues[var].size(),
328 "Trying to access data [" + to_string(var) +
"][" + to_string(cellId)
329 +
"] in m_RANSValues with length " + to_string(LESSolver().m_RANSValues[var].size())
330 +
", domainId: " + to_string(LESSolver().domainId()));
332 LESSolver().m_RANSValues[var][cellId] = RANSSolver().a_pvariable(RANSId, var);
340template <MInt nDim,
class SysEqn>
344 const MInt N = RANSSolver().m_sysEqn.PV->N;
346 if(LESSolver().grid().isActive()) {
349 const MFloat rRe = F1 / LESSolver().m_sysEqn.m_Re0;
359 MFloat tuFreeStream = 0.05;
361 if(abs(m_turbulentIntensity + 1) < 1e-16) {
362 std::vector<std::pair<MFloat, MFloat>> tuFreeStreamData = {
363 std::make_pair(31171.1711712, 0.0451546391753), std::make_pair(34774.7747748, 0.0428865979381),
364 std::make_pair(38378.3783784, 0.0407216494845), std::make_pair(42702.7027027, 0.0385567010309),
365 std::make_pair(51711.7117117, 0.0349484536082), std::make_pair(58558.5585586, 0.0327835051546),
366 std::make_pair(66846.8468468, 0.0305154639175), std::make_pair(78738.7387387, 0.0278350515464),
367 std::make_pair(93513.5135135, 0.0250515463918), std::make_pair(111891.891892, 0.0223711340206),
368 std::make_pair(132432.432432, 0.0198969072165), std::make_pair(158738.738739, 0.0175257731959),
369 std::make_pair(186126.126126, 0.0154639175258), std::make_pair(215675.675676, 0.0137113402062),
370 std::make_pair(243783.783784, 0.0124742268041), std::make_pair(273693.693694, 0.0113402061856),
371 std::make_pair(301801.801802, 0.0105154639175)};
374 MInt length = (
MInt)tuFreeStreamData.size();
375 for(
MInt i = 0; i < length; i++) {
376 if(tuFreeStreamData[i].first > LESSolver().m_Re * m_tuLengthScaleCorrection) {
377 tuFreeStream = tuFreeStreamData[i - 1].second
378 + (tuFreeStreamData[i].second - tuFreeStreamData[i - 1].second)
379 / (tuFreeStreamData[i].first - tuFreeStreamData[i - 1].first)
380 * (LESSolver().m_Re * m_tuLengthScaleCorrection - tuFreeStreamData[i - 1].first);
385 if(LESSolver().m_Re * m_tuLengthScaleCorrection < tuFreeStreamData[0].first) {
386 tuFreeStream = tuFreeStreamData[0].second
387 + (tuFreeStreamData[1].second - tuFreeStreamData[0].second)
388 / (tuFreeStreamData[1].first - tuFreeStreamData[0].first)
389 * (LESSolver().m_Re * m_tuLengthScaleCorrection - tuFreeStreamData[0].first);
391 if(LESSolver().m_Re * m_tuLengthScaleCorrection > tuFreeStreamData[length - 1].first) {
392 tuFreeStream = tuFreeStreamData[length - 2].second
393 + (tuFreeStreamData[length - 1].second - tuFreeStreamData[length - 2].second)
394 / (tuFreeStreamData[length - 1].first - tuFreeStreamData[length - 2].first)
395 * (LESSolver().m_Re * m_tuLengthScaleCorrection - tuFreeStreamData[length - 2].first);
398 tuFreeStream *= 0.95;
400 m_log <<
"interpolation of freestream turbulence intensity: " << tuFreeStream << endl;
403 tuFreeStream = m_turbulentIntensity;
406 for(
MInt c = 0; c < m_noRntBcCells; c++) {
407 MInt cellId = m_rntBcCells[c];
408 vector<MInt>::iterator findLESId =
409 find(LESSolver().m_LESAverageCells.begin(), LESSolver().m_LESAverageCells.end(), cellId);
410 if(findLESId == LESSolver().m_LESAverageCells.end()) TERMM(1,
"Something went wrong " + to_string(cellId));
411 MInt LESAvgId = distance(LESSolver().m_LESAverageCells.begin(), findLESId);
420 for(
MInt i = 0; i < nDim; i++) {
421 for(
MInt j = count_; j < nDim; j++) {
422 index1 = index_ + noRANSVariables();
424 ASSERT(c < (
MInt)LESSolver().m_LESVarAverage[index1].size(),
425 "Trying to access data [" + to_string(index1) +
"][" + to_string(LESAvgId)
426 +
"] in LESSolver().m_LESVarAverage with length "
427 + to_string(LESSolver().m_LESVarAverage[index1].size()));
430 * (LESSolver().m_LESVarAverage[index1][LESAvgId]
431 - pow(LESSolver().m_LESVarAverage[index2][LESAvgId], F2));
432 tuarg += (LESSolver().m_LESVarAverage[index1][LESAvgId]
433 - pow(LESSolver().m_LESVarAverage[index2][LESAvgId], F2));
441 tuarg = max(tuarg, epss);
443 MFloat tu = sqrt(tuarg / 3.0) / LESSolver().m_Ma;
444 MFloat tufac = tanh((tu - tuFreeStream) / tuFreeStream);
445 MFloat tulim = max(tu, tuFreeStream);
448 k = k * tufac * tulim;
451 MFloat du[3][3]{{F0, F0, F0}, {F0, F0, F0}, {F0, F0, F0}};
452 const MInt recData = LESSolver().a_reconstructionData(cellId);
454 const MFloat u[3] = {LESSolver().m_LESVarAverage[0][LESAvgId], LESSolver().m_LESVarAverage[1][LESAvgId],
455 LESSolver().m_LESVarAverage[2][LESAvgId]};
457 for(
MInt nghbr = 0; nghbr < LESSolver().a_noReconstructionNeighbors(cellId); nghbr++) {
458 const MInt recNghbrId = LESSolver().a_reconstructionNeighborId(cellId, nghbr);
459 const MFloat recConst_x = LESSolver().m_reconstructionConstants[nDim * (recData + nghbr) + 0];
460 const MFloat recConst_y = LESSolver().m_reconstructionConstants[nDim * (recData + nghbr) + 1];
461 const MFloat recConst_z = LESSolver().m_reconstructionConstants[nDim * (recData + nghbr) + 2];
463 vector<MInt>::iterator findRecNghbrId =
464 find(LESSolver().m_LESAverageCells.begin(), LESSolver().m_LESAverageCells.end(), recNghbrId);
466 if(findRecNghbrId == LESSolver().m_LESAverageCells.end())
467 TERMM(1,
"Something went wrong in nghbr " + to_string(recNghbrId));
469 MInt LESRecNghbrId = distance(LESSolver().m_LESAverageCells.begin(), findRecNghbrId);
471 for(
MInt dim = 0; dim < nDim; dim++) {
472 ASSERT(c < (
MInt)LESSolver().m_LESVarAverage[dim].size(),
473 "Trying to access data [" + to_string(dim) +
"][" + to_string(LESRecNghbrId)
474 +
"] in LESSolver().m_LESVarAverage with length "
475 + to_string(LESSolver().m_LESVarAverage[dim].size()));
477 const MFloat delta_u = LESSolver().m_LESVarAverage[dim][LESRecNghbrId] - u[dim];
478 if(abs(LESSolver().m_LESVarAverage[dim][LESRecNghbrId]) > epss
479 || abs(u[dim] / LESSolver().m_LESVarAverage[dim][LESRecNghbrId]) > 100) {
480 du[dim][0] += recConst_x * delta_u;
481 du[dim][1] += recConst_y * delta_u;
482 du[dim][2] += recConst_z * delta_u;
488 for(
MInt d1 = 0; d1 < nDim; d1++) {
489 for(
MInt d2 = 0; d2 < nDim; d2++) {
490 MFloat sij = 0.5 * (du[d1][d2] + du[d2][d1]);
495 const MFloat SijSijLim = (4.0 * pow(LESSolver().m_Ma, F2)) * 0.0001;
496 SijSij = max(SijSij, SijSijLim);
498 MFloat omega = 1 / sqrt(c_mu) * sqrt(2 * SijSij);
499 omega = max(omega, epss);
502 MFloat nuTurb = max(k / (omega * rRe), LESSolver().m_nuTildeInfinity);
503 MFloat nuTilde = LESSolver().m_nuTildeInfinity;
504 if(std::isnan(omega) || tulim < 1) {
505 nuTurb = LESSolver().m_nuTildeInfinity;
508 if(
approx(tulim, F1, eps)) {
509 const MFloat rho = LESSolver().a_pvariable(cellId, LESSolver().m_sysEqn.PV->RHO);
510 const MFloat p = LESSolver().a_pvariable(cellId, LESSolver().m_sysEqn.PV->P);
511 const MFloat T = LESSolver().m_gamma * p / rho;
512 const MFloat mue = (T * sqrt(T) * LESSolver().m_sutherlandPlusOne) / (T + LESSolver().m_sutherlandConstant);
513 const MFloat nuLaminar = mue / rho;
516 MInt NewtonIter = 50;
524 while(abs(nu_new - nu_old) > eps && icount < NewtonIter) {
527 MFloat chi = nu_old / nuLaminar;
528 MFloat chi3 = pow(chi, 3.0);
530 MFloat fv1 = chi3 / (chi3 + cv13);
533 func_n = nu_old * fv1 - nut;
535 derv_n = fv1 + 3.0 * fv1 - 3.0 * fv1 * fv1;
537 nu_new = nu_old - func_n / derv_n;
545 LESSolver().m_LESVarAverage[N][LESAvgId] = nuTilde;
551template <MInt nDim,
class SysEqn>
555 if(LESSolver().grid().isActive()) {
556 for(
MInt c = 0; c < (
MInt)LESSolver().m_LESAverageCells.size(); c++) {
557 MInt cellId = LESSolver().m_LESAverageCells[c];
561 MFloat nuTilde = RANSSolver().a_pvariable(RANSId, RANSSolver().m_sysEqn.PV->N);
563 for(
MInt i = 0; i < nDim; i++) {
564 add += F2B3 * RANSSolver().a_slope(RANSId, i, i);
569 for(
MInt i = 0; i < nDim; i++) {
570 for(
MInt j = count; j < nDim; j++) {
571 MInt indexAvg = index + noRANSVariables();
573 ASSERT(c < (
MInt)LESSolver().m_LESVarAverage[indexAvg].size(),
574 "Trying to access data [" + to_string(indexAvg) +
"][" + to_string(c)
575 +
"] in LESSolver().m_LESVarAverage with length "
576 + to_string(LESSolver().m_LESVarAverage[indexAvg].size()));
579 LESSolver().m_LESVarAverage[indexAvg][c] =
580 LESSolver().m_LESVarAverage[i][c] * LESSolver().m_LESVarAverage[j][c]
581 - nuTilde * (RANSSolver().a_slope(RANSId, i, j) + RANSSolver().a_slope(RANSId, j, i) - add);
583 LESSolver().m_LESVarAverage[indexAvg][c] =
584 LESSolver().m_LESVarAverage[i][c] * LESSolver().m_LESVarAverage[j][c]
585 - nuTilde * (RANSSolver().a_slope(RANSId, i, j) + RANSSolver().a_slope(RANSId, j, i));
static MInt propertyLength(const MString &name, MInt solverId=m_noSolvers)
Returns the number of elements of a property.
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
void reconstructAverageFromNut()
void transferSolverData()
void determineNutReconstructionCells()
FvZonalRTV(const MInt couplingId, RANS *R, LES *L)
void reconstructNutilde()
void determineZonalPositions()
void finalizeCouplerInit()
MInt convertIdParent(SolverA &solverA, SolverB &solverB, const MInt solverAId)
Conversion from solverA id to the solverB id If no cell on the same level is found,...
MBool approx(const T &, const U &, const T)
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
static constexpr MFloat cv1to3