MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
fvstructuredsolver2d.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 "COMM/mpioverride.h"
10#include "IO/parallelio_hdf5.h"
11#include "globals.h"
12
13using namespace std;
14
15
20 const MPI_Comm comm)
21 : FvStructuredSolver<2>(solverId, grid_, propertiesGroups, comm) {
22 TRACE();
23 const MLong oldAllocatedBytes = allocatedBytes();
24
25 // count the no of necessary FQ fields and allocate
27
28 // compute the cell center coordinates from point coordinates
30
31 if(m_rans) {
33 } else {
35 }
36
38
39 // assign coordinates to all ghost points
41
42 // allocate memory for aux data maps (cf,cp)
44
45 // if we are Rans we should allocate a new RANS solver
46 if(m_rans == true) {
48 }
49
51 RECORD_TIMER_START(m_timers[Timers::ComputeMetrics]);
52 m_grid->computeMetrics();
53 RECORD_TIMER_STOP(m_timers[Timers::ComputeMetrics]);
54 RECORD_TIMER_START(m_timers[Timers::ComputeJacobian]);
55 m_grid->computeJacobian();
56 RECORD_TIMER_STOP(m_timers[Timers::ComputeJacobian]);
57
58 // TODO_SS labels:FV By now I am not sure if Code performs correctly for wrongly oriented meshes
59 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - 1; j++) {
60 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - 1; i++) {
61 const MInt cellId = cellIndex(i, j);
62 if(m_cells->cellJac[cellId] < 0.0) {
63 mTerm(1, "Negative Jacobian found! Check first if code can cope this!");
64 }
65 }
66 }
67
69
70 m_convergence = false;
71
72 // Assign handlers to the correct boundary conditions
74
75 // Computation of modified wall distance in porous computation requires to set the porosity,
76 // Da-number etc. first; on the other hand we need to wait for initializeFQField to be called
77 if(m_porous) {
78 initPorous();
79 // exchange6002();
80 }
81
82 if(m_rans) {
85 // m_structuredBndryCnd->computeLocalWallDistances();
86 else
88 }
89
90 // utau is required in RANS models for the computation of y+; In case the wall distance is very
91 // large, the utau computation is skipped; In such situations the default value of utau=0 would
92 // yield a y+=0 even very far away from walls
93 // TODO_SS labels:FV currently in UTAU we save the inverse of the turbulent length scale
94 if(FQ->neededFQVariables[FQ->UTAU]) {
95 for(MInt cellId = 0; cellId < m_noCells; ++cellId) {
96 m_cells->fq[FQ->UTAU][cellId] = 1.0;
97 }
98 }
99 }
100
101 printAllocatedMemory(oldAllocatedBytes, "FvStructuredSolver2D", m_StructuredComm);
102 RECORD_TIMER_STOP(m_timers[Timers::Constructor]);
103}
104
106 // set the MUSCL-scheme to the right function
107 if(m_rans == true) {
110 } else {
111 if(m_viscCompact)
112 viscFluxMethod = &FvStructuredSolver2D::viscousFluxLESCompact<>;
113 else
114 viscFluxMethod = &FvStructuredSolver2D::viscousFluxLES<>;
115 if(m_limiter) {
117 case ALBADA: {
118 m_log << "Using VAN ALBADA limiter!" << endl;
120 break;
121 }
122 default: {
123 stringstream errorMessage;
124 errorMessage << "Limiter function " << m_limiterMethod << " not implemented!" << endl;
125 mTerm(1, AT_, errorMessage.str());
126 }
127 }
128 } else {
129 if(m_musclScheme == "Standard") {
130 m_log << "Using unlimited MUSCL! (standard Formulation)" << endl;
131 if(m_ausmScheme == "Standard") {
132 switch(CV->noVariables) {
133 case 4: {
134 reconstructSurfaceData = &FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES, 4>;
135 break;
136 }
137 case 5: {
138 reconstructSurfaceData = &FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES, 5>;
139 break;
140 }
141 case 6: {
142 reconstructSurfaceData = &FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES, 6>;
143 break;
144 }
145 default: {
146 stringstream errorMessage;
147 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
148 mTerm(1, AT_);
149 }
150 }
151 } else if(m_ausmScheme == "PTHRC") {
152 switch(CV->noVariables) {
153 case 4: {
154 reconstructSurfaceData = &FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES_PTHRC, 4>;
155 break;
156 }
157 case 5: {
158 reconstructSurfaceData = &FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES_PTHRC, 5>;
159 break;
160 }
161 case 6: {
162 reconstructSurfaceData = &FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES_PTHRC, 6>;
163 break;
164 }
165 default: {
166 stringstream errorMessage;
167 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
168 mTerm(1, AT_);
169 }
170 }
171 } else if(m_ausmScheme == "AUSMDV") {
172 switch(CV->noVariables) {
173 case 4: {
174 reconstructSurfaceData = &FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmDV, 4>;
175 break;
176 }
177 case 5: {
178 reconstructSurfaceData = &FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmDV, 5>;
179 break;
180 }
181 case 6: {
182 reconstructSurfaceData = &FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmDV, 6>;
183 break;
184 }
185 default: {
186 stringstream errorMessage;
187 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
188 mTerm(1, AT_);
189 }
190 }
191 }
192 } else if(m_musclScheme == "Stretched") {
193 m_log << "Using unlimited MUSCL (streched Grids)";
194 mAlloc(m_cells->cellLength, nDim, m_noCells, "m_cells->cellLength", -F1, AT_);
196 if(m_ausmScheme == "Standard") {
197 switch(CV->noVariables) {
198 case 4: {
199 reconstructSurfaceData = &FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES, 4>;
200 break;
201 }
202 case 5: {
203 reconstructSurfaceData = &FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES, 5>;
204 break;
205 }
206 case 6: {
207 reconstructSurfaceData = &FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES, 6>;
208 break;
209 }
210 default: {
211 stringstream errorMessage;
212 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
213 mTerm(1, AT_);
214 }
215 }
216 } else if(m_ausmScheme == "PTHRC") {
217 switch(CV->noVariables) {
218 case 4: {
219 reconstructSurfaceData = &FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES_PTHRC, 4>;
220 break;
221 }
222 case 5: {
223 reconstructSurfaceData = &FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES_PTHRC, 5>;
224 break;
225 }
226 case 6: {
227 reconstructSurfaceData = &FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES_PTHRC, 6>;
228 break;
229 }
230 default: {
231 stringstream errorMessage;
232 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
233 mTerm(1, AT_);
234 }
235 }
236 }
237 }
238 }
239 }
240}
241
243 TRACE();
244
246 if(m_rans) {
247 delete m_ransSolver;
248 }
249
250 if(m_hasSingularity) {
251 delete[] m_singularity;
252 }
253}
254
255
257 // this function can be moved into the MusclSchemeStreched later but for testing it is easier
258 // REMEMBER: FOR MOVINg GRIDS THIS NEEDS TO BE CALLED EACH TIME
259
260 for(MInt j = 0; j < m_nCells[0]; j++) {
261 for(MInt i = 0; i < m_nCells[1]; i++) {
262 const MInt cellId = cellIndex(i, j);
263 const MInt P1 = getPointIdFromCell(i, j);
264 const MInt P2 = getPointIdFromPoint(P1, 1, 0);
265 const MInt P3 = getPointIdFromPoint(P1, 1, 1);
266 const MInt P4 = getPointIdFromPoint(P1, 0, 1);
267 //----------Idirection
268 // face 1
269 const MFloat f1x = F1B2 * (m_grid->m_coordinates[0][P1] + m_grid->m_coordinates[0][P4]);
270 const MFloat f1y = F1B2 * (m_grid->m_coordinates[1][P1] + m_grid->m_coordinates[1][P4]);
271 // face 2
272 const MFloat f2x = F1B2 * (m_grid->m_coordinates[0][P2] + m_grid->m_coordinates[0][P3]);
273 const MFloat f2y = F1B2 * (m_grid->m_coordinates[1][P2] + m_grid->m_coordinates[1][P3]);
274 m_cells->cellLength[0][cellId] = sqrt(POW2(f2x - f1x) + POW2(f2y - f1y));
275 //----------Jdirection
276 // face 3
277 const MFloat f3x = F1B2 * (m_grid->m_coordinates[0][P1] + m_grid->m_coordinates[0][P2]);
278 const MFloat f3y = F1B2 * (m_grid->m_coordinates[1][P1] + m_grid->m_coordinates[1][P2]);
279 // face 4
280 const MFloat f4x = F1B4 * (m_grid->m_coordinates[0][P3] + m_grid->m_coordinates[0][P4]);
281 const MFloat f4y = F1B4 * (m_grid->m_coordinates[1][P3] + m_grid->m_coordinates[1][P4]);
282 m_cells->cellLength[1][cellId] = sqrt(POW2(f4x - f3x) + POW2(f4y - f3y));
283 }
284 }
285}
286
287
296 TRACE();
297
298 std::ignore = mode;
299
300 // Compute infinity values from property file
301 // and (if no restart) fill cells according
302 // to the initialCondition property
304
305 if(m_restart) {
307 }
308
309 setTimeStep();
310
311 // initialize moving grid
312 // functions and move grid
313 // to correct position
314 if(m_movingGrid) {
315 RECORD_TIMER_START(m_timers[Timers::MovingGrid]);
316 RECORD_TIMER_START(m_timers[Timers::MGMoveGrid]);
318 RECORD_TIMER_STOP(m_timers[Timers::MGMoveGrid]);
319 RECORD_TIMER_STOP(m_timers[Timers::MovingGrid]);
320 }
321
322 // Get the correct values
323 // in the exchange ghostcells
324 exchange();
325
326 // Call the init function of each BC
328
329 // Apply boundary conditions
330 // and fill the non-exchange ghostcells
332
333 // Convert SA turb. quantities to k-epsilon when restarting from SA solution
335
336 // Check for NaNs
337 checkNans();
338
340}
341
342
344 TRACE();
345
346 MBool restartFromSA = false;
347 restartFromSA = Context::getSolverProperty<MBool>("restartFromSA", m_solverId, AT_, &restartFromSA);
348 if(!restartFromSA) return;
349
350 if(domainId() == 0) cout << "\033[1;31m !!!Converting SA turbulence quantities to k & epsilon!!!\033[0m\n" << endl;
351
352 MFloat* const RESTRICT p = &m_cells->pvariables[PV->P][0];
353 MFloat* const RESTRICT rho = &m_cells->pvariables[PV->RHO][0];
354 MFloat* const RESTRICT nuTilde = &m_cells->pvariables[PV->RANS_VAR[0]][0];
355
356 for(MInt i = 0; i < m_noCells; ++i) {
357 const MFloat T = m_gamma * p[i] / rho[i];
358 // decode the kinematic turbulent viscosity from the turb dynamic visc arrays
359 const MFloat nuLaminar = SUTHERLANDLAW(T) / rho[i];
360 const MFloat chi = nuTilde[i] / (nuLaminar);
361 const MFloat fv1 = pow(chi, 3) / (pow(chi, 3) + RM_SA_DV::cv1to3);
362 const MFloat nuTurb = fv1 * nuTilde[i];
363 m_cells->fq[FQ->NU_T][i] = nuTurb;
364 m_cells->fq[FQ->MU_T][i] = rho[i] * nuTurb;
365 }
366
367 // compute friction velocity at wall
369 // communicate wall properties to all cells
371
372 const MFloat rRe0 = 1.0 / m_Re0;
373 const MFloat fac_nonDim = m_keps_nonDimType ? 1.0 : PV->UInfinity;
374 MFloat* const RESTRICT u = &m_cells->pvariables[PV->U][0];
375 MFloat* const RESTRICT v = &m_cells->pvariables[PV->V][0];
376 const MFloat* const RESTRICT utau = &m_cells->fq[FQ->UTAU][0];
377 const MFloat* const RESTRICT wallDist = &m_cells->fq[FQ->WALLDISTANCE][0];
378 const MFloat* const RESTRICT muTurb = &m_cells->fq[FQ->MU_T][0];
379 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
380 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
381 const MInt IJ = cellIndex(i, j);
382 const MInt IPJ = cellIndex((i + 1), j);
383 const MInt IMJ = cellIndex(i - 1, j);
384 const MInt IJM = cellIndex(i, j - 1);
385 const MInt IJP = cellIndex(i, (j + 1));
386
387 const MFloat invCellJac = 1.0 / m_cells->cellJac[IJ];
388
389 const MFloat dudxi = 0.5 * (u[IPJ] - u[IMJ]);
390 const MFloat dudet = 0.5 * (u[IJP] - u[IJM]);
391 const MFloat dvdxi = 0.5 * (v[IPJ] - v[IMJ]);
392 const MFloat dvdet = 0.5 * (v[IJP] - v[IJM]);
393
394 const MFloat dudx =
395 dudxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ] + dudet * m_cells->cellMetrics[ysd * 2 + xsd][IJ];
396 const MFloat dudy =
397 dudxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ] + dudet * m_cells->cellMetrics[ysd * 2 + ysd][IJ];
398 const MFloat dvdx =
399 dvdxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ] + dvdet * m_cells->cellMetrics[ysd * 2 + xsd][IJ];
400 const MFloat dvdy =
401 dvdxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ] + dvdet * m_cells->cellMetrics[ysd * 2 + ysd][IJ];
402
403 const MFloat P_ = (rRe0 / POW2(fac_nonDim) * invCellJac * muTurb[IJ]
404 * (2.0 * POW2(dudx) + 2.0 * POW2(dvdy) + POW2(dudy + dvdx)))
405 * invCellJac;
406 const MFloat rhoEps = P_ / fac_nonDim;
407 m_cells->pvariables[PV->RANS_VAR[1]][IJ] = rhoEps / rho[IJ];
408 m_cells->variables[PV->RANS_VAR[1]][IJ] = rhoEps;
409
410 //
411 // const MFloat T = m_gamma*p[i]/rho[i];
412 // const MFloat nuLaminar = SUTHERLANDLAW(T)/rho[IJ];
413 // TODO_SS labels:FV
414 const MFloat yp = utau[IJ] * wallDist[IJ]; // utau[IJ]*wallDist[IJ]/nuLaminar;
415 const MFloat f_mu = 1 - exp(-RM_KEPS::C3 * m_Re0 * yp);
416 const MFloat rhoTKE = sqrt(rhoEps * muTurb[IJ] / (RM_KEPS::C_mu * f_mu * m_Re0 * fac_nonDim));
417 m_cells->pvariables[PV->RANS_VAR[0]][IJ] = rhoTKE / rho[IJ];
418 m_cells->variables[PV->RANS_VAR[0]][IJ] = rhoTKE;
419 }
420 }
421
422 //
423 exchange();
425}
426
433 TRACE();
434
435 const MFloat gammaMinusOne = m_gamma - 1.0;
436 MFloat UT;
437 // MFloat pressure=F0;
438 // MFloat Frho; switched off cause of compiler
439
440 PV->TInfinity = 1.0 / (1.0 + F1B2 * gammaMinusOne * POW2(m_Ma));
441 UT = m_Ma * sqrt(PV->TInfinity);
442 PV->UInfinity = UT * cos(m_angle[0]) * cos(m_angle[1]);
443 PV->VInfinity = UT * sin(m_angle[0]) * cos(m_angle[1]);
444 PV->VVInfinity[0] = PV->UInfinity;
445 PV->VVInfinity[1] = PV->VInfinity;
446 PV->PInfinity = pow(PV->TInfinity, (m_gamma / gammaMinusOne)) / m_gamma;
447
448 // compute conservative variables
449 CV->rhoInfinity = pow(PV->TInfinity, (1.0 / gammaMinusOne));
450 CV->rhoUInfinity = CV->rhoInfinity * PV->UInfinity;
451 CV->rhoVInfinity = CV->rhoInfinity * PV->VInfinity;
452 CV->rhoVVInfinity[0] = CV->rhoUInfinity;
453 CV->rhoVVInfinity[1] = CV->rhoVInfinity;
454 CV->rhoEInfinity = PV->PInfinity / gammaMinusOne + CV->rhoInfinity * (F1B2 * POW2(UT));
455
456 // internal Reynolds number Re0 = Re / ( rho8*M*sqrt(T8)/T8^F072)
457 m_Re0 = m_Re * SUTHERLANDLAW(PV->TInfinity) / (CV->rhoInfinity * m_Ma * sqrt(PV->TInfinity));
458
459 // reference enthalpies (needed for combustion computations)
460 m_hInfinity = PV->PInfinity / CV->rhoInfinity * m_gamma / gammaMinusOne;
461
462 // reference time (convection time)
464
465 m_deltaP = F0;
466 // pressure loss per unit length dp = rho_00 u_tau^2 L / D ) here: D=1.0, L=1;
467 // channel: dp = rho_00 u_tau^2 L / D )
468 // m_deltaP = POW2( m_Ma * m_ReTau * sqrt(PV->TInfinity) / m_Re ) * CV->rhoInfinity / m_referenceLength;x
469 // result is obtained by making deltap dimensionless with a_0^2 and rho_0
470 // pipe: dp = lambda * L/D * rho/2 * u^2, lambda = 0.3164 Re^(-1/4) (Blasius)
471
472 if(m_rans) {
474 const MFloat rho = CV->rhoInfinity;
475 const MFloat lamVisc = SUTHERLANDLAW(PV->TInfinity);
476 const MFloat k8 = m_keps_nonDimType ? 1.5 * POW2(UT * m_I) : 1.5 * POW2(m_I);
477 PV->ransInfinity[0] = k8;
478 if(m_kepsICMethod == 1) {
479 PV->ransInfinity[1] = RM_KEPS::C_mu * pow(k8, 1.5) / m_epsScale;
480 } else if(m_kepsICMethod == 2) {
481 PV->ransInfinity[1] = m_keps_nonDimType ? RM_KEPS::C_mu * rho * POW2(k8) * m_Re0 / (lamVisc * m_epsScale)
482 : RM_KEPS::C_mu * rho * POW2(k8) * m_Re0 * UT / (lamVisc * m_epsScale);
483 } else {
484 PV->ransInfinity[1] = m_keps_nonDimType ? m_epsScale * UT * UT * UT : m_epsScale;
485 }
486 CV->ransInfinity[0] = CV->rhoInfinity * PV->ransInfinity[0];
487 CV->ransInfinity[1] = CV->rhoInfinity * PV->ransInfinity[1];
488 } else {
489 MFloat chi = 0.1;
490 chi = Context::getSolverProperty<MFloat>("chi", m_solverId, AT_, &chi);
491 const MFloat lamVisc = SUTHERLANDLAW(PV->TInfinity);
492 CV->ransInfinity[0] = chi * (lamVisc);
493 PV->ransInfinity[0] = chi * (lamVisc / CV->rhoInfinity);
494 }
495 }
496
497 m_log << "**************************" << endl;
498 m_log << "Initial Condition summary" << endl;
499 m_log << "**************************" << endl;
500 m_log << "Re = " << m_Re << endl;
501 m_log << "Re0 = " << m_Re0 << endl;
502 m_log << "Ma = " << m_Ma << endl;
503 m_log << "TInfinity = " << PV->TInfinity << endl;
504 m_log << "UInfinity = " << PV->UInfinity << endl;
505 m_log << "VInfinity = " << PV->VInfinity << endl;
506 m_log << "PInfinity = " << PV->PInfinity << endl;
507 m_log << "rhoInfinity = " << CV->rhoInfinity << endl;
508 m_log << "rhoEInfinity = " << CV->rhoEInfinity << endl;
509 for(MInt ransVarId = 0; ransVarId < m_noRansEquations; ++ransVarId)
510 m_log << "Rans" << ransVarId << "Infinity = " << PV->ransInfinity[ransVarId] * 1e8 << "e-8" << endl;
511 m_log << "referenceTime = " << m_timeRef << endl;
512
513 if(domainId() == 0) {
514 cout << "**************************" << endl;
515 cout << "Initial Condition summary" << endl;
516 cout << "**************************" << endl;
517 cout << "Re = " << m_Re << endl;
518 cout << "Re0 = " << m_Re0 << endl;
519 cout << "Ma = " << m_Ma << endl;
520 cout << "TInfinity = " << PV->TInfinity << endl;
521 cout << "UInfinity = " << PV->UInfinity << endl;
522 cout << "VInfinity = " << PV->VInfinity << endl;
523 cout << "PInfinity = " << PV->PInfinity << endl;
524 cout << "rhoInfinity = " << CV->rhoInfinity << endl;
525 cout << "rhoEInfinity = " << CV->rhoEInfinity << endl;
526 for(MInt ransVarId = 0; ransVarId < m_noRansEquations; ++ransVarId)
527 cout << "Rans" << ransVarId << "Infinity = " << PV->ransInfinity[ransVarId] * 1e8 << "e-8" << endl;
528 cout << "referenceTime = " << m_timeRef << endl;
529 }
530
531
532 if(!m_restart) {
533 // inflow condition
534 // ----------------
535
536 switch(m_initialCondition) {
537 case 0:
538 case 465: // quiscient state
539 {
540 MFloat u_infty[nDim]{};
541 if(m_initialCondition == 0) {
542 u_infty[0] = PV->VVInfinity[0];
543 u_infty[1] = PV->VVInfinity[1];
544 }
545 // parallel inflow field
546 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
547 // go through every cell
548 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
549 for(MInt i = 0; i < nDim; i++) {
550 m_cells->pvariables[PV->VV[i]][cellId] = u_infty[i]; // PV->VVInfinity[i];
551 }
552
553 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
554
555 if(m_rans) {
556 for(MInt ransVarId = 0; ransVarId < m_noRansEquations; ++ransVarId) {
557 m_cells->pvariables[PV->RANS_VAR[ransVarId]][cellId] = PV->ransInfinity[ransVarId];
558 }
559 }
560 }
561 break;
562 }
563 case 43: {
564 // parallel inflow field
565 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
566 // go through every cell
567 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
568 for(MInt i = 0; i < nDim; i++) {
569 m_cells->pvariables[PV->VV[i]][cellId] = F0;
570 }
571
572 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
573
574 MFloat radius =
575 sqrt(POW2(m_cells->coordinates[0][cellId] - 0.5) + POW2(m_cells->coordinates[1][cellId] - 0.5));
576 // impose pressure peak in the middle of the domain
577 if(radius <= 0.05) {
578 MFloat pAmp = 0.005;
579 MFloat pressureSignal = sin(radius / 0.05 * PI) * pAmp + PV->PInfinity;
580 m_cells->pvariables[PV->P][cellId] = pressureSignal;
581 }
582 }
583 break;
584 }
585 case 314: // stagnating flow field
586 {
587 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
588 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity;
589 for(MInt i = 0; i < nDim; i++) {
590 m_cells->pvariables[PV->VV[i]][cellid] = F0;
591 }
592
593 m_cells->pvariables[PV->P][cellid] = PV->PInfinity;
594 }
595 cout << "I.C. stagnating flow field was applied! " << endl;
596 break;
597 }
598 case 333: {
599 // parallel inflow field
600 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
601 // go through every cell
602 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
603 for(MInt i = 0; i < nDim; i++) {
604 m_cells->pvariables[PV->VV[i]][cellId] = PV->VVInfinity[i];
605 }
606
607 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
608
609 // impose pressure peak in the middle of the domain
610 if(m_cells->coordinates[0][cellId] > 0.4 && m_cells->coordinates[0][cellId] < 0.5) {
611 MFloat pAmp = 0.005;
612 MFloat xCoordinate = m_cells->coordinates[0][cellId] - 0.4;
613 MFloat pressureSignal = sin(xCoordinate / 0.1 * PI) * pAmp + PV->PInfinity;
614 m_cells->pvariables[PV->P][cellId] = pressureSignal / (m_gamma - F1);
615 }
616 }
617 break;
618 }
619 case 79091: // Turbulent plate
620 {
621 const MFloat epss = 1e-10;
622 const MFloat reTheta = 1000.0;
623 const MFloat theta = 1.0;
624 const MFloat delta0 = 72.0 / 7.0 * theta;
625 const MFloat K = 0.4;
626 const MFloat C1 = 3.573244189003983; // With coles
627 const MFloat PI1 = 0.55;
628 const MFloat cf = 0.024 / pow(reTheta, 0.25);
629
630 for(MInt j = 0; j < m_nCells[0]; j++) {
631 for(MInt i = 0; i < m_nCells[1]; i++) {
632 const MInt cellId = cellIndex(i, j);
633 const MFloat mu = SUTHERLANDLAW(PV->TInfinity);
634 const MFloat utau = sqrt(cf / 2.0) * m_Ma * sqrt(PV->TInfinity);
635 const MFloat yplus = m_cells->coordinates[1][cellId] * sqrt(cf / 2.) * CV->rhoUInfinity / mu * m_Re0;
636 const MFloat eta = m_cells->coordinates[1][cellId] / delta0; // y/delta
637
638 // 1-7th profile
639 // log-law + wake
640 if(m_cells->coordinates[1][cellId] > delta0) {
641 m_cells->pvariables[PV->U][cellId] = PV->UInfinity; // Outside BL
642 } else if(yplus < 10) {
643 m_cells->pvariables[PV->U][cellId] = utau * yplus;
644 } else {
645 m_cells->pvariables[PV->U][cellId] = mMin(
646 utau * ((1. / K) * log(max(yplus, epss)) + C1 + 2 * PI1 / K * (3 * eta * eta - 2 * eta * eta * eta)),
647 PV->UInfinity);
648 }
649
650 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
651 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
652 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
653
654 if(m_rans) {
655 for(MInt ransVarId = 0; ransVarId < m_noRansEquations; ++ransVarId) {
656 m_cells->pvariables[PV->RANS_VAR[ransVarId]][cellId] = PV->ransInfinity[ransVarId];
657 }
658 }
659 }
660 }
661
662 break;
663 }
664 case 999: {
665 // blasius laminar bl
666 m_log << "Blasius initial condition (incompressible)" << endl;
667 if(!m_useBlasius) mTerm(1, "property Blasius not set. Refer to the description of the property");
668 if(domainId() == 0) {
669 ofstream blasiusf;
670 // write velocity to file
671 blasiusf.open("velocity_x0.dat", ios::trunc);
672 if(blasiusf) {
673 blasiusf << "#y eta u v" << endl;
674 MFloat d0 = 0.0;
675 MFloat d1 = 0.0;
676 MFloat d2 = 0.0;
677 MBool d0Set = false;
678
679 for(MInt i = 0; i < m_blasius_noPoints; i++) {
680 // coord
681 const MFloat y = i * 0.05;
682 blasiusf << y << " " << getBlasiusEta(F0, y);
683 // velocity
684 MFloat vel[nDim];
685 getBlasiusVelocity(F0, y, vel);
686 for(MInt dim = 0; dim < nDim; dim++)
687 blasiusf << " " << vel[dim] / PV->UInfinity;
688 blasiusf << endl;
689
690 if(!d0Set && vel[0] >= 0.99 * PV->UInfinity) {
691 d0 = y;
692 d0Set = true;
693 }
694
695 if(y < 10.0) {
696 d1 += (1 - vel[0] / PV->UInfinity) * 0.05;
697 d2 += vel[0] / PV->UInfinity * (1 - vel[0] / PV->UInfinity) * 0.05;
698 }
699 }
700 blasiusf.close();
701
702 cout << "x0: " << m_blasius_x0 << endl;
703 cout << "d0: " << d0 << " d1: " << d1 << " d2: " << d2 << endl;
704 }
705 }
706
707 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
708 MFloat vel[nDim];
709 getBlasiusVelocity(cellid, vel);
710 for(MInt i = 0; i < nDim; i++) {
711 m_cells->pvariables[PV->VV[i]][cellid] = vel[i];
712 }
713 m_cells->pvariables[PV->P][cellid] = PV->PInfinity;
714 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity;
715 }
716
717 break;
718 }
719
720 default: {
721 // put the parallel flow field input in here
722 // force output that no specific initial condition was chosen
723 m_log << "No (correct) initial Condition is given! Used initial Condtion of parallel inflow!!!!!" << endl;
724 break;
725 }
726 }
727 }
728}
729
731 TRACE();
732
733 MInt pointId = 0;
734
735 // First approach: save whole mesh in m_mgInitCoordinates (for analytical channel with indentation)
736
737 for(MInt j = 0; j < m_nPoints[0]; ++j) {
738 for(MInt i = 0; i < m_nPoints[1]; ++i) {
739 pointId = pointIndex(i, j);
740 for(MInt isd = xsd; isd < nDim; ++isd) {
741 m_grid->m_initCoordinates[isd][pointId] = m_grid->m_coordinates[isd][pointId];
742 }
743 }
744 }
745
746 // Second approach: save only parts of the mesh depending on moving grid case
747 switch(m_gridMovingMethod) {
748 case 4: {
749 // do nothing
750 break;
751 }
752 case 10:
753 // travelling wave defined by non-plus units
754 {
755 m_travelingWave = true;
756 if(!m_restart) {
758 }
759 m_waveSpeed = 0.0;
760 m_waveLength = 0.0;
761 m_waveAmplitude = 0.0;
763 if(!m_restart) {
765 }
766
767 // time needs to be constant for traveling wave
768 m_constantTimeStep = true;
769
782 m_waveLength = 0.0;
783 m_waveLength = Context::getSolverProperty<MFloat>("waveLength", m_solverId, AT_, &m_waveLengthPlus);
784
797 m_waveAmplitude = 0.0;
798 m_waveAmplitude = Context::getSolverProperty<MFloat>("waveAmplitude", m_solverId, AT_, &m_waveAmplitudePlus);
799
812 m_waveTime = 0.0;
813 m_waveTime = Context::getSolverProperty<MFloat>("waveTime", m_solverId, AT_, &m_waveTimePlus);
814
827 m_waveYBeginTransition = 2000000.0;
828 if(Context::propertyExists("waveYBeginTransition", m_solverId)) {
830 Context::getSolverProperty<MFloat>("waveYBeginTransition", m_solverId, AT_, &m_waveYBeginTransition);
831 }
832
845 m_waveYEndTransition = 2000000.0;
846 if(Context::propertyExists("waveYEndTransition", m_solverId)) {
848 Context::getSolverProperty<MFloat>("waveYEndTransition", m_solverId, AT_, &m_waveYEndTransition);
849 }
850
851
866 if(Context::propertyExists("waveTemporalTransition", m_solverId)) {
868 Context::getSolverProperty<MFloat>("waveTemporalTransition", m_solverId, AT_, &m_waveOutEndTransition);
869 }
870
872 const MFloat deltaX = abs(m_grid->m_coordinates[0][0] - m_grid->m_coordinates[0][m_nPoints[1]]);
873 m_waveCellsPerWaveLength = round(m_waveLength / deltaX);
874
875 const MFloat speedAmplitude = 2 * PI * m_waveAmplitude / m_waveTime;
876
877 m_log << "/////////////////// TRAVELING WAVE /////////////////////////////" << endl;
878 m_log << "Wavelength: " << m_waveLength << " Amplitude: " << m_waveAmplitude << " Period: " << m_waveTime
879 << " Speed: " << m_waveSpeed << endl;
880 m_log << "Max up/down speed: " << speedAmplitude << endl;
881 m_log << "Max up/down speed: " << m_waveSpeed * m_waveAmplitude << endl;
882 m_log << "////////////////////////////////////////////////////////////////" << endl;
883
885 break;
886 }
887 case 12:
888 // streamwise travelling wave defined by non-plus units
889 {
891 if(!m_restart) {
893 }
894 m_waveSpeed = 0.0;
895 m_waveLength = 0.0;
896 m_waveAmplitude = 0.0;
898 if(!m_restart) {
900 }
901 // time needs to be constant for traveling wave
902 m_constantTimeStep = true;
903
916 m_waveLength = 0.0;
917 if(Context::propertyExists("waveLength", m_solverId)) {
918 m_waveLength = Context::getSolverProperty<MFloat>("waveLength", m_solverId, AT_, &m_waveLengthPlus);
919 } else {
920 mTerm(1, AT_, "Property waveLength not specified in property file");
921 }
922
936 m_waveAmplitude = 0.0;
937 if(Context::propertyExists("waveAmplitude", m_solverId)) {
938 m_waveAmplitude = Context::getSolverProperty<MFloat>("waveAmplitude", m_solverId, AT_, &m_waveAmplitudePlus);
939 } else {
940 mTerm(1, AT_, "Property waveAmplitude not specified in property file");
941 }
942
955 m_waveTime = 0.0;
956 if(Context::propertyExists("waveTime", m_solverId)) {
957 m_waveTime = Context::getSolverProperty<MFloat>("waveTime", m_solverId, AT_, &m_waveTimePlus);
958 } else {
959 mTerm(1, AT_, "Property waveTime not specified in property file");
960 }
961
962
977 Context::getSolverProperty<MFloat>("waveBeginTransition", m_solverId, AT_, &m_waveBeginTransition);
978
993 Context::getSolverProperty<MFloat>("waveEndTransition", m_solverId, AT_, &m_waveEndTransition);
994
1007 m_waveOutBeginTransition = 1000000.0;
1009 Context::getSolverProperty<MFloat>("waveOutBeginTransition", m_solverId, AT_, &m_waveOutBeginTransition);
1010
1023 m_waveOutEndTransition = 2000000.0;
1025 Context::getSolverProperty<MFloat>("waveOutEndTransition", m_solverId, AT_, &m_waveOutEndTransition);
1026
1039 m_waveYBeginTransition = 2000000.0;
1040 if(Context::propertyExists("waveYBeginTransition", m_solverId)) {
1042 Context::getSolverProperty<MFloat>("waveYBeginTransition", m_solverId, AT_, &m_waveYBeginTransition);
1043 }
1044
1045
1058 m_waveYEndTransition = 2000000.0;
1059 if(Context::propertyExists("waveYEndTransition", m_solverId)) {
1061 Context::getSolverProperty<MFloat>("waveYEndTransition", m_solverId, AT_, &m_waveYEndTransition);
1062 }
1063
1077 if(Context::propertyExists("waveTemporalTransition", m_solverId)) {
1079 Context::getSolverProperty<MFloat>("waveTemporalTransition", m_solverId, AT_, &m_waveTemporalTransition);
1080 }
1081
1083 const MFloat speedAmplitude = 2 * PI * m_waveAmplitude / m_waveTime;
1084
1085 m_log << "/////////////////// TRAVELING WAVE /////////////////////////////" << endl;
1086 m_log << "Wavelength: " << m_waveLength << " Amplitude: " << m_waveAmplitude << " Period: " << m_waveTime
1087 << " Speed: " << m_waveSpeed << endl;
1088 m_log << "Speed amplitude: " << speedAmplitude << endl;
1089 m_log << "Phase speed: " << m_waveSpeed << endl;
1090 m_log << "////////////////////////////////////////////////////////////////" << endl;
1092 break;
1093 }
1094 case 14:
1095 // oscillating cylinder
1096 {
1097 // time needs to be constant for traveling wave
1098 m_constantTimeStep = true;
1099
1112 m_oscAmplitude = 0.2;
1113 m_oscAmplitude = Context::getSolverProperty<MFloat>("oscAmplitude", m_solverId, AT_, &m_oscAmplitude);
1114
1115 m_oscSr = 0.195;
1116 m_oscSr = Context::getSolverProperty<MFloat>("oscSr", m_solverId, AT_, &m_oscSr);
1117
1118 MFloat freqFactor = 0.8;
1119 freqFactor = Context::getSolverProperty<MFloat>("oscFreqFactor", m_solverId, AT_, &freqFactor);
1120
1121 const MFloat freq0 = m_oscSr * PV->UInfinity / m_referenceLength;
1122 m_oscFreq = freq0 * freqFactor;
1123 break;
1124 }
1125 default: {
1126 stringstream errorMessage;
1127 errorMessage << "Grid moving method " << m_gridMovingMethod << " not implemented!" << endl;
1128 mTerm(1, AT_, errorMessage.str());
1129 }
1130 }
1131
1132 m_grid->saveGrid();
1133
1134 // now move the grid to the correct position
1135 if(m_restart) {
1136 if(m_movingGrid) {
1138 // if this is an initial start of the
1139 // grid movement, just move to initial pos
1140 moveGrid(true, false);
1141 m_grid->saveGrid();
1142 } else {
1143 // move to last pos before restart,
1144 // save and move to current pos again
1145 // this way the grid velocity is computed
1146 // correctly in the BC
1147 m_time -= m_timeStep;
1148 moveGrid(true, false);
1149 m_grid->saveGrid();
1150 m_time += m_timeStep;
1151 moveGrid(true, false);
1152 }
1153 }
1154 } else {
1155 moveGrid(true, false);
1156 m_grid->saveGrid();
1157 }
1158
1159 m_log << "Initializing moving grid methods... DONE!" << endl;
1160}
1161
1162
1163void FvStructuredSolver2D::moveGrid(const MBool isRestart, const MBool zeroPos) {
1164 TRACE();
1165 const MFloat pi = 4.0 * atan(1);
1166 const MFloat t = (isRestart) ? m_time : m_time + m_timeStep * m_RKalpha[m_RKStep];
1167
1168 switch(m_gridMovingMethod) {
1169 case 4: // inner grid movement
1170 {
1171 const MFloat beta = 16.0l;
1172 const MFloat StrNum = m_wallVel; // Strouhal Number, set by wallVel
1173 const MFloat ver = 0.0l; // ver can be used to translate x coordinate
1174 const MFloat y_max = 1.0l; // can be used to scale
1175
1176 // for Square:
1177 const MFloat x2 = y_max * (ver + 0.1l);
1178 const MFloat x3 = y_max * (ver + 0.5l);
1179 const MFloat x4 = y_max * (ver + 0.5l);
1180 const MFloat x5 = y_max * (ver + 0.9l);
1181
1182 const MFloat omega = m_Ma * sqrt(PV->TInfinity) * StrNum * 2.0l * pi / y_max;
1183 const MFloat h = F1B2 * 0.35l * (F1 - cos(omega * t));
1184 const MFloat hvel = F1B2 * 0.35l * (omega * sin(omega * t));
1185
1186 for(MInt j = 0; j < m_nPoints[0]; j++) {
1187 for(MInt i = 0; i < m_nPoints[1]; i++) {
1188 const MInt pointId = pointIndex(i, j);
1189
1190 const MFloat x = m_grid->m_initCoordinates[0][pointId];
1191 const MFloat y = m_grid->m_initCoordinates[1][pointId];
1192
1193 MFloat g = F0;
1194 if(y > x2 && y < x5 && x > x2 && x < x5) {
1195 g = ((y < x3) ? (1.0l + tanhl(beta * (y - (x2 + x3) / 2.0l) / y_max)) / 2.0l
1196 : ((y < x4) ? 1.0l : (1.0l - tanhl(beta * (y - (x4 + x5) / 2.0l) / y_max)) / 2.0l));
1197 }
1198 m_grid->m_coordinates[0][pointId] = x * (F1 - h * g * (F1 - x));
1199 m_grid->m_velocity[0][pointId] = x * (-hvel * g * (F1 - x));
1200
1201 g = F0;
1202 if(x > x2 && x < x5 && y > x2 && y < x5) {
1203 g = ((x < x3) ? (1.0l + tanhl(beta * (x - (x2 + x3) / 2.0l) / y_max)) / 2.0l
1204 : ((x < x4) ? 1.0l : (1.0l - tanhl(beta * (x - (x4 + x5) / 2.0l) / y_max)) / 2.0l));
1205 }
1206 m_grid->m_coordinates[1][pointId] = y * (F1 - h * g * (F1 - y));
1207 m_grid->m_velocity[1][pointId] = y * (-hvel * g * (F1 - y));
1208 }
1209 }
1210
1211 break;
1212 }
1213 case 10: {
1214 // traveling wave case
1215 MFloat t_offset = t - m_movingGridTimeOffset;
1216 if(zeroPos) {
1217 t_offset = F0;
1218 }
1219
1220 const MFloat ytransitionLength = m_waveYEndTransition - m_waveYBeginTransition;
1221
1222 MFloat fadeInFactor = 0.0;
1223 MFloat fadeInFactorPrime = 0.0;
1224 MFloat fadeInFactorPrimePrime = 0.0;
1225 if(t_offset < m_waveTemporalTransition) {
1226 fadeInFactor = (1.0 - cos(t_offset / m_waveTemporalTransition * pi)) * F1B2;
1227 fadeInFactorPrime = (pi / m_waveTemporalTransition) * sin(t_offset / m_waveTemporalTransition * pi) * F1B2;
1228 fadeInFactorPrimePrime =
1229 POW2(pi / m_waveTemporalTransition) * cos(t_offset / m_waveTemporalTransition * pi) * F1B2;
1230 } else {
1231 fadeInFactor = 1.0;
1232 fadeInFactorPrime = 0.0;
1233 fadeInFactorPrimePrime = 0.0;
1234 }
1235
1236 if(zeroPos) {
1237 fadeInFactor = F1;
1238 }
1239
1240 for(MInt j = 0; j < m_nPoints[0]; j++) {
1241 for(MInt i = 0; i < m_nPoints[1]; i++) {
1242 const MInt pointId = pointIndex(i, j);
1243 const MFloat xInit = m_grid->m_initCoordinates[0][pointId];
1244 const MFloat yInit = m_grid->m_initCoordinates[1][pointId];
1245
1246
1247 // To modify the activation function along the wall normal direction
1248 MFloat ytransitionFactor = F0;
1249 if(yInit <= m_waveYBeginTransition) {
1250 ytransitionFactor = F1;
1251 } else if(yInit > m_waveYBeginTransition && yInit < m_waveYEndTransition) {
1252 ytransitionFactor = (1 + cos((yInit - m_waveYBeginTransition) / ytransitionLength * pi)) * F1B2;
1253 } else {
1254 ytransitionFactor = F0;
1255 }
1256
1257 // Modified activation function
1258 const MFloat func =
1259 ytransitionFactor * (m_waveAmplitude * cos((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset)));
1260 const MFloat funcPrime = ytransitionFactor * (2 * PI * m_waveSpeed / m_waveLength) * m_waveAmplitude
1261 * sin((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset));
1262 const MFloat funcPrimePrime = -ytransitionFactor * POW2(2 * PI * m_waveSpeed / m_waveLength) * m_waveAmplitude
1263 * cos((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset));
1264
1265 // Base activation function
1266 /* const MFloat func = transitionFactor
1267 * (m_waveAmplitude * cos((F2 * pi) / m_waveLength * (zPrime - m_waveSpeed * t_offset)));
1268 const MFloat funcPrime = transitionFactor * (2 * PI * m_waveSpeed / m_waveLength) * m_waveAmplitude
1269 * sin((F2 * pi) / m_waveLength * (zPrime - m_waveSpeed * t_offset));
1270 const MFloat funcPrimePrime = -transitionFactor * POW2(2 * PI * m_waveSpeed / m_waveLength)
1271 * m_waveAmplitude
1272 * cos((F2 * pi) / m_waveLength * (zPrime - m_waveSpeed * t_offset));
1273 */
1274
1275 m_grid->m_coordinates[1][pointId] = func * fadeInFactor + yInit;
1276 m_grid->m_velocity[1][pointId] = func * fadeInFactorPrime + funcPrime * fadeInFactor;
1277 m_grid->m_acceleration[1][pointId] =
1278 funcPrimePrime * fadeInFactor + 2 * funcPrime * fadeInFactorPrime + func * fadeInFactorPrimePrime;
1279 }
1280 }
1281
1282 break;
1283 }
1284 case 12: {
1285 // streamwise traveling wave case
1286 MFloat t_offset = t - m_movingGridTimeOffset;
1287 if(zeroPos) {
1288 t_offset = F0;
1289 }
1290 const MFloat transitionLength = m_waveEndTransition - m_waveBeginTransition;
1291 const MFloat transitionOutLength = m_waveOutEndTransition - m_waveOutBeginTransition;
1292 const MFloat yTransitionLength = m_waveYEndTransition - m_waveYBeginTransition;
1293
1294 MFloat fadeInFactor = 0.0;
1295 MFloat fadeInFactorPrime = 0.0;
1296 MFloat fadeInFactorPrimePrime = 0.0;
1297 if(t_offset < m_waveTemporalTransition) {
1298 fadeInFactor = (1.0 - cos(t_offset / m_waveTemporalTransition * pi)) * F1B2;
1299 fadeInFactorPrime = (pi / m_waveTemporalTransition) * sin(t_offset / m_waveTemporalTransition * pi) * F1B2;
1300 fadeInFactorPrimePrime =
1301 POW2(pi / m_waveTemporalTransition) * cos(t_offset / m_waveTemporalTransition * pi) * F1B2;
1302 } else {
1303 fadeInFactor = 1.0;
1304 fadeInFactorPrime = 0.0;
1305 fadeInFactorPrimePrime = 0.0;
1306 }
1307
1308 if(zeroPos) {
1309 fadeInFactor = F1;
1310 }
1311
1312
1313 for(MInt j = 0; j < m_nPoints[0]; j++) {
1314 for(MInt i = 0; i < m_nPoints[1]; i++) {
1315 const MInt pointId = pointIndex(i, j);
1316 const MFloat xInit = m_grid->m_initCoordinates[0][pointId];
1317 const MFloat yInit = m_grid->m_initCoordinates[1][pointId];
1318
1319 MFloat transitionFactor = F0;
1320 if(xInit <= m_waveBeginTransition) {
1321 transitionFactor = F0;
1322 } else if(xInit > m_waveBeginTransition && xInit < m_waveEndTransition) {
1323 transitionFactor = (1 - cos((xInit - m_waveBeginTransition) / transitionLength * pi)) * F1B2;
1324 } else if(m_waveEndTransition <= xInit && xInit <= m_waveOutBeginTransition) {
1325 transitionFactor = F1;
1326 } else if(xInit > m_waveOutBeginTransition && xInit < m_waveOutEndTransition) {
1327 transitionFactor = (1 + cos((xInit - m_waveOutBeginTransition) / transitionOutLength * pi)) * F1B2;
1328 } else {
1329 transitionFactor = F0;
1330 }
1331
1332 MFloat yTransitionFactor = F1;
1333 if(yInit <= m_waveYBeginTransition) {
1334 yTransitionFactor = F1;
1335 } else if(yInit > m_waveYBeginTransition && yInit < m_waveYEndTransition) {
1336 yTransitionFactor = (1 + cos((yInit - m_waveYBeginTransition) / yTransitionLength * pi)) * F1B2;
1337 } else {
1338 yTransitionFactor = F0;
1339 }
1340
1341 const MFloat func = transitionFactor * yTransitionFactor
1342 * (m_waveAmplitude * cos((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset)));
1343 const MFloat funcPrime = transitionFactor * yTransitionFactor * (2 * PI * m_waveSpeed / m_waveLength)
1344 * m_waveAmplitude * sin((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset));
1345 const MFloat funcPrimePrime = -transitionFactor * yTransitionFactor
1347 * cos((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset));
1348
1349 m_grid->m_coordinates[1][pointId] = func * fadeInFactor + yInit;
1350 m_grid->m_velocity[1][pointId] = func * fadeInFactorPrime + funcPrime * fadeInFactor;
1351 m_grid->m_acceleration[1][pointId] =
1352 funcPrimePrime * fadeInFactor + 2 * funcPrime * fadeInFactorPrime + func * fadeInFactorPrimePrime;
1353 }
1354 }
1355
1356 break;
1357 }
1358 case 14: {
1359 // oscillating cylinder
1360 MFloat t_offset = t - m_movingGridTimeOffset;
1361 if(zeroPos) {
1362 t_offset = F0;
1363 }
1364
1365 MFloat fadeInFactor = 0;
1366 const MFloat timeRelaxation = 1.0;
1367
1368 if(t_offset < timeRelaxation) {
1369 fadeInFactor = (1.0 - cos(t_offset / timeRelaxation * pi)) * F1B2;
1370 } else {
1371 fadeInFactor = 1.0;
1372 }
1373
1374 if(zeroPos) {
1375 fadeInFactor = F1;
1376 }
1377
1378 for(MInt i = 0; i < m_nPoints[1]; i++) {
1379 for(MInt j = 0; j < m_nPoints[0] - 1; j++) {
1380 const MInt pIJ = pointIndex(i, j);
1381 const MFloat x = m_grid->m_initCoordinates[0][pIJ];
1382 const MFloat y = m_grid->m_initCoordinates[1][pIJ];
1383
1384 const MFloat r = sqrt(POW2(x) + POW2(y));
1385
1386 MFloat spaceTransition = F1;
1387
1388 if(r < 1.0) {
1389 spaceTransition = F0;
1390 } else if(r >= 1.0 && r <= 41.0) {
1391 spaceTransition = fabs(r - 1.0) / 40.0;
1392 } else {
1393 spaceTransition = F1;
1394 }
1395
1396 m_grid->m_coordinates[1][pIJ] =
1397 y * spaceTransition
1398 + (1.0 - spaceTransition) * (y + fadeInFactor * m_oscAmplitude * sin(2 * PI * m_oscFreq * t_offset));
1399 m_grid->m_velocity[1][pIJ] =
1400 (1.0 - spaceTransition)
1401 * (fadeInFactor * m_oscAmplitude * 2 * PI * m_oscFreq * cos(2 * PI * m_oscFreq * t_offset));
1402 m_grid->m_acceleration[1][pIJ] =
1403 (1.0 - spaceTransition)
1404 * (-fadeInFactor * m_oscAmplitude * POW2(2 * PI * m_oscFreq) * sin(2 * PI * m_oscFreq * t_offset));
1405 }
1406 }
1407
1408 break;
1409 }
1410 default: {
1411 mTerm(1, AT_, "Grid Moving Method not implemented!");
1412 }
1413 }
1414
1415 RECORD_TIMER_START(m_timers[Timers::MGExchange]);
1416
1417 if(m_gridMovingMethod != 1) {
1419 m_grid->extrapolateGhostPointCoordinates();
1420 }
1422 }
1423
1424 if(noDomains() > 1) {
1426 m_grid->exchangePoints(m_sndComm, m_rcvComm, PARTITION_NORMAL);
1427 }
1428 }
1429 RECORD_TIMER_STOP(m_timers[Timers::MGExchange]);
1430
1431 RECORD_TIMER_START(m_timers[Timers::MGCellCenterCoordinates]);
1432 m_grid->computeCellCenterCoordinates();
1433 RECORD_TIMER_STOP(m_timers[Timers::MGCellCenterCoordinates]);
1434
1435 RECORD_TIMER_START(m_timers[Timers::MGMetrics]);
1436 m_grid->computeMetrics();
1437 RECORD_TIMER_STOP(m_timers[Timers::MGMetrics]);
1438
1439 RECORD_TIMER_START(m_timers[Timers::MGJacobian]);
1440 m_grid->computeJacobian();
1441
1442 RECORD_TIMER_STOP(m_timers[Timers::MGJacobian]);
1443}
1444
1446 TRACE();
1448}
1449
1451 TRACE();
1453}
1454
1456 TRACE();
1457 // treat Dirichlet and Neumann BC in one go!!!
1459}
1460
1462 // function to compute the coordinates at cell centre
1463 // calculated over I, J loop but changed to one array
1464 for(MInt j = 0; j < m_nCells[0]; ++j) {
1465 for(MInt i = 0; i < m_nCells[1]; ++i) {
1466 const MInt IJ = getPointIdFromCell(i, j);
1467 const MInt IP1J = getPointIdFromPoint(IJ, 1, 0);
1468 const MInt IJP1 = getPointIdFromPoint(IJ, 0, 1);
1469 const MInt IP1JP1 = getPointIdFromPoint(IJ, 1, 1);
1470 const MInt cellId = cellIndex(i, j);
1471
1472 for(MInt dim = 0; dim < nDim; dim++) {
1473 // average the coordinates for cell centre data
1474 m_cells->coordinates[dim][cellId] = F1B4
1475 * (m_grid->m_coordinates[dim][IJ] + m_grid->m_coordinates[dim][IP1J]
1476 + m_grid->m_coordinates[dim][IJP1] + m_grid->m_coordinates[dim][IP1JP1]);
1477 }
1478 }
1479 }
1480}
1481
1483 TRACE();
1484
1485 if(globalTimeStep % m_residualInterval != 0) return true;
1486 MFloat epsilon = pow(10.0, -10.0);
1487 m_avrgResidual = F0;
1488 MInt cellId = F0;
1489 MFloat tmpResidual = F0;
1490 MFloat maxResidual1 = F0;
1491 MInt maxResIndex[3];
1492 // MInt localCounter=F0;
1493 MFloat maxResidualOrg = F0;
1494 MFloat localMaxResidual = F0;
1495 MFloat localAvrgResidual = F0;
1496 MFloat accumAvrgResidual = F0;
1497 MFloat globalMaxResidual = F0;
1498 // MInt accumCounter=0;
1499 for(MInt dim = 0; dim < nDim; dim++) {
1500 maxResIndex[dim] = F0;
1501 }
1502
1503 if(!m_localTimeStep) {
1504 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
1505 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
1506 cellId = cellIndex(i, j);
1507 tmpResidual = m_timeStep / (m_cfl * m_cells->cellJac[cellId]) * fabs(m_cells->rightHandSide[CV->RHO][cellId]);
1508 m_avrgResidual += tmpResidual;
1509 if(tmpResidual > maxResidual1) {
1510 maxResIndex[0] = i - m_noGhostLayers;
1511 maxResIndex[1] = j - m_noGhostLayers;
1512 maxResidual1 = tmpResidual;
1513 }
1514 }
1515 }
1516 } else {
1517 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
1518 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
1519 cellId = cellIndex(i, j);
1520 tmpResidual = m_cells->localTimeStep[cellId] / (m_cfl * m_cells->cellJac[cellId])
1521 * fabs(m_cells->rightHandSide[CV->RHO][cellId]);
1522 m_avrgResidual += tmpResidual;
1523 if(tmpResidual > maxResidual1) {
1524 maxResIndex[0] = i - m_noGhostLayers;
1525 maxResIndex[1] = j - m_noGhostLayers;
1526 maxResidual1 = tmpResidual;
1527 }
1528 }
1529 }
1530 }
1531
1532 // localCounter = counter;
1533 localMaxResidual = maxResidual1;
1534 localAvrgResidual = m_avrgResidual;
1535 // reset average Residual
1536 m_avrgResidual = F0;
1537
1538 MPI_Allreduce(&localAvrgResidual, &accumAvrgResidual, 1, MPI_DOUBLE, MPI_SUM, m_StructuredComm, AT_,
1539 "localAvrgResidual", "accumAvrgResidual");
1540 MPI_Allreduce(&localMaxResidual, &globalMaxResidual, 1, MPI_DOUBLE, MPI_MAX, m_StructuredComm, AT_,
1541 "localMaxResidual", "globalMaxResidual");
1542 m_avrgResidual = accumAvrgResidual; // m_residualRcv.avrgRes;
1543 maxResidualOrg = globalMaxResidual;
1545
1546 // write first residuals;
1547 if(fabs(m_firstMaxResidual) < epsilon) {
1548 m_firstMaxResidual = mMax(epsilon, globalMaxResidual);
1550 if(approx(localMaxResidual, maxResidualOrg, m_eps)) {
1551 // write out values into residual file
1552 FILE* f_residual;
1553 f_residual = fopen("./Residual", "a+");
1554 fprintf(f_residual, "#MaxRes_1: %1.10e \n", m_firstMaxResidual);
1555 fprintf(f_residual, "#MaxAvgRes_1: %1.10e \n", m_firstAvrgResidual);
1556 fprintf(f_residual, "#iter, physTime, time, dT, wLoad, avrgRes, maxRes, blockId, i, j");
1557 fclose(f_residual);
1558 }
1559 }
1560
1561 // normalize residuals
1562 globalMaxResidual = globalMaxResidual / m_firstMaxResidual;
1564
1565 if(std::isnan(m_avrgResidual)) {
1566 cerr << "Solution diverged, average residual is nan " << endl;
1567 m_log << "Solution diverged, average residual is nan " << endl;
1568 RECORD_TIMER_STOP(m_timers[Timers::MainLoop]);
1569 RECORD_TIMER_STOP(m_timers[Timers::Run]);
1570 saveSolverSolution(true);
1572 mTerm(1, AT_, "Solution diverged, average residual is nan ");
1573 }
1574
1575 // convergence Check
1576 m_convergence = false;
1577 if(maxResidual1 < m_convergenceCriterion) {
1578 m_convergence = true;
1579 }
1580
1581 // processor with the highest Residual writes out!!! saves communication;
1582 if(approx(localMaxResidual, maxResidualOrg,
1583 m_eps)) { // so only cpu with the max writes out ==> no need to communicate the max index[i]
1584 // write out values into residual file
1585 FILE* f_residual;
1586 f_residual = fopen("./Residual", "a+");
1587 fprintf(f_residual, "%d", globalTimeStep);
1588 fprintf(f_residual, " %f", m_physicalTime);
1589 fprintf(f_residual, " %f", m_time);
1590 fprintf(f_residual, " %f", m_timeStep);
1591 fprintf(f_residual, " %f", m_workload);
1592 fprintf(f_residual, " %1.10e", m_avrgResidual);
1593 fprintf(f_residual, " %1.10e", globalMaxResidual);
1594 fprintf(f_residual, " %d", m_blockId);
1595 fprintf(f_residual, " %d", m_nOffsetCells[1] + maxResIndex[0]); // i
1596 fprintf(f_residual, " %d", m_nOffsetCells[0] + maxResIndex[1]); // j
1597 fprintf(f_residual, "\n");
1598 fclose(f_residual);
1599 }
1600
1601 if(maxResidual1 < m_convergenceCriterion) {
1602 return true;
1603 } else {
1604 return false;
1605 }
1606}
1607
1609 MFloat result = vec1[xsd] * vec2[ysd] - vec1[ysd] * vec2[xsd];
1610 return result;
1611}
1612
1613
1614inline MInt FvStructuredSolver2D::getPointIdFromCell(MInt i, MInt j) { return i + (j * (m_nCells[1] + 1)); }
1615
1617 return origin + incI + incJ * m_nPoints[1];
1618}
1619
1621 return origin + incI + incJ * m_nCells[1];
1622}
1623
1624inline MInt FvStructuredSolver2D::cellIndex(MInt i, MInt j) { return i + (j * m_nCells[1]); }
1625
1626inline MInt FvStructuredSolver2D::pointIndex(MInt i, MInt j) { return i + (j * m_nPoints[1]); }
1627
1629
1631 TRACE();
1632
1633 if(m_debugOutput) {
1634 for(MInt j = 0; j < (m_nCells[0]); j++) {
1635 for(MInt i = 0; i < (m_nCells[1]); i++) {
1636 MInt cellId = cellIndex(i, j);
1637 m_cells->fq[FQ->CELLID][cellId] = cellId;
1638 m_cells->fq[FQ->BLOCKID][cellId] = domainId();
1639 }
1640 }
1641 }
1642
1643 // 1) extrapolate GhostPoints
1644 m_grid->extrapolateGhostPointCoordinates();
1645 // 2) communicate GhostPoints
1646
1647 m_grid->exchangePoints(m_sndComm, m_rcvComm, PARTITION_NORMAL);
1648 m_grid->exchangePoints(m_sndComm, m_rcvComm, PERIODIC_BC);
1649
1651
1653
1654 // MUST be done after cell center computation!!!
1655 m_grid->exchangePoints(m_sndComm, m_rcvComm, SINGULAR);
1657
1658 if(m_hasSingularity > 0) {
1660 }
1661
1662 // 3) write the totalGridFile with GhostPoints
1664 m_grid->writePartitionedGrid();
1665 }
1666}
1667
1668
1670 for(MInt bcId = 0; bcId < (MInt)m_structuredBndryCnd->m_physicalBCMap.size(); ++bcId) {
1671 // all the periodic BCs are NOT included.
1672 // also skip the channel bc
1673 if(m_structuredBndryCnd->m_physicalBCMap[bcId]->BC == 2401
1674 || m_structuredBndryCnd->m_physicalBCMap[bcId]->BC == 2402
1675 || (m_structuredBndryCnd->m_physicalBCMap[bcId]->BC >= 6000
1676 && m_structuredBndryCnd->m_physicalBCMap[bcId]->BC < 6010)) {
1677 continue;
1678 }
1679
1680 MInt* start = m_structuredBndryCnd->m_physicalBCMap[bcId]->start1;
1681 MInt* end = m_structuredBndryCnd->m_physicalBCMap[bcId]->end1;
1682 MInt index = m_structuredBndryCnd->m_physicalBCMap[bcId]->face / 2;
1683 MInt step = m_structuredBndryCnd->m_physicalBCMap[bcId]->face % 2;
1684 MInt pos[2], fix[2], mirror[2], ij[2], extendij[2];
1685 MInt pointId, FixPointId, MirrorPointId;
1686
1687 extendij[0] = 1;
1688 extendij[1] = 1;
1689 extendij[index] = 0;
1690
1691 for(ij[1] = start[1]; ij[1] < end[1] + extendij[1]; ++ij[1]) {
1692 for(ij[0] = start[0]; ij[0] < end[0] + extendij[0]; ++ij[0]) {
1693 for(MInt m = 0; m < 2; ++m) {
1694 if(index == m) {
1695 if(step == 1) {
1696 pos[m] = ij[m] + 1;
1697 fix[m] = start[m];
1698 mirror[m] = 2 * fix[m] - pos[m];
1699 } else {
1700 pos[m] = ij[m];
1701 fix[m] = end[m];
1702 mirror[m] = 2 * fix[m] - pos[m];
1703 }
1704 } else {
1705 pos[m] = ij[m];
1706 fix[m] = ij[m];
1707 mirror[m] = ij[m];
1708 }
1709 } // m
1710
1711 pointId = pointIndex(pos[0], pos[1]);
1712 FixPointId = pointIndex(fix[0], fix[1]);
1713 MirrorPointId = pointIndex(mirror[0], mirror[1]);
1714
1715 for(MInt dim = 0; dim < nDim; dim++) {
1716 m_grid->m_coordinates[dim][pointId] =
1717 (2 * m_grid->m_coordinates[dim][FixPointId] - m_grid->m_coordinates[dim][MirrorPointId]);
1718 }
1719 } // ij
1720 }
1721
1722 } // bcid
1723}
1724
1725
1726void FvStructuredSolver2D::Muscl(MInt NotUsed(timerId)) {
1727 TRACE();
1728
1729 if(m_movingGrid) {
1730 RECORD_TIMER_START(m_timers[Timers::MovingGrid]);
1731 if(m_RKStep == 0) {
1732 RECORD_TIMER_START(m_timers[Timers::MGSaveGrid]);
1733 m_grid->saveGrid();
1734 m_grid->saveCellJacobian();
1735 RECORD_TIMER_STOP(m_timers[Timers::MGSaveGrid]);
1736 }
1737
1738 RECORD_TIMER_START(m_timers[Timers::MGMoveGrid]);
1739 moveGrid(false, false);
1740 RECORD_TIMER_STOP(m_timers[Timers::MGMoveGrid]);
1741
1742 // compute the volume fluxes
1743 RECORD_TIMER_START(m_timers[Timers::MGVolumeFlux]);
1744 m_grid->computeDxt(m_timeStep, m_RKalpha, m_RKStep);
1745 RECORD_TIMER_STOP(m_timers[Timers::MGVolumeFlux]);
1746 RECORD_TIMER_STOP(m_timers[Timers::MovingGrid]);
1747 }
1748
1749 RECORD_TIMER_START(m_timers[Timers::ConvectiveFlux]);
1750 (this->*reconstructSurfaceData)();
1751 RECORD_TIMER_STOP(m_timers[Timers::ConvectiveFlux]);
1752}
1753
1754
1755// Muscl reconstruction with Albada limiter
1757 TRACE();
1758
1759 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
1760 MInt cellId = 0, IP1 = 0, IM1 = 0, IP2 = 0;
1761 // grid stretching factors
1762 MFloat DS = F0, DSP1 = F0, DSM1 = F0, DSP = F0, DSM = F0;
1763 // stencil identifier
1764 MInt IJ[2] = {1, m_nCells[1]};
1765
1766 // flow variables differences
1767 // MFloat DQ=F0, DQP1=F0, DQM1=F0;
1768 MFloatScratchSpace DQ(CV->noVariables, AT_, "DQ");
1769 MFloatScratchSpace DQP1(CV->noVariables, AT_, "DQP1");
1770 MFloatScratchSpace DQM1(CV->noVariables, AT_, "DQM1");
1771
1772 // left and right state
1773 MFloat epsLim = m_eps;
1774 MFloat smps = F0;
1775 MFloat dummy = F0, dummy1 = F0;
1776
1777 MFloat pIM2 = F0, pIM1 = F0, pIP1 = F0, pIP2 = F0;
1778 for(MInt i = 0; i < CV->noVariables; i++) {
1779 DQ[i] = F0;
1780 DQP1[i] = F0;
1781 DQM1[i] = F0;
1782 }
1783 // reduce to onedimensional arrays
1784 MFloat* __restrict x = &m_cells->coordinates[0][0];
1785 MFloat* __restrict y = &m_cells->coordinates[1][0];
1786
1787 MFloat phi = F0, psi = F0, vel = F0;
1788
1790 // MFloat epsi=F1;
1791 // MFloat kappa=F1B3;
1793 for(MInt dim = 0; dim < nDim; ++dim) {
1794 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; ++j) {
1795 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; ++i) {
1796 // cell ids
1797 cellId = cellIndex(i, j);
1798
1799 IP1 = cellId + IJ[dim];
1800 IM1 = cellId - IJ[dim];
1801 IP2 = cellId + 2 * IJ[dim];
1802
1803 // distances q_i+1 - q_i
1804 DS = sqrt(POW2(x[IP1] - x[cellId]) + POW2(y[IP1] - y[cellId]));
1805 // distances q_i - q_i-1
1806 DSM1 = sqrt(POW2(x[cellId] - x[IM1]) + POW2(y[cellId] - y[IM1]));
1807 DSP1 = sqrt(POW2(x[IP2] - x[IP1]) + POW2(y[IP2] - y[IP1]));
1808 // account for grid stretching
1809 // like tfs comment
1810 // DSP=F2*DS/POW2(DSP1+DS);
1811 // DSM=F2*DS/POW2(DSM1+DS);
1812 // like tfs
1813 DSP = DS / POW2(DSP1 + DS);
1814 DSM = DS / POW2(DSM1 + DS);
1815
1816
1817 for(MInt var = 0; var < CV->noVariables; ++var) {
1818 DQ[var] = m_cells->variables[var][IP1] - m_cells->variables[var][cellId];
1819
1820 DQP1[var] = m_cells->variables[var][IP2] - m_cells->variables[var][IP1];
1821
1822 DQM1[var] = m_cells->variables[var][cellId] - m_cells->variables[var][IM1];
1823 // limiter
1824 }
1825 vel = F0;
1826 for(MInt dim1 = 0; dim1 < nDim; ++dim1) {
1827 vel += POW2(m_cells->variables[CV->RHO_VV[dim1]][IM1] / m_cells->variables[CV->RHO][IM1]);
1828 }
1829 pIM2 = m_cells->variables[CV->RHO_E][IM1] - F1B2 * m_cells->variables[CV->RHO][IM1] * vel;
1830 vel = F0;
1831 for(MInt dim1 = 0; dim1 < nDim; ++dim1) {
1832 vel += POW2(m_cells->variables[CV->RHO_VV[dim1]][cellId] / m_cells->variables[CV->RHO][cellId]);
1833 }
1834 pIM1 = m_cells->variables[CV->RHO_E][cellId] - F1B2 * m_cells->variables[CV->RHO][cellId] * vel;
1835
1836 vel = F0;
1837 for(MInt dim1 = 0; dim1 < nDim; ++dim1) {
1838 vel += POW2(m_cells->variables[CV->RHO_VV[dim1]][IP2] / m_cells->variables[CV->RHO][IP2]);
1839 }
1840 pIP2 = m_cells->variables[CV->RHO_E][IP2] - F1B2 * m_cells->variables[CV->RHO][IP2] * vel;
1841 vel = F0;
1842 for(MInt dim1 = 0; dim1 < nDim; ++dim1) {
1843 vel += POW2(m_cells->variables[CV->RHO_VV[dim1]][IP1] / m_cells->variables[CV->RHO][IP1]);
1844 }
1845 pIP1 = m_cells->variables[CV->RHO_E][IP1] - F1B2 * m_cells->variables[CV->RHO][IP1] * vel;
1846
1847 smps = DS * DSP1;
1848
1849 dummy = fabs(pIM2 - F2 * pIM1 + pIP1) / (pIM2 + F2 * pIM1 + pIP1);
1850 dummy1 = fabs(pIM1 - F2 * pIP1 + pIP2) / (pIM1 + F2 * pIP1 + pIP2);
1851
1852 psi = mMin(F1, F6 * mMax(dummy, dummy1));
1853 epsLim = mMax(m_eps, pow(F1B2 * smps, F5));
1854
1855
1856 for(MInt var = 0; var < CV->noVariables; ++var) {
1857 phi = F1B2
1858 - (F1B2
1859 - mMax(F0, (DQP1[var] * DQM1[var] * smps + F1B2 * epsLim)
1860 / (POW2(DQP1[var] * DS) + POW2(DQM1[var] * DSP1) + epsLim)))
1861 * psi;
1862
1863 m_QLeft[var] = m_cells->variables[var][cellId] + DSM * (DSM1 * DQ[var] + DS * DQM1[var]) * phi;
1864 m_QRight[var] = m_cells->variables[var][IP1] - DSP * (DS * DQP1[var] + DSP1 * DQ[var]) * phi;
1865
1866 // PHI(IP,IM,ID)=F2-(F2-MAX(F0,(DQ(IP,ID)*DQ(IM,ID)*SMSP+EPSMP2)
1867 // & /((DQ(IP,ID)*SM)**2+(DQ(IM,ID)*SP)**2+EPSMP)))*PSI
1868 }
1869
1870
1871 AusmLES(m_QLeft, m_QRight, dim, cellId); // Flux balance in AUSM
1872 }
1873 }
1874
1875
1876 // FLUX BALANCE
1877 for(MInt v = 0; v < CV->noVariables; ++v) {
1878 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; ++j) {
1879 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; ++i) {
1880 const MInt I = cellIndex(i, j);
1881 IM1 = I - IJ[dim];
1882 m_cells->rightHandSide[v][I] += flux[v][IM1] - flux[v][I];
1883 }
1884 }
1885 }
1886 }
1887}
1888
1890
1891template <FvStructuredSolver2D::fluxmethod ausm, MInt noVars>
1893 TRACE();
1894 // stencil identifier
1895 const MUint noCells = m_noCells;
1896 const MInt IJK[2] = {1, m_nCells[1]};
1897
1898 const MFloat* const RESTRICT x = ALIGNED_F(m_cells->coordinates[0]);
1899 const MFloat* const RESTRICT y = ALIGNED_F(m_cells->coordinates[1]);
1900
1901 const MFloat* const RESTRICT cellVariables = ALIGNED_F(m_cells->pvariables[0]);
1902 MFloat* const RESTRICT cellRhs = ALIGNED_MF(m_cells->rightHandSide[0]);
1903 MFloat* const RESTRICT qleft = ALIGNED_MF(m_QLeft);
1904 MFloat* const RESTRICT qright = ALIGNED_MF(m_QRight);
1905 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
1906
1907 for(MInt dim = 0; dim < nDim; dim++) {
1908 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; j++) {
1909 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; i++) {
1910 const MInt I = cellIndex(i, j);
1911 const MInt IP1 = I + IJK[dim];
1912 const MInt IM1 = I - IJK[dim];
1913 const MInt IP2 = I + 2 * IJK[dim];
1914
1915 // distances q_i+1 - q_i
1916 const MFloat DS = sqrt(POW2(x[IP1] - x[I]) + POW2(y[IP1] - y[I]));
1917 // distances q_i - q_i-1
1918 const MFloat DSM1 = sqrt(POW2(x[I] - x[IM1]) + POW2(y[I] - y[IM1]));
1919 const MFloat DSP1 = sqrt(POW2(x[IP2] - x[IP1]) + POW2(y[IP2] - y[IP1]));
1920 const MFloat DSP = DS / POW2(DSP1 + DS);
1921 const MFloat DSM = DS / POW2(DSM1 + DS);
1922
1923 for(MUint v = 0; v < noVars; ++v) {
1924 const MUint offset = v * noCells;
1925 const MFloat* const RESTRICT vars = ALIGNED_F(cellVariables + offset);
1926 const MFloat DQ = vars[IP1] - vars[I];
1927 const MFloat DQP1 = vars[IP2] - vars[IP1];
1928 const MFloat DQM1 = vars[I] - vars[IM1];
1929 qleft[v] = vars[I] + DSM * (DSM1 * DQ + DS * DQM1);
1930 qright[v] = vars[IP1] - DSP * (DS * DQP1 + DSP1 * DQ);
1931 }
1932
1933 (this->*ausm)(m_QLeft, m_QRight, dim, I); // Flux balance in AUSM
1934 }
1935 }
1936
1937 // FLUX BALANCE
1938 for(MUint v = 0; v < noVars; v++) {
1939 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
1940 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
1941 const MInt I = cellIndex(i, j);
1942 const MInt IM1 = I - IJK[dim];
1943 const MUint offset = v * noCells;
1944 MFloat* const RESTRICT rhs = ALIGNED_F(cellRhs + offset);
1945 rhs[I] += flux[v][IM1] - flux[v][I];
1946 }
1947 }
1948 }
1949 }
1950}
1951
1952// standard Ausm
1953template void FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES, 5>();
1954template void FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES, 6>();
1955template void FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES, 7>();
1956// pthrc Ausm
1957template void FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES_PTHRC, 5>();
1958template void FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES_PTHRC, 6>();
1959template void FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmLES_PTHRC, 7>();
1960// ausm dv
1961template void FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmDV, 5>();
1962template void FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmDV, 6>();
1963template void FvStructuredSolver2D::Muscl_<&FvStructuredSolver2D::AusmDV, 7>();
1964
1965
1966template <FvStructuredSolver2D::fluxmethod ausm, MInt noVars>
1968 TRACE();
1969
1970 // stencil identifier
1971 const MInt IJK[2] = {1, m_nCells[1]};
1972 const MFloat* const RESTRICT cellVariables = ALIGNED_F(m_cells->pvariables[0]);
1973 const MFloat* const RESTRICT cellLength = ALIGNED_F(m_cells->cellLength[0]);
1974 MFloat* const RESTRICT cellRhs = ALIGNED_MF(m_cells->rightHandSide[0]);
1975 MFloat* const RESTRICT qleft = ALIGNED_MF(m_QLeft);
1976 MFloat* const RESTRICT qright = ALIGNED_MF(m_QRight);
1977 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
1979 const MFloat phi = F1;
1980 const MFloat kappa = F0; // F1B3;
1982 for(MInt dim = 0; dim < nDim; dim++) {
1983 const MUint dimOffset = dim * m_noCells;
1984 const MFloat* const RESTRICT length = ALIGNED_F(cellLength + dimOffset);
1985
1986 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; j++) {
1987 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; i++) {
1988 const MInt I = cellIndex(i, j);
1989 const MInt IP1 = I + IJK[dim];
1990 const MInt IM1 = I - IJK[dim];
1991 const MInt IP2 = I + 2 * IJK[dim];
1992
1993 const MFloat rp = (length[I] + length[IP1]) / (F2 * length[I]);
1994 const MFloat rm = (length[I] + length[IM1]) / (F2 * length[I]);
1995 const MFloat f = phi / (F2 * (rp + rm));
1996 const MFloat f1 = (rm + kappa * phi) / rp;
1997 const MFloat f2 = (rp - kappa * phi) / rm;
1998
1999 const MFloat rp1 = (length[IP1] + length[IP2]) / (F2 * length[IP1]);
2000 const MFloat rm1 = (length[IP1] + length[I]) / (F2 * length[IP1]);
2001 const MFloat fa = phi / (F2 * (rp1 + rm1));
2002 const MFloat fb = (rm1 - kappa * phi) / rp1;
2003 const MFloat fc = (rp1 + kappa * phi) / rm1;
2004
2005 for(MUint v = 0; v < noVars; v++) {
2006 const MUint offset = v * m_noCells;
2007 const MFloat* const RESTRICT vars = ALIGNED_F(cellVariables + offset);
2008 // left variables
2009 const MFloat DQ = (vars[IP1] - vars[I]);
2010 const MFloat DQM1 = (vars[I] - vars[IM1]);
2011 qleft[v] = vars[I] + f * (f1 * DQ + f2 * DQM1);
2012
2013 // right variables
2014 const MFloat DQP1 = (vars[IP2] - vars[IP1]);
2015 const MFloat DQ1 = (vars[IP1] - vars[I]);
2016 qright[v] = vars[IP1] - fa * (fb * DQP1 + fc * DQ1);
2017 }
2018
2019 (this->*ausm)(m_QLeft, m_QRight, dim, I); // Flux balance in AUSM
2020 }
2021 }
2022
2023 // FLUX BALANCE
2024 for(MUint v = 0; v < noVars; v++) {
2025 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
2026 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
2027 const MInt I = cellIndex(i, j);
2028 const MInt IM1 = I - IJK[dim];
2029 const MUint offset = v * m_noCells;
2030 MFloat* const RESTRICT rhs = ALIGNED_F(cellRhs + offset);
2031 rhs[I] += flux[v][IM1] - flux[v][I];
2032 }
2033 }
2034 }
2035 }
2036}
2037// standard Ausm
2038template void FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES, 5>();
2039template void FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES, 6>();
2040template void FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES, 7>();
2041// pthrc
2042template void FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES_PTHRC, 5>();
2043template void FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES_PTHRC, 6>();
2044template void FvStructuredSolver2D::MusclStretched_<&FvStructuredSolver2D::AusmLES_PTHRC, 7>();
2045
2046
2048 // Ausm routines have been moved and are called from inside Muscl (better performance)
2049}
2050
2051
2057// inline void FvStructuredSolver2D::AusmNew(MFloat* QLeft, MFloat* QRight, const MInt dim, const MInt I)
2058inline void FvStructuredSolver2D::AusmLES(MFloat* QLeft, MFloat* QRight, const MInt dim, const MInt I) {
2059 const MFloat gamma = m_gamma;
2060 const MFloat gammaMinusOne = gamma - 1.0;
2061 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
2062
2063 const MFloat surf0 = m_cells->surfaceMetrics[dim * 2 + 0][I];
2064 const MFloat surf1 = m_cells->surfaceMetrics[dim * 2 + 1][I];
2065
2066 const MFloat dxdtau = m_cells->dxt[dim][I];
2067
2068 // calculate pressure
2069 const MFloat PL = QLeft[PV->P];
2070 const MFloat UL = QLeft[PV->U];
2071 const MFloat VL = QLeft[PV->V];
2072 const MFloat RHOL = QLeft[PV->RHO];
2073
2074 const MFloat PR = QRight[PV->P];
2075 const MFloat UR = QRight[PV->U];
2076 const MFloat VR = QRight[PV->V];
2077 const MFloat RHOR = QRight[PV->RHO];
2078
2079 // compute lenght of metric vector for normalization
2080 const MFloat metricLength = sqrt(POW2(surf0) + POW2(surf1));
2081 const MFloat fMetricLength = F1 / metricLength;
2082
2083 // scale by metric length to get velocity in the new basis (get normalized basis vectors)
2084 const MFloat UUL = ((UL * surf0 + VL * surf1) - dxdtau) * fMetricLength;
2085
2086
2087 const MFloat UUR = ((UR * surf0 + VR * surf1) - dxdtau) * fMetricLength;
2088
2089
2090 // speed of sound
2091 const MFloat AL = sqrt(gamma * mMax(m_eps, PL / mMax(m_eps, RHOL)));
2092 const MFloat AR = sqrt(gamma * mMax(m_eps, PR / mMax(m_eps, RHOR)));
2093
2094 const MFloat MAL = UUL / AL;
2095 const MFloat MAR = UUR / AR;
2096
2097 const MFloat MALR = F1B2 * (MAL + MAR);
2098 const MFloat PLR = F1B2 * (PL + PR);
2099
2100 const MFloat RHO_AL = RHOL * AL;
2101 const MFloat RHO_AR = RHOR * AR;
2102
2103 const MFloat PLfRHOL = PL / RHOL;
2104 const MFloat PRfRHOR = PR / RHOR;
2105
2106 const MFloat e0 = PLfRHOL * FgammaMinusOne + 0.5 * (POW2(UL) + POW2(VL)) + PLfRHOL;
2107 const MFloat e1 = PRfRHOR * FgammaMinusOne + 0.5 * (POW2(UR) + POW2(VR)) + PRfRHOR;
2108
2109 const MFloat RHOU = F1B2 * (MALR * (RHO_AL + RHO_AR) + fabs(MALR) * (RHO_AL - RHO_AR)) * metricLength;
2110 const MFloat RHOU2 = F1B2 * RHOU;
2111 // multiply by metric length to take surface area into account
2112 const MFloat AbsRHO_U2 = fabs(RHOU2);
2113
2114 MFloat* const* const RESTRICT flux = ALIGNED_MF(m_cells->flux);
2115
2116 flux[CV->RHO_U][I] = RHOU2 * (UL + UR) + AbsRHO_U2 * (UL - UR) + PLR * surf0;
2117 flux[CV->RHO_V][I] = RHOU2 * (VL + VR) + AbsRHO_U2 * (VL - VR) + PLR * surf1;
2118 flux[CV->RHO_E][I] = RHOU2 * (e0 + e1) + AbsRHO_U2 * (e0 - e1) + PLR * dxdtau;
2119 flux[CV->RHO][I] = RHOU;
2120}
2121
2122
2129inline void FvStructuredSolver2D::AusmLES_PTHRC(MFloat* QLeft, MFloat* QRight, MInt dim, MInt I) {
2130 const MFloat gamma = m_gamma;
2131 const MFloat gammaMinusOne = gamma - 1.0;
2132 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
2133
2134 const MFloat surf0 = m_cells->surfaceMetrics[dim * 2 + 0][I];
2135 const MFloat surf1 = m_cells->surfaceMetrics[dim * 2 + 1][I];
2136
2137 const MFloat* const RESTRICT p = ALIGNED_F(m_cells->pvariables[PV->P]);
2138
2139 const MFloat dxdtau = m_cells->dxt[dim][I];
2140
2141 // calculate pressure
2142 const MFloat PL = QLeft[PV->P];
2143 const MFloat UL = QLeft[PV->U];
2144 const MFloat VL = QLeft[PV->V];
2145 const MFloat RHOL = QLeft[PV->RHO];
2146
2147 const MFloat PR = QRight[PV->P];
2148 const MFloat UR = QRight[PV->U];
2149 const MFloat VR = QRight[PV->V];
2150 const MFloat RHOR = QRight[PV->RHO];
2151
2152 // compute lenght of metric vector for normalization
2153 const MFloat metricLength = sqrt(POW2(surf0) + POW2(surf1));
2154 const MFloat fMetricLength = F1 / metricLength;
2155
2156 // scale by metric length to get velocity in the new basis (get normalized basis vectors)
2157 const MFloat UUL = ((UL * surf0 + VL * surf1) - dxdtau) * fMetricLength;
2158
2159
2160 const MFloat UUR = ((UR * surf0 + VR * surf1) - dxdtau) * fMetricLength;
2161
2162
2163 // speed of sound
2164 const MFloat AL = sqrt(gamma * mMax(m_eps, PL / mMax(m_eps, RHOL)));
2165 const MFloat AR = sqrt(gamma * mMax(m_eps, PR / mMax(m_eps, RHOR)));
2166
2167 const MFloat MAL = UUL / AL;
2168 const MFloat MAR = UUR / AR;
2169
2170 const MFloat MALR = F1B2 * (MAL + MAR);
2171
2172 // compute splitting pressure
2173 const MInt IPJK = getCellIdFromCell(I, 1, 0);
2174 const MInt IMJK = getCellIdFromCell(I, -1, 0);
2175 const MInt IP2JK = getCellIdFromCell(I, 2, 0);
2176 const MInt IM2JK = getCellIdFromCell(I, -2, 0);
2177
2178 const MInt IJPK = getCellIdFromCell(I, 0, 1);
2179 const MInt IJMK = getCellIdFromCell(I, 0, -1);
2180 const MInt IJP2K = getCellIdFromCell(I, 0, 2);
2181 const MInt IJM2K = getCellIdFromCell(I, 0, -2);
2182
2183 const MFloat p4I4 = F4 * (p[IPJK] + p[IMJK]) - F6 * (p[I]) - p[IP2JK] - p[IM2JK];
2184 const MFloat p4J4 = F4 * (p[IJPK] + p[IJMK]) - F6 * (p[I]) - p[IJP2K] - p[IJM2K];
2185
2186 const MFloat cfac = 1.0 / 1.3;
2187 const MFloat pfac = fabs(p4I4) + fabs(p4J4);
2188 MFloat fac = cfac * pfac;
2189 fac = min(1 / 64.0, fac * 5.0);
2190
2191 const MFloat PLR = PL * (F1B2 + fac * MAL) + PR * (F1B2 - fac * MAR);
2192
2193 const MFloat RHO_AL = RHOL * AL;
2194 const MFloat RHO_AR = RHOR * AR;
2195
2196 const MFloat PLfRHOL = PL / RHOL;
2197 const MFloat PRfRHOR = PR / RHOR;
2198
2199 const MFloat e0 = PLfRHOL * FgammaMinusOne + 0.5 * (POW2(UL) + POW2(VL)) + PLfRHOL;
2200 const MFloat e1 = PRfRHOR * FgammaMinusOne + 0.5 * (POW2(UR) + POW2(VR)) + PRfRHOR;
2201
2202 const MFloat RHOU = F1B2 * (MALR * (RHO_AL + RHO_AR) + fabs(MALR) * (RHO_AL - RHO_AR)) * metricLength;
2203 const MFloat RHOU2 = F1B2 * RHOU;
2204 // multiply by metric length to take surface area into account
2205 const MFloat AbsRHO_U2 = fabs(RHOU2);
2206
2207 MFloat* const* const RESTRICT flux = m_cells->flux;
2208
2209 flux[CV->RHO_U][I] = RHOU2 * (UL + UR) + AbsRHO_U2 * (UL - UR) + PLR * surf0;
2210 flux[CV->RHO_V][I] = RHOU2 * (VL + VR) + AbsRHO_U2 * (VL - VR) + PLR * surf1;
2211 flux[CV->RHO_E][I] = RHOU2 * (e0 + e1) + AbsRHO_U2 * (e0 - e1) + PLR * dxdtau;
2212 flux[CV->RHO][I] = RHOU;
2213}
2214
2215void FvStructuredSolver2D::AusmDV(MFloat* QLeft, MFloat* QRight, const MInt dim, const MInt I) {
2216 const MFloat gamma = m_gamma;
2217 const MFloat gammaMinusOne = gamma - 1.0;
2218 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
2219
2220 const MFloat surf0 = m_cells->surfaceMetrics[dim * 2 + 0][I];
2221 const MFloat surf1 = m_cells->surfaceMetrics[dim * 2 + 1][I];
2222
2223 // left side
2224 const MFloat RHOL = QLeft[PV->RHO];
2225 const MFloat FRHOL = F1 / RHOL;
2226 MFloat UL = QLeft[PV->U];
2227 MFloat VL = QLeft[PV->V];
2228 const MFloat PL = QLeft[PV->P];
2229
2230 // right side
2231 const MFloat RHOR = QRight[PV->RHO];
2232 const MFloat FRHOR = F1 / RHOR;
2233 MFloat UR = QRight[PV->U];
2234 MFloat VR = QRight[PV->V];
2235 const MFloat PR = QRight[PV->P];
2236
2237 const MFloat PLfRHOL = PL / RHOL;
2238 const MFloat PRfRHOR = PR / RHOR;
2239 const MFloat e0 = PLfRHOL * FgammaMinusOne + 0.5 * (POW2(UL) + POW2(VL)) + PLfRHOL;
2240 const MFloat e1 = PRfRHOR * FgammaMinusOne + 0.5 * (POW2(UR) + POW2(VR)) + PRfRHOR;
2241
2242
2243 // compute lenght of metric vector for normalization
2244 const MFloat DGRAD = sqrt(POW2(surf0) + POW2(surf1));
2245 const MFloat FDGRAD = F1 / DGRAD;
2246
2247 // scale by metric length to get velocity in the new basis (get normalized basis vectors)
2248 const MFloat UUL = ((UL * surf0 + VL * surf1)) * FDGRAD;
2249
2250
2251 const MFloat UUR = ((UR * surf0 + VR * surf1)) * FDGRAD;
2252
2253 MFloat AL = FRHOL * PL;
2254 MFloat AR = FRHOR * PR;
2255
2256 const MFloat FALR = 2.0 / (AL + AR);
2257 const MFloat ALPHAL = AL * FALR;
2258 const MFloat ALPHAR = AR * FALR;
2259
2260 AL = sqrt(gamma * AL);
2261 AR = sqrt(gamma * AR);
2262 AL = mMax(AL, AR);
2263 AR = AL;
2264
2265 const MFloat XMAL = UUL / AL;
2266 const MFloat XMAR = UUR / AR;
2267
2268 AL = AL * DGRAD;
2269 AR = AR * DGRAD;
2270
2271 const MFloat RHOAL = AL * RHOL;
2272 const MFloat RHOAR = AR * RHOR;
2273
2274 const MInt IJK[2] = {1, m_nCells[1]};
2275 const MInt IP1 = I + IJK[dim];
2276
2277 const MFloat FDV = 0.3;
2278 const MFloat DXDXEZ = m_cells->coordinates[0][IP1] - m_cells->coordinates[0][I];
2279 const MFloat DYDXEZ = m_cells->coordinates[1][IP1] - m_cells->coordinates[1][I];
2280 MFloat SV = 2.0 * DGRAD / (m_cells->cellJac[I] + m_cells->cellJac[IP1]) * (FDV + (F1 - FDV) * getPSI(I, dim));
2281 const MFloat SV1 = SV * DXDXEZ;
2282 const MFloat SV2 = SV * DYDXEZ;
2283
2284 const MFloat XMAL1 = mMin(F1, mMax(-F1, XMAL));
2285 const MFloat XMAR1 = mMin(F1, mMax(-F1, XMAR));
2286
2287 MFloat FXMA = F1B2 * (XMAL1 + fabs(XMAL1));
2288 const MFloat XMALP = ALPHAL * (F1B4 * POW2(XMAL1 + F1) - FXMA) + FXMA + (mMax(F1, XMAL) - F1);
2289 FXMA = F1B2 * (XMAR1 - fabs(XMAR1));
2290 const MFloat XMARM = ALPHAR * (-F1B4 * POW2(XMAR1 - F1) - FXMA) + FXMA + (mMin(-F1, XMAR) + F1);
2291
2292 const MFloat FLP = PL * ((F2 - XMAL1) * POW2(F1 + XMAL1));
2293 const MFloat FRP = PR * ((F2 + XMAR1) * POW2(F1 - XMAR1));
2294 const MFloat PLR = F1B4 * (FLP + FRP);
2295
2296 const MFloat RHOUL = XMALP * RHOAL;
2297 const MFloat RHOUR = XMARM * RHOAR;
2298 const MFloat RHOU = RHOUL + RHOUR;
2299 const MFloat RHOU2 = F1B2 * RHOU;
2300 const MFloat ARHOU2 = fabs(RHOU2);
2301
2302 const MFloat UUL2 = SV1 * UUL;
2303 const MFloat UUR2 = SV1 * UUR;
2304 UL = UL - UUL2;
2305 UR = UR - UUR2;
2306 const MFloat UUL3 = SV2 * UUL;
2307 const MFloat UUR3 = SV2 * UUR;
2308 VL = VL - UUL3;
2309 VR = VR - UUR3;
2310
2311
2312 MFloat* const* const RESTRICT flux = m_cells->flux;
2313
2314 flux[CV->RHO_U][I] = RHOU2 * (UL + UR) + ARHOU2 * (UL - UR) + PLR * surf0 + RHOUL * UUL2 + RHOUR * UUR2;
2315 flux[CV->RHO_V][I] = RHOU2 * (VL + VR) + ARHOU2 * (VL - VR) + PLR * surf1 + RHOUL * UUL3 + RHOUR * UUR3;
2316 flux[CV->RHO_E][I] = RHOU2 * (e0 + e1) + ARHOU2 * (e0 - e1);
2317 flux[CV->RHO][I] = RHOU;
2318}
2319
2321 TRACE();
2322 m_timeStep = 1000.0;
2323 const MFloat* const RESTRICT dxtx = ALIGNED_F(m_cells->dxt[0]);
2324 const MFloat* const RESTRICT dxty = ALIGNED_F(m_cells->dxt[1]);
2325 const MFloat* const* const RESTRICT metric = m_cells->cellMetrics;
2326
2327 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
2328 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
2329 const MInt cellId = cellIndex(i, j);
2330 const MFloat Frho = F1 / m_cells->pvariables[PV->RHO][cellId];
2331
2332 // compute the speed of sound
2333 const MFloat speedOfSound = sqrt(m_gamma * pressure(cellId) * Frho);
2334
2335 // no need for simplified metrics, since information is already contained
2336 // in cell metrics
2337 const MFloat lenXi = sqrt(POW2(metric[0][cellId]) + POW2(metric[1][cellId]));
2338
2339 const MFloat lenEt = sqrt(POW2(metric[2][cellId]) + POW2(metric[3][cellId]));
2340
2341 // contravariant velocities
2342 MFloat U_c = F0;
2343 MFloat V_c = F0;
2344
2345 for(MInt isd = xsd; isd < nDim; isd++) {
2346 U_c += m_cells->pvariables[PV->VV[isd]][cellId] * metric[xsd * nDim + isd][cellId];
2347 V_c += m_cells->pvariables[PV->VV[isd]][cellId] * metric[ysd * nDim + isd][cellId];
2348 }
2349
2350 // subtract grid velocity
2351 U_c -= dxtx[cellId];
2352 V_c -= dxty[cellId];
2353
2354 U_c = fabs(U_c);
2355 V_c = fabs(V_c);
2356
2357 // has area information in it due to metric terms
2358 const MFloat eigenvalue = U_c + V_c + speedOfSound * (lenXi + lenEt);
2359
2360 // divide volume information (jacobian) through area to get characteristic length for CFL
2361 const MFloat deltaT = m_cfl * m_cells->cellJac[cellId] / eigenvalue;
2362 if(m_localTimeStep) {
2363 m_cells->localTimeStep[cellId] = deltaT;
2364 m_timeStep = F1;
2365 m_timeRef = F1;
2366 } else {
2367 // TODO_SS labels:FV if jacobian is negative, then timeStep will be negative and the following mMin won't
2368 // work
2369 m_timeStep = mMin(m_timeStep, deltaT);
2370 }
2371 }
2372 }
2373}
2374
2376 TRACE();
2378}
2379
2381 TRACE();
2382 const MInt noVars = CV->noVariables;
2383 const MUint noCells = m_noCells;
2384 const MFloat rkAlpha = m_RKalpha[m_RKStep];
2385 const MFloat rkFactor = rkAlpha * m_timeStep;
2386
2387#ifdef MAIA_EXTRA_DEBUG
2388 savePartitions(); // testing only
2389#endif
2390
2391 MFloat* const RESTRICT oldVars = ALIGNED_F(m_cells->oldVariables[0]);
2392 MFloat* const RESTRICT vars = ALIGNED_F(m_cells->variables[0]);
2393 MFloat* const RESTRICT oldCellJac = ALIGNED_MF(m_cells->oldCellJac);
2394 const MFloat* const RESTRICT cellJac = ALIGNED_MF(m_cells->cellJac);
2395 const MFloat* const RESTRICT rhs = ALIGNED_MF(m_cells->rightHandSide[0]);
2396
2397 // set old variables
2398 if(m_RKStep == 0) {
2399 for(MInt v = 0; v < noVars; v++) {
2400 const MUint offset = v * noCells;
2401 MFloat* const RESTRICT oldCellVars = ALIGNED_F(oldVars + offset);
2402 const MFloat* const RESTRICT cellVars = ALIGNED_F(vars + offset);
2403 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
2404 oldCellVars[cellId] = cellVars[cellId];
2405 }
2406 }
2407 }
2408
2409
2410 switch(m_rungeKuttaOrder) {
2411 case 2: {
2412 if(m_localTimeStep) {
2413 for(MInt v = 0; v < noVars; v++) {
2414 const MUint cellOffset = v * noCells;
2415 MFloat* const RESTRICT cellVars = vars + cellOffset;
2416 const MFloat* const RESTRICT oldCellVars = oldVars + cellOffset;
2417 const MFloat* const RESTRICT cellRhs = rhs + cellOffset;
2418
2419 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
2420 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
2421 const MInt cellId = cellIndex(i, j);
2422 const MFloat factor = (rkAlpha * m_cells->localTimeStep[cellId]) / m_cells->cellJac[cellId];
2423 cellVars[cellId] = oldCellVars[cellId] + factor * cellRhs[cellId];
2424 }
2425 }
2426 }
2427 } else if(m_movingGrid) {
2428 for(MInt v = 0; v < noVars; v++) {
2429 const MUint cellOffset = v * noCells;
2430 MFloat* const RESTRICT cellVars = vars + cellOffset;
2431 const MFloat* const RESTRICT oldCellVars = oldVars + cellOffset;
2432 const MFloat* const RESTRICT cellRhs = rhs + cellOffset;
2433
2434 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
2435 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
2436 const MInt cellId = cellIndex(i, j);
2437 cellVars[cellId] =
2438 (oldCellVars[cellId] * oldCellJac[cellId] + rkFactor * cellRhs[cellId]) / cellJac[cellId];
2439 }
2440 }
2441 }
2442 } else {
2443 for(MInt v = 0; v < noVars; v++) {
2444 const MUint cellOffset = v * noCells;
2445 MFloat* const RESTRICT cellVars = vars + cellOffset;
2446 const MFloat* const RESTRICT oldCellVars = oldVars + cellOffset;
2447 const MFloat* const RESTRICT cellRhs = rhs + cellOffset;
2448
2449 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
2450 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
2451 const MInt cellId = cellIndex(i, j);
2452 const MFloat factor = (rkAlpha * m_timeStep) / m_cells->cellJac[cellId];
2453 cellVars[cellId] = oldCellVars[cellId] + factor * cellRhs[cellId];
2454 }
2455 }
2456 }
2457 }
2458 break;
2459 }
2460 case 3: {
2461 for(MInt v = 0; v < noVars; v++) {
2462 const MUint cellOffset = v * noCells;
2463 MFloat* const RESTRICT cellVars = vars + cellOffset;
2464 const MFloat* const RESTRICT oldCellVars = oldVars + cellOffset;
2465 const MFloat* const RESTRICT cellRhs = rhs + cellOffset;
2466
2467 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
2468 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
2469 const MInt cellId = cellIndex(i, j);
2470 const MFloat factor = (rkAlpha * m_timeStep) / m_cells->cellJac[cellId];
2471 cellVars[cellId] =
2472 rkAlpha * cellVars[cellId] + (F1 - rkAlpha) * oldCellVars[cellId] - factor * cellRhs[cellId];
2473 }
2474 }
2475 }
2476 break;
2477 }
2478 default: {
2479 stringstream errorMessage;
2480 errorMessage << "Given RungeKutta Order " << m_rungeKuttaOrder << " not implemented! " << endl;
2481 mTerm(1, AT_, errorMessage.str());
2482 }
2483 }
2484
2485 ++m_RKStep;
2486
2487 if(m_RKStep == m_noRKSteps) {
2489 m_time += m_timeStep;
2490
2491 m_RKStep = 0;
2492
2493 return true;
2494 } else {
2495 return false;
2496 }
2497}
2498
2500
2502
2503
2504template <MBool twoEqRans>
2506 TRACE();
2507 const MFloat rPrLam = F1 / m_Pr;
2508 const MFloat rPrTurb = F1 / 0.9;
2509 const MFloat rRe = F1 / m_Re0;
2510 const MFloat gammaMinusOne = m_gamma - 1.0;
2511 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
2512
2513 const MFloat* const RESTRICT u = &m_cells->pvariables[PV->U][0];
2514 const MFloat* const RESTRICT v = &m_cells->pvariables[PV->V][0];
2515 const MFloat* const RESTRICT p = &m_cells->pvariables[PV->P][0];
2516 const MFloat* const RESTRICT rho = &m_cells->pvariables[PV->RHO][0];
2517 MFloat* const RESTRICT T = &m_cells->temperature[0];
2518 MFloat* const RESTRICT muLam = &m_cells->fq[FQ->MU_L][0];
2519 MFloat* const RESTRICT muTurb = &m_cells->fq[FQ->MU_T][0]; // this is zero for LES
2520
2521 MFloat* const* const RESTRICT eflux = ALIGNED_MF(m_cells->eFlux);
2522 MFloat* const* const RESTRICT fflux = ALIGNED_MF(m_cells->fFlux);
2523 MFloat* const* const RESTRICT vflux = ALIGNED_MF(m_cells->viscousFlux);
2524
2525 // only relevant for 2-eq Rans model (Waiting for if constexpr)
2526 const MFloat* const RESTRICT TKE = (twoEqRans) ? ALIGNED_F(m_cells->pvariables[PV->RANS_VAR[0]]) : nullptr;
2527 MFloat TKEcorner = 0;
2528
2529 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers + 1; j++) {
2530 for(MInt ii = m_noGhostLayers - 1; ii < m_nCells[1] - m_noGhostLayers + 1; ii++) {
2531 const MInt I = cellIndex(ii, j);
2532 T[I] = m_gamma * p[I] / rho[I];
2533 muLam[I] = SUTHERLANDLAW(T[I]);
2534 }
2535 }
2536
2537 MFloat tau1, tau2, tau4;
2538 MFloat dTdx, dTdy;
2539
2540 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; j++) {
2541 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; i++) {
2542 // get the adjacent cells;
2543 const MInt IJ = cellIndex(i, j);
2544 const MInt IPJ = cellIndex((i + 1), j);
2545 const MInt IPJP = cellIndex((i + 1), (j + 1));
2546 const MInt IJP = cellIndex(i, (j + 1));
2547
2548 const MFloat dudxi = F1B2 * (u[IPJP] + u[IPJ] - u[IJP] - u[IJ]);
2549 const MFloat dudet = F1B2 * (u[IPJP] + u[IJP] - u[IPJ] - u[IJ]);
2550
2551 const MFloat dvdxi = F1B2 * (v[IPJP] + v[IPJ] - v[IJP] - v[IJ]);
2552 const MFloat dvdet = F1B2 * (v[IPJP] + v[IJP] - v[IPJ] - v[IJ]);
2553
2554 const MFloat dTdxi = F1B2 * (T[IPJP] + T[IPJ] - T[IJP] - T[IJ]);
2555 const MFloat dTdet = F1B2 * (T[IPJP] + T[IJP] - T[IPJ] - T[IJ]);
2556
2557 const MFloat uAvg = F1B4 * (u[IJP] + u[IPJP] + u[IJ] + u[IPJ]);
2558 const MFloat vAvg = F1B4 * (v[IJP] + v[IPJP] + v[IJ] + v[IPJ]);
2559
2560 const MFloat muLamAvg = F1B4 * (muLam[IJP] + muLam[IPJP] + muLam[IJ] + muLam[IPJ]);
2561 const MFloat muTurbAvg = F1B4 * (muTurb[IJP] + muTurb[IPJP] + muTurb[IJ] + muTurb[IPJ]);
2562
2563 if(twoEqRans) {
2564 if(m_rans2eq_mode == "production")
2565 TKEcorner =
2566 -2 / 3 * F1B4 * (rho[IJP] * TKE[IJP] + rho[IPJP] * TKE[IPJP] + rho[IJ] * TKE[IJ] + rho[IPJ] * TKE[IPJ]);
2567 }
2568
2569 const MFloat cornerMetrics[4] = {m_cells->cornerMetrics[0][IJ], m_cells->cornerMetrics[1][IJ],
2570 m_cells->cornerMetrics[2][IJ], m_cells->cornerMetrics[3][IJ]};
2571
2572 // compute tau1 = 2 du/dx - 2/3 ( du/dx + dv/dy + dw/dz )
2573
2574 // tau_xx = 4/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx )
2575 // - 2/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy)
2576 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
2577 tau1 = F4B3 * (dudxi * cornerMetrics[xsd * 2 + xsd] + dudet * cornerMetrics[ysd * 2 + xsd]) -
2578
2579 F2B3 * (dvdxi * cornerMetrics[xsd * 2 + ysd] + dvdet * cornerMetrics[ysd * 2 + ysd]);
2580
2581 // compute tau2 = du/dy + dv/dx
2582
2583 // tau_xy = du/dxi * dxi/dy + du/deta * deta/dy + du/dzeta * dzeta/dy
2584 // + dv/dxi * dxi/dx + dv/deta * deta/dx + dv/dzeta * dzeta/dx
2585 tau2 = dudxi * cornerMetrics[xsd * 2 + ysd] + dudet * cornerMetrics[ysd * 2 + ysd] +
2586
2587 dvdxi * cornerMetrics[xsd * 2 + xsd] + dvdet * cornerMetrics[ysd * 2 + xsd];
2588
2589 // compute tau4 = 2 dv/dy - 2/3 ( du/dx + dv/dy + dw/dz )
2590
2591 // tau_yy = 4/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy )
2592 // - 2/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx)
2593 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
2594 tau4 = F4B3 * (dvdxi * cornerMetrics[xsd * 2 + ysd] + dvdet * cornerMetrics[ysd * 2 + ysd]) -
2595
2596 F2B3 * (dudxi * cornerMetrics[xsd * 2 + xsd] + dudet * cornerMetrics[ysd * 2 + xsd]);
2597
2598
2599 dTdx = dTdxi * cornerMetrics[xsd * 2 + xsd] + dTdet * cornerMetrics[ysd * 2 + xsd];
2600
2601 dTdy = dTdxi * cornerMetrics[xsd * 2 + ysd] + dTdet * cornerMetrics[ysd * 2 + ysd];
2602
2603 const MFloat fJac = 1.0 / m_cells->cornerJac[IJ];
2604 const MFloat mueOverRe = rRe * fJac * (muLamAvg + muTurbAvg);
2605 tau1 = mueOverRe * tau1 + TKEcorner;
2606 tau2 *= mueOverRe;
2607 tau4 = mueOverRe * tau4 + TKEcorner;
2608
2609 const MFloat muCombined = FgammaMinusOne * rRe * fJac * (rPrLam * muLamAvg + rPrTurb * muTurbAvg);
2610 const MFloat qx = muCombined * dTdx + uAvg * tau1 + vAvg * tau2;
2611 const MFloat qy = muCombined * dTdy + uAvg * tau2 + vAvg * tau4;
2612
2613 // efluxes
2614 eflux[0][IJ] = tau1 * cornerMetrics[xsd * 2 + xsd] + tau2 * cornerMetrics[xsd * 2 + ysd];
2615
2616 eflux[1][IJ] = tau2 * cornerMetrics[xsd * 2 + xsd] + tau4 * cornerMetrics[xsd * 2 + ysd];
2617
2618 eflux[2][IJ] = qx * cornerMetrics[xsd * 2 + xsd] + qy * cornerMetrics[xsd * 2 + ysd];
2619
2620 // ffluxes
2621 fflux[0][IJ] = tau1 * cornerMetrics[ysd * 2 + xsd] + tau2 * cornerMetrics[ysd * 2 + ysd];
2622
2623 fflux[1][IJ] = tau2 * cornerMetrics[ysd * 2 + xsd] + tau4 * cornerMetrics[ysd * 2 + ysd];
2624
2625 fflux[2][IJ] = qx * cornerMetrics[ysd * 2 + xsd] + qy * cornerMetrics[ysd * 2 + ysd];
2626 }
2627 }
2628
2629
2630 // viscous flux correction for the singular points
2631 // m_hasSingularity=0 means no singular points in this block, otherwise do flux correction
2632 if(m_hasSingularity > 0) {
2634 }
2635
2636 for(MInt var = 0; var < 3; ++var) {
2637 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; ++j) {
2638 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; ++i) {
2639 const MInt IJ = cellIndex(i, j);
2640 const MInt IJM = cellIndex(i, (j - 1));
2641
2642 vflux[0][IJ] = F1B2 * (eflux[var][IJ] + eflux[var][IJM]);
2643 }
2644 }
2645
2646 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; ++j) {
2647 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; ++i) {
2648 const MInt IJ = cellIndex(i, j);
2649 const MInt IMJ = cellIndex((i - 1), j);
2650
2651 vflux[1][IJ] = F1B2 * (fflux[var][IJ] + fflux[var][IMJ]);
2652 }
2653 }
2654
2655 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; ++j) {
2656 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; ++i) {
2657 const MInt IJ = cellIndex(i, j);
2658 const MInt IMJ = cellIndex((i - 1), j);
2659 const MInt IJM = cellIndex(i, (j - 1));
2660 m_cells->rightHandSide[var][IJ] += (vflux[0][IJ] - vflux[0][IMJ] + vflux[1][IJ] - vflux[1][IJM]);
2661 }
2662 }
2663 }
2664}
2665template void FvStructuredSolver2D::viscousFluxLES<true>();
2666
2667
2668/*template <MBool twoEqRans>
2669 void FvStructuredSolver2D::viscousFluxLESCompact()
2670 {
2671 TRACE();
2672 const MInt noCells = m_noCells;
2673 const MFloat rPrLam = F1/m_Pr;
2674 const MFloat rPrTurb = F1/0.9;
2675 const MFloat rRe = F1/m_Re0;
2676 const MFloat gammaMinusOne = m_gamma - 1.0;
2677 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
2678
2679 MFloat* const RESTRICT u = &m_cells->pvariables[PV->U][0];
2680 MFloat* const RESTRICT v = &m_cells->pvariables[PV->V][0];
2681 MFloat* const RESTRICT p = &m_cells->pvariables[PV->P][0];
2682 MFloat* const RESTRICT rho = &m_cells->pvariables[PV->RHO][0];
2683 MFloat* const RESTRICT T = &m_cells->temperature[0];
2684 MFloat* const RESTRICT muLam = &m_cells->fq[FQ->MU_L][0];
2685 MFloat* const RESTRICT muTurb = &m_cells->fq[FQ->MU_T][0]; //this is zero for LES
2686
2687 MFloat *const RESTRICT eflux= ALIGNED_MF(m_cells->eFlux);
2688 MFloat *const RESTRICT fflux= ALIGNED_MF(m_cells->fFlux);
2689
2690 for(MInt j=m_noGhostLayers-1; j<m_nCells[0]-m_noGhostLayers+1; j++) {
2691 for(MInt ii=m_noGhostLayers-1; ii<m_nCells[1]-m_noGhostLayers+1; ii++) {
2692 const MInt I=cellIndex(ii,j);
2693 T[I] = m_gamma*p[I]/rho[I];
2694 muLam[I] = SUTHERLANDLAW(T[I]);
2695 }
2696 }
2697
2698 // Save some aux. variables at the corners
2699 for(MInt j=m_noGhostLayers-1; j<m_nCells[0]-m_noGhostLayers; j++) {
2700 for(MInt i=m_noGhostLayers-1; i<m_nCells[1]-m_noGhostLayers; i++) {
2701 const MInt IJ = cellIndex(i,j);
2702 const MInt IPJ = cellIndex((i+1),j);
2703 const MInt IPJP = cellIndex((i+1),(j+1));
2704 const MInt IJP = cellIndex(i,(j+1));
2705
2706 const MFloat dudxi=F1B2*(u[IPJP]+u[IPJ]-u[IJP]-u[IJ]);
2707 const MFloat dudet=F1B2*(u[IPJP]+u[IJP]-u[IPJ]-u[IJ]);
2708
2709 const MFloat dvdxi=F1B2*(v[IPJP]+v[IPJ]-v[IJP]-v[IJ]);
2710 const MFloat dvdet=F1B2*(v[IPJP]+v[IJP]-v[IPJ]-v[IJ]);
2711
2712 const MFloat dTdxi=F1B2*(T[IPJP]+T[IPJ]-T[IJP]-T[IJ]);
2713 const MFloat dTdet=F1B2*(T[IPJP]+T[IJP]-T[IPJ]-T[IJ]);
2714
2715 // Temporarily save corner derivatives
2716 fflux[ 0*noCells+IJ ] = dudxi;
2717 fflux[ 1*noCells+IJ ] = dvdxi;
2718 fflux[ 2*noCells+IJ ] = dTdxi;
2719
2720 eflux[ 0*noCells+IJ ] = dudet;
2721 eflux[ 1*noCells+IJ ] = dvdet;
2722 eflux[ 2*noCells+IJ ] = dTdet;
2723 }
2724 }
2725
2726 // xi-Flux
2727 for(MInt j=m_noGhostLayers; j<m_nCells[0]-m_noGhostLayers; j++) {
2728 for(MInt i=m_noGhostLayers-1; i<m_nCells[1]-m_noGhostLayers; i++) {
2729 const MInt IJ = cellIndex(i,j);
2730 const MInt IPJ = cellIndex(i+1,j);
2731 const MInt IJM = cellIndex(i,j-1);
2732 // const MFloat surf[nDim*nDim] = {0.5*(m_cells->cornerMetrics[0*noCells+IJ] +
2733 m_cells->cornerMetrics[0*noCells+IJM]),
2734 // 0.5*(m_cells->cornerMetrics[1*noCells+IJ] +
2735 m_cells->cornerMetrics[1*noCells+IJM]),
2736 // 0.5*(m_cells->cornerMetrics[2*noCells+IJ] +
2737 m_cells->cornerMetrics[2*noCells+IJM]),
2738 // 0.5*(m_cells->cornerMetrics[3*noCells+IJ] +
2739 m_cells->cornerMetrics[3*noCells+IJM])}; const MFloat *const surf = m_cells->surfaceMetrics[IJ]; const MFloat
2740 invSurfJac = 2.0/(m_cells->cornerJac[IJ]+m_cells->cornerJac[IJM]); //TODO_SS labels:FV Is this the right way to go?
2741
2742 const MFloat dudxi = u[IPJ]-u[IJ];
2743 const MFloat dvdxi = v[IPJ]-v[IJ];
2744 const MFloat dTdxi = T[IPJ]-T[IJ];
2745 const MFloat dudet = 0.5*(eflux[0*noCells+IJ]+eflux[0*noCells+IJM]);
2746 const MFloat dvdet = 0.5*(eflux[1*noCells+IJ]+eflux[1*noCells+IJM]);
2747 const MFloat dTdet = 0.5*(eflux[2*noCells+IJ]+eflux[2*noCells+IJM]);
2748
2749 const MFloat uAvg = F1B2*(u[IJ]+u[IPJ]);
2750 const MFloat vAvg = F1B2*(v[IJ]+v[IPJ]);
2751
2752 const MFloat muLamAvg = F1B2*(muLam[IJ]+muLam[IPJ]);
2753 const MFloat muTurbAvg = F1B2*(muTurb[IJ]+muTurb[IPJ]);
2754
2755 // compute tau1 = 2 du/dx - 2/3 ( du/dx + dv/dy + dw/dz )
2756
2757 // tau_xx = 4/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx )
2758 // - 2/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy)
2759 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
2760 MFloat tau1 = F4B3 * ( dudxi * surf[ xsd * 2 + xsd ] +
2761 dudet * surf[ ysd * 2 + xsd ] ) -
2762
2763 F2B3 * ( dvdxi * surf[ xsd * 2 + ysd ] +
2764 dvdet * surf[ ysd * 2 + ysd ] );
2765
2766 // compute tau2 = du/dy + dv/dx
2767
2768 // tau_xy = du/dxi * dxi/dy + du/deta * deta/dy + du/dzeta * dzeta/dy
2769 // + dv/dxi * dxi/dx + dv/deta * deta/dx + dv/dzeta * dzeta/dx
2770 MFloat tau2 = dudxi * surf[ xsd * 2 + ysd ] +
2771 dudet * surf[ ysd * 2 + ysd ] +
2772
2773 dvdxi * surf[ xsd * 2 + xsd ] +
2774 dvdet * surf[ ysd * 2 + xsd ];
2775
2776 // compute tau4 = 2 dv/dy - 2/3 ( du/dx + dv/dy + dw/dz )
2777
2778 // tau_yy = 4/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy )
2779 // - 2/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx)
2780 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
2781 MFloat tau4 = F4B3 * ( dvdxi * surf[ xsd * 2 + ysd ] +
2782 dvdet * surf[ ysd * 2 + ysd ] ) -
2783
2784 F2B3 * ( dudxi * surf[ xsd * 2 + xsd ] +
2785 dudet * surf[ ysd * 2 + xsd ]);
2786
2787 const MFloat dTdx = dTdxi * surf[ xsd * 2 + xsd ] +
2788 dTdet * surf[ ysd * 2 + xsd ];
2789
2790 const MFloat dTdy = dTdxi * surf[ xsd * 2 + ysd ] +
2791 dTdet * surf[ ysd * 2 + ysd ];
2792
2793 const MFloat mueOverRe = rRe*invSurfJac*(muLamAvg + muTurbAvg);
2794 tau1=mueOverRe*tau1;
2795 tau2*=mueOverRe;
2796 tau4=mueOverRe*tau4;
2797
2798 const MFloat muCombined=FgammaMinusOne*rRe*invSurfJac*(rPrLam*muLamAvg + rPrTurb*muTurbAvg);
2799 const MFloat qx=muCombined*dTdx+uAvg*tau1+vAvg*tau2;
2800 const MFloat qy=muCombined*dTdy+uAvg*tau2+vAvg*tau4;
2801
2802 //efluxes
2803 eflux[ 0*noCells+IJM ] = tau1 * surf[ xsd * 2 + xsd ] +
2804 tau2 * surf[ xsd * 2 + ysd ];
2805
2806 eflux[ 1*noCells+IJM ] = tau2 * surf[ xsd * 2 + xsd ] +
2807 tau4 * surf[ xsd * 2 + ysd ];
2808
2809 eflux[ 2*noCells+IJM ] = qx * surf[ xsd * 2 + xsd ] +
2810 qy * surf[ xsd * 2 + ysd ];
2811 }
2812 }
2813
2814 // eta-Flux
2815 for(MInt j=m_noGhostLayers-1; j<m_nCells[0]-m_noGhostLayers; j++) {
2816 for(MInt i=m_noGhostLayers; i<m_nCells[1]-m_noGhostLayers; i++) {
2817 const MInt IJ = cellIndex(i,j);
2818 const MInt IJP = cellIndex(i,j+1);
2819 const MInt IMJ = cellIndex(i-1,j);
2820 // const MFloat surf[nDim*nDim] = {0.5*(m_cells->cornerMetrics[0*noCells+IJ] +
2821 m_cells->cornerMetrics[0*noCells+IMJ]),
2822 // 0.5*(m_cells->cornerMetrics[1*noCells+IJ] +
2823 m_cells->cornerMetrics[1*noCells+IMJ]),
2824 // 0.5*(m_cells->cornerMetrics[2*noCells+IJ] +
2825 m_cells->cornerMetrics[2*noCells+IMJ]),
2826// 0.5*(m_cells->cornerMetrics[3*noCells+IJ] +
2827 m_cells->cornerMetrics[3*noCells+IMJ])}; const MFloat *const surf = m_cells->surfaceMetrics[IJ]; const MFloat
2828 invSurfJac = 2.0/(m_cells->cornerJac[IJ]+m_cells->cornerJac[IMJ]); //TODO_SS labels:FV Is this the right way to go?
2829
2830const MFloat dudet = (u[IJP]-u[IJ]);
2831const MFloat dvdet = (v[IJP]-v[IJ]);
2832const MFloat dTdet = (T[IJP]-T[IJ]);
2833const MFloat dudxi = 0.5*(fflux[0*noCells+IJ]+fflux[0*noCells+IMJ]);
2834const MFloat dvdxi = 0.5*(fflux[1*noCells+IJ]+fflux[1*noCells+IMJ]);
2835const MFloat dTdxi = 0.5*(fflux[2*noCells+IJ]+fflux[2*noCells+IMJ]);
2836
2837const MFloat uAvg = F1B2*(u[IJ]+u[IJP]);
2838const MFloat vAvg = F1B2*(v[IJ]+v[IJP]);
2839
2840const MFloat muLamAvg = F1B2*(muLam[IJ]+muLam[IJP]);
2841const MFloat muTurbAvg = F1B2*(muTurb[IJ]+muTurb[IJP]);
2842
2843// compute tau1 = 2 du/dx - 2/3 ( du/dx + dv/dy + dw/dz )
2844
2845// tau_xx = 4/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx )
2846// - 2/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy)
2847// - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
2848MFloat tau1 = F4B3 * ( dudxi * surf[ xsd * 2 + xsd ] +
2849dudet * surf[ ysd * 2 + xsd ] ) -
2850
2851F2B3 * ( dvdxi * surf[ xsd * 2 + ysd ] +
2852dvdet * surf[ ysd * 2 + ysd ] );
2853
2854// compute tau2 = du/dy + dv/dx
2855
2856// tau_xy = du/dxi * dxi/dy + du/deta * deta/dy + du/dzeta * dzeta/dy
2857// + dv/dxi * dxi/dx + dv/deta * deta/dx + dv/dzeta * dzeta/dx
2858MFloat tau2 = dudxi * surf[ xsd * 2 + ysd ] +
2859dudet * surf[ ysd * 2 + ysd ] +
2860
2861dvdxi * surf[ xsd * 2 + xsd ] +
2862dvdet * surf[ ysd * 2 + xsd ];
2863
2864// compute tau4 = 2 dv/dy - 2/3 ( du/dx + dv/dy + dw/dz )
2865
2866// tau_yy = 4/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy )
2867// - 2/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx)
2868// - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
2869MFloat tau4 = F4B3 * ( dvdxi * surf[ xsd * 2 + ysd ] +
2870dvdet * surf[ ysd * 2 + ysd ] ) -
2871
2872F2B3 * ( dudxi * surf[ xsd * 2 + xsd ] +
2873dudet * surf[ ysd * 2 + xsd ]);
2874
2875const MFloat dTdx = dTdxi * surf[ xsd * 2 + xsd ] +
2876dTdet * surf[ ysd * 2 + xsd ];
2877
2878const MFloat dTdy = dTdxi * surf[ xsd * 2 + ysd ] +
2879dTdet * surf[ ysd * 2 + ysd ];
2880
2881const MFloat mueOverRe = rRe*invSurfJac*(muLamAvg + muTurbAvg);
2882tau1=mueOverRe*tau1;
2883tau2*=mueOverRe;
2884tau4=mueOverRe*tau4;
2885
2886const MFloat muCombined=FgammaMinusOne*rRe*invSurfJac*(rPrLam*muLamAvg + rPrTurb*muTurbAvg);
2887const MFloat qx=muCombined*dTdx+uAvg*tau1+vAvg*tau2;
2888const MFloat qy=muCombined*dTdy+uAvg*tau2+vAvg*tau4;
2889
2890//ffluxes
2891fflux[ 0*noCells+IMJ ] = tau1 * surf[ ysd * 2 + xsd ] + tau2 * surf[ ysd * 2 + ysd ];
2892
2893fflux[ 1*noCells+IMJ ] = tau2 * surf[ ysd * 2 + xsd ] + tau4 * surf[ ysd * 2 + ysd ];
2894
2895fflux[ 2*noCells+IMJ ] = qx * surf[ ysd * 2 + xsd ] + qy * surf[ ysd * 2 + ysd ];
2896
2897}
2898}
2899
2900//TODO_SS labels:FV
2901for(MInt var = 0; var < 3; ++var) {
2902for(MInt j=m_noGhostLayers; j<m_nCells[0]-m_noGhostLayers; ++j) {
2903for(MInt i=m_noGhostLayers; i<m_nCells[1]-m_noGhostLayers; ++i) {
2904const MInt IJ = cellIndex(i,j);
2905const MInt IMJ = cellIndex(i-1,j);
2906const MInt IJM = cellIndex(i,j-1);
2907const MInt IMJM = cellIndex(i-1,j-1);
2908
2909m_cells->rightHandSide[var][IJ]+= (eflux[var*noCells+IJM] - eflux[var*noCells+IMJM] +
2910fflux[var*noCells+IMJ] - fflux[var*noCells+IMJM]);
2911
2912}
2913}
2914}
2915}
2916template void FvStructuredSolver2D::viscousFluxLESCompact<true>();
2917*/
2918
2919template <MBool twoEqRans>
2921 TRACE();
2922 const MFloat rPrLam = F1 / m_Pr;
2923 const MFloat rPrTurb = F1 / 0.9;
2924 const MFloat rRe = F1 / m_Re0;
2925 const MFloat gammaMinusOne = m_gamma - 1.0;
2926 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
2927
2928 MFloat* const RESTRICT u = &m_cells->pvariables[PV->U][0];
2929 MFloat* const RESTRICT v = &m_cells->pvariables[PV->V][0];
2930 MFloat* const RESTRICT p = &m_cells->pvariables[PV->P][0];
2931 MFloat* const RESTRICT rho = &m_cells->pvariables[PV->RHO][0];
2932 MFloat* const RESTRICT T = &m_cells->temperature[0];
2933 MFloat* const RESTRICT muLam = &m_cells->fq[FQ->MU_L][0];
2934 MFloat* const RESTRICT muTurb = &m_cells->fq[FQ->MU_T][0]; // this is zero for LES
2935
2936 MFloat* const* const RESTRICT eflux = ALIGNED_MF(m_cells->eFlux);
2937 MFloat* const* const RESTRICT fflux = ALIGNED_MF(m_cells->fFlux);
2938 MFloat* const* const RESTRICT dT = ALIGNED_MF(m_cells->dT);
2939
2940 // only relevant for 2-eq Rans model (Waiting for if constexpr)
2941 const MFloat* const RESTRICT TKE = (twoEqRans) ? ALIGNED_F(m_cells->pvariables[PV->RANS_VAR[0]]) : nullptr;
2942 MFloat TKEcorner = 0;
2943
2944 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers + 1; j++) {
2945 for(MInt ii = m_noGhostLayers - 1; ii < m_nCells[1] - m_noGhostLayers + 1; ii++) {
2946 const MInt I = cellIndex(ii, j);
2947 T[I] = m_gamma * p[I] / rho[I];
2948 muLam[I] = SUTHERLANDLAW(T[I]);
2949 }
2950 }
2951
2952 // Save some aux. variables at the corners
2953 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; j++) {
2954 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; i++) {
2955 const MInt IJ = cellIndex(i, j);
2956 const MInt IPJ = cellIndex((i + 1), j);
2957 const MInt IPJP = cellIndex((i + 1), (j + 1));
2958 const MInt IJP = cellIndex(i, (j + 1));
2959
2960 const MFloat invCornerJac = F1 / m_cells->cornerJac[IJ];
2961 const MFloat cornerMetrics[nDim * nDim] = {
2962 m_cells->cornerMetrics[0][IJ] * invCornerJac, m_cells->cornerMetrics[1][IJ] * invCornerJac,
2963 m_cells->cornerMetrics[2][IJ] * invCornerJac, m_cells->cornerMetrics[3][IJ] * invCornerJac};
2964
2965 const MFloat dudxi = F1B2 * (u[IPJP] + u[IPJ] - u[IJP] - u[IJ]);
2966 const MFloat dudet = F1B2 * (u[IPJP] + u[IJP] - u[IPJ] - u[IJ]);
2967
2968 const MFloat dvdxi = F1B2 * (v[IPJP] + v[IPJ] - v[IJP] - v[IJ]);
2969 const MFloat dvdet = F1B2 * (v[IPJP] + v[IJP] - v[IPJ] - v[IJ]);
2970
2971 const MFloat dTdxi = F1B2 * (T[IPJP] + T[IPJ] - T[IJP] - T[IJ]);
2972 const MFloat dTdet = F1B2 * (T[IPJP] + T[IJP] - T[IPJ] - T[IJ]);
2973
2974 eflux[0][IJ] = dudet * cornerMetrics[ysd * 2 + ysd] + dvdet * cornerMetrics[ysd * 2 + xsd];
2975 eflux[1][IJ] = dudet * cornerMetrics[ysd * 2 + xsd];
2976 eflux[2][IJ] = dvdet * cornerMetrics[ysd * 2 + ysd];
2977
2978 fflux[0][IJ] = dudxi * cornerMetrics[xsd * 2 + ysd] + dvdxi * cornerMetrics[xsd * 2 + xsd];
2979 fflux[1][IJ] = dudxi * cornerMetrics[xsd * 2 + xsd];
2980 fflux[2][IJ] = dvdxi * cornerMetrics[xsd * 2 + ysd];
2981
2982 dT[0][IJ] = dTdet * cornerMetrics[ysd * 2 + xsd];
2983 dT[1][IJ] = dTdet * cornerMetrics[ysd * 2 + ysd];
2984 dT[2][IJ] = dTdxi * cornerMetrics[xsd * 2 + xsd];
2985 dT[3][IJ] = dTdxi * cornerMetrics[xsd * 2 + ysd];
2986 }
2987 }
2988
2989 if(m_hasSingularity) {
2991 }
2992
2993 // xi-Flux
2994 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; j++) {
2995 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; i++) {
2996 const MInt IJ = cellIndex(i, j);
2997 const MInt IPJ = cellIndex(i + 1, j);
2998 const MInt IJM = cellIndex(i, j - 1);
2999 const MFloat surf0 = m_cells->surfaceMetrics[0][IJ];
3000 const MFloat surf1 = m_cells->surfaceMetrics[1][IJ];
3001 // TODO_SS labels:FV here surface jac (m_cells->surfJac) verwenden!!!
3002 const MFloat invSurfJac =
3003 2.0 / (m_cells->cornerJac[IJ] + m_cells->cornerJac[IJM]); // TODO_SS labels:FV Is this the right way to go?
3004
3005 const MFloat dudxi = (u[IPJ] - u[IJ]) * invSurfJac;
3006 const MFloat dvdxi = (v[IPJ] - v[IJ]) * invSurfJac;
3007 const MFloat dTdxi = (T[IPJ] - T[IJ]) * invSurfJac;
3008
3009 const MFloat uAvg = F1B2 * (u[IJ] + u[IPJ]);
3010 const MFloat vAvg = F1B2 * (v[IJ] + v[IPJ]);
3011
3012 const MFloat muLamAvg = F1B2 * (muLam[IJ] + muLam[IPJ]);
3013 const MFloat muTurbAvg = F1B2 * (muTurb[IJ] + muTurb[IPJ]);
3014
3015 // The underscores in the variable names should indicate, that these are just
3016 // one contribution to the full, e.g. dudx
3017 const MFloat dudx_ = F1B2 * (eflux[1][IJ] + eflux[1][IJM]);
3018 const MFloat dvdy_ = F1B2 * (eflux[2][IJ] + eflux[2][IJM]);
3019 const MFloat S12_ = F1B2 * (eflux[0][IJ] + eflux[0][IJM]);
3020 const MFloat dTdx_ = F1B2 * (dT[0][IJ] + dT[0][IJM]);
3021 const MFloat dTdy_ = F1B2 * (dT[1][IJ] + dT[1][IJM]);
3022
3023 if(twoEqRans) {
3024 if(m_rans2eq_mode == "production") TKEcorner = -2 / 3 * F1B2 * (rho[IJ] * TKE[IJ] + rho[IPJ] * TKE[IPJ]);
3025 }
3026
3027 // compute tau1 = 2 du/dx - 2/3 ( du/dx + dv/dy + dw/dz )
3028
3029 // tau_xx = 4/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx )
3030 // - 2/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy)
3031 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
3032 MFloat tau1 = F4B3 * (dudxi * surf0 + dudx_) - F2B3 * (dvdxi * surf1 + dvdy_);
3033
3034 // compute tau2 = du/dy + dv/dx
3035
3036 // tau_xy = du/dxi * dxi/dy + du/deta * deta/dy + du/dzeta * dzeta/dy
3037 // + dv/dxi * dxi/dx + dv/deta * deta/dx + dv/dzeta * dzeta/dx
3038 MFloat tau2 = dudxi * surf1 + dvdxi * surf0 + S12_;
3039
3040 // compute tau4 = 2 dv/dy - 2/3 ( du/dx + dv/dy + dw/dz )
3041
3042 // tau_yy = 4/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy )
3043 // - 2/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx)
3044 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
3045 MFloat tau4 = F4B3 * (dvdxi * surf1 + dvdy_) - F2B3 * (dudxi * surf0 + dudx_);
3046
3047 const MFloat dTdx = dTdxi * surf0 + dTdx_;
3048 const MFloat dTdy = dTdxi * surf1 + dTdy_;
3049
3050 const MFloat mueOverRe = rRe * (muLamAvg + muTurbAvg);
3051 tau1 = mueOverRe * tau1 + TKEcorner;
3052 tau2 *= mueOverRe;
3053 tau4 = mueOverRe * tau4 + TKEcorner;
3054
3055 const MFloat muCombined = FgammaMinusOne * rRe * (rPrLam * muLamAvg + rPrTurb * muTurbAvg);
3056 const MFloat qx = muCombined * dTdx + uAvg * tau1 + vAvg * tau2;
3057 const MFloat qy = muCombined * dTdy + uAvg * tau2 + vAvg * tau4;
3058
3059 MFloat limiterVisc = 1.0;
3060 if(m_limiterVisc) {
3061 // TODO_SS labels:FV limiter should preserve conservativity
3062 const MFloat mu_ref = F1B2 * (m_cells->fq[FQ->LIMITERVISC][IJ] + m_cells->fq[FQ->LIMITERVISC][IPJ]);
3063 limiterVisc = std::min(1.0, mu_ref / std::abs(mueOverRe)); // TODO_SS labels:FV evtl: scale with Re
3064 }
3065
3066 // efluxes
3067 eflux[0][IJM] = (tau1 * surf0 + tau2 * surf1) * limiterVisc;
3068 eflux[1][IJM] = (tau2 * surf0 + tau4 * surf1) * limiterVisc;
3069 eflux[2][IJM] = (qx * surf0 + qy * surf1) * limiterVisc; // TODO_SS labels:FV aufpassen mit limiter
3070 }
3071 }
3072
3073 // eta-Flux
3074 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; j++) {
3075 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; i++) {
3076 const MInt IJ = cellIndex(i, j);
3077 const MInt IJP = cellIndex(i, j + 1);
3078 const MInt IMJ = cellIndex(i - 1, j);
3079 const MFloat surf0 = m_cells->surfaceMetrics[2 + 0][IJ];
3080 const MFloat surf1 = m_cells->surfaceMetrics[2 + 1][IJ];
3081 // TODO_SS labels:FV here surface jac (m_cells->surfJac) verwenden!!!
3082 const MFloat invSurfJac =
3083 2.0 / (m_cells->cornerJac[IJ] + m_cells->cornerJac[IMJ]); // TODO_SS labels:FV Is this the right way to go?
3084
3085 const MFloat dudet = (u[IJP] - u[IJ]) * invSurfJac;
3086 const MFloat dvdet = (v[IJP] - v[IJ]) * invSurfJac;
3087 const MFloat dTdet = (T[IJP] - T[IJ]) * invSurfJac;
3088
3089 const MFloat uAvg = F1B2 * (u[IJ] + u[IJP]);
3090 const MFloat vAvg = F1B2 * (v[IJ] + v[IJP]);
3091
3092 const MFloat muLamAvg = F1B2 * (muLam[IJ] + muLam[IJP]);
3093 const MFloat muTurbAvg = F1B2 * (muTurb[IJ] + muTurb[IJP]);
3094
3095 // The underscores in the variable names should indicate, that these are just
3096 // one contribution to the full, e.g. dudx
3097 const MFloat dudx_ = F1B2 * (fflux[1][IJ] + fflux[1][IMJ]);
3098 const MFloat dvdy_ = F1B2 * (fflux[2][IJ] + fflux[2][IMJ]);
3099 const MFloat S12_ = F1B2 * (fflux[0][IJ] + fflux[0][IMJ]);
3100 const MFloat dTdx_ = F1B2 * (dT[2][IJ] + dT[2][IMJ]);
3101 const MFloat dTdy_ = F1B2 * (dT[3][IJ] + dT[3][IMJ]);
3102
3103 if(twoEqRans) {
3104 if(m_rans2eq_mode == "production") TKEcorner = -2 / 3 * F1B2 * (rho[IJ] * TKE[IJ] + rho[IJP] * TKE[IJP]);
3105 }
3106
3107 // compute tau1 = 2 du/dx - 2/3 ( du/dx + dv/dy + dw/dz )
3108
3109 // tau_xx = 4/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx )
3110 // - 2/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy)
3111 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
3112 MFloat tau1 = F4B3 * (dudx_ + dudet * surf0) - F2B3 * (dvdy_ + dvdet * surf1);
3113
3114 // compute tau2 = du/dy + dv/dx
3115
3116 // tau_xy = du/dxi * dxi/dy + du/deta * deta/dy + du/dzeta * dzeta/dy
3117 // + dv/dxi * dxi/dx + dv/deta * deta/dx + dv/dzeta * dzeta/dx
3118 MFloat tau2 = dudet * surf1 + dvdet * surf0 + S12_;
3119
3120 // compute tau4 = 2 dv/dy - 2/3 ( du/dx + dv/dy + dw/dz )
3121
3122 // tau_yy = 4/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy )
3123 // - 2/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx)
3124 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
3125 MFloat tau4 = F4B3 * (dvdy_ + dvdet * surf1) - F2B3 * (dudx_ + dudet * surf0);
3126
3127 const MFloat dTdx = dTdet * surf0 + dTdx_;
3128 const MFloat dTdy = dTdet * surf1 + dTdy_;
3129
3130 const MFloat mueOverRe = rRe * (muLamAvg + muTurbAvg);
3131 tau1 = mueOverRe * tau1 + TKEcorner;
3132 tau2 *= mueOverRe;
3133 tau4 = mueOverRe * tau4 + TKEcorner;
3134
3135 const MFloat muCombined = FgammaMinusOne * rRe * (rPrLam * muLamAvg + rPrTurb * muTurbAvg);
3136 const MFloat qx = muCombined * dTdx + uAvg * tau1 + vAvg * tau2;
3137 const MFloat qy = muCombined * dTdy + uAvg * tau2 + vAvg * tau4;
3138
3139 MFloat limiterVisc = 1.0;
3140 if(m_limiterVisc) {
3141 // TODO_SS labels:FV limiter should preserve conservativity
3142 const MFloat mu_ref = F1B2 * (m_cells->fq[FQ->LIMITERVISC][IJ] + m_cells->fq[FQ->LIMITERVISC][IJP]);
3143 limiterVisc = std::min(1.0, mu_ref / std::abs(mueOverRe)); // TODO_SS labels:FV evtl: scale with Re
3144 }
3145
3146 // ffluxes
3147 fflux[0][IMJ] = (tau1 * surf0 + tau2 * surf1) * limiterVisc;
3148 fflux[1][IMJ] = (tau2 * surf0 + tau4 * surf1) * limiterVisc;
3149 fflux[2][IMJ] = (qx * surf0 + qy * surf1) * limiterVisc; // TODO_SS labels:FV aufpassen mit limiter
3150 }
3151 }
3152
3153 for(MInt var = 0; var < 3; ++var) {
3154 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; ++j) {
3155 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; ++i) {
3156 const MInt IJ = cellIndex(i, j);
3157 const MInt IMJ = cellIndex(i - 1, j);
3158 const MInt IJM = cellIndex(i, j - 1);
3159 const MInt IMJM = cellIndex(i - 1, j - 1);
3160
3161 MFloat limiterVisc = 1.0;
3162 /* if (m_limiterVisc) {
3163 // TODO_SS labels:FV limiter should preserve conservativity
3164 const MFloat mu_ref = m_cells->fq[FQ->LIMITERVISC][IJ];
3165 // TODO_SS labels:FV evtl: scale with Re
3166 limiterVisc = std::min(1.0, mu_ref/std::abs(rRe*(muLam[IJ]+muTurb[IJ])));
3167 }*/
3168 m_cells->rightHandSide[var][IJ] +=
3169 (eflux[var][IJM] - eflux[var][IMJM] + (fflux[var][IMJ] - fflux[var][IMJM])) * limiterVisc;
3170 }
3171 }
3172 }
3173}
3174template void FvStructuredSolver2D::viscousFluxLESCompact<true>();
3175
3176
3177template <MBool twoEqRans>
3179 mTerm(1, "I don't think that this correction is ok, becuase of the cornerMetrics at the singular point!");
3180 const MFloat rPr = F1 / m_Pr;
3181 const MFloat rPrTurb = F1 / 0.9;
3182 const MFloat rRe = F1 / m_Re0;
3183 const MFloat gammaMinusOne = m_gamma - 1.0;
3184 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
3185
3186 const MFloat* const RESTRICT u_ = &m_cells->variables[PV->U][0];
3187 const MFloat* const RESTRICT v_ = &m_cells->variables[PV->V][0];
3188 const MFloat* const RESTRICT p_ = &m_cells->variables[PV->P][0];
3189 const MFloat* const RESTRICT rho_ = &m_cells->variables[PV->RHO][0];
3190 const MFloat* const RESTRICT muTurb_ = &m_cells->fq[FQ->MU_T][0]; // this is zero for LES
3191
3192 MFloat* const* const RESTRICT eflux = &m_cells->eFlux[0];
3193 MFloat* const* const RESTRICT fflux = &m_cells->fFlux[0];
3194
3195 // only relevant for 2-eq Rans model (Waiting for if constexpr)
3196 const MFloat* const RESTRICT TKE_ = (twoEqRans) ? ALIGNED_F(m_cells->pvariables[PV->RANS_VAR[0]]) : nullptr;
3197
3198 // MInt dim = 0;
3199 MInt start[nDim], end[nDim], nghbr[10];
3200 MInt len1[nDim];
3201 // MInt totalCells;
3202
3203 for(MInt i = 0; i < m_hasSingularity; ++i) {
3204 // only correct for bc 6000 not for bc 4000-5000
3205 if(m_singularity[i].BC == -6000) {
3206 // totalCells=1;
3207 for(MInt j = 0; j < nDim; j++) {
3208 len1[j] = m_singularity[i].end[j] - m_singularity[i].start[j];
3209 // if(len1[j]!=0) totalCells*=len1[j];
3210 }
3211
3212 for(MInt n = 0; n < nDim; ++n) {
3213 if(m_singularity[i].end[n] - m_singularity[i].start[n] > 1) {
3214 mTerm(1, "In 2D not possible!");
3215 // dim=n;
3216 // start[n]=m_singularity[i].start[n]+1;
3217 start[n] = m_singularity[i].start[n] + 1;
3218 end[n] = m_singularity[i].end[n] - 1;
3219 } else {
3220 start[n] = m_singularity[i].start[n];
3221 end[n] = m_singularity[i].end[n];
3222 }
3223 }
3224
3225 MFloat u[10], v[10], T[10], muTurb[10], TKE[10];
3226 MFloat U, V, t, muTurb_corner, TKEcorner, dudx, dudy, dvdx, dvdy, dTdx, dTdy;
3227 MFloat tau1, tau2, tau4;
3228 MFloat mueOverRe, mue, mueH;
3229 for(MInt jj = start[1]; jj < end[1]; ++jj) {
3230 for(MInt ii = start[0]; ii < end[0]; ++ii) {
3231 MInt count = 0;
3232 // MInt temp[nDim]{};
3233 MInt IJK = cellIndex(ii + m_singularity[i].Viscous[0], jj + m_singularity[i].Viscous[1]);
3234
3235 const MFloat cornerMetrics[nDim * nDim] = {m_cells->cornerMetrics[0][IJK], m_cells->cornerMetrics[1][IJK],
3236 m_cells->cornerMetrics[2][IJK], m_cells->cornerMetrics[3][IJK]};
3237
3238 // temp[dim]=1;
3239 nghbr[count++] = cellIndex(ii, jj);
3240 // nghbr[count++]=cellIndex(ii+temp[0],jj+temp[1],kk+temp[2]);
3241
3242 for(MInt m = 0; m < m_singularity[i].Nstar - 1; ++m) {
3243 MInt* change = m_singularity[i].displacement[m];
3244 nghbr[count++] = cellIndex(ii + change[0], jj + change[1]);
3245 // nghbr[count++]=cellIndex(ii+temp[0]+change[0],jj+temp[1]+change[1],kk+temp[2]+change[2]);
3246 }
3247
3248 if(count != m_singularity[i].Nstar) {
3249 cout << "what the hell! it is wrong!!! count=" << count << " Nstar=" << m_singularity[i].Nstar << endl;
3250 }
3251
3252 for(MInt m = 0; m < m_singularity[i].Nstar; ++m) {
3253 u[m] = u_[nghbr[m]];
3254 v[m] = v_[nghbr[m]];
3255 // T[m]=(m_gamma*gammaMinusOne*(rhoE[nghbr[m]]-F1B2*rho[nghbr[m]]*(POW2(u[m])+POW2(v[m]))))/rho[nghbr[m]];
3256 T[m] = m_gamma * p_[nghbr[m]] / rho_[nghbr[m]];
3257 muTurb[m] = muTurb_[nghbr[m]];
3258 if(twoEqRans && m_rans2eq_mode == "production") TKE[m] = rho_[nghbr[m]] * TKE_[nghbr[m]];
3259 }
3260
3261 U = F0;
3262 V = F0;
3263 t = F0;
3264 muTurb_corner = F0;
3265 TKEcorner = F0;
3266 dudx = F0;
3267 dudy = F0;
3268 dvdx = F0;
3269 dvdy = F0;
3270 dTdx = F0;
3271 dTdy = F0;
3272
3273 MInt id2 = ii - start[0] + (jj - start[1]) * len1[0];
3274
3275 for(MInt n = 0; n < count; n++) {
3276 MInt ID = id2 * count + n;
3277 U += m_singularity[i].ReconstructionConstants[0][ID] * u[n];
3278 dudx += m_singularity[i].ReconstructionConstants[1][ID] * u[n];
3279 dudy += m_singularity[i].ReconstructionConstants[2][ID] * u[n];
3280
3281 V += m_singularity[i].ReconstructionConstants[0][ID] * v[n];
3282 dvdx += m_singularity[i].ReconstructionConstants[1][ID] * v[n];
3283 dvdy += m_singularity[i].ReconstructionConstants[2][ID] * v[n];
3284
3285 t += m_singularity[i].ReconstructionConstants[0][ID] * T[n];
3286 dTdx += m_singularity[i].ReconstructionConstants[1][ID] * T[n];
3287 dTdy += m_singularity[i].ReconstructionConstants[2][ID] * T[n];
3288
3289 muTurb_corner += m_singularity[i].ReconstructionConstants[0][ID] * muTurb[n];
3290
3291 if(twoEqRans && m_rans2eq_mode == "production")
3292 TKEcorner += m_singularity[i].ReconstructionConstants[0][ID] * TKE[n];
3293 }
3294
3295 // cout << globalTimeStep << "(" << m_RKStep << ") dom=" << domainId() << " x|y=" <<
3296 // m_cells->coordinates[0][IJK] << "|" << m_cells->coordinates[1][IJK] << " U=" << U << " V=" << V
3297 // << " t=" << t << " cornerMetrics=" << cornerMetrics[0] << "|" << cornerMetrics[1] << "|" <<
3298 // cornerMetrics[2] << "|" << cornerMetrics[3] << endl;
3299
3300 tau1 = 2 * dudx - 2 / 3 * (dudx + dvdy);
3301 tau2 = dudy + dvdx;
3302 tau4 = 2 * dvdy - 2 / 3 * (dudx + dvdy);
3303
3304 mue = SUTHERLANDLAW(t);
3305 TKEcorner *= -2 / 3;
3306 mueOverRe = (mue + muTurb_corner) * rRe;
3307 tau1 = mueOverRe * tau1 + TKEcorner;
3308 tau2 *= mueOverRe;
3309 tau4 = mueOverRe * tau4 + TKEcorner;
3310 mueH = FgammaMinusOne * rRe * (rPr * mue + rPrTurb * muTurb_corner);
3311
3312 const MFloat qx = mueH * dTdx + U * tau1 + V * tau2;
3313 const MFloat qy = mueH * dTdy + U * tau2 + V * tau4;
3314
3315 // efluxes
3316 eflux[0][IJK] = tau1 * cornerMetrics[xsd * 2 + xsd] + tau2 * cornerMetrics[xsd * 2 + ysd];
3317 eflux[1][IJK] = tau2 * cornerMetrics[xsd * 2 + xsd] + tau4 * cornerMetrics[xsd * 2 + ysd];
3318 eflux[2][IJK] = qx * cornerMetrics[xsd * 2 + xsd] + qy * cornerMetrics[xsd * 2 + ysd];
3319
3320 // ffluxes
3321 fflux[0][IJK] = tau1 * cornerMetrics[ysd * 2 + xsd] + tau2 * cornerMetrics[ysd * 2 + ysd];
3322 fflux[1][IJK] = tau2 * cornerMetrics[ysd * 2 + xsd] + tau4 * cornerMetrics[ysd * 2 + ysd];
3323 fflux[2][IJK] = qx * cornerMetrics[ysd * 2 + xsd] + qy * cornerMetrics[ysd * 2 + ysd];
3324 }
3325 }
3326 }
3327 }
3328}
3329
3330
3331template <MBool twoEqRans>
3333 MFloat* RESTRICT u_ = &m_cells->pvariables[PV->U][0];
3334 MFloat* RESTRICT v_ = &m_cells->pvariables[PV->V][0];
3335 MFloat* RESTRICT p_ = &m_cells->pvariables[PV->P][0];
3336 MFloat* RESTRICT rho_ = &m_cells->pvariables[PV->RHO][0];
3337
3338 MFloat* const* const RESTRICT eflux = ALIGNED_MF(m_cells->eFlux);
3339 MFloat* const* const RESTRICT fflux = ALIGNED_MF(m_cells->fFlux);
3340 MFloat* const* const RESTRICT dT = ALIGNED_MF(m_cells->dT);
3341
3342 // MInt dim = 0;
3343 MInt start[nDim], end[nDim], nghbr[10];
3344 MInt len1[nDim];
3345 // MInt totalCells;
3346
3347 for(MInt i = 0; i < m_hasSingularity; ++i) {
3348 // only correct for bc 6000 not for bc 4000-5000
3349 if(m_singularity[i].BC == -6000) {
3350 // totalCells=1;
3351 for(MInt j = 0; j < nDim; j++) {
3352 len1[j] = m_singularity[i].end[j] - m_singularity[i].start[j];
3353 // if(len1[j]!=0) totalCells*=len1[j];
3354 }
3355
3356 for(MInt n = 0; n < nDim; ++n) {
3357 if(m_singularity[i].end[n] - m_singularity[i].start[n] > 1) {
3358 mTerm(1, "In 2D not possible!");
3359 // dim=n;
3360 // start[n]=m_singularity[i].start[n]+1;
3361 start[n] = m_singularity[i].start[n] + 1;
3362 end[n] = m_singularity[i].end[n] - 1;
3363 } else {
3364 start[n] = m_singularity[i].start[n];
3365 end[n] = m_singularity[i].end[n];
3366 }
3367 }
3368
3369 MFloat u[10], v[10], T[10];
3370 MFloat U, V, t;
3371 for(MInt jj = start[1]; jj < end[1]; ++jj) {
3372 for(MInt ii = start[0]; ii < end[0]; ++ii) {
3373 MInt count = 0;
3374 // MInt temp[nDim]{};
3375 MInt IJ_ = cellIndex(ii + m_singularity[i].Viscous[0], jj + m_singularity[i].Viscous[1]);
3376
3377 // dxidx, dxidy, detadx, detady
3378 const MFloat surfaceMetrics[nDim * nDim] = {
3381
3382 // temp[dim]=1;
3383 const MInt IJ = cellIndex(ii, jj);
3384 nghbr[count++] = IJ;
3385 // nghbr[count++]=cellIndex(ii+temp[0],jj+temp[1],kk+temp[2]);
3386
3387 for(MInt m = 0; m < m_singularity[i].Nstar - 1; ++m) {
3388 MInt* change = m_singularity[i].displacement[m];
3389 nghbr[count++] = cellIndex(ii + change[0], jj + change[1]);
3390 // nghbr[count++]=cellIndex(ii+temp[0]+change[0],jj+temp[1]+change[1],kk+temp[2]+change[2]);
3391 }
3392
3393 if(count != m_singularity[i].Nstar) {
3394 cout << "what the hell! it is wrong!!! count=" << count << " Nstar=" << m_singularity[i].Nstar << endl;
3395 }
3396
3397 for(MInt m = 0; m < m_singularity[i].Nstar; ++m) {
3398 u[m] = u_[nghbr[m]];
3399 v[m] = v_[nghbr[m]];
3400 // T[m]=(m_gamma*gammaMinusOne*(rhoE[nghbr[m]]-F1B2*rho[nghbr[m]]*(POW2(u[m])+POW2(v[m]))))/rho[nghbr[m]];
3401 T[m] = m_gamma * p_[nghbr[m]] / rho_[nghbr[m]];
3402 }
3403
3404 U = F0;
3405 V = F0;
3406 t = F0;
3407
3408 MInt id2 = ii - start[0] + (jj - start[1]) * len1[0];
3409
3410 for(MInt n = 0; n < count; n++) {
3411 MInt ID = id2 * count + n;
3412 U += m_singularity[i].ReconstructionConstants[0][ID] * u[n];
3413 V += m_singularity[i].ReconstructionConstants[0][ID] * v[n];
3414 t += m_singularity[i].ReconstructionConstants[0][ID] * T[n];
3415 }
3416
3417 // cout << globalTimeStep << "(" << m_RKStep << ") dom=" << domainId() << " x|y=" <<
3418 // m_cells->coordinates[0][IJK] << "|" << m_cells->coordinates[1][IJK] << " U=" << U << " V=" << V
3419 // << " t=" << t << " cornerMetrics=" << cornerMetrics[0] << "|" << cornerMetrics[1] << "|" <<
3420 // cornerMetrics[2] << "|" << cornerMetrics[3] << endl;
3421
3422 const MInt sign_xi = 2 * m_singularity[i].Viscous[0] + 1; //-1,+1
3423 const MInt sign_eta = 2 * m_singularity[i].Viscous[1] + 1; //-1,+1
3424
3425 const MInt IPMJ = getCellIdFromCell(IJ, sign_xi, 0);
3426 const MInt IJPM = getCellIdFromCell(IJ, 0, sign_eta);
3427
3428 const MFloat dudet = sign_eta * 0.5 * (U - 0.5 * (u[0] + u_[IPMJ]));
3429 const MFloat dvdet = sign_eta * 0.5 * (V - 0.5 * (v[0] + v_[IPMJ]));
3430 const MFloat T1 = m_gamma * p_[IPMJ] / rho_[IPMJ];
3431 const MFloat dTdet = sign_eta * 0.5 * (t - 0.5 * (T[0] + T1));
3432
3433 const MFloat dudxi = sign_xi * 0.5 * (U - 0.5 * (u[0] + u_[IJPM]));
3434 const MFloat dvdxi = sign_xi * 0.5 * (V - 0.5 * (v[0] + v_[IJPM]));
3435 const MFloat T2 = m_gamma * p_[IJPM] / rho_[IJPM];
3436 const MFloat dTdxi = sign_xi * 0.5 * (t - 0.5 * (T[0] + T2));
3437
3438 eflux[0][IJ_] = dudet * surfaceMetrics[ysd * 2 + ysd] + dvdet * surfaceMetrics[ysd * 2 + xsd];
3439 eflux[1][IJ_] = dudet * surfaceMetrics[ysd * 2 + xsd];
3440 eflux[2][IJ_] = dvdet * surfaceMetrics[ysd * 2 + ysd];
3441
3442 fflux[0][IJ_] = dudxi * surfaceMetrics[xsd * 2 + ysd] + dvdxi * surfaceMetrics[xsd * 2 + xsd];
3443 fflux[1][IJ_] = dudxi * surfaceMetrics[xsd * 2 + xsd];
3444 fflux[2][IJ_] = dvdxi * surfaceMetrics[xsd * 2 + ysd];
3445
3446 dT[0][IJ_] = dTdet * surfaceMetrics[ysd * 2 + xsd];
3447 dT[1][IJ_] = dTdet * surfaceMetrics[ysd * 2 + ysd];
3448 dT[2][IJ_] = dTdxi * surfaceMetrics[xsd * 2 + xsd];
3449 dT[3][IJ_] = dTdxi * surfaceMetrics[xsd * 2 + ysd];
3450 }
3451 }
3452 }
3453 }
3454}
3455
3456
3458 TRACE();
3459
3460 static constexpr MFloat minMFloat =
3461 1e-16; // std::min(std::numeric_limits<MFloat>::min(), 1.0/std::numeric_limits<MFloat>::max());
3462 const MFloat rRe0 = 1.0 / m_Re0;
3463
3464 const MFloat* const* const RESTRICT pvars = m_cells->pvariables;
3465 const MFloat* const RESTRICT muLam = &m_cells->fq[FQ->MU_L][0];
3466 const MFloat* const RESTRICT por = &m_cells->fq[FQ->POROSITY][0];
3467 const MFloat* const RESTRICT Da = &m_cells->fq[FQ->DARCY][0];
3468 const MFloat* const RESTRICT cf = &m_cells->fq[FQ->FORCH][0];
3469 const MFloat* const RESTRICT utau = &m_cells->fq[FQ->UTAU][0];
3470 const MFloat* const RESTRICT wallDist = &m_cells->fq[FQ->WALLDISTANCE][0];
3471
3472 if(isRans) {
3473 const MFloat* const RESTRICT u_ = &pvars[PV->U][0];
3474 const MFloat* const RESTRICT v_ = &pvars[PV->V][0];
3475 const MFloat* const RESTRICT rho = &pvars[PV->RHO][0];
3476 const MFloat* const RESTRICT p = &pvars[PV->P][0];
3477 const MFloat* const RESTRICT TKE = &pvars[PV->RANS_VAR[0]][0];
3478 const MFloat* const RESTRICT eps = &pvars[PV->RANS_VAR[1]][0];
3479 const MFloat* const RESTRICT muTurb = &m_cells->fq[FQ->MU_T][0];
3480
3481 MFloat* const* const RESTRICT eflux = ALIGNED_F(m_cells->eFlux);
3482 MFloat* const* const RESTRICT fflux = ALIGNED_F(m_cells->fFlux);
3483 MFloat* const* const RESTRICT vflux = ALIGNED_F(m_cells->viscousFlux);
3484 MFloat* const* const RESTRICT sa_1flux = ALIGNED_F(m_cells->saFlux1);
3485 MFloat* const* const RESTRICT sa_2flux = ALIGNED_F(m_cells->saFlux2);
3486
3487 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; ++j) {
3488 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; ++i) {
3489 // get the adjacent cells;
3490 const MInt IJ = cellIndex(i, j);
3491 const MInt IPJ = cellIndex((i + 1), j);
3492 const MInt IPJP = cellIndex((i + 1), (j + 1));
3493 const MInt IJP = cellIndex(i, (j + 1));
3494
3495 // Compute Reynolds stresses at the corners
3496 const MFloat dudxi = F1B2 * (u_[IPJP] + u_[IPJ] - u_[IJP] - u_[IJ]);
3497 const MFloat dudet = F1B2 * (u_[IPJP] + u_[IJP] - u_[IPJ] - u_[IJ]);
3498
3499 const MFloat dvdxi = F1B2 * (v_[IPJP] + v_[IPJ] - v_[IJP] - v_[IJ]);
3500 const MFloat dvdet = F1B2 * (v_[IPJP] + v_[IJP] - v_[IPJ] - v_[IJ]);
3501
3502 const MFloat rhoAvg = F1B4 * (rho[IJP] + rho[IPJP] + rho[IJ] + rho[IPJ]);
3503 const MFloat muTurbAvg = F1B4 * (muTurb[IJP] + muTurb[IPJP] + muTurb[IJ] + muTurb[IPJ]);
3504 const MFloat nuTurbAvg = muTurbAvg / rhoAvg;
3505
3506 const MFloat TKEcorner =
3507 (m_rans2eq_mode == "production") ? -2 / 3 * F1B4 * (TKE[IJP] + TKE[IPJP] + TKE[IJ] + TKE[IPJ]) : 0.0;
3508
3509 const MFloat cornerMetrics[4] = {m_cells->cornerMetrics[0][IJ], m_cells->cornerMetrics[1][IJ],
3510 m_cells->cornerMetrics[2][IJ], m_cells->cornerMetrics[3][IJ]};
3511
3512 // compute tau1 = 2 du/dx - 2/3 ( du/dx + dv/dy + dw/dz )
3513
3514 // tau_xx = 4/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx )
3515 // - 2/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy)
3516 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
3517 MFloat tau1 = F4B3 * (dudxi * cornerMetrics[xsd * 2 + xsd] + dudet * cornerMetrics[ysd * 2 + xsd]) -
3518
3519 F2B3 * (dvdxi * cornerMetrics[xsd * 2 + ysd] + dvdet * cornerMetrics[ysd * 2 + ysd]);
3520
3521 // compute tau2 = du/dy + dv/dx
3522
3523 // tau_xy = du/dxi * dxi/dy + du/deta * deta/dy + du/dzeta * dzeta/dy
3524 // + dv/dxi * dxi/dx + dv/deta * deta/dx + dv/dzeta * dzeta/dx
3525 MFloat tau2 = dudxi * cornerMetrics[xsd * 2 + ysd] + dudet * cornerMetrics[ysd * 2 + ysd] +
3526
3527 dvdxi * cornerMetrics[xsd * 2 + xsd] + dvdet * cornerMetrics[ysd * 2 + xsd];
3528
3529 // compute tau4 = 2 dv/dy - 2/3 ( du/dx + dv/dy + dw/dz )
3530
3531 // tau_yy = 4/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy )
3532 // - 2/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx)
3533 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
3534 MFloat tau4 = F4B3 * (dvdxi * cornerMetrics[xsd * 2 + ysd] + dvdet * cornerMetrics[ysd * 2 + ysd]) -
3535
3536 F2B3 * (dudxi * cornerMetrics[xsd * 2 + xsd] + dudet * cornerMetrics[ysd * 2 + xsd]);
3537
3538 const MFloat fJac = 1.0 / m_cells->cornerJac[IJ];
3539 const MFloat mueOverRe = rRe0 * fJac * nuTurbAvg;
3540 tau1 = mueOverRe * tau1 + TKEcorner;
3541 tau2 *= mueOverRe;
3542 tau4 = mueOverRe * tau4 + TKEcorner;
3543
3544 vflux[0][IJ] = -tau1;
3545 vflux[1][IJ] = -tau2;
3546 vflux[2][IJ] = -tau4;
3547
3548 // c_Dp-term
3549 const MFloat dTKEdxi = F1B2 * (TKE[IPJP] + TKE[IPJ] - TKE[IJP] - TKE[IJ]);
3550 const MFloat dTKEdet = F1B2 * (TKE[IPJP] + TKE[IJP] - TKE[IPJ] - TKE[IJ]);
3551
3552 const MFloat depsdxi = F1B2 * (eps[IPJP] + eps[IPJ] - eps[IJP] - eps[IJ]);
3553 const MFloat depsdet = F1B2 * (eps[IPJP] + eps[IJP] - eps[IPJ] - eps[IJ]);
3554
3555 // const MFloat TKEAvg = F1B4*(TKE[IJP]+TKE[IPJP]+TKE[IJ]+TKE[IPJ]);
3556 // const MFloat epsAvg = F1B4*(eps[IJP]+eps[IPJP]+eps[IJ]+eps[IPJ]);
3557 // const MFloat temp = POW2(TKEAvg)/std::max(epsAvg, minMFloat);
3558
3559 const MFloat dTKEdx = dTKEdxi * cornerMetrics[xsd * 2 + xsd] + dTKEdet * cornerMetrics[ysd * 2 + xsd];
3560
3561 const MFloat dTKEdy = dTKEdxi * cornerMetrics[xsd * 2 + ysd] + dTKEdet * cornerMetrics[ysd * 2 + ysd];
3562
3563 const MFloat depsdx = depsdxi * cornerMetrics[xsd * 2 + xsd] + depsdet * cornerMetrics[ysd * 2 + xsd];
3564
3565 const MFloat depsdy = depsdxi * cornerMetrics[xsd * 2 + ysd] + depsdet * cornerMetrics[ysd * 2 + ysd];
3566
3567 // Compute indicator function
3568 const MFloat dpdxi = F1B2 * (p[IPJP] + p[IPJ] - p[IJP] - p[IJ]);
3569 const MFloat dpdet = F1B2 * (p[IPJP] + p[IJP] - p[IPJ] - p[IJ]);
3570
3571 const MFloat dpdx = dpdxi * cornerMetrics[xsd * 2 + xsd] + dpdet * cornerMetrics[ysd * 2 + xsd];
3572
3573 const MFloat dpdy = dpdxi * cornerMetrics[xsd * 2 + ysd] + dpdet * cornerMetrics[ysd * 2 + ysd];
3574
3575 const MFloat uAvg = F1B4 * (u_[IJP] + u_[IPJP] + u_[IJ] + u_[IPJ]);
3576 const MFloat vAvg = F1B4 * (v_[IJP] + v_[IPJP] + v_[IJ] + v_[IPJ]);
3577 const MFloat velAbs = sqrt(POW2(uAvg) + POW2(vAvg));
3578 const MFloat muLamAvg = F1B4 * (muLam[IJP] + muLam[IPJP] + muLam[IJ] + muLam[IPJ]);
3579 const MFloat porAvg = F1B4 * (por[IJP] + por[IPJP] + por[IJ] + por[IPJ]);
3580 // TODO_SS labels:FV,toenhance For now I take the Da and cf of the current cell and not at the corner;
3581 // To do it correctly we need to exchange Da and cf similar to porosity
3582 const MFloat rDaAvg = 1.0 / Da[IJ];
3583 const MFloat cfAvg = cf[IJ];
3584 const MFloat indicator = (dpdx * uAvg + dpdy * vAvg)
3585 / std::max(POW2(velAbs)
3586 * (rRe0 * porAvg * muLamAvg * rDaAvg
3587 + rhoAvg * POW2(porAvg) * cfAvg * sqrt(rDaAvg) * velAbs),
3588 minMFloat);
3589 const MFloat c_Dp_eff = m_c_Dp * (-0.5 * tanh(indicator - 5.0) + 0.5);
3590 const MFloat c_Dp_eps_eff = m_c_Dp_eps * (-0.5 * tanh(indicator - 5.0) + 0.5);
3591 m_cells->fq[FQ->POROUS_INDICATOR][IJ] =
3592 (-0.5 * tanh(indicator - 5.0) + 0.5); // it's not exactly the cell center indicator
3593
3594 // TODO_SS labels:FV evtl. das f_mu wieder loeschen, wenn der Code auch ohne laueft
3595 const MFloat nuLaminarAvg = muLamAvg / rhoAvg;
3596 const MFloat utauAvg = F1B4 * (utau[IJP] + utau[IPJP] + utau[IJ] + utau[IPJ]);
3597 const MFloat wallDistAvg = F1B4 * (wallDist[IJP] + wallDist[IPJP] + wallDist[IJ] + wallDist[IPJ]);
3598 const MFloat yp = utauAvg * wallDistAvg / nuLaminarAvg;
3599 const MFloat f_mu = 1.0 - exp(-RM_KEPS::C3 * 40 * m_Re0 * yp); // TODO_SS labels:FV
3600
3601 MFloat limiterVisc1 = 1.0;
3602 MFloat limiterVisc2 = 1.0;
3603 if(m_limiterVisc) {
3604 // TODO_SS labels:FV limiter should preserve conservativity; auch in computePorousRHSCorrection einbauen
3605 const MFloat mu_ref = F1B4
3606 * (m_cells->fq[FQ->LIMITERVISC][IPJP] + m_cells->fq[FQ->LIMITERVISC][IPJ]
3607 + m_cells->fq[FQ->LIMITERVISC][IJP] + m_cells->fq[FQ->LIMITERVISC][IJ]);
3608 // limiterVisc1 = std::min(1.0, mu_ref/std::abs( c_Dp_eff*temp ));
3609 // limiterVisc2 = std::min(1.0, mu_ref/std::abs( c_Dp_eps_eff*temp ));
3610 limiterVisc1 = std::min(1.0,
3611 mu_ref
3612 / std::abs(rRe0 * c_Dp_eff * RM_KEPS::rsigma_k
3613 * muTurbAvg)); // TODO_SS labels:FV scale with Re-number?
3614 limiterVisc2 = std::min(1.0, mu_ref / std::abs(rRe0 * c_Dp_eps_eff * RM_KEPS::rsigma_eps * muTurbAvg));
3615 }
3616
3617 const MFloat Frj = rRe0 * fJac;
3618
3619 const MFloat sax1 = Frj * c_Dp_eff * RM_KEPS::rsigma_k * muTurbAvg * f_mu * limiterVisc1
3620 * (dTKEdx * cornerMetrics[xsd * 2 + xsd] + dTKEdy * cornerMetrics[xsd * 2 + ysd]);
3621 const MFloat say1 = Frj * c_Dp_eff * RM_KEPS::rsigma_k * muTurbAvg * f_mu * limiterVisc1
3622 * (dTKEdx * cornerMetrics[ysd * 2 + xsd] + dTKEdy * cornerMetrics[ysd * 2 + ysd]);
3623
3624 const MFloat sax2 = Frj * c_Dp_eps_eff * muTurbAvg * RM_KEPS::rsigma_eps * f_mu * limiterVisc2
3625 * (depsdx * cornerMetrics[xsd * 2 + xsd] + depsdy * cornerMetrics[xsd * 2 + ysd]);
3626 const MFloat say2 = Frj * c_Dp_eps_eff * muTurbAvg * RM_KEPS::rsigma_eps * f_mu * limiterVisc2
3627 * (depsdx * cornerMetrics[ysd * 2 + xsd] + depsdy * cornerMetrics[ysd * 2 + ysd]);
3628
3629 // const MFloat sax1 = fJac*c_Dp_eff*temp*
3630 // (dTKEdx * cornerMetrics[ xsd * 2 + xsd ]+
3631 // dTKEdy * cornerMetrics[ xsd * 2 + ysd ]);
3632 // const MFloat say1 = fJac*c_Dp_eff*temp*
3633 // (dTKEdx * cornerMetrics[ ysd * 2 + xsd ]+
3634 // dTKEdy * cornerMetrics[ ysd * 2 + ysd ]);
3635
3636 // TODO_SS labels:FV for now I assume that whenever rans-porous, then sa_1flux array is allocated
3637 sa_1flux[0][IJ] = sax1;
3638 sa_1flux[1][IJ] = say1;
3639 sa_2flux[0][IJ] = sax2;
3640 sa_2flux[1][IJ] = say2;
3641 }
3642 }
3643
3645
3646 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; ++j) {
3647 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; ++i) {
3648 const MInt IJ = cellIndex(i, j);
3649 const MInt IJM = cellIndex(i, (j - 1));
3650
3651 sa_1flux[0][IJM] = F1B2 * (sa_1flux[0][IJ] + sa_1flux[0][IJM]);
3652 sa_2flux[0][IJM] = F1B2 * (sa_2flux[0][IJ] + sa_2flux[0][IJM]);
3653 }
3654 }
3655 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; ++j) {
3656 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; ++i) {
3657 const MInt IJ = cellIndex(i, j);
3658 const MInt IMJ = cellIndex((i - 1), j);
3659
3660 sa_1flux[1][IMJ] = F1B2 * (sa_1flux[1][IJ] + sa_1flux[1][IMJ]);
3661 sa_2flux[1][IMJ] = F1B2 * (sa_2flux[1][IJ] + sa_2flux[1][IMJ]);
3662 }
3663 }
3664
3665 for(MInt var = 0; var < 3; ++var) {
3666 // intermediate saving of Reynolds stresses in the surface centers
3667 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; ++j) {
3668 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; ++i) {
3669 const MInt IJ = cellIndex(i, j);
3670 const MInt IJM = cellIndex(i, j - 1);
3671
3672 eflux[var][IJ] = 0.5 * (vflux[var][IJ] + vflux[var][IJM]);
3673 }
3674 }
3675 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; ++j) {
3676 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; ++i) {
3677 const MInt IJ = cellIndex(i, j);
3678 const MInt IMJ = cellIndex((i - 1), j);
3679
3680 fflux[var][IJ] = 0.5 * (vflux[var][IJ] + vflux[var][IMJ]);
3681 }
3682 }
3683 }
3684
3685 // intermediate saving of velocity magnitude in the cell centers
3686 // TODO_SS labels:FV this intermediate could have done in the first for loop already
3687 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers + 1; ++j) {
3688 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers + 1; ++i) {
3689 const MInt IJ = cellIndex(i, j);
3690
3691 vflux[0][IJ] = sqrt(POW2(u_[IJ]) + POW2(v_[IJ]));
3692 vflux[1][IJ] = 1.0 / std::max(vflux[0][IJ], minMFloat);
3693 }
3694 }
3695
3696 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; ++j) {
3697 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; ++i) {
3698 const MInt IJ = cellIndex(i, j);
3699 const MInt IMJ = cellIndex(i - 1, j);
3700 const MInt IJM = cellIndex(i, j - 1);
3701 const MInt IPJ = cellIndex(i + 1, j);
3702 const MInt IJP = cellIndex(i, j + 1);
3703
3704 const MFloat velAbs = vflux[0][IJ]; // sqrt(POW2(u_[IJ]) + POW2(v_[IJ]));
3705 const MFloat rDa = 1.0 / Da[IJ];
3706 const MFloat porPOW2 = POW2(por[IJ]);
3707
3708 const MFloat invCellJac = 1.0 / m_cells->cellJac[IJ];
3709
3710 // Average Reynolds stresses in the surface centers into cell center
3711 const MFloat tau1 = 0.25 * (eflux[0][IJ] + eflux[0][IMJ] + fflux[0][IJ] + fflux[0][IJM]);
3712 const MFloat tau2 = 0.25 * (eflux[1][IJ] + eflux[1][IMJ] + fflux[1][IJ] + fflux[1][IJM]);
3713 const MFloat tau4 = 0.25 * (eflux[2][IJ] + eflux[2][IMJ] + fflux[2][IJ] + fflux[2][IJM]);
3714
3715 const MFloat dtau1dxi = eflux[0][IJ] - eflux[0][IMJ];
3716 const MFloat dtau2dxi = eflux[1][IJ] - eflux[1][IMJ];
3717 const MFloat dtau4dxi = eflux[2][IJ] - eflux[2][IMJ];
3718 const MFloat dtau1det = fflux[0][IJ] - fflux[0][IJM];
3719 const MFloat dtau2det = fflux[1][IJ] - fflux[1][IJM];
3720 const MFloat dtau4det = fflux[2][IJ] - fflux[2][IJM];
3721
3722 const MFloat dtau1dx =
3723 (dtau1dxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ] + dtau1det * m_cells->cellMetrics[ysd * 2 + xsd][IJ])
3724 * invCellJac;
3725 const MFloat dtau1dy =
3726 (dtau1dxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ] + dtau1det * m_cells->cellMetrics[ysd * 2 + ysd][IJ])
3727 * invCellJac;
3728 const MFloat dtau2dx =
3729 (dtau2dxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ] + dtau2det * m_cells->cellMetrics[ysd * 2 + xsd][IJ])
3730 * invCellJac;
3731 const MFloat dtau2dy =
3732 (dtau2dxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ] + dtau2det * m_cells->cellMetrics[ysd * 2 + ysd][IJ])
3733 * invCellJac;
3734 const MFloat dtau4dx =
3735 (dtau4dxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ] + dtau4det * m_cells->cellMetrics[ysd * 2 + xsd][IJ])
3736 * invCellJac;
3737 const MFloat dtau4dy =
3738 (dtau4dxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ] + dtau4det * m_cells->cellMetrics[ysd * 2 + ysd][IJ])
3739 * invCellJac;
3740
3741 // central discretization
3742 const MFloat dTKEdxi = 0.5 * (TKE[IPJ] - TKE[IMJ]);
3743 const MFloat dTKEdet = 0.5 * (TKE[IJP] - TKE[IJM]);
3744 const MFloat depsdxi = 0.5 * (eps[IPJ] - eps[IMJ]);
3745 const MFloat depsdet = 0.5 * (eps[IJP] - eps[IJM]);
3746 const MFloat dTKEdx =
3747 (dTKEdxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ] + dTKEdet * m_cells->cellMetrics[ysd * 2 + xsd][IJ])
3748 * invCellJac;
3749 const MFloat dTKEdy =
3750 (dTKEdxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ] + dTKEdet * m_cells->cellMetrics[ysd * 2 + ysd][IJ])
3751 * invCellJac;
3752 const MFloat depsdx =
3753 (depsdxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ] + depsdet * m_cells->cellMetrics[ysd * 2 + xsd][IJ])
3754 * invCellJac;
3755 const MFloat depsdy =
3756 (depsdxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ] + depsdet * m_cells->cellMetrics[ysd * 2 + ysd][IJ])
3757 * invCellJac;
3758
3759 // central discretization
3760 const MFloat dvelAbsdxi = 0.5 * (vflux[0][IPJ] - vflux[0][IMJ]);
3761 const MFloat dvelAbsdet = 0.5 * (vflux[0][IJP] - vflux[0][IJM]);
3762 const MFloat dvelAbsdx = (dvelAbsdxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ]
3763 + dvelAbsdet * m_cells->cellMetrics[ysd * 2 + xsd][IJ])
3764 * invCellJac;
3765 const MFloat dvelAbsdy = (dvelAbsdxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ]
3766 + dvelAbsdet * m_cells->cellMetrics[ysd * 2 + ysd][IJ])
3767 * invCellJac;
3768
3769 // central discretization
3770 const MFloat dvel11dxi = 0.5 * (u_[IPJ] * u_[IPJ] * vflux[1][IPJ] - u_[IMJ] * u_[IMJ] * vflux[1][IMJ]);
3771 const MFloat dvel11det = 0.5 * (u_[IJP] * u_[IJP] * vflux[1][IJP] - u_[IJM] * u_[IJM] * vflux[1][IJM]);
3772 const MFloat dvel12dxi = 0.5 * (u_[IPJ] * v_[IPJ] * vflux[1][IPJ] - u_[IMJ] * v_[IMJ] * vflux[1][IMJ]);
3773 const MFloat dvel12det = 0.5 * (u_[IJP] * v_[IJP] * vflux[1][IJP] - u_[IJM] * v_[IJM] * vflux[1][IJM]);
3774 const MFloat dvel22dxi = 0.5 * (v_[IPJ] * v_[IPJ] * vflux[1][IPJ] - v_[IMJ] * v_[IMJ] * vflux[1][IMJ]);
3775 const MFloat dvel22det = 0.5 * (v_[IJP] * v_[IJP] * vflux[1][IJP] - v_[IJM] * v_[IJM] * vflux[1][IJM]);
3776 const MFloat dvel11dx =
3777 (dvel11dxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ] + dvel11det * m_cells->cellMetrics[ysd * 2 + xsd][IJ])
3778 * invCellJac;
3779 const MFloat dvel11dy =
3780 (dvel11dxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ] + dvel11det * m_cells->cellMetrics[ysd * 2 + ysd][IJ])
3781 * invCellJac;
3782 const MFloat dvel12dx =
3783 (dvel12dxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ] + dvel12det * m_cells->cellMetrics[ysd * 2 + xsd][IJ])
3784 * invCellJac;
3785 const MFloat dvel12dy =
3786 (dvel12dxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ] + dvel12det * m_cells->cellMetrics[ysd * 2 + ysd][IJ])
3787 * invCellJac;
3788 const MFloat dvel22dx =
3789 (dvel22dxi * m_cells->cellMetrics[xsd * 2 + xsd][IJ] + dvel22det * m_cells->cellMetrics[ysd * 2 + xsd][IJ])
3790 * invCellJac;
3791 const MFloat dvel22dy =
3792 (dvel22dxi * m_cells->cellMetrics[xsd * 2 + ysd][IJ] + dvel22det * m_cells->cellMetrics[ysd * 2 + ysd][IJ])
3793 * invCellJac;
3794
3795 const MFloat u = u_[IJ];
3796 const MFloat v = v_[IJ];
3797
3798 const MFloat temp = u * u * tau1 + 2.0 * u * v * tau2 + v * v * tau4;
3799 const MFloat kovereps = TKE[IJ] / std::max(eps[IJ], minMFloat);
3800 const MFloat velAbsInv = vflux[1][IJ];
3801 const MFloat tau111 = 3.0 * (tau1 * dtau1dx + tau2 * dtau1dy);
3802 const MFloat tau112 = 2.0 * (tau1 * dtau2dx + tau2 * dtau2dy) + tau2 * dtau1dx + tau4 * dtau1dy;
3803 const MFloat tau122 = tau1 * dtau4dx + tau2 * dtau4dy + 2 * (tau2 * dtau2dx + tau4 * dtau2dy);
3804 const MFloat tau222 = 3.0 * (tau2 * dtau4dx + tau4 * dtau4dy);
3805
3806 // c_Dp-term
3807 const MInt IMJM = cellIndex(i - 1, j - 1);
3808 /* MFloat limiterVisc = 1.0;
3809 if (m_limiterVisc) {
3810 //TODO_SS labels:FV limiter should preserve conservativity
3811 const MFloat mu_ref = m_cells->fq[FQ->LIMITERVISC][IJ];
3812 limiterVisc = std::min(1.0, mu_ref/std::abs( m_c_Dp*TKE[IJ]*kovereps ));
3813 }*/
3814 const MFloat diffusion_TKE =
3815 ((sa_1flux[0][IJM] - sa_1flux[0][IMJM]) + (sa_1flux[1][IMJ] - sa_1flux[1][IMJM])); // * limiterVisc;
3816 const MFloat diffusion_eps =
3817 ((sa_2flux[0][IJM] - sa_2flux[0][IMJM]) + (sa_2flux[1][IMJ] - sa_2flux[1][IMJM])); // * limiterVisc;
3818
3819 /* m_cells->fq[FQ->VAR5][IJ] = diffusion_TKE;
3820 m_cells->fq[FQ->VAR6][IJ] = (- 2.0*rRe0*rDa*por[IJ]*muLam[IJ]*TKE[IJ]
3821 - 0.5*sqrt(rDa)*porPOW2*cf[IJ]*rho[IJ]*(
3822 4.0*TKE[IJ]*velAbs
3823 + 2.0*velAbsInv*temp))*m_cells->cellJac[IJ];*/
3824
3825 // RHS
3826 m_cells->rightHandSide[CV->RHO_U][IJ] +=
3827 (-rRe0 * rDa * por[IJ] * muLam[IJ] * u
3828 - sqrt(rDa) * porPOW2 * cf[IJ] * rho[IJ]
3829 * ((velAbs + TKE[IJ] * velAbsInv - 0.5 * pow(velAbsInv, 3) * temp) * u
3830 + velAbsInv * (u * tau1 + v * tau2)))
3831 * m_cells->cellJac[IJ];
3832 m_cells->rightHandSide[CV->RHO_V][IJ] +=
3833 (-rRe0 * rDa * por[IJ] * muLam[IJ] * v
3834 - sqrt(rDa) * porPOW2 * cf[IJ] * rho[IJ]
3835 * ((velAbs + TKE[IJ] * velAbsInv - 0.5 * pow(velAbsInv, 3) * temp) * v
3836 + velAbsInv * (u * tau2 + v * tau4)))
3837 * m_cells->cellJac[IJ];
3838 m_cells->rightHandSide[CV->RANS_VAR[0]][IJ] +=
3839 diffusion_TKE
3840 + (-2.0 * rRe0 * rDa * por[IJ] * muLam[IJ] * TKE[IJ]
3841 - 0.5 * sqrt(rDa) * porPOW2 * cf[IJ] * rho[IJ]
3842 * (4.0 * TKE[IJ] * velAbs + 2.0 * velAbsInv * temp
3843 + 3.0 * velAbsInv * m_c_t * kovereps * (u * tau111 + u * tau122 + v * tau112 + v * tau222)
3844 - pow(velAbsInv, 3) * m_c_t * kovereps
3845 * (u * u * u * tau111 + 3.0 * u * u * v * tau112 + 3.0 * u * v * v * tau122
3846 + v * v * v * tau222)))
3847 * m_cells->cellJac[IJ];
3848 m_cells->rightHandSide[CV->RANS_VAR[1]][IJ] +=
3849 diffusion_eps
3850 + (-2.0 * rRe0 * rDa * por[IJ] * muLam[IJ] * eps[IJ]
3851 - sqrt(rDa) * porPOW2 * cf[IJ] * rho[IJ]
3852 * (F8B3 * velAbs * eps[IJ]
3853 + 2.0 * rRe0 * (muLam[IJ] / rho[IJ]) * (dvelAbsdx * dTKEdx + dvelAbsdy * dTKEdy)
3854 - 2.0 * m_c_eps * kovereps * velAbsInv
3855 * (u * tau1 * depsdx + v * tau2 * depsdx + u * tau2 * depsdy + v * tau4 * depsdy)
3856 + rRe0 * (muLam[IJ] / rho[IJ])
3857 * (dvel11dx * dtau1dx + dvel11dy * dtau1dy + 2.0 * dvel12dx * dtau2dx
3858 + 2.0 * dvel12dy * dtau2dy + dvel22dx * dtau4dx + dvel22dy * dtau4dy)))
3859 * m_cells->cellJac[IJ];
3860
3861 // m_cells->fq[FQ->VAR3][IJ] = rho[IJ]*diffusion_TKE;
3862 // m_cells->fq[FQ->VAR4][IJ] = - 2.0*rRe0*rDa*por[IJ]*muLam[IJ]*TKE[IJ]*m_cells->cellJac[IJ];
3863 // m_cells->fq[FQ->VAR5][IJ] = -
3864 // 0.5*sqrt(rDa)*porPOW2*cf[IJ]*rho[IJ]*(4.0*TKE[IJ]*velAbs)*m_cells->cellJac[IJ];
3865 // m_cells->fq[FQ->VAR6][IJ] = -
3866 // 0.5*sqrt(rDa)*porPOW2*cf[IJ]*rho[IJ]*(2.0*velAbsInv*temp)*m_cells->cellJac[IJ];
3867
3868 // const MFloat dx0 = m_cells->coordinates[1][IJ] - m_cells->coordinates[1][IJM];
3869 // const MFloat dx1 = m_cells->coordinates[1][IJP] - m_cells->coordinates[1][IJ];
3870 // const MFloat ddTKE = 2.0*(TKE[IJP]*dx0 - TKE[IJ]*(dx0+dx1) +
3871 // TKE[IJM]*dx1)/(POW2(dx0)*dx1+POW2(dx1)*dx0); m_cells->fq[FQ->VAR7][IJ] =
3872 // m_c_Dp*POW2(TKE[IJ])/eps[IJ]*rho[IJ]*ddTKE;///(2.0*rRe0*rDa*por[IJ]*muLam[IJ]*TKE[IJ]);
3873 /* std::ignore = (rho[IJ]*diffusion_TKE
3874 - 2.0*rRe0*rDa*por[IJ]*muLam[IJ]*TKE[IJ]
3875 - 0.5*sqrt(rDa)*porPOW2*cf[IJ]*rho[IJ]*(
3876 4.0*TKE[IJ]*velAbs
3877 + 2.0*velAbsInv*temp
3878 + 3.0*velAbsInv*m_c_t*kovereps*(u*tau111+u*tau122+v*tau112+v*tau222)
3879 -
3880 pow(velAbsInv,3)*m_c_t*kovereps*(u*u*u*tau111+3.0*u*u*v*tau112+3.0*u*v*v*tau122+v*v*v*tau222)))*m_cells->cellJac[IJ];
3881 std::ignore = (-2.0*rRe0*rDa*por[IJ]*muLam[IJ]*eps[IJ]
3882 - sqrt(rDa)*porPOW2*cf[IJ]*rho[IJ]*(
3883 F8B3*velAbs*eps[IJ]
3884 + 2.0*rRe0*(muLam[IJ]/rho[IJ])*(dvelAbsdx*dTKEdx+dvelAbsdy*dTKEdy)
3885 - 2.0*m_c_eps*kovereps*velAbsInv*(u*tau1*depsdx+v*tau2*depsdx+u*tau2*depsdy+v*tau4*depsdy)
3886 +
3887 rRe0*(muLam[IJ]/rho[IJ])*(dvel11dx*dtau1dx+dvel11dy*dtau1dy+2.0*dvel12dx*dtau2dx+2.0*dvel12dy*dtau2dy+dvel22dx*dtau4dx+dvel22dy*dtau4dy)))*m_cells->cellJac[IJ];*/
3888 }
3889 }
3890 } else { // LES
3891 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; ++j) {
3892 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; ++i) {
3893 const MInt IJK = cellIndex(i, j);
3894 MFloat velAbs = F0;
3895 for(MInt dim = 0; dim < nDim; ++dim) {
3896 velAbs += POW2(pvars[PV->VV[dim]][IJK]);
3897 }
3898 velAbs = sqrt(velAbs);
3899 const MFloat rDa = 1.0 / Da[IJK];
3900 const MFloat porPOW2 = POW2(por[IJK]);
3901 for(MInt dim = 0; dim < nDim; ++dim) {
3902 m_cells->rightHandSide[CV->RHO_VV[dim]][IJK] +=
3903 -(rRe0 * rDa * por[IJK] * muLam[IJK] + porPOW2 * sqrt(rDa) * cf[IJK] * velAbs * pvars[PV->RHO][IJK])
3904 * pvars[PV->VV[dim]][IJK] * m_cells->cellJac[IJK];
3905 }
3906 }
3907 }
3908 }
3909}
3910
3911
3913 static constexpr MFloat minMFloat =
3914 1e-16; // std::min(std::numeric_limits<MFloat>::min(), 1.0/std::numeric_limits<MFloat>::max());
3915 const MFloat rRe0 = 1.0 / m_Re0;
3916
3917 MFloat* RESTRICT u_ = &m_cells->pvariables[PV->U][0];
3918 MFloat* RESTRICT v_ = &m_cells->pvariables[PV->V][0];
3919 MFloat* RESTRICT p_ = &m_cells->pvariables[PV->P][0];
3920 MFloat* RESTRICT rho_ = &m_cells->pvariables[PV->RHO][0];
3921 const MFloat* const RESTRICT muLam_ = &m_cells->fq[FQ->MU_L][0];
3922 MFloat* RESTRICT muTurb_ = &m_cells->fq[FQ->MU_T][0];
3923 MFloat* const RESTRICT TKE_ = &m_cells->pvariables[PV->RANS_VAR[0]][0];
3924 MFloat* const RESTRICT EPS_ = &m_cells->pvariables[PV->RANS_VAR[1]][0];
3925 const MFloat* const RESTRICT por_ = &m_cells->fq[FQ->POROSITY][0];
3926 const MFloat* const RESTRICT Da = &m_cells->fq[FQ->DARCY][0];
3927 const MFloat* const RESTRICT cf = &m_cells->fq[FQ->FORCH][0];
3928
3929 // MFloat *const RESTRICT eflux= ALIGNED_MF(m_cells->eFlux);
3930 // MFloat *const RESTRICT fflux= ALIGNED_MF(m_cells->fFlux);
3931 MFloat* const* const RESTRICT vflux = ALIGNED_MF(m_cells->viscousFlux);
3932 MFloat* const* const RESTRICT sa_1flux = ALIGNED_F(m_cells->saFlux1);
3933 MFloat* const* const RESTRICT sa_2flux = ALIGNED_F(m_cells->saFlux2);
3934
3935 MInt start[nDim], end[nDim], nghbr[6];
3936 MInt len1[nDim];
3937
3938 for(MInt i = 0; i < m_hasSingularity; ++i) {
3939 // only correct for bc 6000 not for bc 4000-5000
3940 if(m_singularity[i].BC == -6000) {
3941 // totalCells=1;
3942 for(MInt j = 0; j < nDim; j++) {
3943 len1[j] = m_singularity[i].end[j] - m_singularity[i].start[j];
3944 // if(len1[j]!=0) totalCells*=len1[j];
3945 }
3946
3947 for(MInt n = 0; n < nDim; ++n) {
3948 if(m_singularity[i].end[n] - m_singularity[i].start[n] > 1) {
3949 mTerm(1, "In 2D not possible!");
3950 // dim=n;
3951 // start[n]=m_singularity[i].start[n]+1;
3952 start[n] = m_singularity[i].start[n] + 1;
3953 end[n] = m_singularity[i].end[n] - 1;
3954 } else {
3955 start[n] = m_singularity[i].start[n];
3956 end[n] = m_singularity[i].end[n];
3957 }
3958 }
3959
3960 MFloat u[6], v[6], p[6], rho[6], muTurb[6], muLam[6], TKE[6], EPS[6], POR[6];
3961 MFloat U, V, RHO, muTurb_corner, muLam_corner, TKEcorner, EPScorner, PORcorner, dudx, dudy, dvdx, dvdy, dTKEdx,
3962 dTKEdy, depsdx, depsdy, dpdx, dpdy;
3963 MFloat tau1, tau2, tau4;
3964 MFloat mueOverRe;
3965 for(MInt jj = start[1]; jj < end[1]; ++jj) {
3966 for(MInt ii = start[0]; ii < end[0]; ++ii) {
3967 MInt count = 0;
3968 // MInt temp[nDim]{};
3969 MInt IJ_ = cellIndex(ii + m_singularity[i].Viscous[0], jj + m_singularity[i].Viscous[1]);
3970
3971 // temp[dim]=1;
3972 const MInt IJ = cellIndex(ii, jj);
3973 nghbr[count++] = IJ;
3974 // nghbr[count++]=cellIndex(ii+temp[0],jj+temp[1],kk+temp[2]);
3975
3976 const MInt IPMJ_ = getCellIdFromCell(IJ, m_singularity[i].Viscous[0], 0);
3977 const MInt IJPM_ = getCellIdFromCell(IJ, 0, m_singularity[i].Viscous[1]);
3978
3979 const MFloat surfaceMetrics[nDim * nDim] = {
3980 m_cells->surfaceMetrics[0][IPMJ_], m_cells->surfaceMetrics[1][IPMJ_], m_cells->surfaceMetrics[2][IJPM_],
3981 m_cells->surfaceMetrics[3][IJPM_]};
3982
3983 for(MInt m = 0; m < m_singularity[i].Nstar - 1; ++m) {
3984 MInt* change = m_singularity[i].displacement[m];
3985 nghbr[count++] = cellIndex(ii + change[0], jj + change[1]);
3986 // nghbr[count++]=cellIndex(ii+temp[0]+change[0],jj+temp[1]+change[1],kk+temp[2]+change[2]);
3987 }
3988
3989 if(count != m_singularity[i].Nstar) {
3990 cout << "what the hell! it is wrong!!! count=" << count << " Nstar=" << m_singularity[i].Nstar << endl;
3991 }
3992
3993 for(MInt m = 0; m < m_singularity[i].Nstar; ++m) {
3994 u[m] = u_[nghbr[m]];
3995 v[m] = v_[nghbr[m]];
3996 muTurb[m] = muTurb_[nghbr[m]] / rho_[nghbr[m]]; // nuTurb
3997 muLam[m] = muLam_[nghbr[m]];
3998 TKE[m] = TKE_[nghbr[m]];
3999 EPS[m] = EPS_[nghbr[m]];
4000 p[m] = p_[nghbr[m]];
4001 rho[m] = rho_[nghbr[m]];
4002 POR[m] = por_[nghbr[m]];
4003 }
4004
4005 U = F0;
4006 V = F0;
4007 RHO = F0;
4008 muTurb_corner = F0;
4009 muLam_corner = F0;
4010 TKEcorner = F0, EPScorner = F0, PORcorner = F0;
4011 dudx = F0;
4012 dudy = F0;
4013 dvdx = F0;
4014 dvdy = F0;
4015 dTKEdx = F0;
4016 dTKEdy = F0;
4017 depsdx = F0;
4018 depsdy = F0;
4019 dpdx = F0;
4020 dpdy = F0;
4021
4022 MInt id2 = ii - start[0] + (jj - start[1]) * len1[0];
4023
4024 for(MInt n = 0; n < count; n++) {
4025 MInt ID = id2 * count + n;
4026 U += m_singularity[i].ReconstructionConstants[0][ID] * u[n];
4027 dudx += m_singularity[i].ReconstructionConstants[1][ID] * u[n];
4028 dudy += m_singularity[i].ReconstructionConstants[2][ID] * u[n];
4029
4030 V += m_singularity[i].ReconstructionConstants[0][ID] * v[n];
4031 dvdx += m_singularity[i].ReconstructionConstants[1][ID] * v[n];
4032 dvdy += m_singularity[i].ReconstructionConstants[2][ID] * v[n];
4033
4034 TKEcorner += m_singularity[i].ReconstructionConstants[0][ID] * TKE[n];
4035 dTKEdx += m_singularity[i].ReconstructionConstants[1][ID] * TKE[n];
4036 dTKEdy += m_singularity[i].ReconstructionConstants[2][ID] * TKE[n];
4037
4038 dpdx += m_singularity[i].ReconstructionConstants[1][ID] * p[n];
4039 dpdy += m_singularity[i].ReconstructionConstants[2][ID] * p[n];
4040
4041 RHO += m_singularity[i].ReconstructionConstants[0][ID] * rho[n];
4042
4043 EPScorner += m_singularity[i].ReconstructionConstants[0][ID] * EPS[n];
4044 depsdx += m_singularity[i].ReconstructionConstants[1][ID] * EPS[n];
4045 depsdy += m_singularity[i].ReconstructionConstants[2][ID] * EPS[n];
4046
4047 muTurb_corner += m_singularity[i].ReconstructionConstants[0][ID] * muTurb[n];
4048 muLam_corner += m_singularity[i].ReconstructionConstants[0][ID] * muLam[n];
4049 PORcorner += m_singularity[i].ReconstructionConstants[0][ID] * POR[n];
4050 }
4051
4052 // cout << globalTimeStep << "(" << m_RKStep << ") dom=" << domainId() << " x|y=" <<
4053 // m_cells->coordinates[0][IJK] << "|" << m_cells->coordinates[1][IJK] << " U=" << U << " V=" << V
4054 // << " t=" << t << " cornerMetrics=" << cornerMetrics[0] << "|" << cornerMetrics[1] << "|" <<
4055 // cornerMetrics[2] << "|" << cornerMetrics[3] << endl;
4056
4057
4058 tau1 = 2 * dudx - 2 / 3 * (dudx + dvdy);
4059 tau2 = dudy + dvdx;
4060 tau4 = 2 * dvdy - 2 / 3 * (dudx + dvdy);
4061
4062 TKEcorner *= -2 / 3;
4063 mueOverRe = muTurb_corner * rRe0;
4064 tau1 = mueOverRe * tau1 + TKEcorner;
4065 tau2 *= mueOverRe;
4066 tau4 = mueOverRe * tau4 + TKEcorner;
4067
4068 vflux[0][IJ_] = -tau1;
4069 vflux[1][IJ_] = -tau2;
4070 vflux[2][IJ_] = -tau4;
4071
4072
4073 const MFloat temp = POW2(TKEcorner) / std::max(EPScorner, minMFloat);
4074 const MFloat velAbs = sqrt(POW2(U) + POW2(V));
4075 // TODO_SS labels:FV,toenhance For now I take the Da and cf of the current cell and not at the corner;
4076 // To do it correctly we need to exchange Da and cf similar to porosity
4077 const MFloat rDaAvg = 1.0 / Da[IJ];
4078 const MFloat cfAvg = cf[IJ];
4079 const MFloat indicator = (dpdx * U + dpdy * V)
4080 / std::max(POW2(velAbs)
4081 * (rRe0 * PORcorner * muLam_corner * rDaAvg
4082 + RHO * POW2(PORcorner) * cfAvg * sqrt(rDaAvg) * velAbs),
4083 minMFloat);
4084 const MFloat c_Dp_eff = m_c_Dp * (-0.5 * tanh(indicator - 5.0) + 0.5);
4085 const MFloat c_Dp_eps_eff = m_c_Dp_eps * (-0.5 * tanh(indicator - 5.0) + 0.5);
4086 m_cells->fq[FQ->POROUS_INDICATOR][IJ_] =
4087 (-0.5 * tanh(indicator - 5.0) + 0.5); // it's not exactly the cell center indicator
4088
4089 // TODO_SS labels:FV f_mu & limiterVisc !!!!!!!!
4090 const MFloat sax1 = c_Dp_eff * RM_KEPS::rsigma_k * temp
4091 * (dTKEdx * surfaceMetrics[xsd * 2 + xsd] + dTKEdy * surfaceMetrics[xsd * 2 + ysd]);
4092 const MFloat say1 = c_Dp_eff * RM_KEPS::rsigma_k * temp
4093 * (dTKEdx * surfaceMetrics[ysd * 2 + xsd] + dTKEdy * surfaceMetrics[ysd * 2 + ysd]);
4094 const MFloat sax2 = c_Dp_eps_eff * RM_KEPS::rsigma_eps * temp
4095 * (depsdx * surfaceMetrics[xsd * 2 + xsd] + depsdy * surfaceMetrics[xsd * 2 + ysd]);
4096 const MFloat say2 = c_Dp_eps_eff * RM_KEPS::rsigma_eps * temp
4097 * (depsdx * surfaceMetrics[ysd * 2 + xsd] + depsdy * surfaceMetrics[ysd * 2 + ysd]);
4098
4099 // TODO_SS labels:FV for now I assume that whenever rans-porous, then sa_1flux array is allocated
4100 sa_1flux[0][IJ_] = sax1;
4101 sa_1flux[1][IJ_] = say1;
4102 sa_2flux[0][IJ_] = sax2;
4103 sa_2flux[1][IJ_] = say2;
4104 }
4105 }
4106 }
4107 }
4108}
4109
4110
4113 if(domainId() == 0) {
4114 cout << "Loading BC2600 values..." << endl;
4115 }
4116
4117 ParallelIo::size_type bcCells[2] = {m_grid->getMyBlockNoCells(0), m_noGhostLayers};
4118 MInt noCellsBC = bcCells[0] * bcCells[1];
4119 ParallelIo::size_type bcOffset[2] = {0, 0};
4120 MFloatScratchSpace tmpRestartVars(noCellsBC * CV->noVariables, AT_, "m_tmpRestartVars2600");
4121
4122 if(domainId() == 0) {
4123 stringstream restartFileName;
4124 MString restartFile = Context::getSolverProperty<MString>("restartVariablesFileName", m_solverId, AT_);
4125 restartFileName << outputDir() << restartFile;
4126
4127 ParallelIoHdf5 pio(restartFileName.str(), maia::parallel_io::PIO_READ, MPI_COMM_SELF);
4128 stringstream pathStr;
4129 pathStr << "/block" << m_blockId << "/bc2600" << endl;
4130 std::string path = pathStr.str();
4131
4132 for(MInt var = 0; var < CV->noVariables; var++) {
4133 cout << "Loading " << m_variableNames[var] << " offset: " << var * noCellsBC << endl;
4134 pio.readArray(&tmpRestartVars[var * noCellsBC], path, m_variableNames[var], nDim, bcOffset, bcCells);
4135 }
4136
4137 }
4138
4139 MPI_Bcast(&tmpRestartVars[0], noCellsBC * CV->noVariables, MPI_DOUBLE, 0, m_StructuredComm, AT_,
4140 "tmpRestartVars[0]");
4141
4142 if(domainId() == 0) {
4143 cout << "Loading BC2600 values... SUCCESSFUL!" << endl;
4144 }
4145
4146 if(m_bc2600) {
4147 MInt startGC[2] = {0, 0};
4148 MInt endGC[2] = {0, 0};
4149
4150 if(m_bc2600noOffsetCells[0] == 0) {
4151 startGC[0] = m_noGhostLayers;
4152 }
4153 if(m_bc2600noOffsetCells[0] + m_bc2600noActiveCells[0] == bcCells[0]) {
4154 endGC[0] = m_noGhostLayers;
4155 }
4156
4157 MInt startI = 0, endI = 0;
4158 if(m_bc2600Face == 0) {
4159 startI = 0;
4160 endI = m_noGhostLayers;
4161 } else if(m_bc2600Face == 1) {
4162 startI = m_nCells[2] - m_noGhostLayers - 1;
4163 endI = m_nCells[2];
4164 }
4165
4166 for(MInt i = startI; i < endI; i++) {
4167 for(MInt j = startGC[0]; j < m_bc2600noCells[0] - endGC[0]; j++) {
4168 MInt cellId = cellIndex(i, j);
4169 MInt globalI = i;
4170 MInt globalJ = m_bc2600noOffsetCells[0] - m_noGhostLayers + j;
4171 MInt cellIdBC = globalI + globalJ * bcCells[1];
4172
4173 // load values from restart field
4174 for(MInt var = 0; var < CV->noVariables; var++) {
4175 m_cells->variables[var][cellId] = tmpRestartVars[var * noCellsBC + cellIdBC];
4176 }
4177 }
4178 }
4179
4180
4181 // Fix diagonal cells at end of domain
4182 if(m_bc2600noOffsetCells[0] + m_bc2600noActiveCells[0] == m_grid->getMyBlockNoCells(0)) {
4183 for(MInt i = startI; i < endI; i++) {
4184 const MInt cellIdA2 = cellIndex(i, m_noGhostLayers + m_bc2600noActiveCells[0] - 2);
4185 const MInt cellIdA1 = cellIndex(i, m_noGhostLayers + m_bc2600noActiveCells[0] - 1);
4186 const MInt cellIdG1 = cellIndex(i, m_noGhostLayers + m_bc2600noActiveCells[0]);
4187 for(MInt var = 0; var < CV->noVariables; var++) {
4188 const MFloat distA1A2 = sqrt(POW2(m_cells->coordinates[0][cellIdA1] - m_cells->coordinates[0][cellIdA2])
4189 + POW2(m_cells->coordinates[2][cellIdA1] - m_cells->coordinates[1][cellIdA2]));
4190 const MFloat slope = (m_cells->variables[var][cellIdA1] - m_cells->variables[var][cellIdA2]) / distA1A2;
4191 const MFloat distG1A1 = sqrt(POW2(m_cells->coordinates[0][cellIdG1] - m_cells->coordinates[0][cellIdA1])
4192 + POW2(m_cells->coordinates[2][cellIdG1] - m_cells->coordinates[1][cellIdA1]));
4193 m_cells->variables[var][cellIdG1] = m_cells->variables[var][cellIdA1] + distG1A1 * slope;
4194 }
4195 }
4196 }
4197 }
4198 }
4199}
4200
4201template <MFloat (FvStructuredSolver<2>::*pressure_func)(MInt) const>
4203 const MFloat gammaMinusOne = m_gamma - 1.0;
4204
4205 MFloat** const RESTRICT cvars = m_cells->variables;
4206 MFloat** const RESTRICT pvars = m_cells->pvariables;
4207
4208 for(MInt j = m_noGhostLayers; j < m_nCells[0] - m_noGhostLayers; ++j) {
4209 for(MInt i = m_noGhostLayers; i < m_nCells[1] - m_noGhostLayers; ++i) {
4210 const MInt cellId = cellIndex(i, j);
4211 const MFloat fRho = F1 / cvars[CV->RHO][cellId];
4212 MFloat velPOW2 = F0;
4213 for(MInt vel = 0; vel < nDim; ++vel) { // compute velocity
4214 pvars[vel][cellId] = cvars[vel][cellId] * fRho;
4215 velPOW2 += POW2(pvars[vel][cellId]);
4216 }
4217
4218 // density and pressure:
4219 pvars[PV->RHO][cellId] = cvars[CV->RHO][cellId]; // density
4220 pvars[PV->P][cellId] =
4221 gammaMinusOne
4222 * (cvars[CV->RHO_E][cellId] - F1B2 * pvars[PV->RHO][cellId] * velPOW2 + (this->*pressure_func)(cellId));
4223
4224 for(MInt ransVar = 0; ransVar < m_noRansEquations; ransVar++) {
4225 cvars[CV->RANS_VAR[ransVar]][cellId] =
4226 mMax(cvars[CV->RANS_VAR[ransVar]][cellId], 1e-16 /*F0*/); // TODO_SS labels:FV maybe activate this
4227 pvars[PV->RANS_VAR[ransVar]][cellId] = cvars[CV->RANS_VAR[ransVar]][cellId] * fRho;
4228 }
4229 }
4230 }
4231}
4232
4234 if(noRansEquations(m_ransMethod) == 2) {
4235 if(m_rans2eq_mode == "production")
4236 computePrimitiveVariables_<&FvStructuredSolver::pressure_twoEqRans>();
4237 else
4239 } else
4241}
4242
4243
4245 for(MInt i = 0; i < m_hasSingularity; ++i) {
4246 MInt len[nDim];
4249
4250 for(MInt j = 0; j < nDim; j++) {
4251 len[j] = m_singularity[i].end[j] - m_singularity[i].start[j];
4252 m_singularity[i].totalPoints *= (len[j] + 1);
4253 m_singularity[i].totalCells *= len[j];
4254 }
4255
4256 // 4 unknowns and Nstar cells
4257 mAlloc(m_singularity[i].ReconstructionConstants, nDim + 1, m_singularity[i].totalCells * m_singularity[i].Nstar,
4258 "ReconstructionConstants", 0.0, AT_);
4259 }
4260}
4261
4262
4263void FvStructuredSolver2D::gather(const MBool periodicExchange,
4264 std::vector<std::unique_ptr<StructuredComm<nDim>>>& sndComm) {
4265 for(auto& snd : sndComm) {
4266 if(isPeriodicComm(snd) && !periodicExchange) continue;
4267 if(periodicExchange && skipPeriodicDirection(snd)) continue;
4268
4269 MInt pos = 0;
4270 for(MInt var = 0; var < snd->noVars; var++) {
4271 for(MInt j = snd->startInfoCells[1]; j < snd->endInfoCells[1]; j++) {
4272 for(MInt i = snd->startInfoCells[0]; i < snd->endInfoCells[0]; i++) {
4273 const MInt cellId = i + j * m_nCells[1];
4274 snd->cellBuffer[pos] = snd->variables[var][cellId];
4275 pos++;
4276 }
4277 }
4278 }
4279 }
4280}
4281
4282
4283void FvStructuredSolver2D::scatter(const MBool periodicExchange,
4284 std::vector<std::unique_ptr<StructuredComm<nDim>>>& rcvComm) {
4285 // the ordering of the grid points can be different from
4286 // sending instance ==> reorder it and copy it to the
4287 // right place
4288
4289 for(auto& rcv : rcvComm) {
4290 if(isPeriodicComm(rcv) && !periodicExchange) continue;
4291 if(periodicExchange && skipPeriodicDirection(rcv)) continue;
4292
4293 MInt step2[2];
4294 MInt start1[2];
4295 MInt start2[2];
4296 MInt end2[2];
4297 MInt len2[2];
4298 MInt totalCells = 1;
4299 MInt len1[2];
4300
4301 for(MInt j = 0; j < nDim; j++) {
4302 len1[j] = rcv->endInfoCells[j] - rcv->startInfoCells[j];
4303 if(len1[j] != 0) totalCells *= len1[j];
4304 step2[rcv->orderInfo[j]] = rcv->stepInfo[j];
4305 }
4306
4307 for(MInt j = 0; j < nDim; j++) {
4308 start2[j] = 0;
4309 end2[j] = len1[j] - 1;
4310 len2[rcv->orderInfo[j]] = len1[j];
4311 if(step2[j] < 0) {
4312 MInt dummy = start2[j];
4313 start2[j] = end2[j];
4314 end2[j] = dummy;
4315 }
4316 }
4317
4318 MInt pos = 0;
4319 for(MInt var = 0; var < rcv->noVars; var++) {
4320 MInt j2 = start2[1];
4321 for(MInt j = rcv->startInfoCells[1]; j < rcv->endInfoCells[1]; j++) {
4322 MInt i2 = start2[0];
4323 for(MInt i = rcv->startInfoCells[0]; i < rcv->endInfoCells[0]; i++) {
4324 start1[rcv->orderInfo[0]] = i2;
4325 start1[rcv->orderInfo[1]] = j2;
4326
4327 const MInt id2 = var * totalCells + start1[0] + (start1[1]) * len2[0];
4328 const MInt cellId = i + j * m_nCells[1];
4329 rcv->variables[var][cellId] = rcv->cellBuffer[id2];
4330
4331 i2 += step2[0];
4332 pos++;
4333 }
4334 j2 += step2[1];
4335 }
4336 }
4337 }
4338}
4339
4340
4342 MInt nghbr[15 /*30*/]; //,dim = 0;
4343 MInt start[nDim], end[nDim];
4345 const MInt recDim = (m_orderOfReconstruction == 2) ? (IPOW2(nDim) + 1) : nDim + 1;
4346 MInt maxNoSingularityRecNghbrIds = 7; // 14;
4347 MFloatScratchSpace tmpA(maxNoSingularityRecNghbrIds, recDim, AT_, "tmpA");
4348 MFloatScratchSpace tmpC(recDim, maxNoSingularityRecNghbrIds, AT_, "tmpC");
4349 MFloatScratchSpace weights(maxNoSingularityRecNghbrIds, AT_, "weights");
4350 MFloat counter = F0;
4351 MFloat avg = F0;
4352 MFloat maxc = F0;
4353
4354 for(MInt i = 0; i < m_hasSingularity; ++i) {
4355 if(m_singularity[i].BC == -6000) {
4356 // MInt totalCells=1;
4357 MInt len1[nDim];
4358
4359 //(p)reset the reconstruction constants
4360 for(MInt n = 0; n < nDim + 1; ++n) {
4361 for(MInt m = 0; m < m_singularity[i].totalCells * m_singularity[i].Nstar; ++m) {
4362 m_singularity[i].ReconstructionConstants[n][m] = -999;
4363 }
4364 }
4365
4366 for(MInt j = 0; j < nDim; j++) {
4367 len1[j] = m_singularity[i].end[j] - m_singularity[i].start[j];
4368 // if(len1[j]!=0) totalCells*=len1[j];
4369 ASSERT(len1[j] == 1, "");
4370 }
4371
4372 for(MInt n = 0; n < nDim; ++n) {
4373 // if(m_singularity[i].end[n]-m_singularity[i].start[n]>1) {
4374 // dim=n;
4375 // start[n]=m_singularity[i].start[n]+1;
4376 // end[n]=m_singularity[i].end[n]-1;
4377 // } else {
4378 start[n] = m_singularity[i].start[n];
4379 end[n] = m_singularity[i].end[n];
4380 // }
4381 }
4382
4383 // for( MInt kk = start[2]; kk <end[2]; ++kk ) {
4384 for(MInt jj = start[1]; jj < end[1]; ++jj) {
4385 for(MInt ii = start[0]; ii < end[0]; ++ii) {
4386 MInt count = 0;
4387 // MInt temp[nDim]{};
4388 // temp[dim]=1;
4389
4390 nghbr[count++] = cellIndex(ii, jj);
4391 // nghbr[count++]=cellIndex(ii+temp[0],jj+temp[1],kk+temp[2]);
4392
4393 // the coordinates of the corner where the viscousflux should be corrected.
4394 MInt ijk = getPointIdFromCell(ii + m_singularity[i].Viscous[0], jj + m_singularity[i].Viscous[1]);
4395 ijk = getPointIdFromPoint(ijk, 1, 1);
4396
4397 for(MInt m = 0; m < m_singularity[i].Nstar - 1; ++m) {
4398 MInt* change = m_singularity[i].displacement[m];
4399 nghbr[count++] = cellIndex(ii + change[0], jj + change[1]);
4400 // nghbr[count++]=cellIndex(ii+temp[0]+change[0],jj+temp[1]+change[1],kk+temp[2]+change[2]);
4401 }
4402
4403 if(count != m_singularity[i].Nstar) {
4404 cerr << "Something wrong with the singularities in the LS coeffiecient computation" << endl;
4405 }
4406
4407 // weighted Least square
4408 weights.fill(F0);
4409
4410 // Compute weights with RBF (take mean distance as R0)
4411 for(MInt n = 0; n < count; n++) {
4412 MInt nghbrId = nghbr[n];
4413 MFloat dxdx = F0;
4414 for(MInt m = 0; m < nDim; ++m) {
4415 dxdx += POW2(m_cells->coordinates[m][nghbrId] - m_grid->m_coordinates[m][ijk]);
4416 }
4417
4418 weights[n] = 1 / dxdx; // RBF( dxdx, POW2( dist) );
4419 }
4420
4421 MInt id2 = ii - start[0] + (jj - start[1]) * len1[0];
4422 ASSERT(id2 == 0, "");
4423 MInt ID = id2 * m_singularity[i].Nstar;
4424
4425 MFloat condNum = computeRecConstSVD(ijk, count, nghbr, ID, i, tmpA, tmpC, weights, recDim);
4426 avg += condNum;
4427 maxc = mMax(maxc, condNum);
4428 counter += F1;
4429 if(condNum < F0 || condNum > 1e7 || std::isnan(condNum)) {
4430 cerr << domainId() << " SVD decomposition for pointId " << ijk
4431 << " with large condition number: " << condNum << " num of neighbor" << count << "x" << recDim << " "
4432 << " coords " << m_grid->m_coordinates[0][ijk] << ", " << m_grid->m_coordinates[1][ijk] << endl;
4433 }
4434 }
4435 }
4436 // }
4437 }
4438 }
4439}
4440
4441
4442#include <numeric>
4444 if(m_rans && m_ransMethod != RANS_KEPSILON) mTerm(1, "Porous RANS computation is only supported by k-epsilon model!");
4445 // if (!m_porous)
4446 // mTerm(1, "bc6002 requires the property porous to be set to true!");
4447
4448 // 0) Check if initBc6002 is called for the first time
4449 // for(MInt bcId_=0; bcId_ < bcId; ++bcId_) {
4450 // if (m_physicalBCMap[bcId_]->BC==6002) return;
4451 // }
4452
4453 // Determine normal vectors and save for later use
4454 for(MInt bcId_ = 0; bcId_ < (MInt)m_structuredBndryCnd->m_physicalBCMap.size(); ++bcId_) {
4455 if(m_structuredBndryCnd->m_physicalBCMap[bcId_]->BC == 6002
4456 && m_structuredBndryCnd->m_physicalBCMap[bcId_]->Nstar == -1) {
4457 MInt* start = m_structuredBndryCnd->m_physicalBCMap[bcId_]->start1;
4458 MInt* end = m_structuredBndryCnd->m_physicalBCMap[bcId_]->end1;
4459
4460 const MInt IJKP[nDim] = {1, m_nPoints[1]};
4461 const MInt IJ[nDim] = {1, m_nCells[1]};
4462
4463 const MInt pp[2][4] = {{0, 0, 0, 1}, {0, 0, 1, 0}};
4464
4465 const MInt face = m_structuredBndryCnd->m_physicalBCMap[bcId_]->face;
4466
4467 const MInt normalDir = face / 2;
4468 const MInt firstTangentialDir = (normalDir + 1) % nDim;
4469 const MInt normalDirStart = start[normalDir];
4470 const MInt firstTangentialStart = start[firstTangentialDir];
4471 const MInt firstTangentialEnd = end[firstTangentialDir];
4472 const MInt incp[nDim] = {IJKP[normalDir], IJKP[firstTangentialDir]};
4473 const MInt inc[nDim] = {IJ[normalDir], IJ[firstTangentialDir]};
4474
4475 const MInt n = (face % 2) * 2 - 1; //-1,+1
4476 const MInt g1p = normalDirStart + 2 * ((MInt)(0.5 - (0.5 * (MFloat)n))); //+2,0
4477 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
4478
4479 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
4480 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1];
4481
4482 // compute four surrounding points of surface centroid
4483 const MInt ij = g1p * incp[0] + t1 * incp[1];
4484 const MInt pp1 = getPointIdFromPoint(ij, pp[normalDir][0], pp[normalDir][1]);
4485 const MInt pp2 = getPointIdFromPoint(ij, pp[normalDir][2], pp[normalDir][3]);
4486 const MInt pp3 = getPointIdFromPoint(ij, n * (1 - normalDir), n * normalDir); // point lying outside domain
4487
4488 // compute the velocity of the surface centroid
4489 MFloat firstVec[nDim] = {F0, F0};
4490 MFloat normalVec[nDim] = {F0, F0};
4491 MFloat normalVec_[nDim]{};
4492 for(MInt dim = 0; dim < nDim; dim++) {
4493 firstVec[dim] = m_grid->m_coordinates[dim][pp2] - m_grid->m_coordinates[dim][pp1];
4494 normalVec_[dim] = m_grid->m_coordinates[dim][pp3] - m_grid->m_coordinates[dim][pp1];
4495 }
4496
4497 // compute normal vector of surface
4498 normalVec[0] = -firstVec[1];
4499 normalVec[1] = firstVec[0];
4500 const MFloat normalLength = sqrt(POW2(normalVec[0]) + POW2(normalVec[1]));
4501
4502 MFloat sgn = (std::inner_product(&normalVec[0], &normalVec[0] + nDim, &normalVec_[0], 0.0) < 0.0) ? -1 : 1;
4503 if(m_blockType == "fluid") sgn *= -1;
4504
4505 for(MInt dim = 0; dim < nDim; dim++) {
4506 normalVec[dim] /= normalLength;
4507 m_cells->fq[FQ->NORMAL[dim]][cellIdG1] = sgn * normalVec[dim];
4508 }
4509 }
4510 }
4511 }
4512
4513 // Determine normal vector at singularities
4514 for(MInt i = 0; i < m_hasSingularity; ++i) {
4515 const auto& singularity = m_singularity[i];
4516 // only correct for bc 6000 not for bc 4000-5000
4517 if(singularity.BC == -6000) {
4518 MBool takeIt = false;
4519 for(MInt n = 0; n < singularity.Nstar; ++n) {
4520 if(singularity.BCsingular[n] == -6002) takeIt = true;
4521 }
4522
4523 if(takeIt) {
4524 MInt start[nDim], end[nDim];
4525 for(MInt n = 0; n < nDim; ++n) {
4526 if(singularity.end[n] - singularity.start[n] > 1) {
4527 mTerm(1, "In 2D not possible!");
4528 // dim=n;
4529 // start[n]=singularity.start[n]+1;
4530 start[n] = singularity.start[n] + 1;
4531 end[n] = singularity.end[n] - 1;
4532 } else {
4533 start[n] = singularity.start[n];
4534 end[n] = singularity.end[n];
4535 }
4536 }
4537
4538 for(MInt jj = start[1]; jj < end[1]; ++jj) {
4539 for(MInt ii = start[0]; ii < end[0]; ++ii) {
4540 const MInt IJ = cellIndex(ii, jj);
4541 if(abs(m_cells->fq[FQ->NORMAL[0]][IJ]) > 1e-8) mTerm(1, "");
4542 for(MInt m = 0; m < 2; ++m) {
4543 const MInt* change = singularity.displacement[m];
4544 const MInt nghbr = cellIndex(ii + change[0], jj + change[1]);
4545 for(MInt d = 0; d < nDim; ++d)
4546 m_cells->fq[FQ->NORMAL[d]][IJ] += m_cells->fq[FQ->NORMAL[d]][nghbr];
4547 }
4548 }
4549 }
4550 }
4551 }
4552 }
4553
4554 // TODO_SS labels:FV,toenhance The exchange of all the normals is an overhead, because it is only needed at
4555 // singularity points
4559 // MInt sendSizeTotal = 0;
4560 std::vector<MInt> receiveSizes;
4561 for(auto& snd : m_sndComm) {
4562 // TODO_SS labels:FV right now exchange at all 6000er not only 6002 because of singularities
4563 if(snd->bcId == -6000 || snd->bcId == -6002) {
4564 // Gather
4565
4566 MInt size = 1;
4567 for(MInt dim = 0; dim < nDim; ++dim)
4568 size *= snd->endInfoCells[dim] - snd->startInfoCells[dim];
4569 // std::vector<MFloat> bufferSnd(size*(1+nDim));
4570 // sendSizeTotal += size;
4571
4572 MInt pos = 0;
4573 for(MInt j = snd->startInfoCells[1]; j < snd->endInfoCells[1]; j++) {
4574 for(MInt i = snd->startInfoCells[0]; i < snd->endInfoCells[0]; i++) {
4575 const MInt cellId = i + (j * m_nCells[1]);
4576 // TODO_SS labels:FV Latter only allocate FQ->POROSITY for m_blockType==porous
4577 // if (m_blockType=="fluid")
4578 // bufferSnd[pos++] = 1;
4579 // else
4580 snd->cellBuffer[pos] = m_cells->fq[FQ->POROSITY][cellId];
4581 for(MInt d = 0; d < nDim; ++d) {
4582 snd->cellBuffer[(1 + d) * size + pos] = m_cells->fq[FQ->NORMAL[d]][cellId];
4583 }
4584 ++pos;
4585 }
4586 }
4587
4588 // Send
4589 MInt tag = domainId() + (snd->tagHelper) * noDomains();
4590 MInt err = MPI_Isend((void*)&snd->cellBuffer[0], size * (nDim + 1), MPI_DOUBLE, snd->nghbrId, tag,
4591 m_StructuredComm, &snd->mpi_request, AT_, "(void*)&snd->cellBuffer[0]");
4592 if(err) cout << "rank " << domainId() << " sending throws error " << endl;
4593
4594
4595 // Determine size of receive buffer
4596 // TODO_SS labels:FV right now exchange at all 6000er not only 6002 because of singularities
4597 size = 1;
4598 for(MInt dim = 0; dim < nDim; ++dim)
4599 size *= snd->endInfoCells[dim] - snd->startInfoCells[dim];
4600 receiveSizes.push_back(size);
4601 }
4602 }
4603
4607 std::vector<MFloat> bufferRcv(std::accumulate(receiveSizes.begin(), receiveSizes.end(), 0) * (nDim + 1));
4608 MInt offset = 0;
4609 MInt cnt = 0;
4610 for(auto& rcv : m_rcvComm) {
4611 // TODO_SS labels:FV right now exchange at all 6000er not only 6002 because of singularities
4612 if(rcv->bcId == -6002 || rcv->bcId == -6000) {
4613 const MInt rcvSize = receiveSizes[cnt];
4614 MInt tag = rcv->nghbrId + (rcv->tagHelper) * noDomains();
4615 MInt err = MPI_Irecv(&bufferRcv[offset], rcvSize * (1 + nDim), MPI_DOUBLE, rcv->nghbrId, tag, m_StructuredComm,
4616 &rcv->mpi_request, AT_, "(void*)&rcvSize");
4617 if(err) cout << "rank " << domainId() << " sending throws error " << endl;
4618
4619 offset += rcvSize * (1 + nDim);
4620 ++cnt;
4621 }
4622 }
4623
4627 for(auto& snd : m_sndComm) {
4628 if(snd->bcId == -6002 || snd->bcId == -6000) {
4629 MPI_Wait(&(snd->mpi_request), &(snd->mpi_status), AT_);
4630 }
4631 }
4632
4633
4634 for(auto& rcv : m_rcvComm) {
4635 if(rcv->bcId == -6002 || rcv->bcId == -6000) {
4636 MPI_Wait(&(rcv->mpi_request), &(rcv->mpi_status), AT_);
4637 }
4638 }
4639
4643 // TODO_SS labels:FV,toremove
4644 ScratchSpace<MFloat> normals_temp(m_noCells * nDim, AT_, "normal_temp");
4645 offset = 0;
4646 cnt = 0;
4647 for(auto& rcv : m_rcvComm) {
4648 if(rcv->bcId == -6002 || rcv->bcId == -6000) {
4649 // TODO_SS labels:FV right now exchange at all 6000er not only 6002 because of singularities
4650
4651 MInt j2, i2, id2;
4652 MInt step2[nDim];
4653 MInt start1[nDim];
4654 MInt start2[nDim];
4655 MInt end2[nDim];
4656 MInt len2[nDim];
4657 MInt totalCells = 1;
4658 MInt len1[nDim];
4659
4660 for(MInt j = 0; j < nDim; j++) {
4661 len1[j] = rcv->endInfoCells[j] - rcv->startInfoCells[j];
4662 if(len1[j] != 0) totalCells *= len1[j];
4663 // added check the step for RCV part !!!!!!!!important
4664 step2[rcv->orderInfo[j]] = rcv->stepInfo[j];
4665 }
4666
4667 // Sanity check
4668 ASSERT(totalCells == receiveSizes[cnt], "");
4669
4670 for(MInt j = 0; j < nDim; j++) {
4671 start2[j] = 0;
4672 end2[j] = len1[j] - 1;
4673 len2[rcv->orderInfo[j]] = len1[j];
4674 if(step2[j] < 0) {
4675 MInt dummy = start2[j];
4676 start2[j] = end2[j];
4677 end2[j] = dummy;
4678 }
4679 }
4680
4681 MInt pos = 0;
4682 j2 = start2[1];
4683 for(MInt j = rcv->startInfoCells[1]; j < rcv->endInfoCells[1]; j++) {
4684 i2 = start2[0];
4685 for(MInt i = rcv->startInfoCells[0]; i < rcv->endInfoCells[0]; i++) {
4686 start1[rcv->orderInfo[0]] = i2;
4687 start1[rcv->orderInfo[1]] = j2;
4688
4689 id2 = start1[0] + start1[1] * len2[0];
4690 const MInt cellId = i + (j * m_nCells[1]);
4691 m_cells->fq[FQ->POROSITY][cellId] = bufferRcv[offset * (nDim + 1) + id2];
4692 for(MInt d = 0; d < nDim; ++d) {
4693 normals_temp[m_noCells * d + cellId] = bufferRcv[offset * (nDim + 1) + (d + 1) * totalCells + id2];
4694 // m_cells->fq[FQ->NORMAL[d]][cellId] = bufferRcv[offset*(nDim+1)+(d+1)*totalCells+id2];
4695 }
4696
4697 i2 += step2[0];
4698 pos++;
4699 }
4700 j2 += step2[1];
4701 }
4702
4703 offset += totalCells;
4704 ++cnt;
4705 }
4706 }
4707
4708 // Determine normal vector at singularities
4709 for(MInt i = 0; i < m_hasSingularity; ++i) {
4710 const auto& singularity = m_singularity[i];
4711 // only correct for bc 6000 not for bc 4000-5000
4712 if(singularity.BC == -6000) {
4713 MBool takeIt = false;
4714 for(MInt n = 0; n < singularity.Nstar; ++n) {
4715 if(singularity.BCsingular[n] == -6002) takeIt = true;
4716 }
4717
4718 if(takeIt) {
4719 MInt start[nDim], end[nDim];
4720 for(MInt n = 0; n < nDim; ++n) {
4721 if(singularity.end[n] - singularity.start[n] > 1) {
4722 mTerm(1, "In 2D not possible!");
4723 // dim=n;
4724 // start[n]=singularity.start[n]+1;
4725 start[n] = singularity.start[n] + 1;
4726 end[n] = singularity.end[n] - 1;
4727 } else {
4728 start[n] = singularity.start[n];
4729 end[n] = singularity.end[n];
4730 }
4731 }
4732
4733 const MInt nstar = singularity.Nstar;
4734
4735 for(MInt jj = start[1]; jj < end[1]; ++jj) {
4736 for(MInt ii = start[0]; ii < end[0]; ++ii) {
4737 const MInt IJ = cellIndex(ii, jj);
4738 MFloat temp[nDim];
4739 for(MInt d = 0; d < nDim; ++d) {
4740 temp[d] = m_cells->fq[FQ->NORMAL[d]][IJ];
4741 }
4742 for(MInt m = 0; m < nstar - 1; ++m) {
4743 const MInt* change = singularity.displacement[m];
4744 const MInt nghbr = cellIndex(ii + change[0], jj + change[1]);
4745 for(MInt d = 0; d < nDim; ++d)
4746 temp[d] += normals_temp[m_noCells * d + nghbr];
4747 }
4748
4749 MFloat l = 0;
4750 for(MInt d = 0; d < nDim; ++d) {
4751 m_cells->fq[FQ->NORMAL[d]][IJ] = temp[d] / (2 * nstar);
4752 l += POW2(m_cells->fq[FQ->NORMAL[d]][IJ]);
4753 }
4754 l = sqrt(l);
4755 for(MInt d = 0; d < nDim; ++d) {
4756 m_cells->fq[FQ->NORMAL[d]][IJ] /= l;
4757 }
4758
4759 for(MInt m = 0; m < nstar - 1; ++m) {
4760 const MInt* change = singularity.displacement[m];
4761 const MInt nghbr = cellIndex(ii + change[0], jj + change[1]);
4762 for(MInt d = 0; d < nDim; ++d)
4763 m_cells->fq[FQ->NORMAL[d]][nghbr] = m_cells->fq[FQ->NORMAL[d]][IJ];
4764 }
4765 }
4766 }
4767 }
4768 }
4769 }
4770
4772#if 0
4773 // 1) Gather
4774 std::vector<MFloat> sendBuffer;
4775 std::vector<MInt> sendcounts;
4776 std::vector<MInt> snghbrs;
4777 std::vector<MInt> tags;
4778 for(auto& snd: m_sndComm) {
4779 if (snd->bcId==-6002) {
4780 snghbrs.push_back(snd->nghbrId);
4781 tags.push_back(domainId()+(snd->tagHelper)*m_solver->noDomains());
4782
4783 MInt size = 1;
4784 for (MInt dim = 0; dim < nDim; ++dim)
4785 size *= snd->endInfoCells[dim] - snd->startInfoCells[dim];
4786 sendcounts.push_back(size);
4787
4788 sendBuffer.resize(pos+size);
4789 for(MInt j=snd->startInfoCells[1]; j<snd->endInfoCells[1]; j++) {
4790 for(MInt i=snd->startInfoCells[0]; i<snd->endInfoCells[0]; i++) {
4791 const MInt cellId = cellIndex(i,j);
4792 // TODO_SS labels:FV Latter only allocate FQ->POROSITY for m_blockType==porous
4793 // if (m_blockType=="fluid")
4794 // sendBuffer[pos++] = 1;
4795 // else
4796 sendBuffer[pos++] = m_cells->fq[FQ->POROSITY][cellId];
4797 }
4798 }
4799 }
4800 }
4801
4802 const MInt noNeighborDomains = snghbrs.size();
4803
4804 // 2) Send & receive
4805 std::vector<MInt> recvcounts(noNeighborDomains);
4806 std::vector<MInt> rdispls(noNeighborDomains);
4807 std::vector<MFloat> recvBuffer = maia::mpi::mpiExchangePointToPoint(&sendBuffer[0],
4808 &snghbrs[0],
4809 noNeighborDomains,
4810 &sendcounts[0],
4811 &snghbrs[0],
4812 noNeighborDomains,
4814 m_solver->domainId(),
4815 1,
4816 recvcounts.data(),
4817 rdispls.data());
4818 // 2.5) Send & receive the tags
4819 std::vector<MInt> sendcounts2(noNeighborDomains, 1);
4820 std::vector<MInt> recvTags = maia::mpi::mpiExchangePointToPoint(&tags[0],
4821 &snghbrs[0],
4822 noNeighborDomains,
4823 &sendcounts2[0],
4824 &snghbrs[0],
4825 noNeighborDomains,
4827 m_solver->domainId(),
4828 1);
4829
4830 // 3) Scatter
4831 for(auto& rcv: m_rcvComm) {
4832 if (rcv->bcId==-6002) {
4833 const MInt tag = rcv->nghbrId+rcv->tagHelper*m_solver->noDomains();
4834 MInt n;
4835 for (n = 0; n < noNeighborDomains; ++n) {
4836 if (tag==recvTags[n])
4837 break;
4838 }
4839 if (n==noNeighborDomains) mTerm(1, "n == noNeighborDomains");
4840
4841 const MFloat* const recvBuffer_ = &recvBuffer[rdispls[n]];
4842 const MInt noReceivedElements = recvcounts[n];
4843
4845 MInt j2, i2, id2;
4846 MInt step2[nDim];
4847 MInt start1[nDim];
4848 MInt start2[nDim];
4849 MInt end2[nDim];
4850 MInt len2[nDim];
4851 MInt totalCells=1;
4852 MInt len1[nDim];
4853
4854 for(MInt j=0; j<nDim; j++) {
4855 len1[j]=rcv->endInfoCells[j] - rcv->startInfoCells[j];
4856 if(len1[j]!=0) totalCells*=len1[j];
4857 //added check the step for RCV part !!!!!!!!important
4858 step2[rcv->orderInfo[j]]=rcv->stepInfo[j];
4859 }
4860
4861 //TODO_SS labels:FV check if this assert makes sense
4862 ASSERT(noReceivedElements==totalCells, "noReceivedElements==totalCells");
4863
4864 for(MInt j=0; j<nDim; j++) {
4865 start2[j]=0;
4866 end2[j]=len1[j]-1;
4867 len2[rcv->orderInfo[j]]=len1[j];
4868 if(step2[j]<0) {
4869 MInt dummy=start2[j];
4870 start2[j]=end2[j];
4871 end2[j]=dummy;
4872 }
4873 }
4874
4875 MInt* startInfo=rcv->startInfoCells;
4876 MInt* endInfo=rcv->endInfoCells;
4877
4878 MInt pos=0;
4879 j2=start2[1];
4880 for(MInt j=startInfo[1]; j<endInfo[1]; j++) {
4881 i2=start2[0];
4882 for(MInt i=startInfo[0]; i<endInfo[0]; i++) {
4883 start1[rcv->orderInfo[0]]=i2;
4884 start1[rcv->orderInfo[1]]=j2;
4885
4886 id2=start1[0]+start1[1]*len2[0];
4887 const MInt cellId = i +(j*m_nCells[1]);
4888 m_cells->fq[FQ->POROSITY][cellId]= recvBuffer_[id2];
4889
4890 i2+=step2[0];
4891 pos++;
4892 }
4893 j2+=step2[1];
4894 }
4895 }
4896 }
4897#endif
4899}
4900
4901
4903 const MFloat FK = 18.0;
4904 const MInt IJK[2] = {1, m_nCells[1]};
4905 const MInt IP1 = I + IJK[dim];
4906 const MInt IM1 = I - IJK[dim];
4907 const MInt IP2 = I + 2 * IJK[dim];
4908
4909 const MFloat PIM2 = m_cells->pvariables[PV->P][IM1];
4910 const MFloat PIM1 = m_cells->pvariables[PV->P][I];
4911 const MFloat PIP2 = m_cells->pvariables[PV->P][IP2];
4912 const MFloat PIP1 = m_cells->pvariables[PV->P][IP1];
4913
4914 const MFloat PSI =
4915 mMin(F1, FK
4916 * mMax(mMax(fabs((PIM2 - PIM1) / mMin(PIM2, PIM1)), fabs((PIM1 - PIP1) / mMin(PIM1, PIP1))),
4917 fabs((PIP1 - PIP2) / mMin(PIP1, PIP2))));
4918 return PSI;
4919}
MLong allocatedBytes()
Return the number of allocated bytes.
Definition: alloc.cpp:121
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
FvStructuredSolver2D(MInt, StructuredGrid< 2 > *, MBool *, const MPI_Comm comm)
Constructor for the 2D structured solver.
void AusmDV(MFloat *QLeft, MFloat *QRight, const MInt dim, const MInt cellId)
void AusmLES_PTHRC(MFloat *QLeft, MFloat *QRight, MInt dim, MInt cellId)
Same AUSM scheme as AusmLES with additional damping controlled by the 4th order pressure derivative....
void gather(const MBool, std::vector< std::unique_ptr< StructuredComm< 2 > > > &) override
void moveGrid(const MBool isRestart, const MBool zeroPos) override
MInt getPointIdFromPoint(MInt origin, MInt incI, MInt incJ)
MInt cellIndex(MInt i, MInt j)
void AusmLES(MFloat *QLeft, MFloat *QRight, const MInt dim, const MInt cellId)
AUSM Central.
virtual void initialCondition()
Computation of infinity values for the conservative and primitive variables Initialization ot the ent...
void scatter(const MBool, std::vector< std::unique_ptr< StructuredComm< 2 > > > &) override
MFloat pressure(MInt cellId)
StructuredBndryCnd< 2 > * m_structuredBndryCnd
virtual void initSolutionStep(MInt mode)
initalize the solution step
MInt pointIndex(MInt i, MInt j)
virtual void computePorousRHS(MBool) override
static constexpr const MInt nDim
FvStructuredSolver2DRans * m_ransSolver
MInt getPointIdFromCell(MInt i, MInt j)
MInt getCellIdFromCell(MInt origin, MInt incI, MInt incJ)
void computePrimitiveVariables() override
void(FvStructuredSolver2D::* viscFluxMethod)()
MFloat crossProduct(MFloat vec1[2], MFloat vec2[2])
friend class FvStructuredSolver2DRans
void Muscl(MInt timerId=-1) override
void(FvStructuredSolver2D::* reconstructSurfaceData)()
Base class of the structured solver.
virtual MFloat getBlasiusEta(MFloat coordX, MFloat coordY)
MBool isPeriodicComm(std::unique_ptr< StructuredComm< nDim > > &)
std::unique_ptr< StructuredFQVariables > FQ
void checkNans()
Checks whole domain for NaNs and adds the number of NaNs globally.
void saveSolverSolution(MBool=false, const MBool=false) override
void loadRestartFile()
Load Restart File (primitive and conservative output) general formulation.
MFloat computeRecConstSVD(const MInt ijk, const MInt noNghbrIds, MInt *nghbr, MInt ID, MInt sID, MFloatScratchSpace &tmpA, MFloatScratchSpace &tmpC, MFloatScratchSpace &weights, const MInt recDim)
AUX DATA ENDS /////////////////////////////////////////////////////////////.
MBool skipPeriodicDirection(std::unique_ptr< StructuredComm< nDim > > &)
MFloat dummy(MInt) const
std::array< MInt, Timers::_count > m_timers
std::vector< std::unique_ptr< StructuredComm< nDim > > > m_sndComm
StructuredGrid< nDim > * m_grid
virtual void computeConservativeVariables()
SingularInformation * m_singularity
void savePartitions()
Saves the partitioned grid into an HDF5 file. Not used in production use but useful for debugging.
virtual void getBlasiusVelocity(MInt cellId, MFloat *const vel)
Load variables for the specified timeStep.
std::unique_ptr< MPrimitiveVariables< nDim > > PV
std::unique_ptr< MConservativeVariables< nDim > > CV
void initializeFQField()
Counts the number of necessary FQ fields, allocates them and corrects the indexes of the FQ variable ...
void exchange()
SVD STUFF ENDS /////////////////////////////////////////////////////////////.
std::vector< std::unique_ptr< StructuredComm< nDim > > > m_rcvComm
void allocateAuxDataMaps()
AUX DATA //////////////////////////////////////////////////////////////////.
void readArray(T *array, const MString &name, size_type memoryStride=-1, size_type diskStride=-1)
Read array data from file. [MPI]
Definition: parallelio.h:1523
This class is a ScratchSpace.
Definition: scratch.h:758
void fill(T val)
fill the scratch with a given value
Definition: scratch.h:311
MString outputDir() const
Return the directory for output files.
Definition: solver.h:407
virtual MInt domainId() const
Return the domainId (rank)
Definition: solver.h:383
MInt m_residualInterval
The number of timesteps before writing the next residual.
Definition: solver.h:87
const MInt m_solverId
a unique solver identifier
Definition: solver.h:90
virtual MInt noDomains() const
Definition: solver.h:387
MBool restartFile()
Definition: solver.h:427
MFloat m_Re
the Reynolds number
Definition: solver.h:68
MFloat m_Ma
the Mach number
Definition: solver.h:71
Class for the 2D stuctured boundary conditions.
virtual void computeLocalExtendedDistancesAndSetComm()
virtual void computeFrictionCoef()
virtual void updateSpongeLayer()
virtual void distributeWallAndFPProperties()
std::vector< std::unique_ptr< StructuredWindowMap< nDim > > > & m_physicalBCMap
virtual void computeWallDistances()
virtual void correctBndryCndIndices()
MFloat ** cornerMetrics
MFloat ** variables
MFloat ** surfaceMetrics
MFloat ** rightHandSide
MFloat ** coordinates
MFloat * temperature
MFloat ** pvariables
MFloat * localTimeStep
MFloat ** surfaceMetricsSingularity
MFloat ** cellLength
MFloat ** viscousFlux
MFloat ** oldVariables
MFloat ** cellMetrics
Structured grid class.
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
Definition: enums.cpp:20
@ PARTITION_NORMAL
Definition: enums.h:343
@ PERIODIC_BC_SINGULAR
Definition: enums.h:343
@ PERIODIC_BC
Definition: enums.h:343
@ SINGULAR
Definition: enums.h:343
@ RANS_SA_DV
Definition: enums.h:54
@ RANS_KEPSILON
Definition: enums.h:58
@ ALBADA
Definition: enums.h:341
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
MBool approx(const T &, const U &, const T)
Definition: functions.h:272
constexpr T mMin(const T &x, const T &y)
Definition: functions.h:90
constexpr T mMax(const T &x, const T &y)
Definition: functions.h:94
MInt noRansEquations(RansMethod ransMethod)
MInt globalTimeStep
void printAllocatedMemory(const MLong oldAllocatedBytes, const MString &solverName, const MPI_Comm comm)
Prints currently allocated memory.
InfoOutFile m_log
constexpr MLong IPOW2(MInt x)
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
int64_t MLong
Definition: maiatypes.h:64
bool MBool
Definition: maiatypes.h:58
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_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait
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
std::vector< T > mpiExchangePointToPoint(const T *const sendBuffer, const MInt *const snghbrs, const MInt nosnghbrs, const MInt *const sendcounts, const MInt *const rnghbrs, const MInt nornghbrs, const MPI_Comm &mpi_comm, const MInt domainId, const MInt dataBlockSize, MInt *const recvcounts_=nullptr, MInt *const rdispls_=nullptr)
Definition: mpiexchange.h:1057
const MInt PIO_READ
Definition: parallelio.h:40
MFloat ** ReconstructionConstants
MInt displacement[5][3]
define array structures