MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
fvstructuredbndrycnd3d.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7
8#include <cmath>
9#include <fstream>
10#include <iostream>
11
12#include "COMM/mpiexchange.h"
13#include "COMM/mpioverride.h"
14#include "INCLUDE/maiatypes.h"
15#include "IO/parallelio_hdf5.h"
16#include "UTIL/kdtree.h"
17#include "UTIL/pointbox.h"
19#include "fvstructuredsolver.h"
21
22using namespace std;
23
24template <MBool isRans>
26template <MBool isRans>
28
34template <MBool isRans>
36 return rand() / MFloat(RAND_MAX);
37}
38
49template <MBool isRans>
51 return pow((rand() / MFloat(RAND_MAX)), m_solver->m_stgEddieDistribution);
52}
53
54
60template <MBool isRans>
62 : StructuredBndryCnd<3>(solver, grid) {
63 TRACE();
64
65 const MLong oldAllocatedBytes = allocatedBytes();
66
67 m_solver = static_cast<FvStructuredSolver3D*>(solver);
68
69 // allocate virtual box
71 mAlloc(m_stgVbStart, 3, "m_stgVbStart", 0.0, AT_);
72 mAlloc(m_stgVbEnd, 3, "m_stgVbEnd", 0.0, AT_);
73 }
74
75 // read rescaling bc properties
89 m_rescalingBLT = 5.95;
90 m_rescalingBLT = Context::getSolverProperty<MFloat>("rescalingBLT", m_solverId, AT_);
91 }
92
93 // compute sponge coefficients for each cell
95 RECORD_TIMER_START(m_solver->timer(Timers::BuildUpSponge));
97 RECORD_TIMER_STOP(m_solver->timer(Timers::BuildUpSponge));
98 }
99
100 printAllocatedMemory(oldAllocatedBytes, "StructuredBndryCnd3D", m_StructuredComm);
101}
102
103
104template <MBool isRans>
106 MInt noSpongeInfo = m_solver->m_windowInfo->m_spongeInfoMap.size(); // contains the size of the maps
107 MInt memSize = 0;
108
109 // 1)
110 // allocate the space for all the coordinates of the sponge in Scratch!
111 // memory will not be needed later ==> Scratch!
112
113 // 1.1) determine the storage size
114 // determine the size and to store the whole data
115 for(MInt i = 0; i < noSpongeInfo; ++i) {
116 MInt size = 1;
117 for(MInt dim = 0; dim < 3; ++dim) {
118 size *= (m_solver->m_windowInfo->m_spongeInfoMap[i]->end1[dim]
119 - m_solver->m_windowInfo->m_spongeInfoMap[i]->start1[dim] + 1);
120 }
121 memSize += size;
122 }
123
124 // 1.2) allocate the memory
125 MFloatScratchSpace coordMem(3 * memSize, AT_, "spongeCoordinates");
126 MFloatPointerScratchSpace spongeCoords(noSpongeInfo, AT_, "spongeCoordPointer");
127
128 MInt totMemSize = 0;
129 for(MInt i = 0; i < noSpongeInfo; ++i) {
130 MInt size = 1;
131 for(MInt dim = 0; dim < 3; ++dim) {
132 size *= (m_solver->m_windowInfo->m_spongeInfoMap[i]->end1[dim]
133 - m_solver->m_windowInfo->m_spongeInfoMap[i]->start1[dim] + 1);
134 }
135 spongeCoords[i] = &coordMem[totMemSize];
136 totMemSize += 3 * size;
137 }
138
139
140 // 2)
141 // we do not need the corner points but the centre coordinates of the face
142 // we need to allocate the memory for the faces (==cell size) for the sponge face
143 // ->determine the size and allocate the memory (again only scratch)
144
145 // 2.1) calculate the number of cells to store.
146 MInt cellmemSize = 0;
147 // determine the size and to store the whole data
148 for(MInt i = 0; i < noSpongeInfo; ++i) {
149 MInt size = 1;
150 for(MInt dim = 0; dim < 3; ++dim) {
151 if(m_solver->m_windowInfo->m_spongeInfoMap[i]->end1[dim] - m_solver->m_windowInfo->m_spongeInfoMap[i]->start1[dim]
152 == 0)
153 continue;
154 size *= (m_solver->m_windowInfo->m_spongeInfoMap[i]->end1[dim]
155 - m_solver->m_windowInfo->m_spongeInfoMap[i]->start1[dim]);
156 }
157 cellmemSize += size;
158 }
159 // 2.2) allocate the space for all the coordinates in Scratch!
160 // memory will not be needed later!
161 MFloatScratchSpace coordCellMem(3 * cellmemSize, AT_, "spongeCellCoordinates");
162 MFloatPointerScratchSpace spongeSurfCoords(noSpongeInfo, AT_, "spongeCellCoordPointer");
163
164 MInt totCellMemSize = 0;
165 for(MInt i = 0; i < noSpongeInfo; ++i) {
166 MInt size = 1;
167 for(MInt dim = 0; dim < 3; ++dim) {
168 if(m_solver->m_windowInfo->m_spongeInfoMap[i]->end1[dim] - m_solver->m_windowInfo->m_spongeInfoMap[i]->start1[dim]
169 == 0)
170 continue;
171 size *= (m_solver->m_windowInfo->m_spongeInfoMap[i]->end1[dim]
172 - m_solver->m_windowInfo->m_spongeInfoMap[i]->start1[dim]);
173 }
174 spongeSurfCoords[i] = &coordCellMem[totCellMemSize];
175 totCellMemSize += 3 * size;
176 }
177
178 // 3) read in the coordinates of the grid points
179 // open file for reading the grid data
180 MString gridFileName = m_grid->m_gridInputFileName;
181
182 // unique identifier needed to associate grid and solution in case of restart
183 // const char* aUID= new char[18];
184
185 m_log << "Loading and broadcasting all sponge windows..." << endl;
186 // open file and read number of solvers and uid
187 ParallelIoHdf5 pio(gridFileName, maia::parallel_io::PIO_READ, m_StructuredComm);
188
189 // read the data in and distribute ist
190
191 // the split of reading and distributing is done on purpose!
192 // this is because we then know what the library is doing
193 // and not what the io_library such as hdf or netcdf should do
194 // but does not
195 // a good library should handle that directly! TEST IT
196 memSize = 1;
197 // read in the data if processor zero else read nothing!!!
198 if(m_solver->domainId() == 0) {
199 for(MInt i = 0; i < noSpongeInfo; ++i) {
200 ParallelIo::size_type offset[3] = {0, 0, 0};
201 ParallelIo::size_type size[3] = {0, 0, 0};
202 memSize = 1;
203 for(MInt dim = 2; dim >= 0; --dim) {
204 size[dim] = (m_solver->m_windowInfo->m_spongeInfoMap[i]->end1[2 - dim]
205 - m_solver->m_windowInfo->m_spongeInfoMap[i]->start1[2 - dim] + 1);
206 memSize *= size[dim];
207 offset[dim] = m_solver->m_windowInfo->m_spongeInfoMap[i]->start1[2 - dim];
208 }
209 // read in the data if processor zero else read nothing!!!
210 // determine the Solver name
211 MString bName = "block";
212 stringstream number;
213 number << m_solver->m_windowInfo->m_spongeInfoMap[i]->Id1;
214 bName += number.str();
215 pio.readArray(&spongeCoords[i][0], bName, "x", 3, offset, size);
216 pio.readArray(&spongeCoords[i][memSize], bName, "y", 3, offset, size);
217 pio.readArray(&spongeCoords[i][memSize * 2], bName, "z", 3, offset, size);
218 }
219 } else {
220 for(MInt i = 0; i < noSpongeInfo; ++i) {
221 ParallelIo::size_type offset[3] = {0, 0, 0};
222 ParallelIo::size_type size[3] = {0, 0, 0};
223 MString bName = "block";
224 stringstream number;
225 number << m_solver->m_windowInfo->m_spongeInfoMap[i]->Id1;
226 bName += number.str();
227 MFloat empty = 0;
228 pio.readArray(&empty, bName, "x", 3, offset, size);
229 pio.readArray(&empty, bName, "y", 3, offset, size);
230 pio.readArray(&empty, bName, "z", 3, offset, size);
231 }
232 }
233
234 // now broadcast the information to everyone!!!
235 MPI_Bcast(&spongeCoords[0][0], totMemSize, MPI_DOUBLE, 0, m_StructuredComm, AT_, "spongeCoords[0][0]");
236 m_log << "Loading and broadcasting all sponge windows... SUCCESSFUL!" << endl;
237 m_log << "Computing sponge surface center coordinates..." << endl;
238
239 // 4) computing the coordinates of surface center from corner points;
240
241 for(MInt ii = 0; ii < noSpongeInfo; ++ii) {
242 MInt label, size1, size2, count = 0;
243 for(label = 0; label < 3; label++) { // 3== dimensions
244 if(m_solver->m_windowInfo->m_spongeInfoMap[ii]->end1[label]
245 - m_solver->m_windowInfo->m_spongeInfoMap[ii]->start1[label]
246 == 0)
247 break;
248 }
249 switch(label) {
250 case 0: {
251 size1 = (m_solver->m_windowInfo->m_spongeInfoMap[ii]->end1[1]
252 - m_solver->m_windowInfo->m_spongeInfoMap[ii]->start1[1] + 1);
253 size2 = (m_solver->m_windowInfo->m_spongeInfoMap[ii]->end1[2]
254 - m_solver->m_windowInfo->m_spongeInfoMap[ii]->start1[2] + 1);
255 for(MInt j = 0; j < size2 - 1; j++) {
256 for(MInt i = 0; i < size1 - 1; i++) {
257 MInt IJ = i + j * size1;
258 MInt IPJ = i + (j + 1) * size1;
259 MInt IJP = i + 1 + j * size1;
260 MInt IPJP = i + 1 + (j + 1) * size1;
261 spongeSurfCoords[ii][count] =
262 0.25 * (spongeCoords[ii][IJ] + spongeCoords[ii][IPJ] + spongeCoords[ii][IJP] + spongeCoords[ii][IPJP]);
263 spongeSurfCoords[ii][count + (size1 - 1) * (size2 - 1)] =
264 0.25
265 * (spongeCoords[ii][IJ + size1 * size2] + spongeCoords[ii][IPJ + size1 * size2]
266 + spongeCoords[ii][IJP + size1 * size2] + spongeCoords[ii][IPJP + size1 * size2]);
267 spongeSurfCoords[ii][count + 2 * (size1 - 1) * (size2 - 1)] =
268 0.25
269 * (spongeCoords[ii][IJ + 2 * size1 * size2] + spongeCoords[ii][IPJ + 2 * size1 * size2]
270 + spongeCoords[ii][IJP + 2 * size1 * size2] + spongeCoords[ii][IPJP + 2 * size1 * size2]);
271 count++;
272 }
273 }
274 break;
275 }
276 case 1: {
277 size1 = (m_solver->m_windowInfo->m_spongeInfoMap[ii]->end1[0]
278 - m_solver->m_windowInfo->m_spongeInfoMap[ii]->start1[0] + 1);
279 size2 = (m_solver->m_windowInfo->m_spongeInfoMap[ii]->end1[2]
280 - m_solver->m_windowInfo->m_spongeInfoMap[ii]->start1[2] + 1);
281 for(MInt j = 0; j < size2 - 1; j++) {
282 for(MInt i = 0; i < size1 - 1; i++) {
283 MInt IJ = i + j * size1;
284 MInt IPJ = i + (j + 1) * size1;
285 MInt IJP = i + 1 + j * size1;
286 MInt IPJP = i + 1 + (j + 1) * size1;
287 spongeSurfCoords[ii][count] =
288 0.25 * (spongeCoords[ii][IJ] + spongeCoords[ii][IPJ] + spongeCoords[ii][IJP] + spongeCoords[ii][IPJP]);
289 spongeSurfCoords[ii][count + (size1 - 1) * (size2 - 1)] =
290 0.25
291 * (spongeCoords[ii][IJ + size1 * size2] + spongeCoords[ii][IPJ + size1 * size2]
292 + spongeCoords[ii][IJP + size1 * size2] + spongeCoords[ii][IPJP + size1 * size2]);
293 spongeSurfCoords[ii][count + 2 * (size1 - 1) * (size2 - 1)] =
294 0.25
295 * (spongeCoords[ii][IJ + 2 * size1 * size2] + spongeCoords[ii][IPJ + 2 * size1 * size2]
296 + spongeCoords[ii][IJP + 2 * size1 * size2] + spongeCoords[ii][IPJP + 2 * size1 * size2]);
297 count++;
298 }
299 }
300 break;
301 }
302 case 2: {
303 size1 = (m_solver->m_windowInfo->m_spongeInfoMap[ii]->end1[0]
304 - m_solver->m_windowInfo->m_spongeInfoMap[ii]->start1[0] + 1);
305 size2 = (m_solver->m_windowInfo->m_spongeInfoMap[ii]->end1[1]
306 - m_solver->m_windowInfo->m_spongeInfoMap[ii]->start1[1] + 1);
307 for(MInt j = 0; j < size2 - 1; j++) {
308 for(MInt i = 0; i < size1 - 1; i++) {
309 MInt IJ = i + j * size1;
310 MInt IPJ = i + (j + 1) * size1;
311 MInt IJP = i + 1 + j * size1;
312 MInt IPJP = i + 1 + (j + 1) * size1;
313 spongeSurfCoords[ii][count] =
314 0.25 * (spongeCoords[ii][IJ] + spongeCoords[ii][IPJ] + spongeCoords[ii][IJP] + spongeCoords[ii][IPJP]);
315 spongeSurfCoords[ii][count + (size1 - 1) * (size2 - 1)] =
316 0.25
317 * (spongeCoords[ii][IJ + size1 * size2] + spongeCoords[ii][IPJ + size1 * size2]
318 + spongeCoords[ii][IJP + size1 * size2] + spongeCoords[ii][IPJP + size1 * size2]);
319 spongeSurfCoords[ii][count + 2 * (size1 - 1) * (size2 - 1)] =
320 0.25
321 * (spongeCoords[ii][IJ + 2 * size1 * size2] + spongeCoords[ii][IPJ + 2 * size1 * size2]
322 + spongeCoords[ii][IJP + 2 * size1 * size2] + spongeCoords[ii][IPJP + 2 * size1 * size2]);
323 count++;
324 }
325 }
326 break;
327 }
328 default:
329 mTerm(1, AT_, "sponge direction is messed up");
330 }
331 }
332
333 m_log << "Computing sponge surface center coordinates... SUCCESSFUL!" << endl;
334 m_log << "Determining shortest distance and sponge factor for each cell..." << endl;
335
336 // cout << "seraching for the nearest points(building sigma sponge)" << endl;
337 // build a k-d-tree for a quick search:
338 // 1) rearrange the coordinates into points;
339 const MInt spongeTotalWorkload = noSpongeInfo * m_noCells;
340 const MInt spongeWorkloadPercentage = (MInt)(spongeTotalWorkload / 10);
341
342 for(MInt i = 0; i < noSpongeInfo; ++i) {
343 MInt noPoints = 1;
344 for(MInt dim = 0; dim < 3; ++dim) {
345 if(m_solver->m_windowInfo->m_spongeInfoMap[i]->end1[dim] - m_solver->m_windowInfo->m_spongeInfoMap[i]->start1[dim]
346 == 0)
347 continue;
348 noPoints *= (m_solver->m_windowInfo->m_spongeInfoMap[i]->end1[dim]
349 - m_solver->m_windowInfo->m_spongeInfoMap[i]->start1[dim]);
350 }
351 // build up the points (surface centres)
352 vector<Point<3>> pts;
353 for(MInt j = 0; j < noPoints; ++j) {
354 Point<3> a(spongeSurfCoords[i][j], spongeSurfCoords[i][j + noPoints], spongeSurfCoords[i][j + 2 * noPoints]);
355 pts.push_back(a);
356 }
357
358 // build up the tree
359 KDtree<3> tree(pts);
360 MFloat distance = -1.0;
361 // go through all the cells an determine the closest distance
362 MFloat spongeThickness = m_solver->m_windowInfo->m_spongeInfoMap[i]->spongeThickness;
363 for(MInt id = 0; id < m_noCells; ++id) {
364 if(m_solver->domainId() == 0) {
365 if((i * m_noCells + id) % spongeWorkloadPercentage == 0) {
366 MInt progress = ceil((MFloat)(i * m_noCells + id) / (MFloat)spongeTotalWorkload * 100.0);
367 cout << "Sponge computation - " << progress << " percent" << endl;
368 }
369 }
370 distance = -1.1111111111111111; // to check
371 Point<3> pt(m_cells->coordinates[0][id], m_cells->coordinates[1][id], m_cells->coordinates[2][id]);
372 (void)tree.nearest(pt, distance);
373 if(distance <= spongeThickness) {
374 MFloat spongeFactor =
375 m_solver->m_windowInfo->m_spongeInfoMap[i]->sigma
376 * pow((spongeThickness - distance) / spongeThickness, m_solver->m_windowInfo->m_spongeInfoMap[i]->beta);
377 m_cells->fq[FQ->SPONGE_FACTOR][id] = mMax(m_cells->fq[FQ->SPONGE_FACTOR][id], spongeFactor);
378 }
379 }
380 }
381
382 m_log << "Determining shortest distance and sponge factor for each cell... SUCCESSFUL!" << endl;
383}
384
385template <MBool isRans>
387 const MFloat gammaMinusOne = m_solver->m_gamma - 1.0;
388 switch(m_spongeLayerType) {
389 case 1: {
390 MFloat deltaRhoE = F0, deltaRho = F0;
391 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
392 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
393 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
394 // compute the forcing term
395 // for the pressure or engery and the velocity
396 MInt cellId = cellIndex(i, j, k);
397
398 const MFloat rhoE =
399 m_cells->pvariables[PV->P][cellId] / gammaMinusOne
400 + F1B2 * m_cells->pvariables[PV->RHO][cellId]
401 * (POW2(m_cells->pvariables[PV->U][cellId]) + POW2(m_cells->pvariables[PV->V][cellId])
402 + POW2(m_cells->pvariables[PV->W][cellId]));
403
404 deltaRhoE = rhoE - CV->rhoEInfinity;
405 deltaRho = m_cells->pvariables[PV->RHO][cellId] - (CV->rhoInfinity * m_targetDensityFactor);
406
407 m_cells->rightHandSide[CV->RHO_E][cellId] -=
408 m_cells->fq[FQ->SPONGE_FACTOR][cellId] * deltaRhoE
409 * m_cells->cellJac[cellId]; // deltaP * m_cells->cellJac[cellId];
410 m_cells->rightHandSide[CV->RHO][cellId] -=
411 m_cells->fq[FQ->SPONGE_FACTOR][cellId] * deltaRho * m_cells->cellJac[cellId];
412 }
413 }
414 }
415 break;
416 }
417 case 2: {
418 // damp to values in the FQ field (set at startup, from RANS etc.)
419 MFloat deltaRhoE = F0, deltaRho = F0;
420 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
421 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
422 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
423 MInt cellId = cellIndex(i, j, k);
424
425 const MFloat rhoE =
426 m_cells->pvariables[PV->P][cellId] / gammaMinusOne
427 + F1B2 * m_cells->pvariables[PV->RHO][cellId]
428 * (POW2(m_cells->pvariables[PV->U][cellId]) + POW2(m_cells->pvariables[PV->V][cellId])
429 + POW2(m_cells->pvariables[PV->W][cellId]));
430
431 deltaRhoE = rhoE - m_cells->fq[FQ->SPONGE_RHO_E][cellId];
432 deltaRho =
433 m_cells->pvariables[PV->RHO][cellId] - (m_cells->fq[FQ->SPONGE_RHO][cellId] * m_targetDensityFactor);
434
435 m_cells->rightHandSide[CV->RHO_E][cellId] -=
436 m_cells->fq[FQ->SPONGE_FACTOR][cellId] * deltaRhoE * m_cells->cellJac[cellId];
437 m_cells->rightHandSide[CV->RHO][cellId] -=
438 m_cells->fq[FQ->SPONGE_FACTOR][cellId] * deltaRho * m_cells->cellJac[cellId];
439 }
440 }
441 }
442 break;
443 }
444 case 3: {
445 // damp to rhoInfinity and pInfinity
446 const MFloat FgammaMinusOne = F1 / (m_solver->m_gamma - F1);
447 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
448 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
449 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
450 // compute the forcing term
451 // for the pressure or engery and the velocity
452 const MInt cellId = cellIndex(i, j, k);
453 const MFloat deltaP = (m_cells->pvariables[PV->P][cellId] - PV->PInfinity) * FgammaMinusOne;
454 const MFloat deltaRho = m_cells->pvariables[PV->RHO][cellId] - (CV->rhoInfinity * m_targetDensityFactor);
455
456 m_cells->rightHandSide[CV->RHO_E][cellId] -=
457 m_cells->fq[FQ->SPONGE_FACTOR][cellId] * deltaP * m_cells->cellJac[cellId];
458 m_cells->rightHandSide[CV->RHO][cellId] -=
459 m_cells->fq[FQ->SPONGE_FACTOR][cellId] * deltaRho * m_cells->cellJac[cellId];
460 }
461 }
462 }
463 break;
464 }
465 case 4: {
466 // damp to rho from FQ and pInfinity
467 const MFloat FgammaMinusOne = F1 / (m_solver->m_gamma - F1);
468 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
469 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
470 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
471 const MInt cellId = cellIndex(i, j, k);
472 const MFloat deltaP = (m_cells->pvariables[PV->P][cellId] - PV->PInfinity) * FgammaMinusOne;
473 const MFloat deltaRho =
474 m_cells->pvariables[PV->RHO][cellId] - (m_cells->fq[FQ->SPONGE_RHO][cellId] * m_targetDensityFactor);
475
476 m_cells->rightHandSide[CV->RHO_E][cellId] -=
477 m_cells->fq[FQ->SPONGE_FACTOR][cellId] * deltaP * m_cells->cellJac[cellId];
478 m_cells->rightHandSide[CV->RHO][cellId] -=
479 m_cells->fq[FQ->SPONGE_FACTOR][cellId] * deltaRho * m_cells->cellJac[cellId];
480 }
481 }
482 }
483 break;
484 }
485 case 5: {
486 // damp to p from FSC
487 const MFloat FgammaMinusOne = F1 / (m_solver->m_gamma - F1);
488 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
489 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
490 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
491 const MInt cellId = cellIndex(i, j, k);
492 const MFloat deltaP =
493 (m_cells->pvariables[PV->P][cellId] - m_solver->getFscPressure(cellId)) * FgammaMinusOne;
494 m_cells->rightHandSide[CV->RHO_E][cellId] -=
495 m_cells->fq[FQ->SPONGE_FACTOR][cellId] * deltaP * m_cells->cellJac[cellId];
496 }
497 }
498 }
499 break;
500 }
501 case 6: {
502 // damp to PInfinity
503 const MFloat FgammaMinusOne = F1 / (m_solver->m_gamma - F1);
504 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
505 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
506 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
507 const MInt cellId = cellIndex(i, j, k);
508 const MFloat deltaP = (m_cells->pvariables[PV->P][cellId] - PV->PInfinity) * FgammaMinusOne;
509 m_cells->rightHandSide[CV->RHO_E][cellId] -=
510 m_cells->fq[FQ->SPONGE_FACTOR][cellId] * deltaP * m_cells->cellJac[cellId];
511 }
512 }
513 }
514 break;
515 }
516 default:
517 mTerm(1, AT_, "Sponge type doesn't exist");
518 }
519}
520
521//>marian: new function to compute distance to nearest wall for each cell
522template <MBool isRans>
524 MInt noWallDistInfo = m_solver->m_windowInfo->m_wallDistInfoMap.size(); // contains the size of the maps
525 MInt memSize = 0;
526
527 // initialize array with high numbers
528 for(MInt id = 0; id < m_noCells; ++id) {
529 m_cells->fq[FQ->WALLDISTANCE][id] = 99999;
530 }
531
532 // 1)
533 // memory will not be needed later ==> Scratch!
534
535 // 1.1) determine the storage size
536 // determine the size and to store the whole data
537 for(MInt i = 0; i < noWallDistInfo; ++i) {
538 MInt size = 1;
539 for(MInt dim = 0; dim < 3; ++dim) {
540 size *= (m_solver->m_windowInfo->m_wallDistInfoMap[i]->end1[dim]
541 - m_solver->m_windowInfo->m_wallDistInfoMap[i]->start1[dim] + 1);
542 }
543 memSize += size;
544 }
545
546 // 1.2) allocate the memory
547 MFloatScratchSpace coordMem(3 * memSize, AT_, "wallCoordinates");
548 MFloatPointerScratchSpace wallDistCoords(noWallDistInfo, AT_, "wallCoordsPointer");
549
550 MInt totMemSize = 0;
551 for(MInt i = 0; i < noWallDistInfo; ++i) {
552 MInt size = 1;
553 for(MInt dim = 0; dim < 3; ++dim) {
554 size *= (m_solver->m_windowInfo->m_wallDistInfoMap[i]->end1[dim]
555 - m_solver->m_windowInfo->m_wallDistInfoMap[i]->start1[dim] + 1);
556 }
557 wallDistCoords[i] = &coordMem[totMemSize];
558 totMemSize += 3 * size;
559 }
560
561
562 // 2)
563 // we do not need the corner points but the centre coordinates of the face
564 // we need to allocate the memory for the faces (==cell size) for the sponge face
565 // ->determine the size and allocate the memory (again only scratch)
566
567 // 2.1) calculate the number of cells to store.
568 MInt cellmemSize = 0;
569 // determine the size and to store the whole data
570 for(MInt i = 0; i < noWallDistInfo; ++i) {
571 MInt size = 1;
572 for(MInt dim = 0; dim < 3; ++dim) {
573 if(m_solver->m_windowInfo->m_wallDistInfoMap[i]->end1[dim]
574 - m_solver->m_windowInfo->m_wallDistInfoMap[i]->start1[dim]
575 == 0)
576 continue;
577 size *= (m_solver->m_windowInfo->m_wallDistInfoMap[i]->end1[dim]
578 - m_solver->m_windowInfo->m_wallDistInfoMap[i]->start1[dim]);
579 }
580 cellmemSize += size;
581 }
582 // 2.2) allocate the space for all the coordinates in Scratch!
583 // memory will not be needed later!
584 MFloatScratchSpace coordCellMem(3 * cellmemSize, AT_, "wallDistCellCoordinates");
585 MFloatPointerScratchSpace wallDistSurfCoords(noWallDistInfo, AT_, "wallDistCellCoordPointer");
586
587 MInt totCellMemSize = 0;
588 for(MInt i = 0; i < noWallDistInfo; ++i) {
589 MInt size = 1;
590 for(MInt dim = 0; dim < 3; ++dim) {
591 if(m_solver->m_windowInfo->m_wallDistInfoMap[i]->end1[dim]
592 - m_solver->m_windowInfo->m_wallDistInfoMap[i]->start1[dim]
593 == 0)
594 continue;
595 size *= (m_solver->m_windowInfo->m_wallDistInfoMap[i]->end1[dim]
596 - m_solver->m_windowInfo->m_wallDistInfoMap[i]->start1[dim]);
597 }
598 wallDistSurfCoords[i] = &coordCellMem[totCellMemSize];
599 totCellMemSize += 3 * size;
600 }
601
602
603 // 3) read in the coordinates of the grid points
604 // open file for reading the grid data
605 MString gridFileName = m_grid->m_gridInputFileName;
606 // open file and read number of solvers and uid
607
608 // read the data in and distribute ist
609
610 // the split of reading and distributing is done on purpose!
611 // this is because we then know what the library is doing
612 // and not what the io_library such as hdf or netcdf should do
613 // but does not
614 // a good library should handle that directly! TEST IT
615 memSize = 1;
616 // read in the data if processor zero else read nothing!!!
617 if(m_solver->domainId() == 0) {
618 ParallelIoHdf5 pio(gridFileName, maia::parallel_io::PIO_READ, MPI_COMM_SELF);
619 for(MInt i = 0; i < noWallDistInfo; ++i) {
620 ParallelIo::size_type offset[3] = {0, 0, 0};
621 ParallelIo::size_type size[3] = {0, 0, 0};
622 memSize = 1;
623 for(MInt dim = 2; dim >= 0; --dim) {
624 size[dim] = (m_solver->m_windowInfo->m_wallDistInfoMap[i]->end1[2 - dim]
625 - m_solver->m_windowInfo->m_wallDistInfoMap[i]->start1[2 - dim] + 1);
626 memSize *= size[dim];
627 offset[dim] = m_solver->m_windowInfo->m_wallDistInfoMap[i]->start1[2 - dim];
628 }
629 // read in the data if processor zero else read nothing!!!
630 // determine the Solver name
631 MString bName = "block";
632 stringstream number;
633 number << m_solver->m_windowInfo->m_wallDistInfoMap[i]->Id1;
634 bName += number.str();
635 pio.readArray(&wallDistCoords[i][0], bName, "x", 3, offset, size);
636 pio.readArray(&wallDistCoords[i][memSize], bName, "y", 3, offset, size);
637 pio.readArray(&wallDistCoords[i][memSize * 2], bName, "z", 3, offset, size);
638 }
639 }
640
641 MPI_Bcast(&wallDistCoords[0][0], totMemSize, MPI_DOUBLE, 0, m_solver->m_StructuredComm, AT_, "wallDistCoords[0][0]");
642
643 if(!m_solver->m_rans) {
644 return;
645 }
646
647
648 // 4) computing the coordinates of surface center from corner points;
649 for(MInt ii = 0; ii < noWallDistInfo; ++ii) {
650 MInt label, size1, size2, count = 0;
651 for(label = 0; label < 3; label++) { // 3== dimensions
652 if(m_solver->m_windowInfo->m_wallDistInfoMap[ii]->end1[label]
653 - m_solver->m_windowInfo->m_wallDistInfoMap[ii]->start1[label]
654 == 0)
655 break;
656 }
657 switch(label) {
658 case 0: {
659 size1 = (m_solver->m_windowInfo->m_wallDistInfoMap[ii]->end1[1]
660 - m_solver->m_windowInfo->m_wallDistInfoMap[ii]->start1[1] + 1);
661 size2 = (m_solver->m_windowInfo->m_wallDistInfoMap[ii]->end1[2]
662 - m_solver->m_windowInfo->m_wallDistInfoMap[ii]->start1[2] + 1);
663 for(MInt j = 0; j < size2 - 1; j++) {
664 for(MInt i = 0; i < size1 - 1; i++) {
665 MInt IJ = i + j * size1;
666 MInt IPJ = i + (j + 1) * size1;
667 MInt IJP = i + 1 + j * size1;
668 MInt IPJP = i + 1 + (j + 1) * size1;
669 wallDistSurfCoords[ii][count] = 0.25
670 * (wallDistCoords[ii][IJ] + wallDistCoords[ii][IPJ]
671 + wallDistCoords[ii][IJP] + wallDistCoords[ii][IPJP]);
672 wallDistSurfCoords[ii][count + (size1 - 1) * (size2 - 1)] =
673 0.25
674 * (wallDistCoords[ii][IJ + size1 * size2] + wallDistCoords[ii][IPJ + size1 * size2]
675 + wallDistCoords[ii][IJP + size1 * size2] + wallDistCoords[ii][IPJP + size1 * size2]);
676 wallDistSurfCoords[ii][count + 2 * (size1 - 1) * (size2 - 1)] =
677 0.25
678 * (wallDistCoords[ii][IJ + 2 * size1 * size2] + wallDistCoords[ii][IPJ + 2 * size1 * size2]
679 + wallDistCoords[ii][IJP + 2 * size1 * size2] + wallDistCoords[ii][IPJP + 2 * size1 * size2]);
680 count++;
681 }
682 }
683 break;
684 }
685 case 1: {
686 size1 = (m_solver->m_windowInfo->m_wallDistInfoMap[ii]->end1[0]
687 - m_solver->m_windowInfo->m_wallDistInfoMap[ii]->start1[0] + 1);
688 size2 = (m_solver->m_windowInfo->m_wallDistInfoMap[ii]->end1[2]
689 - m_solver->m_windowInfo->m_wallDistInfoMap[ii]->start1[2] + 1);
690 for(MInt j = 0; j < size2 - 1; j++) {
691 for(MInt i = 0; i < size1 - 1; i++) {
692 MInt IJ = i + j * size1;
693 MInt IPJ = i + (j + 1) * size1;
694 MInt IJP = i + 1 + j * size1;
695 MInt IPJP = i + 1 + (j + 1) * size1;
696 wallDistSurfCoords[ii][count] = 0.25
697 * (wallDistCoords[ii][IJ] + wallDistCoords[ii][IPJ]
698 + wallDistCoords[ii][IJP] + wallDistCoords[ii][IPJP]);
699 wallDistSurfCoords[ii][count + (size1 - 1) * (size2 - 1)] =
700 0.25
701 * (wallDistCoords[ii][IJ + size1 * size2] + wallDistCoords[ii][IPJ + size1 * size2]
702 + wallDistCoords[ii][IJP + size1 * size2] + wallDistCoords[ii][IPJP + size1 * size2]);
703 wallDistSurfCoords[ii][count + 2 * (size1 - 1) * (size2 - 1)] =
704 0.25
705 * (wallDistCoords[ii][IJ + 2 * size1 * size2] + wallDistCoords[ii][IPJ + 2 * size1 * size2]
706 + wallDistCoords[ii][IJP + 2 * size1 * size2] + wallDistCoords[ii][IPJP + 2 * size1 * size2]);
707 count++;
708 }
709 }
710 break;
711 }
712 case 2: {
713 size1 = (m_solver->m_windowInfo->m_wallDistInfoMap[ii]->end1[0]
714 - m_solver->m_windowInfo->m_wallDistInfoMap[ii]->start1[0] + 1);
715 size2 = (m_solver->m_windowInfo->m_wallDistInfoMap[ii]->end1[1]
716 - m_solver->m_windowInfo->m_wallDistInfoMap[ii]->start1[1] + 1);
717 for(MInt j = 0; j < size2 - 1; j++) {
718 for(MInt i = 0; i < size1 - 1; i++) {
719 MInt IJ = i + j * size1;
720 MInt IPJ = i + (j + 1) * size1;
721 MInt IJP = i + 1 + j * size1;
722 MInt IPJP = i + 1 + (j + 1) * size1;
723 wallDistSurfCoords[ii][count] = 0.25
724 * (wallDistCoords[ii][IJ] + wallDistCoords[ii][IPJ]
725 + wallDistCoords[ii][IJP] + wallDistCoords[ii][IPJP]);
726 wallDistSurfCoords[ii][count + (size1 - 1) * (size2 - 1)] =
727 0.25
728 * (wallDistCoords[ii][IJ + size1 * size2] + wallDistCoords[ii][IPJ + size1 * size2]
729 + wallDistCoords[ii][IJP + size1 * size2] + wallDistCoords[ii][IPJP + size1 * size2]);
730 wallDistSurfCoords[ii][count + 2 * (size1 - 1) * (size2 - 1)] =
731 0.25
732 * (wallDistCoords[ii][IJ + 2 * size1 * size2] + wallDistCoords[ii][IPJ + 2 * size1 * size2]
733 + wallDistCoords[ii][IJP + 2 * size1 * size2] + wallDistCoords[ii][IPJP + 2 * size1 * size2]);
734 count++;
735 }
736 }
737 break;
738 }
739 default:
740 mTerm(1, AT_, "wall direction is messed up");
741 }
742 }
743
744 // now everyone can determine the shortest distance
745
746 m_log << "wall distance computation: searching for the nearest wall" << endl;
747 // cout << "seraching for the nearest" << endl;
748 // build a k-d-tree for a quick search:
749 // 1) rearragne the coordinates into points;
750 for(MInt i = 0; i < noWallDistInfo; ++i) {
751 MInt noPoints = 1;
752 for(MInt dim = 0; dim < 3; ++dim) {
753 if(m_solver->m_windowInfo->m_wallDistInfoMap[i]->end1[dim]
754 - m_solver->m_windowInfo->m_wallDistInfoMap[i]->start1[dim]
755 == 0)
756 continue;
757 noPoints *= (m_solver->m_windowInfo->m_wallDistInfoMap[i]->end1[dim]
758 - m_solver->m_windowInfo->m_wallDistInfoMap[i]->start1[dim]);
759 }
760 // build up the points (surface centres)
761 vector<Point<3>> pts;
762 for(MInt j = 0; j < noPoints; ++j) {
763 Point<3> a(wallDistSurfCoords[i][j], wallDistSurfCoords[i][j + noPoints],
764 wallDistSurfCoords[i][j + 2 * noPoints]);
765 pts.push_back(a);
766 }
767 // build up the tree
768 KDtree<3> tree(pts);
769 MFloat distance = -1.0;
770
771 // go through all the cells an determine the closest distance
772 for(MInt id = 0; id < m_noCells; ++id) {
773 distance = -1.1111111111111111; // to check
774 Point<3> pt(m_cells->coordinates[0][id], m_cells->coordinates[1][id], m_cells->coordinates[2][id]);
775 (void)tree.nearest(pt, distance);
776
777 // take minimum because another bc1000 might be further away than the current but would overwrite the actually
778 // closer distance
779 m_cells->fq[FQ->WALLDISTANCE][id] = mMin(m_cells->fq[FQ->WALLDISTANCE][id], distance);
780 }
781 }
782
783 // correct the wall distance for the effective solution
784 if(m_solver->m_bc2601IsActive) {
785 cout << "Correcting wall distance with gammEpsilon: " << m_solver->m_bc2601GammaEpsilon << endl;
786 for(MInt id = 0; id < m_noCells; ++id) {
787 m_cells->fq[FQ->WALLDISTANCE][id] += m_solver->m_bc2601GammaEpsilon;
788 }
789 }
790
791 m_log << "Wall Distance Computation SUCESSFUL: Saved minimum distance to next wall for all cells " << endl;
792}
793//<marian
794
795
796template <MBool isRans>
798
799template <MBool isRans>
801 return i + (j + k * m_nCells[1]) * m_nCells[2];
802}
803
804template <MBool isRans>
806 return i + (j + k * m_solver->m_stgBoxSize[1]) * m_solver->m_stgBoxSize[2];
807}
808
809// function to correct the index values in the map for the different boundary conditions
810template <MBool isRans>
812 // cout << "in correctBndryCndIndices " << endl;
813 // in correcting cell Information
814 for(MInt bcId = 0; bcId < m_noBndryCndIds; bcId++) {
815 (this->*initBndryCndHandler[bcId])(bcId);
816 }
817}
818
819template <MBool isRans>
821 MFloat dist1 = F0;
822 for(MInt dim = 0; dim < 3; dim++) {
823 dist1 += POW2(a[dim * m_noCells] - b[dim * m_noCells]);
824 }
825 return sqrt(dist1);
826}
827
828template <MBool isRans>
830 (void)bcId;
831}
832
833template <MBool isRans>
835 (void)bcId;
836
849 m_isothermalWallTemperature = F1;
850 if(Context::propertyExists("isothermalWallTemperature", m_solverId)) {
851 m_isothermalWallTemperature =
852 Context::getSolverProperty<MFloat>("isothermalWallTemperature", m_solverId, AT_, &m_isothermalWallTemperature);
853 }
854}
855
856template <MBool isRans>
857void StructuredBndryCnd3D<isRans>::initBc1004(MInt bcId) { // moving adiabatic wall
858 (void)bcId;
859}
860
861template <MBool isRans>
862void StructuredBndryCnd3D<isRans>::initBc1006(MInt bcId) { // moving adiabatic wall
863 (void)bcId;
864
865 m_isothermalWallTemperature = F1;
866 if(Context::propertyExists("isothermalWallTemperature", m_solverId)) {
867 m_isothermalWallTemperature =
868 Context::getSolverProperty<MFloat>("isothermalWallTemperature", m_solverId, AT_, &m_isothermalWallTemperature);
869 }
870}
871
872template <MBool isRans>
873void StructuredBndryCnd3D<isRans>::initBc1007(MInt bcId) { // oscillating non-moving wall
874 (void)bcId;
875
876 m_solver->m_waveBeginTransition = 0.0;
877 m_solver->m_waveEndTransition = 0.0;
878 m_solver->m_waveAmplitude = 0.0;
879 m_solver->m_waveAmplitudePlus = 0.0;
880 m_solver->m_waveTimePlus = 0.0;
881 m_solver->m_waveTime = 0.0;
882
883 // time needs to be constant for traveling wave
884 m_solver->m_constantTimeStep = true;
885 m_solver->m_waveAmplitudePlus =
886 Context::getSolverProperty<MFloat>("waveAmplitudePlus", m_solverId, AT_, &m_solver->m_waveAmplitudePlus);
887 m_solver->m_waveTimePlus =
888 Context::getSolverProperty<MFloat>("waveTimePlus", m_solverId, AT_, &m_solver->m_waveTimePlus);
889 m_solver->m_waveBeginTransition =
890 Context::getSolverProperty<MFloat>("waveBeginTransition", m_solverId, AT_, &m_solver->m_waveBeginTransition);
891 m_solver->m_waveEndTransition =
892 Context::getSolverProperty<MFloat>("waveEndTransition", m_solverId, AT_, &m_solver->m_waveEndTransition);
893
894 // compute Wave parameters
895 const MFloat cf = 0.024 * pow(m_solver->m_Re, -F1B4);
896 const MFloat uTau = sqrt(cf * F1B2) * PV->UInfinity;
897 const MFloat mu8 = SUTHERLANDLAW(PV->TInfinity);
898 m_solver->m_waveAmplitude = m_solver->m_waveAmplitudePlus * uTau;
899 m_solver->m_waveTime = m_solver->m_waveTimePlus * mu8 / (POW2(uTau) * m_solver->m_Re0);
900
901 cout << "Oscillation speed amplitude: " << m_solver->m_waveAmplitude << " time: " << m_solver->m_waveTime << endl;
902}
903
904
910template <MBool isRans>
912 // call simple in/outflow bc to initialize ghost-cells
913 // because bc2024 uses values in the ghost-cells
914 bc2003(bcId);
915}
916
923template <MBool isRans>
925 // bcId is not needed
926 (void)bcId;
927
940 m_sigma = Context::getSolverProperty<MFloat>("shockAngle", m_solverId, AT_);
941 m_sigma = (m_sigma / 180.0) * PI;
942}
943
944template <MBool isRans>
946 bc2003(bcId);
947}
948
949
950template <MBool isRans>
952 (void)bcId;
953 //###############
954 // compute surface of the plenum automatically
955 //###############
956
957 MInt Id = m_plenumSurfaceIndexMap[bcId]; // shift of counter form bcId-> to local counter
958 const MInt* startface = &m_solver->m_windowInfo->plenumInletSurfaceIndices[Id]->start1[0];
959 const MInt* endface = &m_solver->m_windowInfo->plenumInletSurfaceIndices[Id]->end1[0];
960 const MInt face = m_physicalBCMap[bcId]->face;
961
962 // Here we find out the normal direction of the boundary and the two tangential
963 // directions. This way we can make a general formulation of the boundary condition
964 const MInt normalDir = face / 2;
965 const MInt directionT1 = (normalDir + 1) % nDim; // T1 stands for first tangential dir.
966 const MInt directionT2 = (normalDir + 2) % nDim; // T2 stands for second tangential dir.
967
968 const MInt startN = startface[normalDir];
969 const MInt startT1 = startface[directionT1];
970 const MInt endT1 = endface[directionT1];
971 const MInt startT2 = startface[directionT2];
972 const MInt endT2 = endface[directionT2];
973
974 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
975 const MInt inc[nDim] = {IJK[normalDir], IJK[directionT1], IJK[directionT2]};
976
977
978 MFloat surface = F0;
979 m_plenumSurface = F0;
980 const MFloat ii = startN;
981 for(MInt t1 = startT1; t1 < endT1; t1++) {
982 for(MInt t2 = startT2; t2 < endT2; t2++) {
983 const MInt cellId = ii * inc[0] + t1 * inc[1] + t2 * inc[2];
984 surface += sqrt(POW2(m_cells->surfaceMetrics[normalDir * nDim + 0][cellId])
985 + POW2(m_cells->surfaceMetrics[normalDir * nDim + 1][cellId])
986 + POW2(m_cells->surfaceMetrics[normalDir * nDim + 2][cellId]));
987 }
988 }
989 // communicate surface and add up!!!!
990 cout << "local surface " << surface << endl;
991 MPI_Allreduce(&surface, &m_plenumSurface, 1, MPI_DOUBLE, MPI_SUM, m_solver->m_plenumComm, AT_, "surface",
992 "m_plenumSurface");
993
994 m_log << "######### Plenum boundary condition was activated ##########" << endl;
995 cout << "surface of plenum is: " << m_plenumSurface << endl;
996
997
998 mTerm(1, AT_, "After init of plenum surface BC ");
999}
1000
1001
1006template <MBool isRans>
1008 MInt* start = m_physicalBCMap[bcId]->start1;
1009 MInt* end = m_physicalBCMap[bcId]->end1;
1010
1011 for(MInt var = 0; var < PV->noVariables; var++) {
1012 for(MInt i = start[0]; i < end[0]; i++) {
1013 for(MInt j = start[1]; j < end[1]; j++) {
1014 for(MInt k = start[2]; k < end[2]; k++) {
1015 MInt cellId = cellIndex(i, j, k);
1016 MInt cellIdAdj = cellIndex(m_noGhostLayers, j, k);
1017 m_cells->pvariables[var][cellId] = m_cells->pvariables[var][cellIdAdj];
1018 }
1019 }
1020 }
1021 }
1022}
1023
1024
1033template <MBool isRans>
1035 MInt* start = m_physicalBCMap[bcId]->start1;
1036 MInt* end = m_physicalBCMap[bcId]->end1;
1037
1038 bc2003(bcId);
1039
1040 m_solver->m_bc2600 = true;
1041 const MInt maxNoVariables = m_solver->m_maxNoVariables;
1042
1043 switch(m_physicalBCMap[bcId]->face) {
1044 case 0:
1045 case 1: {
1046 if(m_solver->m_bc2600InitialStartup) {
1047 // First copy values from the field into the ghostcells
1048 for(MInt i = start[0]; i < end[0]; i++) {
1049 for(MInt j = start[1]; j < end[1]; j++) {
1050 for(MInt k = start[2]; k < end[2]; k++) {
1051 const MInt cellId = cellIndex(i, j, k);
1052 const MInt cellIdAdj = cellIndex(m_noGhostLayers, j, k);
1053
1054 for(MInt var = 0; var < maxNoVariables; var++) {
1055 m_cells->pvariables[var][cellId] = m_cells->pvariables[var][cellIdAdj];
1056 }
1057 }
1058 }
1059 }
1060
1061 // Fix diagonal cells at end of domain
1062 if(m_solver->m_bc2600noOffsetCells[2] == 0
1063 && m_solver->m_bc2600noOffsetCells[1] + m_solver->m_bc2600noActiveCells[1] == m_grid->getMyBlockNoCells(1)) {
1064 for(MInt i = 0; i < m_solver->m_bc2600noCells[2]; i++) {
1065 for(MInt k = 0; k < m_solver->m_bc2600noCells[0]; k++) {
1066 const MInt cellIdA2 = cellIndex(i, m_noGhostLayers + m_solver->m_bc2600noActiveCells[1] - 2, k);
1067 const MInt cellIdA1 = cellIndex(i, m_noGhostLayers + m_solver->m_bc2600noActiveCells[1] - 1, k);
1068 const MInt cellIdG1 = cellIndex(i, m_noGhostLayers + m_solver->m_bc2600noActiveCells[1], k);
1069 for(MInt var = 0; var < maxNoVariables; var++) {
1070 const MFloat distA1A2 =
1071 sqrt(POW2(m_cells->coordinates[0][cellIdA1] - m_cells->coordinates[0][cellIdA2])
1072 + POW2(m_cells->coordinates[1][cellIdA1] - m_cells->coordinates[1][cellIdA2])
1073 + POW2(m_cells->coordinates[2][cellIdA1] - m_cells->coordinates[2][cellIdA2]));
1074 const MFloat slope =
1075 (m_cells->pvariables[var][cellIdA1] - m_cells->pvariables[var][cellIdA2]) / distA1A2;
1076 const MFloat distG1A1 =
1077 sqrt(POW2(m_cells->coordinates[0][cellIdG1] - m_cells->coordinates[0][cellIdA1])
1078 + POW2(m_cells->coordinates[1][cellIdG1] - m_cells->coordinates[1][cellIdA1])
1079 + POW2(m_cells->coordinates[2][cellIdG1] - m_cells->coordinates[2][cellIdA1]));
1080 m_cells->pvariables[var][cellIdG1] = m_cells->pvariables[var][cellIdA1] + distG1A1 * slope;
1081 }
1082 }
1083 }
1084 }
1085 }
1086
1087
1088 // Then copy the values from the ghostcells into restart field
1089 for(MInt i = start[0]; i < end[0]; i++) {
1090 for(MInt j = start[1]; j < end[1]; j++) {
1091 for(MInt k = start[2]; k < end[2]; k++) {
1092 const MInt cellId = cellIndex(i, j, k);
1093 const MInt cellIdBc = i + (j + k * m_solver->m_bc2600noCells[1]) * m_solver->m_bc2600noCells[2];
1094 for(MInt var = 0; var < maxNoVariables; var++) {
1095 m_solver->m_bc2600Variables[var][cellIdBc] = m_cells->pvariables[var][cellId];
1096 }
1097 }
1098 }
1099 }
1100
1101 break;
1102 }
1103 default: {
1104 mTerm(1, AT_, "Face not implemented");
1105 break;
1106 }
1107 }
1108}
1109
1117template <MBool isRans>
1119 MInt* start = m_physicalBCMap[bcId]->start1;
1120 MInt* end = m_physicalBCMap[bcId]->end1;
1121
1122 m_solver->m_bc2601 = true;
1123
1124 m_2601wave = true;
1125
1126 if(m_2601wave) {
1127 const MFloat timeConversion = 11.59597694e6;
1128 const MFloat timeShift = 10.624277309487987 / 0.015795;
1129 // string fileName = "coefficients_actuated_surface.dat";
1130 MInt step = 0;
1131 m_2601noCoeff = 5; // number of effective coefficients
1132 m_2601noPos = 4; // number of streamwise positions
1133 const MString fileNames[4] = {"coefficients_actuated_surface_00138.dat",
1134 "coefficients_actuated_surface_0014452.dat",
1135 "coefficients_actuated_surface_00148.dat", "coefficients_actuated_surface_00153.dat"};
1136 ifstream infile1(fileNames[0].c_str());
1137 MInt noLines = count(std::istreambuf_iterator<char>(infile1), std::istreambuf_iterator<char>(), '\n');
1138
1139 cout << "NoLines: " << noLines << endl;
1140
1141 mAlloc(m_2601streamwisePos, m_2601noPos, AT_, F0, "m_2601streamwisePos");
1142 m_2601streamwisePos[0] = 0.0138;
1143 m_2601streamwisePos[1] = 0.014452;
1144 m_2601streamwisePos[2] = 0.0148;
1145 m_2601streamwisePos[3] = 0.0153;
1146
1147 noLines++;
1148 mAlloc(m_2601effConst, noLines, m_2601noCoeff * m_2601noPos, AT_, F0, "m_2601effConst");
1149
1150 cout << "Reading in coefficients from file..." << endl;
1151 for(MInt pos = 0; pos < m_2601noPos; pos++) {
1152 step = 0;
1153 ifstream infile2(fileNames[pos].c_str());
1154 while(!infile2.eof() && step < noLines - 1) {
1155 string line[5];
1156 for(MInt i = 0; i < 5; i++) {
1157 infile2 >> line[i];
1158 }
1159
1160 for(MInt i = 0; i < 5; i++) {
1161 m_2601effConst[step][pos * m_2601noCoeff + i] = atof(line[i].c_str());
1162
1163 // if(m_solver->domainId() == 0) {
1164 // cout << "step: " << step << " pos: " << pos << " coeff: " << i << endl;
1165 // }
1166 }
1167
1168 step++;
1169 }
1170 }
1171 cout << "Reading in coefficients from file... FINISHED!" << endl;
1172
1173 const MFloat zeroTime = m_2601effConst[0][0];
1174 for(MInt pos = 0; pos < m_2601noPos; pos++) {
1175 for(MInt iter = 0; iter < noLines; iter++) {
1176 m_2601effConst[iter][pos * m_2601noCoeff + 0] =
1177 (timeConversion * (m_2601effConst[iter][pos * m_2601noCoeff + 0] - zeroTime))
1178 - timeShift; //+m_solver->m_time
1179 }
1180 }
1181
1182 m_2601noSteps = step;
1183 }
1184
1185 switch(m_physicalBCMap[bcId]->face) {
1186 case 2: {
1187 // Copy into zeroth order solution field
1188 for(MInt i = start[0]; i < end[0]; i++) {
1189 for(MInt j = start[1]; j < end[1]; j++) {
1190 for(MInt k = start[2]; k < end[2]; k++) {
1191 const MInt cellId = cellIndex(i, j, k);
1192 const MInt cellIdBc = i + (j + k * m_noGhostLayers) * m_solver->m_nCells[2];
1193 for(MInt var = 0; var < PV->noVariables; var++) {
1194 m_solver->m_bc2601ZerothOrderSolution[var][cellIdBc] = m_cells->pvariables[var][cellId];
1195 }
1196 }
1197 }
1198 }
1199
1200
1201 // Copy the values from the ghostcells into restart field
1202 for(MInt i = m_noGhostLayers; i < end[0] - m_noGhostLayers; i++) {
1203 for(MInt j = 0; j < m_noGhostLayers; j++) {
1204 for(MInt k = m_noGhostLayers; k < end[2] - m_noGhostLayers; k++) {
1205 const MInt cellId = cellIndex(i, j, k);
1206 const MInt cellIdBc =
1207 i - m_noGhostLayers + (j + (k - m_noGhostLayers) * m_noGhostLayers) * m_solver->m_nActiveCells[2];
1208
1209
1210 for(MInt var = 0; var < PV->noVariables; var++) {
1211 m_solver->m_bc2601Variables[var][cellIdBc] = m_cells->pvariables[var][cellId];
1212 }
1213 }
1214 }
1215 }
1216 break;
1217 }
1218 default: {
1219 mTerm(1, AT_, "Face not implemented");
1220 break;
1221 }
1222 }
1223}
1224
1225
1232template <MBool isRans>
1234 TRACE();
1235 m_log << endl << "initBc2700 for bcId " << bcId << endl;
1236 // m_log << " running for " << m_cutOffBndryCndIds[bcId] << endl;
1237
1238 const MFloat time = m_solver->m_physicalTime;
1239
1240 // 1. check the modes and allocate memory
1241 // modeSr
1242 m_modes = Context::propertyLength("modeSr", m_solverId);
1243 MFloatScratchSpace modeSr(m_modes, AT_, "modeSr");
1244 for(MInt i = 0; i < m_modes; i++)
1245 modeSr(i) = Context::getSolverProperty<MFloat>("modeSr", m_solverId, AT_, i);
1246 // m_modeAmp
1247 if(m_modes != Context::propertyLength("modeAmp", m_solverId)) mTerm(1, AT_, "modeAmp does not fit modeSr");
1248 mAlloc(m_modeAmp, m_modes, "m_modeAmp", F0, AT_);
1249 for(MInt i = 0; i < m_modes; i++)
1250 m_modeAmp[i] = Context::getSolverProperty<MFloat>("modeAmp", m_solverId, AT_, i);
1251 // m_modeType
1252 if(m_modes != Context::propertyLength("modeType", m_solverId)) mTerm(1, AT_, "modeType does not fit modeSr");
1253 mAlloc(m_modeType, m_modes, "m_modeType", 0, AT_);
1254 for(MInt i = 0; i < m_modes; i++)
1255 m_modeType[i] = Context::getSolverProperty<MInt>("modeType", m_solverId, AT_, i);
1256 // m_modePhi
1257 if(m_modes != Context::propertyLength("modePhi", m_solverId)) mTerm(1, AT_, "modePhi does not fit modeSr");
1258 mAlloc(m_modePhi, m_modes, "m_modePhi", F0, AT_);
1259 for(MInt i = 0; i < m_modes; i++)
1260 m_modePhi[i] = Context::getSolverProperty<MFloat>("modePhi", m_solverId, AT_, i) * PI / 180.0;
1261 // modeAngle
1262 if(m_modes * 2 != Context::propertyLength("modeAngle", m_solverId)) mTerm(1, AT_, "modeAngle does not fit modeSr");
1263 MFloatScratchSpace modeAngle(m_modes, 2, AT_, "modeAngle");
1264 modeAngle.fill(F0);
1265 for(MInt i = 0; i < m_modes; i++)
1266 for(MInt j = 0; j < nDim - 1; j++)
1267 modeAngle(i, j) = Context::getSolverProperty<MFloat>("modeAngle", m_solverId, AT_, i * 2 + j);
1268 // nmbrOfModes
1269 if(m_modes != Context::propertyLength("nmbrOfModes", m_solverId)) mTerm(1, AT_, "nmbrOfModes does not fit modeSr");
1270 mAlloc(m_nmbrOfModes, m_modes, "m_nmbrOfModes", 0, AT_);
1271 for(MInt i = 0; i < m_modes; i++)
1272 m_nmbrOfModes[i] = Context::getSolverProperty<MInt>("nmbrOfModes", m_solverId, AT_, i);
1273 // memberVariables
1274 mAlloc(m_modeOmega, m_modes, "m_modeOmega", F0, AT_);
1275 mAlloc(m_modeEtaMin, m_modes, "m_modeEtaMin", F0, AT_);
1276 mAlloc(m_modeK, m_modes, nDim, "m_modeK", F0, AT_);
1277
1278 // non-mode specific stuff
1279 MFloat initTime;
1280
1281 m_solver->m_restartBc2800 = F0; // has to be changed, if you add BC2800
1282
1283 if(m_solver->m_restartBc2800)
1284 initTime = m_solver->m_restartTimeBc2800;
1285 else {
1286 initTime = time;
1287 m_solver->m_restartTimeBc2800 = time;
1288 }
1289
1290 m_log << "time = " << time << endl;
1291 m_log << "initTime = " << initTime << endl;
1292
1293 MFloat UInfinity = F0;
1294 for(MInt i = 0; i < nDim; i++)
1295 UInfinity += POW2(PV->VVInfinity[i]);
1296 UInfinity = sqrt(UInfinity);
1297
1298 m_log << "solver: UInfinity " << UInfinity << endl
1299 << "solver: m_referenceLength " << m_solver->m_referenceLength << endl;
1300 for(MInt mode = 0; mode < m_modes; mode++) {
1301 m_log << "-- mode " << mode << " --" << endl;
1302 m_log << " modeType = " << m_modeType[mode] << endl;
1303 m_log << " modeSr = " << modeSr(mode) << endl;
1304 m_log << " modeAmp = " << m_modeAmp[mode] << endl;
1305 m_log << " modePhi = " << m_modePhi[mode] << endl;
1306 m_log << " nmbrOfModes= " << m_nmbrOfModes[mode] << endl;
1307 for(MInt i = 0; i < (nDim - 1); i++)
1308 m_log << " modeAngle(" << i << ") = " << modeAngle(mode, i) << " (rad)" << endl;
1309 // 3. calculate nondimensional mode properties
1310 // 3.1 omega
1311 m_modeOmega[mode] = F2 * PI * modeSr(mode) * UInfinity / m_solver->m_referenceLength;
1312 // 3.2 wave vector modeK
1313 m_modeK[mode][0] = cos(modeAngle(mode, 0)) * cos(modeAngle(mode, 1));
1314 m_modeK[mode][1] = sin(modeAngle(mode, 0)) * cos(modeAngle(mode, 1));
1315 IF_CONSTEXPR(nDim == 3) m_modeK[mode][2] = sin(modeAngle(mode, 1));
1316
1317 MFloat Uk = F0;
1318 for(MInt i = 0; i < nDim; i++)
1319 Uk += PV->VVInfinity[i] * m_modeK[mode][i];
1320
1321 const MFloat propVel = (MFloat)(m_modeType[mode]) * sqrt(PV->TInfinity);
1322 const MFloat K = m_modeOmega[mode] / (Uk + propVel);
1323
1324 for(MInt i = 0; i < nDim; i++)
1325 m_modeK[mode][i] *= K;
1326 // output omega and k
1327 m_log << " Uk = " << Uk << endl;
1328 m_log << " modeOmega = " << m_modeOmega[mode] << endl;
1329 m_log << " K = " << K << endl;
1330 for(MInt i = 0; i < nDim; i++)
1331 m_log << " modeK[" << i << "] = " << m_modeK[mode][i] << endl;
1332 // 4. get the min wave phase
1333 MFloat modeEtaMin = F0;
1334
1335 // here new loop...
1336 MInt* start = m_physicalBCMap[bcId]->start1;
1337 MInt* end = m_physicalBCMap[bcId]->end1;
1338 MInt cellId = -1;
1339
1340 for(MInt k = start[2]; k < end[2]; k++) {
1341 for(MInt j = start[1]; j < end[1]; j++) {
1342 for(MInt i = start[0]; i < end[0]; i++) {
1343 cellId = cellIndex(i, j, k);
1344
1345 // for( MInt id = 0; id < m_sortedCutOffCells[bcId]->size(); id++ ){
1346 // MInt cellId = m_sortedCutOffCells[bcId]->a[ id ];
1347
1348 MFloat eta = F0;
1349 for(MInt dim = 0; dim < nDim; dim++) {
1350 // eta += m_solver->a_coordinate( cellId , i) * m_modeK[mode][i];
1351 eta += m_cells->coordinates[dim][cellId] * m_modeK[mode][dim];
1352 }
1353 eta -= m_modeOmega[mode] * initTime;
1354 // if(cellId == 0)
1355 if((k == start[2]) && (j == start[1]) && (i == start[0]))
1356 modeEtaMin = eta;
1357 else
1358 modeEtaMin = mMin(modeEtaMin, eta);
1359 }
1360 }
1361 }
1362
1363 m_modeEtaMin[mode] = modeEtaMin;
1364 }
1365 m_log << "leaving the initialization" << endl;
1366}
1367
1368
1373template <MBool isRans>
1375 const MInt NU_T = 5;
1376 // const MInt SIJSIJ = 6;
1377 // const MInt LENGTH_SCALE = 7;
1378 // const MInt FLUC_UU = 8;
1379 // const MInt FLUC_VV = 9;
1380 // const MInt FLUC_WW = 10;
1381 // const MInt FLUC_UV = 11;
1382 // const MInt FLUC_VW = 12;
1383 // const MInt FLUC_UW = 13;
1384 // const MInt FLUC_U = 14;
1385 // const MInt FLUC_V = 15;
1386 // const MInt FLUC_W = 16;
1387 MPI_Comm_rank(m_solver->m_commStg, &m_solver->m_stgMyRank);
1388
1389 // initialize RK Step to zero
1390 m_solver->m_RKStep = 0;
1391
1392 mAlloc(m_stgMaxVel, nDim, "m_stgMaxVel", -99999.9, AT_);
1393
1394 const MInt noCellsJ = m_grid->getMyBlockNoCells(1);
1395
1396 if(m_solver->m_stgMyRank == m_solver->m_commStgRoot) {
1397 cout << "Init stgGlobalLengthscales with " << noCellsJ << " cells" << endl;
1398 }
1399 mAlloc(m_stgGlobalLengthScales, noCellsJ, 6, "m_stgGlobalLengthScales", F0, AT_);
1400
1401 MInt* start = m_physicalBCMap[bcId]->start1;
1402 MInt* end = m_physicalBCMap[bcId]->end1;
1403
1404 if(m_solver->m_stgMyRank == m_solver->m_commStgRoot) {
1405 cout << "Initializing BC 7909..." << endl;
1406 }
1407
1408 // Compute size of the Box, take inflow as middle x-coordinate
1409 MFloatScratchSpace bcast_vb(6, AT_, "bcast_vb");
1410
1411 MInt minIndex = getPointIdFromCell(m_noGhostLayers, m_noGhostLayers, m_noGhostLayers);
1412 MInt maxIndex = getPointIdFromCell(m_noGhostLayers, m_noGhostLayers, m_noGhostLayers + m_solver->m_nActiveCells[0]);
1413 MFloat inflowStartLocal[3] = {m_grid->m_coordinates[0][minIndex], m_grid->m_coordinates[1][minIndex],
1414 m_grid->m_coordinates[2][minIndex]};
1415 MFloat inflowEndLocal[3] = {m_grid->m_coordinates[0][maxIndex], m_grid->m_coordinates[1][maxIndex],
1416 m_grid->m_coordinates[2][maxIndex]};
1417 MFloat inflowStart[3] = {99999.9, 99999.9, 99999.9};
1418 MFloat inflowEnd[3] = {F0, F0, F0};
1419
1420 MPI_Allreduce(inflowStartLocal, inflowStart, nDim, MPI_DOUBLE, MPI_MIN, m_solver->m_commStg, AT_, "inflowStartLocal",
1421 "inflowStart");
1422 MPI_Allreduce(inflowEndLocal, inflowEnd, nDim, MPI_DOUBLE, MPI_MAX, m_solver->m_commStg, AT_, "inflowEndLocal",
1423 "inflowEnd");
1424
1425 const MFloat vbDepth = (inflowEnd[2] - inflowStart[2]) * m_solver->m_stgBLT3;
1426 const MFloat zOffset = F1B2 * (inflowEnd[2] - inflowStart[2]) * (m_solver->m_stgBLT3 - F1);
1427
1428 if(m_solver->m_stgMyRank == m_solver->m_commStgRoot) {
1429 m_solver->m_stgRootRank = true;
1430
1431 // Get the coordinate of the inflow
1432 bcast_vb[0] = inflowStart[0] - m_solver->m_stgBLT1 * F1B2;
1433 bcast_vb[1] = inflowStart[1];
1434 bcast_vb[2] = inflowStart[2] - zOffset;
1435
1436 bcast_vb[3] = inflowStart[0] + m_solver->m_stgBLT1 * F1B2;
1437 bcast_vb[4] = inflowStart[1] + m_solver->m_stgBLT2;
1438 bcast_vb[5] = inflowStart[2] - zOffset + vbDepth;
1439
1440 if(m_solver->m_stgBLT3 > 1.5) {
1441 stringstream errorMsg;
1442 errorMsg << "The factor for the depth of the virtual eddy box is probably too large, BLT3: "
1443 << m_solver->m_stgBLT3
1444 << ". This has been changed in the last commit, instead of setting the absolute depth "
1445 << "in z-direction of the domain, now only a scaling factor needs to be given. A factor "
1446 << "of 1.0 will make the virtual box as wide as your domain in z-direction." << endl;
1447 mTerm(1, AT_, errorMsg.str());
1448 }
1449 }
1450
1451 MPI_Bcast(bcast_vb.begin(), 6, MPI_DOUBLE, m_solver->m_commStgRoot, m_solver->m_commStg, AT_, "bcast_vb.begin()");
1452
1453 m_stgVbStart[0] = bcast_vb[0];
1454 m_stgVbStart[1] = bcast_vb[1];
1455 m_stgVbStart[2] = bcast_vb[2];
1456 m_stgVbEnd[0] = bcast_vb[3];
1457 m_stgVbEnd[1] = bcast_vb[4];
1458 m_stgVbEnd[2] = bcast_vb[5];
1459
1460 if(m_solver->m_stgMyRank == m_solver->m_commStgRoot) {
1461 cout << "STG Virtual Box depth factor: " << m_solver->m_stgBLT3 << ", total depth: " << vbDepth << endl
1462 << "STG Virtual Box Information:" << endl
1463 << "STG Virtual Box Start X: " << bcast_vb[0] << " Y: " << bcast_vb[1] << " Z: " << bcast_vb[2] << endl
1464 << "STG Virtual Box End X: " << bcast_vb[3] << " Y: " << bcast_vb[4] << " Z: " << bcast_vb[5] << endl;
1465 }
1466
1467 // Done computing virtual box
1468 if(!m_solver->m_zonal) {
1469 if(m_solver->m_stgInitialStartup) {
1470 // Reading in RANS Profile for BC
1471 // Take 3!!! rows in i-direction because of
1472 // gradient calculations
1473 for(MInt k = start[2]; k < end[2]; k++) {
1474 for(MInt j = start[1]; j < end[1]; j++) {
1475 for(MInt i = start[0]; i < end[0] + 1; i++) {
1476 const MInt cellId = cellIndex(i, j, k);
1477 const MInt cellIdadj = cellIndex(m_noGhostLayers, j, k); // constant in K anyway
1478 const MInt IBC = cellIndexBC(i, j, k);
1479
1480 // Set all variables like in the field
1481 for(MInt var = 0; var < PV->noVariables; var++) {
1482 m_cells->pvariables[var][cellId] = m_cells->pvariables[var][cellIdadj];
1483 }
1484
1485 // fill up the STG FQ field with the RANS values
1486 for(MInt var = 0; var < PV->noVariables; var++) {
1487 m_cells->stg_fq[var][IBC] = m_cells->pvariables[var][cellId];
1488 }
1489
1490 m_cells->stg_fq[NU_T][IBC] = m_cells->fq[FQ->NU_T][cellIdadj];
1491 }
1492 }
1493 }
1494 } else {
1495 for(MInt k = start[2]; k < end[2]; k++) {
1496 for(MInt j = start[1]; j < end[1]; j++) {
1497 for(MInt i = start[0]; i < end[0]; i++) {
1498 const MInt cellId = cellIndex(i, j, k);
1499 const MInt IBC = cellIndexBC(i, j, k);
1500 for(MInt var = 0; var < PV->noVariables; var++) {
1501 m_cells->pvariables[var][cellId] = m_cells->stg_fq[var][IBC];
1502 }
1503 }
1504 }
1505 }
1506 }
1507 }
1508
1509
1510 // create new eddies if it's an initial start or the createNewEddie flag is set
1511 if(!m_solver->m_restart || m_solver->m_stgCreateNewEddies) {
1512 MFloat xk1t, xk2t, xk3t, epsik1, epsik2, epsik3;
1513 MInt nran = m_solver->m_stgMaxNoEddies;
1514 MFloatScratchSpace bcast_eddies(nran * 6, AT_, "bcast_eddies");
1515
1516 MFloat eps = 1e-7;
1517
1518 if(m_solver->m_stgMyRank == m_solver->m_commStgRoot) {
1519 // cout << "Creating new Eddies inside Virtual Box" << endl;
1520 for(MInt n = 0; n < m_solver->m_stgMaxNoEddies; n++) {
1521 xk1t = m_stgVbStart[0] + generate_rand() * (m_stgVbEnd[0] - m_stgVbStart[0]);
1522 xk2t = m_stgVbStart[1] + generate_rand_weighted() * (m_stgVbEnd[1] - m_stgVbStart[1]);
1523 xk3t = m_stgVbStart[2] + generate_rand() * (m_stgVbEnd[2] - m_stgVbStart[2]);
1524
1525 // cout << "Creating eddie at x: " << xk1t << " , y: " << xk2t << " , z: " << xk3t << endl;
1526
1527 epsik1 = 2.0 * generate_rand() - 1.0;
1528 epsik1 = epsik1 / max(abs(epsik1), eps);
1529 epsik2 = 2.0 * generate_rand() - 1.0;
1530 epsik2 = epsik2 / max(abs(epsik2), eps);
1531 epsik3 = 2.0 * generate_rand() - 1.0;
1532 epsik3 = epsik3 / max(abs(epsik3), eps);
1533
1534 bcast_eddies[n + nran * 0] = xk1t;
1535 bcast_eddies[n + nran * 1] = xk2t;
1536 bcast_eddies[n + nran * 2] = xk3t;
1537 bcast_eddies[n + nran * 3] = epsik1;
1538 bcast_eddies[n + nran * 4] = epsik2;
1539 bcast_eddies[n + nran * 5] = epsik3;
1540 }
1541 }
1542
1543 // Broadcast the new/updated eddies to all relevant processes
1544 MPI_Bcast(bcast_eddies.begin(), 6 * nran, MPI_DOUBLE, m_solver->m_commStgRoot, m_solver->m_commStg, AT_,
1545 "bcast_eddies.begin()");
1546
1547 // Copy data into m_FQeddie vector
1548 for(MInt n = 0; n < nran; n++) {
1549 m_solver->m_stgEddies[n][0] = bcast_eddies[n + nran * 0]; // bcast_buffer(n,var);
1550 m_solver->m_stgEddies[n][1] = bcast_eddies[n + nran * 1];
1551 m_solver->m_stgEddies[n][2] = bcast_eddies[n + nran * 2];
1552 m_solver->m_stgEddies[n][3] = bcast_eddies[n + nran * 3];
1553 m_solver->m_stgEddies[n][4] = bcast_eddies[n + nran * 4];
1554 m_solver->m_stgEddies[n][5] = bcast_eddies[n + nran * 5];
1555 }
1556 }
1557}
1558
1559
1564template <MBool isRans>
1566 // for the channel flow we need the surface area of the entering and the outflow domain
1567 //==>determine Channelflow surface (assuming it does not change)
1568 MInt normal = 0;
1569 MInt Id = m_channelSurfaceIndexMap[bcId];
1570 if(Id < 0) cerr << "id smaller than zero ==> error" << endl;
1571 MInt* startface = &m_solver->m_windowInfo->channelSurfaceIndices[Id]->start1[0];
1572 MInt* endface = &m_solver->m_windowInfo->channelSurfaceIndices[Id]->end1[0];
1573 // find out which face it is
1574 MInt fixedind = -1;
1575
1576
1577 if(m_solver->m_initialCondition == 1233) {
1581 MFloat uTau = m_solver->m_ReTau * m_solver->m_Ma * sqrt(PV->TInfinity) / m_solver->m_Re;
1582 m_solver->m_deltaP = -CV->rhoInfinity * POW2(uTau) * F2 * (m_solver->m_channelLength) / m_solver->m_channelHeight;
1583 m_solver->m_channelPresInlet = PV->PInfinity;
1584 m_solver->m_channelPresOutlet = PV->PInfinity + m_solver->m_deltaP;
1585 m_log << "=========== Turb. Channel Flow BC Summary =========== " << endl;
1586 m_log << "-->Turbulent channel flow deltaP: " << m_solver->m_deltaP << endl;
1587 m_log << "-->channel friciton velocity: " << uTau << endl;
1588 m_log << "-->Channel pressure inflow: " << m_solver->m_channelPresInlet << endl;
1589 m_log << "-->Channel pressure outflow: " << m_solver->m_channelPresOutlet << endl;
1590 m_log << "=========== Turb. Channel Flow BC Summary Finished =========== " << endl;
1591 } else if(m_solver->m_initialCondition == 1234) {
1592 cout.precision(10);
1596
1597 m_solver->m_deltaP = -12.0 * PV->UInfinity * SUTHERLANDLAW(PV->TInfinity) * m_solver->m_channelLength
1598 / (POW2(m_solver->m_channelHeight) * m_solver->m_Re0);
1599 m_log << "=========== Lam. Channel Flow BC Summary =========== " << endl;
1600 m_log << "Laminar channel deltaP: " << m_solver->m_deltaP << endl;
1601 m_log << "Theoretical cD total (both channel walls): "
1602 << m_solver->m_deltaP * m_solver->m_channelHeight * m_solver->m_channelWidth
1603 / (0.5 * CV->rhoInfinity * POW2(PV->UInfinity))
1604 << endl;
1605 m_log << "Theoretical cD (single wall): "
1606 << m_solver->m_deltaP * m_solver->m_channelHeight * m_solver->m_channelWidth
1607 / (0.5 * CV->rhoInfinity * POW2(PV->UInfinity) * 2.0)
1608 << endl;
1609 m_log << "Theoretical cF total (both channel walls): "
1610 << m_solver->m_deltaP * m_solver->m_channelHeight
1611 / (0.5 * CV->rhoInfinity * POW2(PV->UInfinity) * m_solver->m_channelLength)
1612 << endl;
1613 m_log << "Theoretical cF (single wall): "
1614 << m_solver->m_deltaP * m_solver->m_channelHeight
1615 / (0.5 * CV->rhoInfinity * POW2(PV->UInfinity) * m_solver->m_channelLength * 2.0)
1616 << endl;
1617 m_log << "=========== Lam. Channel Flow BC Summary Finished =========== " << endl;
1618 } else if(m_solver->m_initialCondition == 1236) {
1622 MFloat uTau = m_solver->m_ReTau * m_solver->m_Ma * sqrt(PV->TInfinity) / m_solver->m_Re;
1623 m_solver->m_deltaP = -4.0 * CV->rhoInfinity * POW2(uTau) * (m_solver->m_channelLength) / m_solver->m_channelHeight;
1624
1625 m_solver->m_channelPresInlet = PV->PInfinity;
1626 m_solver->m_channelPresOutlet = PV->PInfinity + m_solver->m_deltaP;
1627
1628 m_log << "=========== Turb. Pipe Flow BC Summary =========== " << endl;
1629 m_log << "-->Turbulent pipe flow deltaP: " << m_solver->m_deltaP << endl;
1630 m_log << "-->pipe friciton velocity: " << uTau << endl;
1631 m_log << "-->pipe pressure inflow: " << m_solver->m_channelPresInlet << endl;
1632 m_log << "-->pipe pressure outflow: " << m_solver->m_channelPresOutlet << endl;
1633 m_log << "=========== Turb. Pipe Flow BC Summary Finished =========== " << endl;
1634 }
1635
1636 for(MInt dim = 0; dim < nDim; dim++) {
1637 if(startface[dim] == endface[dim]) {
1638 // this is the normal
1639 fixedind = dim;
1640 if(startface[dim] == m_noGhostLayers) {
1641 normal = -1;
1642 } else {
1643 normal = 1;
1644 }
1645 }
1646 }
1647
1648 if(m_physicalBCMap[bcId]->face == 0) {
1649 MPI_Comm_rank(m_solver->m_commChannelIn, &m_channelInflowRank);
1650 }
1651
1652 switch(fixedind) {
1653 case 0: {
1654 MFloat surface = F0;
1655 MInt ii = 0;
1656 if(normal < 0) {
1657 ii = startface[0];
1658
1659 MInt cellId = 0;
1660 for(MInt k = startface[2]; k < endface[2]; k++) {
1661 for(MInt j = startface[1]; j < endface[1]; j++) {
1662 cellId = cellIndex(ii, j, k);
1663 surface += sqrt(POW2(m_cells->cellMetrics[0][cellId]) + POW2(m_cells->cellMetrics[1][cellId])
1664 + POW2(m_cells->cellMetrics[2][cellId]));
1665 }
1666 }
1667 } else {
1668 ii = endface[0];
1669 // activate this or the method below with the 4 points for the surface calculation
1670 // this is less exact (for straight surf.) but works better for curved surfaces
1671
1672 MInt cellId = 0;
1673 for(MInt k = startface[2]; k < endface[2]; k++) {
1674 for(MInt j = startface[1]; j < endface[1]; j++) {
1675 cellId = cellIndex(ii - 1, j, k);
1676 surface += sqrt(POW2(m_cells->cellMetrics[0][cellId]) + POW2(m_cells->cellMetrics[1][cellId])
1677 + POW2(m_cells->cellMetrics[2][cellId]));
1678 }
1679 }
1680 }
1681
1682 if(normal < 0) {
1683 MPI_Allreduce(&surface, &m_channelSurfaceIn, 1, MPI_DOUBLE, MPI_SUM, m_solver->m_commChannelIn, AT_, "surface",
1684 "m_channelSurfaceIn");
1685 cout << "ChannelInSurface: " << m_channelSurfaceIn << endl;
1686 } else {
1687 MPI_Allreduce(&surface, &m_channelSurfaceOut, 1, MPI_DOUBLE, MPI_SUM, m_solver->m_commChannelOut, AT_,
1688 "surface", "m_channelSurfaceOut");
1689 cout << "ChannelOutSurface: " << m_channelSurfaceOut << endl;
1690 }
1691
1692 break;
1693 }
1694 case 1: {
1695 mTerm(1, AT_, "surface calculation for j faces(channel not implemented)");
1696 break;
1697 }
1698 case 2: {
1699 mTerm(1, AT_, "surface calculation for k faces(channel not implemented)");
1700 break;
1701 }
1702 default: {
1703 mTerm(1, AT_, "surface calculation for given faces(channel not implemented)");
1704 }
1705 }
1706}
1707
1708
1709// solid wall bc
1710template <MBool isRans>
1712 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
1713 const MInt* start = m_physicalBCMap[bcId]->start1;
1714 const MInt* end = m_physicalBCMap[bcId]->end1;
1715 const MInt face = m_physicalBCMap[bcId]->face;
1716
1717 // Here we find out the normal direction of the
1718 // boundary and the two tangential directions.
1719 // This way we can make a general formulation of
1720 // the boundary condition
1721 const MInt normalDir = face / 2;
1722 const MInt firstTangentialDir = (normalDir + 1) % nDim;
1723 const MInt secondTangentialDir = (normalDir + 2) % nDim;
1724 const MInt normalDirStart = start[normalDir];
1725 const MInt firstTangentialStart = start[firstTangentialDir];
1726 const MInt firstTangentialEnd = end[firstTangentialDir];
1727 const MInt secondTangentialStart = start[secondTangentialDir];
1728 const MInt secondTangentialEnd = end[secondTangentialDir];
1729 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
1730
1731 const MInt n = (face % 2) * 2 - 1; //-1,+1
1732 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
1733 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
1734 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
1735 const MInt a2 = normalDirStart + (MInt)(0.5 - (2.5 * (MFloat)n)); //+3,-2
1736
1737
1738 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
1739 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
1740 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
1741 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
1742 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
1743 const MInt cellIdA2 = a2 * inc[0] + t1 * inc[1] + t2 * inc[2];
1744
1745 const MFloat p1 = m_cells->pvariables[PV->P][cellIdA1];
1746 const MFloat rho1 = m_cells->pvariables[PV->RHO][cellIdA1];
1747 const MFloat u1 = m_cells->pvariables[PV->U][cellIdA1];
1748 const MFloat v1 = m_cells->pvariables[PV->V][cellIdA1];
1749 const MFloat w1 = m_cells->pvariables[PV->W][cellIdA1];
1750
1751 const MFloat p2 = m_cells->pvariables[PV->P][cellIdA2];
1752 const MFloat rho2 = m_cells->pvariables[PV->RHO][cellIdA2];
1753 const MFloat u2 = m_cells->pvariables[PV->U][cellIdA2];
1754 const MFloat v2 = m_cells->pvariables[PV->V][cellIdA2];
1755 const MFloat w2 = m_cells->pvariables[PV->W][cellIdA2];
1756
1757 m_cells->pvariables[PV->RHO][cellIdG1] = rho1;
1758 m_cells->pvariables[PV->U][cellIdG1] = -u1;
1759 m_cells->pvariables[PV->V][cellIdG1] = -v1;
1760 m_cells->pvariables[PV->W][cellIdG1] = -w1;
1761 m_cells->pvariables[PV->P][cellIdG1] = p1;
1762
1763 m_cells->pvariables[PV->RHO][cellIdG2] = rho2;
1764 m_cells->pvariables[PV->U][cellIdG2] = -u2;
1765 m_cells->pvariables[PV->V][cellIdG2] = -v2;
1766 m_cells->pvariables[PV->W][cellIdG2] = -w2;
1767 m_cells->pvariables[PV->P][cellIdG2] = p2;
1768
1769 if(isRans) {
1770 const MFloat nuTilde1 = m_cells->pvariables[PV->RANS_VAR[0]][cellIdA1];
1771 const MFloat nuTilde2 = m_cells->pvariables[PV->RANS_VAR[0]][cellIdA2];
1772
1773 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG1] = -nuTilde1;
1774 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG2] = -nuTilde2;
1775 }
1776 }
1777 }
1778}
1779
1780// isothermal Wall
1781template <MBool isRans>
1783 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
1784 MInt* start = m_physicalBCMap[bcId]->start1;
1785 MInt* end = m_physicalBCMap[bcId]->end1;
1786 const MInt face = m_physicalBCMap[bcId]->face;
1787
1788 MFloat temp = m_isothermalWallTemperature * PV->TInfinity;
1789 const MFloat gamma = m_solver->m_gamma;
1790
1791 // Here we find out the normal direction of the
1792 // boundary and the two tangential directions.
1793 // This way we can make a general formulation of
1794 // the boundary condition
1795 const MInt normalDir = face / 2;
1796 const MInt firstTangentialDir = (normalDir + 1) % nDim;
1797 const MInt secondTangentialDir = (normalDir + 2) % nDim;
1798 const MInt normalDirStart = start[normalDir];
1799 const MInt firstTangentialStart = start[firstTangentialDir];
1800 const MInt firstTangentialEnd = end[firstTangentialDir];
1801 const MInt secondTangentialStart = start[secondTangentialDir];
1802 const MInt secondTangentialEnd = end[secondTangentialDir];
1803 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
1804
1805 const MInt n = (face % 2) * 2 - 1; //-1,+1
1806 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
1807 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
1808 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
1809 const MInt a2 = normalDirStart + (MInt)(0.5 - (2.5 * (MFloat)n)); //+3,-2
1810
1811
1812 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
1813 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
1814 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
1815 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
1816 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
1817 const MInt cellIdA2 = a2 * inc[0] + t1 * inc[1] + t2 * inc[2];
1818
1819 const MFloat p1 = m_cells->pvariables[PV->P][cellIdA1];
1820 const MFloat rho1 = m_cells->pvariables[PV->RHO][cellIdA1];
1821 const MFloat u1 = m_cells->pvariables[PV->U][cellIdA1];
1822 const MFloat v1 = m_cells->pvariables[PV->V][cellIdA1];
1823 const MFloat w1 = m_cells->pvariables[PV->W][cellIdA1];
1824
1825 const MFloat p2 = m_cells->pvariables[PV->P][cellIdA2];
1826 const MFloat rho2 = m_cells->pvariables[PV->RHO][cellIdA2];
1827 const MFloat u2 = m_cells->pvariables[PV->U][cellIdA2];
1828 const MFloat v2 = m_cells->pvariables[PV->V][cellIdA2];
1829 const MFloat w2 = m_cells->pvariables[PV->W][cellIdA2];
1830
1831 const MFloat rhoWall = p1 * gamma / temp;
1832 const MFloat rhoG1 = F2 * rhoWall - rho1;
1833 const MFloat rhoG2 = F2 * rhoWall - rho2;
1834
1835 m_cells->pvariables[PV->RHO][cellIdG1] = rhoG1;
1836 m_cells->pvariables[PV->U][cellIdG1] = -u1;
1837 m_cells->pvariables[PV->V][cellIdG1] = -v1;
1838 m_cells->pvariables[PV->W][cellIdG1] = -w1;
1839 m_cells->pvariables[PV->P][cellIdG1] = p1;
1840
1841 m_cells->pvariables[PV->RHO][cellIdG2] = rhoG2;
1842 m_cells->pvariables[PV->U][cellIdG2] = -u2;
1843 m_cells->pvariables[PV->V][cellIdG2] = -v2;
1844 m_cells->pvariables[PV->W][cellIdG2] = -w2;
1845 m_cells->pvariables[PV->P][cellIdG2] = p2;
1846 }
1847 }
1848}
1849
1855template <MBool isRans>
1857 MInt* start = m_physicalBCMap[bcId]->start1;
1858 MInt* end = m_physicalBCMap[bcId]->end1;
1859
1860 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
1861 const MInt IJKP[nDim] = {1, m_nPoints[2], m_nPoints[1] * m_nPoints[2]};
1862
1863 const MInt pp[3][12] = {
1864 {0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1}, {0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1}, {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0}};
1865
1866 // MFloat fdt = F0;
1867 // if (m_solver->m_RKStep!=0) {
1868 // fdt = F1/(m_solver->m_timeStep*m_solver->m_RKalpha[m_solver->m_RKStep-1]);
1869 // } else {
1870 // fdt = F1/(m_solver->m_timeStep*m_solver->m_RKalpha[m_solver->m_noRKSteps-1]);
1871 // }
1872
1873 const MInt face = m_physicalBCMap[bcId]->face;
1874
1875 // Here we find out the normal direction of the
1876 // boundary and the two tangential directions.
1877 // This way we can make a general formulation of
1878 // the boundary condition
1879 const MInt normalDir = face / 2;
1880 const MInt firstTangentialDir = (normalDir + 1) % nDim;
1881 const MInt secondTangentialDir = (normalDir + 2) % nDim;
1882 const MInt normalDirStart = start[normalDir];
1883 const MInt firstTangentialStart = start[firstTangentialDir];
1884 const MInt firstTangentialEnd = end[firstTangentialDir];
1885 const MInt secondTangentialStart = start[secondTangentialDir];
1886 const MInt secondTangentialEnd = end[secondTangentialDir];
1887 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
1888 const MInt incp[nDim] = {IJKP[normalDir], IJKP[firstTangentialDir], IJKP[secondTangentialDir]};
1889
1890 const MInt n = (face % 2) * 2 - 1; //-1,+1
1891 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
1892 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
1893 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
1894 const MInt a2 = normalDirStart + (MInt)(0.5 - (2.5 * (MFloat)n)); //+3,-2
1895
1896 const MInt g1p = normalDirStart + 2 * ((MInt)(0.5 - (0.5 * (MFloat)n))); //+1,0
1897
1898 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
1899 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
1900 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
1901 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
1902 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
1903 const MInt cellIdA2 = a2 * inc[0] + t1 * inc[1] + t2 * inc[2];
1904
1905 // compute four surrounding points of surface centroid
1906 const MInt ijk = g1p * incp[0] + t1 * incp[1] + t2 * incp[2];
1907 const MInt pp1 = getPointIdfromPoint(ijk, pp[normalDir][0], pp[normalDir][1], pp[normalDir][2]);
1908 const MInt pp2 = getPointIdfromPoint(ijk, pp[normalDir][3], pp[normalDir][4], pp[normalDir][5]);
1909 const MInt pp3 = getPointIdfromPoint(ijk, pp[normalDir][6], pp[normalDir][7], pp[normalDir][8]);
1910 const MInt pp4 = getPointIdfromPoint(ijk, pp[normalDir][9], pp[normalDir][10], pp[normalDir][11]);
1911
1912 // compute the velocity of the surface centroid
1913 MFloat gridVel[3] = {F0, F0, F0};
1914 MFloat gridAcc[3] = {F0, F0, F0};
1915 MFloat firstVec[3] = {F0, F0, F0};
1916 MFloat secondVec[3] = {F0, F0, F0};
1917 MFloat normalVec[3] = {F0, F0, F0};
1918 for(MInt dim = 0; dim < nDim; dim++) {
1919 firstVec[dim] = m_grid->m_coordinates[dim][pp2] - m_grid->m_coordinates[dim][pp1];
1920 secondVec[dim] = m_grid->m_coordinates[dim][pp3] - m_grid->m_coordinates[dim][pp1];
1921
1922 gridVel[dim] = F1B4
1923 * (m_grid->m_velocity[dim][pp1] + m_grid->m_velocity[dim][pp2] + m_grid->m_velocity[dim][pp3]
1924 + m_grid->m_velocity[dim][pp4]);
1925
1926 gridAcc[dim] = F1B4
1927 * (m_grid->m_acceleration[dim][pp1] + m_grid->m_acceleration[dim][pp2]
1928 + m_grid->m_acceleration[dim][pp3] + m_grid->m_acceleration[dim][pp4]);
1929 }
1930
1931 const MFloat p1 = m_cells->pvariables[PV->P][cellIdA1];
1932 const MFloat rho1 = m_cells->pvariables[PV->RHO][cellIdA1];
1933 const MFloat u1 = m_cells->pvariables[PV->U][cellIdA1];
1934 const MFloat v1 = m_cells->pvariables[PV->V][cellIdA1];
1935 const MFloat w1 = m_cells->pvariables[PV->W][cellIdA1];
1936
1937 const MFloat p2 = m_cells->pvariables[PV->P][cellIdA2];
1938 const MFloat rho2 = m_cells->pvariables[PV->RHO][cellIdA2];
1939 const MFloat u2 = m_cells->pvariables[PV->U][cellIdA2];
1940 const MFloat v2 = m_cells->pvariables[PV->V][cellIdA2];
1941 const MFloat w2 = m_cells->pvariables[PV->W][cellIdA2];
1942
1943
1944 // compute normal acceleration of surface to derive von Neumann BC for pressure and density
1945 // compute normal vector of surface
1946 crossProduct(normalVec, firstVec, secondVec);
1947 const MFloat normalLength = sqrt(POW2(normalVec[0]) + POW2(normalVec[1]) + POW2(normalVec[2]));
1948
1949 for(MInt dim = 0; dim < nDim; dim++) {
1950 normalVec[dim] /= normalLength;
1951 }
1952
1953 // compute distance between ghost point and active point
1954 const MFloat dx = m_cells->coordinates[0][cellIdA1] - m_cells->coordinates[0][cellIdG1];
1955 const MFloat dy = m_cells->coordinates[1][cellIdA1] - m_cells->coordinates[1][cellIdG1];
1956 const MFloat dz = m_cells->coordinates[2][cellIdA1] - m_cells->coordinates[2][cellIdG1];
1957 const MFloat dn = sqrt(POW2(dx) + POW2(dy) + POW2(dz));
1958
1959 const MFloat surfTemp = m_solver->m_gamma * p1 / rho1;
1960 // compute normal acceleration of surface
1961 MFloat an = F0;
1962 for(MInt dim = 0; dim < nDim; dim++) {
1963 an += gridAcc[dim] * normalVec[dim];
1964 }
1965
1966 const MFloat beta = m_solver->m_gamma * an / surfTemp;
1967 const MFloat fac = (F2 + dn * beta) / (F2 - dn * beta);
1968
1969 const MFloat pG1 = p1 * fac;
1970 const MFloat pG2 = p2 * fac;
1971 const MFloat rhoG1 = rho1 * fac;
1972 const MFloat rhoG2 = rho2 * fac;
1973
1974 const MFloat uG1 = F2 * gridVel[0] - u1;
1975 const MFloat vG1 = F2 * gridVel[1] - v1;
1976 const MFloat wG1 = F2 * gridVel[2] - w1;
1977
1978 const MFloat uG2 = F2 * gridVel[0] - u2;
1979 const MFloat vG2 = F2 * gridVel[1] - v2;
1980 const MFloat wG2 = F2 * gridVel[2] - w2;
1981
1982 m_cells->pvariables[PV->RHO][cellIdG1] = rhoG1;
1983 m_cells->pvariables[PV->U][cellIdG1] = uG1;
1984 m_cells->pvariables[PV->V][cellIdG1] = vG1;
1985 m_cells->pvariables[PV->W][cellIdG1] = wG1;
1986 m_cells->pvariables[PV->P][cellIdG1] = pG1;
1987
1988 m_cells->pvariables[PV->RHO][cellIdG2] = rhoG2;
1989 m_cells->pvariables[PV->U][cellIdG2] = uG2;
1990 m_cells->pvariables[PV->V][cellIdG2] = vG2;
1991 m_cells->pvariables[PV->W][cellIdG2] = wG2;
1992 m_cells->pvariables[PV->P][cellIdG2] = pG2;
1993 }
1994 }
1995}
1996
2002template <MBool isRans>
2004 MInt* start = m_physicalBCMap[bcId]->start1;
2005 MInt* end = m_physicalBCMap[bcId]->end1;
2006
2007 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
2008 const MInt IJKP[nDim] = {1, m_nPoints[2], m_nPoints[1] * m_nPoints[2]};
2009
2010 const MInt pp[3][12] = {
2011 {0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1}, {0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1}, {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0}};
2012
2013 const MInt face = m_physicalBCMap[bcId]->face;
2014
2015 MFloat temp = m_isothermalWallTemperature * PV->TInfinity;
2016 const MFloat gamma = m_solver->m_gamma;
2017
2018 // Here we find out the normal direction of the
2019 // boundary and the two tangential directions.
2020 // This way we can make a general formulation of
2021 // the boundary condition
2022 const MInt normalDir = face / 2;
2023 const MInt firstTangentialDir = (normalDir + 1) % nDim;
2024 const MInt secondTangentialDir = (normalDir + 2) % nDim;
2025 const MInt normalDirStart = start[normalDir];
2026 const MInt firstTangentialStart = start[firstTangentialDir];
2027 const MInt firstTangentialEnd = end[firstTangentialDir];
2028 const MInt secondTangentialStart = start[secondTangentialDir];
2029 const MInt secondTangentialEnd = end[secondTangentialDir];
2030 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
2031 const MInt incp[nDim] = {IJKP[normalDir], IJKP[firstTangentialDir], IJKP[secondTangentialDir]};
2032
2033 const MInt n = (face % 2) * 2 - 1; //-1,+1
2034 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
2035 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
2036 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
2037 const MInt a2 = normalDirStart + (MInt)(0.5 - (2.5 * (MFloat)n)); //+3,-2
2038
2039 const MInt g1p = normalDirStart + 2 * ((MInt)(0.5 - (0.5 * (MFloat)n))); //+1,0
2040
2041 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
2042 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
2043 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
2044 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
2045 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
2046 const MInt cellIdA2 = a2 * inc[0] + t1 * inc[1] + t2 * inc[2];
2047
2048 // compute four surrounding points of surface centroid
2049 const MInt ijk = g1p * incp[0] + t1 * incp[1] + t2 * incp[2];
2050 const MInt pp1 = getPointIdfromPoint(ijk, pp[normalDir][0], pp[normalDir][1], pp[normalDir][2]);
2051 const MInt pp2 = getPointIdfromPoint(ijk, pp[normalDir][3], pp[normalDir][4], pp[normalDir][5]);
2052 const MInt pp3 = getPointIdfromPoint(ijk, pp[normalDir][6], pp[normalDir][7], pp[normalDir][8]);
2053 const MInt pp4 = getPointIdfromPoint(ijk, pp[normalDir][9], pp[normalDir][10], pp[normalDir][11]);
2054
2055 // compute the velocity of the surface centroid
2056 MFloat gridVel[3] = {F0, F0, F0};
2057 MFloat gridAcc[3] = {F0, F0, F0};
2058 MFloat firstVec[3] = {F0, F0, F0};
2059 MFloat secondVec[3] = {F0, F0, F0};
2060 MFloat normalVec[3] = {F0, F0, F0};
2061 for(MInt dim = 0; dim < nDim; dim++) {
2062 firstVec[dim] = m_grid->m_coordinates[dim][pp2] - m_grid->m_coordinates[dim][pp1];
2063 secondVec[dim] = m_grid->m_coordinates[dim][pp3] - m_grid->m_coordinates[dim][pp1];
2064
2065 gridVel[dim] = F1B4
2066 * (m_grid->m_velocity[dim][pp1] + m_grid->m_velocity[dim][pp2] + m_grid->m_velocity[dim][pp3]
2067 + m_grid->m_velocity[dim][pp4]);
2068
2069 gridAcc[dim] = F1B4
2070 * (m_grid->m_acceleration[dim][pp1] + m_grid->m_acceleration[dim][pp2]
2071 + m_grid->m_acceleration[dim][pp3] + m_grid->m_acceleration[dim][pp4]);
2072 }
2073
2074 const MFloat p1 = m_cells->pvariables[PV->P][cellIdA1];
2075 const MFloat rho1 = m_cells->pvariables[PV->RHO][cellIdA1];
2076 const MFloat u1 = m_cells->pvariables[PV->U][cellIdA1];
2077 const MFloat v1 = m_cells->pvariables[PV->V][cellIdA1];
2078 const MFloat w1 = m_cells->pvariables[PV->W][cellIdA1];
2079
2080 const MFloat p2 = m_cells->pvariables[PV->P][cellIdA2];
2081 const MFloat rho2 = m_cells->pvariables[PV->RHO][cellIdA2];
2082 const MFloat u2 = m_cells->pvariables[PV->U][cellIdA2];
2083 const MFloat v2 = m_cells->pvariables[PV->V][cellIdA2];
2084 const MFloat w2 = m_cells->pvariables[PV->W][cellIdA2];
2085
2086
2087 // compute normal acceleration of surface to derive von Neumann BC for pressure and density
2088 // compute normal vector of surface
2089 crossProduct(normalVec, firstVec, secondVec);
2090 const MFloat normalLength = sqrt(POW2(normalVec[0]) + POW2(normalVec[1]) + POW2(normalVec[2]));
2091
2092 for(MInt dim = 0; dim < nDim; dim++) {
2093 normalVec[dim] /= normalLength;
2094 }
2095
2096 // compute distance between ghost point and active point
2097 const MFloat dx = m_cells->coordinates[0][cellIdA1] - m_cells->coordinates[0][cellIdG1];
2098 const MFloat dy = m_cells->coordinates[1][cellIdA1] - m_cells->coordinates[1][cellIdG1];
2099 const MFloat dz = m_cells->coordinates[2][cellIdA1] - m_cells->coordinates[2][cellIdG1];
2100 const MFloat dn = sqrt(POW2(dx) + POW2(dy) + POW2(dz));
2101
2102 // compute normal acceleration of surface
2103 MFloat an = F0;
2104 for(MInt dim = 0; dim < nDim; dim++) {
2105 an += gridAcc[dim] * normalVec[dim];
2106 }
2107
2108 const MFloat beta = m_solver->m_gamma * an / temp;
2109 const MFloat fac = (F2 + dn * beta) / (F2 - dn * beta);
2110
2111 const MFloat pG1 = p1 * fac;
2112 const MFloat pG2 = p2 * fac;
2113 const MFloat rhoWall = p1 * gamma / temp;
2114 const MFloat rhoG1 = (F2 * rhoWall - rho1) * fac;
2115 const MFloat rhoG2 = (F2 * rhoWall - rho2) * fac;
2116
2117 const MFloat uG1 = F2 * gridVel[0] - u1;
2118 const MFloat vG1 = F2 * gridVel[1] - v1;
2119 const MFloat wG1 = F2 * gridVel[2] - w1;
2120
2121 const MFloat uG2 = F2 * gridVel[0] - u2;
2122 const MFloat vG2 = F2 * gridVel[1] - v2;
2123 const MFloat wG2 = F2 * gridVel[2] - w2;
2124
2125 m_cells->pvariables[PV->RHO][cellIdG1] = rhoG1;
2126 m_cells->pvariables[PV->U][cellIdG1] = uG1;
2127 m_cells->pvariables[PV->V][cellIdG1] = vG1;
2128 m_cells->pvariables[PV->W][cellIdG1] = wG1;
2129 m_cells->pvariables[PV->P][cellIdG1] = pG1;
2130
2131 m_cells->pvariables[PV->RHO][cellIdG2] = rhoG2;
2132 m_cells->pvariables[PV->U][cellIdG2] = uG2;
2133 m_cells->pvariables[PV->V][cellIdG2] = vG2;
2134 m_cells->pvariables[PV->W][cellIdG2] = wG2;
2135 m_cells->pvariables[PV->P][cellIdG2] = pG2;
2136 }
2137 }
2138}
2139
2145template <MBool isRans>
2147 MInt* start = m_physicalBCMap[bcId]->start1;
2148 MInt* end = m_physicalBCMap[bcId]->end1;
2149 const MFloat t = m_solver->m_time + m_solver->m_timeStep * m_solver->m_RKalpha[m_solver->m_RKStep];
2150
2151 switch(m_physicalBCMap[bcId]->face) {
2152 case 2: {
2153 MFloat gridVel[3] = {F0, F0, F0};
2154
2155 for(MInt k = start[2]; k < end[2]; k++) {
2156 for(MInt i = start[0]; i < end[0]; i++) {
2157 MInt cellIdG2 = cellIndex(i, 0, k); // ghost
2158 MInt cellIdG1 = cellIndex(i, 1, k); // ghost
2159 MInt cellIdA1 = cellIndex(i, 2, k); // field
2160 MInt cellIdA2 = cellIndex(i, 3, k); // field
2161
2162 const MFloat transitionLength = m_solver->m_waveEndTransition - m_solver->m_waveBeginTransition;
2163 const MFloat xInit = m_cells->coordinates[0][cellIdG1];
2164 MFloat transitionFactor = F0;
2165 if(xInit <= m_solver->m_waveBeginTransition) {
2166 transitionFactor = F0;
2167 } else if(xInit > m_solver->m_waveBeginTransition && xInit < m_solver->m_waveEndTransition) {
2168 transitionFactor = (1 - cos((xInit - m_solver->m_waveBeginTransition) / transitionLength * PI)) * F1B2;
2169 } else {
2170 transitionFactor = F1;
2171 }
2172
2173 gridVel[2] = m_solver->m_waveAmplitude * sin(F2 * PI / m_solver->m_waveTime * t) * transitionFactor;
2174
2175 MFloat p1 = m_cells->pvariables[PV->P][cellIdA1];
2176 MFloat rho1 = m_cells->pvariables[PV->RHO][cellIdA1];
2177 MFloat u1 = m_cells->pvariables[PV->U][cellIdA1];
2178 MFloat v1 = m_cells->pvariables[PV->V][cellIdA1];
2179 MFloat w1 = m_cells->pvariables[PV->W][cellIdA1];
2180
2181 MFloat u2 = m_cells->pvariables[PV->U][cellIdA2];
2182 MFloat v2 = m_cells->pvariables[PV->V][cellIdA2];
2183 MFloat w2 = m_cells->pvariables[PV->W][cellIdA2];
2184
2185 MFloat pG1 = p1;
2186 MFloat pG2 = p1;
2187 MFloat rhoG1 = rho1;
2188 MFloat rhoG2 = rho1;
2189
2190 MFloat uG1 = F2 * gridVel[0] - u1;
2191 MFloat vG1 = F2 * gridVel[1] - v1;
2192 MFloat wG1 = F2 * gridVel[2] - w1;
2193
2194 const MFloat uG2 = F2 * gridVel[0] - u2;
2195 const MFloat vG2 = F2 * gridVel[1] - v2;
2196 const MFloat wG2 = F2 * gridVel[2] - w2;
2197
2198 m_cells->pvariables[PV->RHO][cellIdG1] = rhoG1;
2199 m_cells->pvariables[PV->U][cellIdG1] = uG1;
2200 m_cells->pvariables[PV->V][cellIdG1] = vG1;
2201 m_cells->pvariables[PV->W][cellIdG1] = wG1;
2202 m_cells->pvariables[PV->P][cellIdG1] = pG1;
2203
2204 m_cells->pvariables[PV->RHO][cellIdG2] = rhoG2;
2205 m_cells->pvariables[PV->U][cellIdG2] = uG2;
2206 m_cells->pvariables[PV->V][cellIdG2] = vG2;
2207 m_cells->pvariables[PV->W][cellIdG2] = wG2;
2208 m_cells->pvariables[PV->P][cellIdG2] = pG2;
2209 }
2210 }
2211 break;
2212 }
2213 default: {
2214 cout << "bc1007: face not implemented" << endl;
2215 }
2216 }
2217}
2218
2219
2225template <MBool isRans>
2227 // implemented for i-direction only for the moment
2228 MInt* start = m_physicalBCMap[bcId]->start1;
2229 MInt* end = m_physicalBCMap[bcId]->end1;
2230 switch(m_physicalBCMap[bcId]->face) {
2231 case 0: {
2232 MInt cellId = -1;
2233 MInt cellIdadj = -1;
2234 for(MInt k = start[2]; k < end[2]; k++) {
2235 for(MInt j = start[1]; j < end[1]; j++) {
2236 for(MInt i = start[0]; i < end[0]; i++) {
2237 cellId = cellIndex(m_noGhostLayers - 1 - i, j, k);
2238 cellIdadj = cellIndex(m_noGhostLayers - i, j, k);
2239
2240 MFloat y = m_cells->coordinates[1][cellId];
2241 MFloat z = m_cells->coordinates[2][cellId];
2242 MFloat phi = atan2(y, z);
2243 MFloat r = sqrt(POW2(y) + POW2(z));
2244 MFloat rmax = 10.0;
2245
2246 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
2247 m_cells->pvariables[PV->U][cellId] = PV->UInfinity;
2248 m_cells->pvariables[PV->V][cellId] = -(r / rmax) * cos(phi) * PV->UInfinity;
2249 m_cells->pvariables[PV->W][cellId] = (r / rmax) * sin(phi) * PV->UInfinity;
2250 m_cells->pvariables[PV->P][cellId] = m_cells->pvariables[PV->P][cellIdadj];
2251 }
2252 }
2253 }
2254 break;
2255 }
2256 case 2: {
2257 for(MInt k = start[2]; k < end[2]; k++) {
2258 for(MInt j = start[1]; j < end[1]; j++) {
2259 for(MInt i = start[0]; i < end[0]; i++) {
2260 const MInt cellId = cellIndex(i, m_noGhostLayers - j - 1, k); // ghost
2261 const MInt cellIdadj = cellIndex(i, m_noGhostLayers - j, k); // field
2262 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
2263 m_cells->pvariables[PV->U][cellId] = PV->UInfinity;
2264 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
2265 m_cells->pvariables[PV->W][cellId] = PV->WInfinity;
2266
2267 m_cells->pvariables[PV->P][cellId] = m_cells->pvariables[PV->P][cellIdadj];
2268 }
2269 }
2270 }
2271 break;
2272 }
2273 default: {
2274 mTerm(1, AT_, "Face direction not implemented)");
2275 }
2276 }
2277}
2278
2279
2285template <MBool isRans>
2287 MInt* start = m_physicalBCMap[bcId]->start1;
2288 MInt* end = m_physicalBCMap[bcId]->end1;
2289 MInt face = m_physicalBCMap[bcId]->face;
2290 const MInt n = face % 2;
2291 const MInt dim = face / 2;
2292 MInt offset[3] = {0, 0, 0};
2293 MInt inc[3] = {1, 1, 1};
2294 MInt adjInc[3] = {0, 0, 0};
2295
2296 // on face 0,2,4 set offset and
2297 // reverse the incrementor
2298 if(n == 0) {
2299 offset[dim] = m_noGhostLayers - 1;
2300 inc[dim] = -1;
2301 adjInc[dim] = 1;
2302 } else {
2303 inc[dim] = 1;
2304 adjInc[dim] = -1;
2305 }
2306
2307 for(MInt k = start[2]; k < end[2]; k++) {
2308 for(MInt j = start[1]; j < end[1]; j++) {
2309 for(MInt i = start[0]; i < end[0]; i++) {
2310 const MInt ii = inc[0] * (i - start[0]) + start[0] + offset[0];
2311 const MInt jj = inc[1] * (j - start[1]) + start[1] + offset[1];
2312 const MInt kk = inc[2] * (k - start[2]) + start[2] + offset[2];
2313 const MInt cellId = cellIndex(ii, jj, kk);
2314 const MInt cellIdadj = cellIndex(ii + adjInc[0], jj + adjInc[1], kk + adjInc[2]);
2315
2316 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
2317 m_cells->pvariables[PV->U][cellId] = PV->UInfinity;
2318 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
2319 m_cells->pvariables[PV->W][cellId] = PV->WInfinity;
2320 if(isRans) {
2321 m_cells->pvariables[PV->RANS_VAR[0]][cellId] = CV->ransInfinity[0] / CV->rhoInfinity;
2322 }
2323
2324 // extrapolate pressure from the field
2325 m_cells->pvariables[PV->P][cellId] = m_cells->pvariables[PV->P][cellIdadj];
2326 }
2327 }
2328 }
2329}
2330
2337template <MBool isRans>
2339 (void)bcId;
2340}
2341
2342
2348template <MBool isRans>
2350 // implemented for i-direction only for the moment
2351 MInt* start = m_physicalBCMap[bcId]->start1;
2352 MInt* end = m_physicalBCMap[bcId]->end1;
2353 MFloat y = F0;
2354 switch(m_physicalBCMap[bcId]->face) {
2355 case 0: {
2356 for(MInt k = start[2]; k < end[2]; k++) {
2357 for(MInt j = start[1]; j < end[1]; j++) {
2358 for(MInt i = start[0]; i < end[0]; i++) {
2359 const MInt cellId = cellIndex(m_noGhostLayers - 1 - i, j, k);
2360 const MInt cellIdadj = cellIndex(m_noGhostLayers - i, j, k);
2361 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
2362 m_cells->pvariables[PV->U][cellId] = PV->UInfinity;
2363 y = m_cells->coordinates[1][cellId];
2364 if(y < 1.0) {
2365 m_cells->pvariables[PV->U][cellId] = PV->UInfinity * pow(y, (1.0 / 7.0));
2366 }
2367 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
2368 m_cells->pvariables[PV->W][cellId] = PV->WInfinity;
2369 m_cells->pvariables[PV->P][cellId] = m_cells->pvariables[PV->P][cellIdadj];
2370 }
2371 }
2372 }
2373 break;
2374 }
2375 default: {
2376 mTerm(1, AT_, "Face direction not implemented)");
2377 }
2378 }
2379}
2380
2386template <MBool isRans>
2388 TRACE();
2389 // implemented for i-direction only for the moment
2390 MInt* start = m_physicalBCMap[bcId]->start1;
2391 MInt* end = m_physicalBCMap[bcId]->end1;
2392
2393 MInt cellId = -1;
2394 for(MInt k = start[2]; k < end[2]; k++) {
2395 for(MInt j = start[1]; j < end[1]; j++) {
2396 for(MInt i = start[0]; i < end[0]; i++) {
2397 cellId = cellIndex(i, j, k);
2398 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
2399 m_cells->pvariables[PV->U][cellId] = PV->UInfinity;
2400 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
2401 m_cells->pvariables[PV->W][cellId] = PV->WInfinity;
2402 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
2403 if(isRans) {
2404 m_cells->pvariables[PV->RANS_VAR[0]][cellId] = CV->ransInfinity[0] / CV->rhoInfinity;
2405 }
2406 }
2407 }
2408 }
2409}
2410
2414template <MBool isRans>
2416 MInt* start = m_physicalBCMap[bcId]->start1;
2417 MInt* end = m_physicalBCMap[bcId]->end1;
2418 MInt face = m_physicalBCMap[bcId]->face;
2419 const MInt n = face % 2;
2420 const MInt dim = face / 2;
2421 MInt offset[3] = {0, 0, 0};
2422 MInt inc[3] = {1, 1, 1};
2423 MInt adjInc[3] = {0, 0, 0};
2424
2425 // on face 0,2,4 set offset and
2426 // reverse the incrementor
2427 if(n == 0) {
2428 offset[dim] = m_noGhostLayers - 1;
2429 inc[dim] = -1;
2430 adjInc[dim] = 1;
2431 } else {
2432 inc[dim] = 1;
2433 adjInc[dim] = -1;
2434 }
2435
2436 for(MInt k = start[2]; k < end[2]; k++) {
2437 for(MInt j = start[1]; j < end[1]; j++) {
2438 for(MInt i = start[0]; i < end[0]; i++) {
2439 const MInt ii = inc[0] * (i - start[0]) + start[0] + offset[0];
2440 const MInt jj = inc[1] * (j - start[1]) + start[1] + offset[1];
2441 const MInt kk = inc[2] * (k - start[2]) + start[2] + offset[2];
2442 const MInt cellId = cellIndex(ii, jj, kk);
2443 const MInt cellIdadj = cellIndex(ii + adjInc[0], jj + adjInc[1], kk + adjInc[2]);
2444
2445 for(MInt var = 0; var < PV->noVariables; var++) {
2446 m_cells->pvariables[var][cellId] = m_cells->pvariables[var][cellIdadj];
2447 }
2448 }
2449 }
2450 }
2451}
2452
2461template <MBool isRans>
2463 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
2464 MInt* start = m_physicalBCMap[bcId]->start1;
2465 MInt* end = m_physicalBCMap[bcId]->end1;
2466
2467 // Here we find out the normal direction of the
2468 // boundary and the two tangential directions.
2469 // This way we can make a general formulation of
2470 // the boundary condition
2471 const MInt face = m_physicalBCMap[bcId]->face;
2472 const MInt normalDir = face / 2;
2473 const MInt firstTangentialDir = (normalDir + 1) % nDim;
2474 const MInt secondTangentialDir = (normalDir + 2) % nDim;
2475 const MInt normalDirStart = start[normalDir];
2476 const MInt firstTangentialStart = start[firstTangentialDir];
2477 const MInt firstTangentialEnd = end[firstTangentialDir];
2478 const MInt secondTangentialStart = start[secondTangentialDir];
2479 const MInt secondTangentialEnd = end[secondTangentialDir];
2480 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
2481
2482 const MInt n = (face % 2) * 2 - 1; //-1,+1
2483 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
2484 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
2485 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
2486 const MInt a2 = normalDirStart + (MInt)(0.5 - (2.5 * (MFloat)n)); //+3,-2
2487
2488 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
2489 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
2490 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
2491 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
2492 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
2493 const MInt cellIdA2 = a2 * inc[0] + t1 * inc[1] + t2 * inc[2];
2494
2495 const MFloat dxidx = m_cells->surfaceMetrics[normalDir * nDim + 0][cellIdA1];
2496 const MFloat dxidy = m_cells->surfaceMetrics[normalDir * nDim + 1][cellIdA1];
2497 const MFloat dxidz = m_cells->surfaceMetrics[normalDir * nDim + 2][cellIdA1];
2498 // leaving domain of integration in positive coordinate direction,
2499 // therefore multiply with positive F1
2500 const MFloat gradxi = n * F1 / sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz);
2501
2502 const MFloat rhoInner = m_cells->pvariables[PV->RHO][cellIdA1];
2503 const MFloat uInner = m_cells->pvariables[PV->U][cellIdA1];
2504 const MFloat vInner = m_cells->pvariables[PV->V][cellIdA1];
2505 const MFloat wInner = m_cells->pvariables[PV->W][cellIdA1];
2506 const MFloat pInner = m_cells->pvariables[PV->P][cellIdA1];
2507
2508 const MFloat maContravariant =
2509 (dxidx * uInner + dxidy * vInner + dxidz * wInner - m_cells->dxt[normalDir][cellIdA1]) * gradxi;
2510
2511
2512 if(maContravariant < F0) {
2513 // inflow
2514 const MFloat p = pInner;
2515 const MFloat rho = CV->rhoInfinity;
2516
2517 m_cells->pvariables[PV->RHO][cellIdG1] = rho;
2518 m_cells->pvariables[PV->U][cellIdG1] = PV->UInfinity;
2519 m_cells->pvariables[PV->V][cellIdG1] = PV->VInfinity;
2520 m_cells->pvariables[PV->W][cellIdG1] = PV->WInfinity;
2521 m_cells->pvariables[PV->P][cellIdG1] = p;
2522
2523 if(isRans) {
2524 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG1] = CV->ransInfinity[0] / CV->rhoInfinity;
2525 }
2526 } else {
2527 // outflow
2528 const MFloat p = PV->PInfinity;
2529 const MFloat rho = rhoInner;
2530
2531 m_cells->pvariables[PV->RHO][cellIdG1] = rho;
2532 m_cells->pvariables[PV->U][cellIdG1] = uInner;
2533 m_cells->pvariables[PV->V][cellIdG1] = vInner;
2534 m_cells->pvariables[PV->W][cellIdG1] = wInner;
2535 m_cells->pvariables[PV->P][cellIdG1] = p;
2536 if(isRans) {
2537 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG1] =
2538 (F2 * m_cells->pvariables[PV->RANS_VAR[0]][cellIdA1] - m_cells->pvariables[PV->RANS_VAR[0]][cellIdA2]);
2539 }
2540 }
2541
2542 // extrapolate into second ghost cell
2543 for(MInt var = 0; var < PV->noVariables; var++) {
2544 m_cells->pvariables[var][cellIdG2] =
2545 F2 * m_cells->pvariables[var][cellIdG1] - m_cells->pvariables[var][cellIdA1];
2546 }
2547 }
2548 }
2549}
2550
2551
2559template <MBool isRans>
2561 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
2562 const MFloat gamma = m_solver->m_gamma;
2563 MInt* start = m_physicalBCMap[bcId]->start1;
2564 MInt* end = m_physicalBCMap[bcId]->end1;
2565
2566 // Here we find out the normal direction of the
2567 // boundary and the two tangential directions.
2568 // This way we can make a general formulation of
2569 // the boundary condition
2570 const MInt face = m_physicalBCMap[bcId]->face;
2571 const MInt normalDir = face / 2;
2572 const MInt firstTangentialDir = (normalDir + 1) % nDim;
2573 const MInt secondTangentialDir = (normalDir + 2) % nDim;
2574 const MInt normalDirStart = start[normalDir];
2575 const MInt firstTangentialStart = start[firstTangentialDir];
2576 const MInt firstTangentialEnd = end[firstTangentialDir];
2577 const MInt secondTangentialStart = start[secondTangentialDir];
2578 const MInt secondTangentialEnd = end[secondTangentialDir];
2579 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
2580
2581 const MInt n = (face % 2) * 2 - 1; //-1,+1
2582 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
2583 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
2584 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
2585 const MInt a2 = normalDirStart + (MInt)(0.5 - (2.5 * (MFloat)n)); //+3,-2
2586
2587 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
2588 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
2589 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
2590 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
2591 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
2592 const MInt cellIdA2 = a2 * inc[0] + t1 * inc[1] + t2 * inc[2];
2593
2594 const MFloat dxidx = m_cells->surfaceMetrics[normalDir * nDim + 0][cellIdA1];
2595 const MFloat dxidy = m_cells->surfaceMetrics[normalDir * nDim + 1][cellIdA1];
2596 const MFloat dxidz = m_cells->surfaceMetrics[normalDir * nDim + 2][cellIdA1];
2597 // multiply with n, so it will be -1 or +1 depending if we enter
2598 // or leave the domain of integration in positive direction
2599 const MFloat gradxi = n * F1 / sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz);
2600
2601 const MFloat dxHelp = dxidx * gradxi;
2602 const MFloat dyHelp = dxidy * gradxi;
2603 const MFloat dzHelp = dxidz * gradxi;
2604
2605
2606 const MFloat cBC = sqrt(gamma * m_cells->pvariables[PV->P][cellIdG1] / m_cells->pvariables[PV->RHO][cellIdG1]);
2607 const MFloat rhoBC = m_cells->pvariables[PV->RHO][cellIdG1];
2608
2609 const MFloat rhoInner = m_cells->pvariables[PV->RHO][cellIdA1];
2610 const MFloat uInner = m_cells->pvariables[PV->U][cellIdA1];
2611 const MFloat vInner = m_cells->pvariables[PV->V][cellIdA1];
2612 const MFloat wInner = m_cells->pvariables[PV->W][cellIdA1];
2613 const MFloat pInner = m_cells->pvariables[PV->P][cellIdA1];
2614
2615 const MFloat maContravariant =
2616 (dxidx * uInner + dxidy * vInner + dxidz * wInner - m_cells->dxt[normalDir][cellIdA1]) * gradxi;
2617
2618 if(maContravariant < F0) {
2619 // inflow
2620 const MFloat p = F1B2
2621 * (pInner + PV->PInfinity
2622 + rhoBC * cBC
2623 * (dxHelp * (uInner - PV->UInfinity) + dyHelp * (vInner - PV->VInfinity)
2624 + dzHelp * (wInner - PV->WInfinity)));
2625
2626 const MFloat rho = CV->rhoInfinity + (p - PV->PInfinity) / POW2(cBC);
2627 const MFloat help = (p - PV->PInfinity) / (rhoBC * cBC);
2628
2629 m_cells->pvariables[PV->RHO][cellIdG1] = rho;
2630 m_cells->pvariables[PV->U][cellIdG1] = (PV->UInfinity + help * dxHelp);
2631 m_cells->pvariables[PV->V][cellIdG1] = (PV->VInfinity + help * dyHelp);
2632 m_cells->pvariables[PV->W][cellIdG1] = (PV->WInfinity + help * dzHelp);
2633 m_cells->pvariables[PV->P][cellIdG1] = p;
2634 if(isRans) {
2635 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG1] = PV->ransInfinity[0];
2636 }
2637 } else {
2638 // outflow
2639 const MFloat p = PV->PInfinity;
2640 const MFloat rho = rhoInner + (p - pInner) / POW2(cBC);
2641 const MFloat help = (p - pInner) / (rhoBC * cBC);
2642
2643 m_cells->pvariables[PV->RHO][cellIdG1] = rho;
2644 m_cells->pvariables[PV->U][cellIdG1] = (uInner - help * dxHelp);
2645 m_cells->pvariables[PV->V][cellIdG1] = (vInner - help * dyHelp);
2646 m_cells->pvariables[PV->W][cellIdG1] = (wInner - help * dzHelp);
2647 m_cells->pvariables[PV->P][cellIdG1] = p;
2648 if(isRans) {
2649 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG1] =
2650 (F2 * m_cells->pvariables[PV->RANS_VAR[0]][cellIdA1] - m_cells->pvariables[PV->RANS_VAR[0]][cellIdA2]);
2651 }
2652 }
2653
2654 // extrapolate into second ghost cell
2655 for(MInt var = 0; var < PV->noVariables; var++) {
2656 m_cells->pvariables[var][cellIdG2] =
2657 F2 * m_cells->pvariables[var][cellIdG1] - m_cells->pvariables[var][cellIdA1];
2658 }
2659 }
2660 }
2661}
2662
2663
2664template <MBool isRans>
2666 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
2667 const MFloat gamma = m_solver->m_gamma;
2668 MInt* start = m_physicalBCMap[bcId]->start1;
2669 MInt* end = m_physicalBCMap[bcId]->end1;
2670
2671 // Here we find out the normal direction of the
2672 // boundary and the two tangential directions.
2673 // This way we can make a general formulation of
2674 // the boundary condition
2675 const MInt face = m_physicalBCMap[bcId]->face;
2676 const MInt normalDir = face / 2;
2677 const MInt firstTangentialDir = (normalDir + 1) % nDim;
2678 const MInt secondTangentialDir = (normalDir + 2) % nDim;
2679 const MInt normalDirStart = start[normalDir];
2680 const MInt firstTangentialStart = start[firstTangentialDir];
2681 const MInt firstTangentialEnd = end[firstTangentialDir];
2682 const MInt secondTangentialStart = start[secondTangentialDir];
2683 const MInt secondTangentialEnd = end[secondTangentialDir];
2684 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
2685
2686 const MInt n = (face % 2) * 2 - 1; //-1,+1
2687 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
2688 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
2689 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
2690 const MInt a2 = normalDirStart + (MInt)(0.5 - (2.5 * (MFloat)n)); //+3,-2
2691
2692 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
2693 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
2694 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
2695 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
2696 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
2697 const MInt cellIdA2 = a2 * inc[0] + t1 * inc[1] + t2 * inc[2];
2698
2699 const MFloat dxidx = m_cells->surfaceMetrics[normalDir * nDim + 0][cellIdA1];
2700 const MFloat dxidy = m_cells->surfaceMetrics[normalDir * nDim + 1][cellIdA1];
2701 const MFloat dxidz = m_cells->surfaceMetrics[normalDir * nDim + 2][cellIdA1];
2702 // multiply with n, so it will be -1 or +1 depending if we enter
2703 // or leave the domain of integration in positive direction
2704 const MFloat gradxi = n * F1 / sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz);
2705
2706 const MFloat dxHelp = dxidx * gradxi;
2707 const MFloat dyHelp = dxidy * gradxi;
2708 const MFloat dzHelp = dxidz * gradxi;
2709
2710
2711 const MFloat cBC = sqrt(gamma * m_cells->pvariables[PV->P][cellIdG1] / m_cells->pvariables[PV->RHO][cellIdG1]);
2712 const MFloat rhoBC = m_cells->pvariables[PV->RHO][cellIdG1];
2713
2714 const MFloat rhoInner = m_cells->pvariables[PV->RHO][cellIdA1];
2715 const MFloat uInner = m_cells->pvariables[PV->U][cellIdA1];
2716 const MFloat vInner = m_cells->pvariables[PV->V][cellIdA1];
2717 const MFloat wInner = m_cells->pvariables[PV->W][cellIdA1];
2718 const MFloat pInner = m_cells->pvariables[PV->P][cellIdA1];
2719
2720 const MFloat maContravariant =
2721 (dxidx * uInner + dxidy * vInner + dxidz * wInner - m_cells->dxt[normalDir][cellIdA1]) * gradxi;
2722
2723 if(maContravariant < F0) {
2724 // inflow
2725 const MFloat uZonal = m_cells->fq[FQ->AVG_U][cellIdG1];
2726 const MFloat vZonal = m_cells->fq[FQ->AVG_V][cellIdG1];
2727 const MFloat wZonal = m_cells->fq[FQ->AVG_W][cellIdG1];
2728 const MFloat pZonal = m_cells->fq[FQ->AVG_P][cellIdG1];
2729 const MFloat rhoZonal = m_cells->fq[FQ->AVG_RHO][cellIdG1];
2730 const MFloat p =
2731 F1B2
2732 * (pInner + pZonal
2733 + rhoBC * cBC * (dxHelp * (uInner - uZonal) + dyHelp * (vInner - vZonal) + dzHelp * (wInner - wZonal)));
2734
2735 const MFloat rho = rhoZonal + pZonal / POW2(cBC);
2736 const MFloat help = (p - pZonal) / (rhoBC * cBC);
2737
2738 m_cells->pvariables[PV->RHO][cellIdG1] = rho;
2739 m_cells->pvariables[PV->U][cellIdG1] = (uZonal + help * dxHelp);
2740 m_cells->pvariables[PV->V][cellIdG1] = (vZonal + help * dyHelp);
2741 m_cells->pvariables[PV->W][cellIdG1] = (wZonal + help * dzHelp);
2742 m_cells->pvariables[PV->P][cellIdG1] = p;
2743
2744 if(isRans) {
2745 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG1] = m_cells->pvariables[PV->RANS_VAR[0]][cellIdA1];
2746 }
2747 } else {
2748 // outflow
2749 const MFloat pZonal = m_cells->fq[FQ->AVG_P][cellIdG1];
2750 const MFloat rho = rhoInner + (pZonal - pInner) / POW2(cBC);
2751 const MFloat help = (pZonal - pInner) / (rhoBC * cBC);
2752
2753 m_cells->pvariables[PV->RHO][cellIdG1] = rho;
2754 m_cells->pvariables[PV->U][cellIdG1] = (uInner - help * dxHelp);
2755 m_cells->pvariables[PV->V][cellIdG1] = (vInner - help * dyHelp);
2756 m_cells->pvariables[PV->W][cellIdG1] = (wInner - help * dzHelp);
2757 m_cells->pvariables[PV->P][cellIdG1] = pZonal;
2758 if(isRans) {
2759 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG1] =
2760 (F2 * m_cells->pvariables[PV->RANS_VAR[0]][cellIdA1] - m_cells->pvariables[PV->RANS_VAR[0]][cellIdA2]);
2761 }
2762 }
2763
2764 // extrapolate into second ghost cell
2765 for(MInt var = 0; var < PV->noVariables; var++) {
2766 m_cells->pvariables[var][cellIdG2] =
2767 F2 * m_cells->pvariables[var][cellIdG1] - m_cells->pvariables[var][cellIdA1];
2768 }
2769 }
2770 }
2771}
2772
2773
2780template <MBool isRans>
2782 const MFloat gamma = m_solver->m_gamma;
2783 const MFloat gammaMinusOne = gamma - 1.0;
2784 const MFloat gammaPlusOne = gamma + 1.0;
2785 MInt* start = m_physicalBCMap[bcId]->start1;
2786 MInt* end = m_physicalBCMap[bcId]->end1;
2787 MFloat rho2 = F0, u2 = F0, v2tmp = F0, p2 = F0; // Conditions behind the shock
2788 MFloat u1n = F0, v1n = F0, u2n = F0,
2789 v2n = F0; // Velocities normal to the shock upstream and downstream of the shock
2790 MFloat rho21 = F0, p21 = F0; // quotient of the values upstream and downstream of the shock
2791 MFloat beta = F0, M_mean = m_solver->m_Ma;
2792
2793 // pressure and density ratio over the shock
2794 rho21 = gammaPlusOne * POW2(M_mean * sin(m_sigma)) / (gammaMinusOne * POW2(M_mean * sin(m_sigma)) + 2);
2795 p21 = 1.0 + 2 * gamma / gammaPlusOne * (POW2(M_mean * sin(m_sigma)) - 1);
2796
2797
2798 // normal and parallel velocities upstream of the shock
2799 u1n = M_mean * sqrt(PV->TInfinity) * sin(m_sigma);
2800 v1n = M_mean * sqrt(PV->TInfinity) * cos(m_sigma);
2801 // normal and parallel velocity downstream of the shock
2802 u2n = u1n / rho21;
2803 v2n = v1n;
2804
2805 beta = m_sigma - atan(u2n / v2n); // redirection angle of the flow
2806
2807 u2 = sqrt(POW2(u2n) + POW2(v2n)) * cos(beta);
2808 v2tmp = sqrt(POW2(u2n) + POW2(v2n)) * sin(beta);
2809
2810 rho2 = rho21 * CV->rhoInfinity;
2811 p2 = p21 * PV->PInfinity;
2812
2813 switch(m_physicalBCMap[bcId]->face) {
2814 case 3: {
2815 MInt cellId = -1;
2816 MInt cellIdadj = -1;
2817 MInt pIJK = 0, pIJPK = 0, pIJKP = 0, pIJPKP = 0;
2818 // fully new bc
2819 MInt j = start[1];
2820 MFloat pBC = F0, rho = F0, u = F0, v = F0, w = F0;
2821 MFloat drho = F0, du = F0, dv = F0, dw = F0, dp = F0;
2822 MFloat yBC = F0;
2823 MFloat v2 = F0;
2824 // pBC=PV->PInfinity;
2825 MFloat pInner = F0, c02 = F0, distance = F0;
2826
2827 // Change sign of the v velocity
2828 v2 = -v2tmp;
2829
2830 for(MInt k = start[2]; k < end[2]; k++) {
2831 for(MInt i = start[0]; i < end[0]; i++) {
2832 // cellId=cellIndex(i,j,k);
2833 cellIdadj = cellIndex(i, j - 1, k);
2834 // to determine the face coordinates!!!!!!
2835 pIJK = getPointIdFromCell(i, j, k);
2836 pIJPK = getPointIdfromPoint(pIJK, 1, 0, 0);
2837 pIJKP = getPointIdfromPoint(pIJK, 0, 0, 1);
2838 pIJPKP = getPointIdfromPoint(pIJK, 1, 0, 1);
2839
2840 // values at the inner point
2841 pInner = m_cells->pvariables[PV->P][cellIdadj];
2842 c02 = sqrt(gamma * pInner / m_cells->pvariables[PV->RHO][cellIdadj]);
2843 u = m_cells->pvariables[PV->U][cellIdadj];
2844 v = m_cells->pvariables[PV->V][cellIdadj];
2845 w = m_cells->pvariables[PV->W][cellIdadj];
2846
2847 MFloat dxidx = m_cells->surfaceMetrics[3][cellIdadj];
2848 MFloat dxidy = m_cells->surfaceMetrics[4][cellIdadj];
2849 MFloat dxidz = m_cells->surfaceMetrics[5][cellIdadj];
2850
2851 // leaving domain of integration in positive coordinate direction,
2852 // therefore multiply with positive F1
2853 MFloat gradxi = F1 / sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz);
2854
2855 MFloat dxHelp = dxidx * gradxi;
2856 MFloat dyHelp = dxidy * gradxi;
2857 MFloat dzHelp = dxidz * gradxi;
2858
2859 // values at the boundary
2860 pBC = F1B2
2861 * (pInner + p2
2862 + m_cells->pvariables[PV->RHO][cellIdadj] * c02
2863 * (dxHelp * (u - u2) + dyHelp * (v - v2) + dzHelp * (w - PV->WInfinity)));
2864 rho = rho2 + ((pBC - p2) / (c02 * c02));
2865
2866 u = u2 + dxHelp * (pBC - p2) / (m_cells->pvariables[PV->RHO][cellIdadj] * c02);
2867 v = v2 + dyHelp * (pBC - p2) / (m_cells->pvariables[PV->RHO][cellIdadj] * c02);
2868 w = PV->WInfinity + dzHelp * (pBC - p2) / (m_cells->pvariables[PV->RHO][cellIdadj] * c02);
2869
2870 // extrapolate the variables into the ghost cells
2871 // gradients
2872 yBC = F1B4
2873 * (m_grid->m_coordinates[1][pIJK] + m_grid->m_coordinates[1][pIJPK] + m_grid->m_coordinates[1][pIJKP]
2874 + m_grid->m_coordinates[1][pIJPKP]);
2875 distance = (yBC - m_cells->coordinates[1][cellIdadj]);
2876
2877 drho = (rho - m_cells->pvariables[PV->RHO][cellIdadj]) / distance;
2878 du = (u - m_cells->pvariables[PV->U][cellIdadj]) / distance;
2879 dv = (v - m_cells->pvariables[PV->V][cellIdadj]) / distance;
2880 dw = (w - m_cells->pvariables[PV->W][cellIdadj]) / distance;
2881 dp = (pBC - m_cells->pvariables[PV->P][cellIdadj]) / distance;
2882
2883 // extrapolate:
2884 for(MInt jj = start[1]; jj < end[1]; ++jj) {
2885 cellId = cellIndex(i, jj, k);
2886 distance = (m_cells->coordinates[1][cellId] - m_cells->coordinates[1][cellIdadj]);
2887 m_cells->pvariables[PV->RHO][cellId] = m_cells->pvariables[PV->RHO][cellIdadj] + drho * distance;
2888 m_cells->pvariables[PV->U][cellId] = m_cells->pvariables[PV->U][cellIdadj] + du * distance;
2889 m_cells->pvariables[PV->V][cellId] = m_cells->pvariables[PV->V][cellIdadj] + dv * distance;
2890 m_cells->pvariables[PV->W][cellId] = m_cells->pvariables[PV->W][cellIdadj] + dw * distance;
2891 m_cells->pvariables[PV->P][cellId] = m_cells->pvariables[PV->P][cellIdadj] + dp * distance;
2892 }
2893 }
2894 }
2895 break;
2896 }
2897 default: {
2898 mTerm(1, AT_, "BC-face not implemented");
2899 }
2900 }
2901}
2902
2903
2904template <MBool isRans>
2906 const MInt* start = m_physicalBCMap[bcId]->start1;
2907 const MInt* end = m_physicalBCMap[bcId]->end1;
2908 const MInt face = m_physicalBCMap[bcId]->face;
2909
2910 // const MInt dim = face/2;
2911 // const MInt n1m1[9] = {-1,1,1, 1,-1,1, 1,1,-1};
2912
2913 for(MInt k = start[2]; k < end[2]; k++) {
2914 for(MInt j = end[1] - 1; j >= start[1]; j--) {
2915 for(MInt i = start[0]; i < end[0]; i++) {
2916 MInt cellId = -1;
2917 MInt cellIdAdj = -1;
2918 tie(cellId, cellIdAdj) = getMirrorCellIdPair(i, j, k, face);
2919
2920 m_cells->pvariables[PV->RHO][cellId] = m_cells->pvariables[PV->RHO][cellIdAdj];
2921 m_cells->pvariables[PV->P][cellId] = m_cells->pvariables[PV->P][cellIdAdj];
2922 m_cells->pvariables[PV->U][cellId] = (1.0) * m_cells->pvariables[PV->U][cellIdAdj];
2923 m_cells->pvariables[PV->V][cellId] = (-1.0) * m_cells->pvariables[PV->V][cellIdAdj];
2924 m_cells->pvariables[PV->W][cellId] = (1.0) * m_cells->pvariables[PV->W][cellIdAdj];
2925 if(isRans) {
2926 m_cells->pvariables[PV->RANS_VAR[0]][cellId] = m_cells->pvariables[PV->RANS_VAR[0]][cellIdAdj];
2927 }
2928 }
2929 }
2930 }
2931}
2932
2939template <MBool isRans>
2941 (void)bcId;
2942}
2943
2952template <MBool isRans>
2954 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
2955 MInt* start = m_physicalBCMap[bcId]->start1;
2956 MInt* end = m_physicalBCMap[bcId]->end1;
2957
2958 // Here we find out the normal direction of the
2959 // boundary and the two tangential directions.
2960 // This way we can make a general formulation of
2961 // the boundary condition
2962 const MInt face = m_physicalBCMap[bcId]->face;
2963 const MInt normalDir = face / 2;
2964 const MInt firstTangentialDir = (normalDir + 1) % nDim;
2965 const MInt secondTangentialDir = (normalDir + 2) % nDim;
2966 const MInt normalDirStart = start[normalDir];
2967 const MInt firstTangentialStart = start[firstTangentialDir];
2968 const MInt firstTangentialEnd = end[firstTangentialDir];
2969 const MInt secondTangentialStart = start[secondTangentialDir];
2970 const MInt secondTangentialEnd = end[secondTangentialDir];
2971 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
2972
2973 const MInt n = (face % 2) * 2 - 1; //-1,+1
2974 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
2975 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
2976 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
2977 // const MInt a2 = normalDirStart + (MInt)(0.5-(2.5*(MFloat)n)); //+3,-2
2978
2979 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
2980 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
2981 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
2982 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
2983 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
2984 // const MInt cellIdA2 = a2*inc[0] + t1*inc[1] + t2*inc[2];
2985
2986 MFloat vel[nDim];
2987 m_solver->getFscVelocity(cellIdG1, vel);
2988
2989 m_cells->pvariables[PV->U][cellIdG1] = vel[0];
2990 m_cells->pvariables[PV->V][cellIdG1] = vel[1];
2991 m_cells->pvariables[PV->W][cellIdG1] = vel[2];
2992
2993 m_cells->pvariables[PV->P][cellIdG1] = m_cells->pvariables[PV->P][cellIdA1];
2994 m_cells->pvariables[PV->RHO][cellIdG1] = CV->rhoInfinity;
2995
2996 m_solver->getFscVelocity(cellIdG2, vel);
2997 m_cells->pvariables[PV->U][cellIdG2] = vel[0];
2998 m_cells->pvariables[PV->V][cellIdG2] = vel[1];
2999 m_cells->pvariables[PV->W][cellIdG2] = vel[2];
3000 m_cells->pvariables[PV->P][cellIdG1] =
3001 F2 * m_cells->pvariables[PV->P][cellIdG1] - m_cells->pvariables[PV->P][cellIdA1];
3002 m_cells->pvariables[PV->RHO][cellIdG2] = CV->rhoInfinity;
3003 }
3004 }
3005}
3006
3011template <MBool isRans>
3013 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
3014 MInt* start = m_physicalBCMap[bcId]->start1;
3015 MInt* end = m_physicalBCMap[bcId]->end1;
3016
3017 // Here we find out the normal direction of the
3018 // boundary and the two tangential directions.
3019 // This way we can make a general formulation of
3020 // the boundary condition
3021 const MInt face = m_physicalBCMap[bcId]->face;
3022 const MInt normalDir = face / 2;
3023 const MInt firstTangentialDir = (normalDir + 1) % nDim;
3024 const MInt secondTangentialDir = (normalDir + 2) % nDim;
3025 const MInt normalDirStart = start[normalDir];
3026 const MInt firstTangentialStart = start[firstTangentialDir];
3027 const MInt firstTangentialEnd = end[firstTangentialDir];
3028 const MInt secondTangentialStart = start[secondTangentialDir];
3029 const MInt secondTangentialEnd = end[secondTangentialDir];
3030 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
3031
3032 const MInt n = (face % 2) * 2 - 1; //-1,+1
3033 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
3034 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
3035 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
3036
3037 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
3038 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
3039 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
3040 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
3041 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
3042
3043 const MFloat rhoInner = m_cells->pvariables[PV->RHO][cellIdA1];
3044 const MFloat uInner = m_cells->pvariables[PV->U][cellIdA1];
3045 const MFloat vInner = m_cells->pvariables[PV->V][cellIdA1];
3046 const MFloat wInner = m_cells->pvariables[PV->W][cellIdA1];
3047
3048 m_cells->pvariables[PV->U][cellIdG1] = uInner;
3049 m_cells->pvariables[PV->V][cellIdG1] = vInner;
3050 m_cells->pvariables[PV->W][cellIdG1] = wInner;
3051 m_cells->pvariables[PV->P][cellIdG1] = m_solver->getFscPressure(cellIdG1);
3052 m_cells->pvariables[PV->RHO][cellIdG1] = rhoInner;
3053
3054 // extrapolate into second ghost cell
3055 for(MInt var = 0; var < PV->noVariables; var++) {
3056 m_cells->pvariables[var][cellIdG2] =
3057 F2 * m_cells->pvariables[var][cellIdG1] - m_cells->pvariables[var][cellIdA1];
3058 }
3059 }
3060 }
3061}
3062
3071template <MBool isRans>
3073 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
3074 MInt* start = m_physicalBCMap[bcId]->start1;
3075 MInt* end = m_physicalBCMap[bcId]->end1;
3076
3077 // Here we find out the normal direction of the
3078 // boundary and the two tangential directions.
3079 // This way we can make a general formulation of
3080 // the boundary condition
3081 const MInt face = m_physicalBCMap[bcId]->face;
3082 const MInt normalDir = face / 2;
3083 const MInt firstTangentialDir = (normalDir + 1) % nDim;
3084 const MInt secondTangentialDir = (normalDir + 2) % nDim;
3085 const MInt normalDirStart = start[normalDir];
3086 const MInt firstTangentialStart = start[firstTangentialDir];
3087 const MInt firstTangentialEnd = end[firstTangentialDir];
3088 const MInt secondTangentialStart = start[secondTangentialDir];
3089 const MInt secondTangentialEnd = end[secondTangentialDir];
3090 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
3091
3092 const MInt n = (face % 2) * 2 - 1; //-1,+1
3093 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
3094 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
3095 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
3096 // const MInt a2 = normalDirStart + (MInt)(0.5-(2.5*(MFloat)n)); //+3,-2
3097
3098 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
3099 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
3100 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
3101 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
3102 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
3103 // const MInt cellIdA2 = a2*inc[0] + t1*inc[1] + t2*inc[2];
3104
3105 MFloat vel[nDim];
3106 m_solver->getBlasiusVelocity(cellIdG1, vel);
3107
3108 m_cells->pvariables[PV->U][cellIdG1] = vel[0];
3109 m_cells->pvariables[PV->V][cellIdG1] = vel[1];
3110 m_cells->pvariables[PV->W][cellIdG1] = vel[2];
3111
3112 m_cells->pvariables[PV->P][cellIdG1] = m_cells->pvariables[PV->P][cellIdA1];
3113 m_cells->pvariables[PV->RHO][cellIdG1] = CV->rhoInfinity;
3114
3115 m_solver->getBlasiusVelocity(cellIdG2, vel);
3116 m_cells->pvariables[PV->U][cellIdG2] = vel[0];
3117 m_cells->pvariables[PV->V][cellIdG2] = vel[1];
3118 m_cells->pvariables[PV->W][cellIdG2] = vel[2];
3119 m_cells->pvariables[PV->P][cellIdG2] =
3120 F2 * m_cells->pvariables[PV->P][cellIdG1] - m_cells->pvariables[PV->P][cellIdA1];
3121 m_cells->pvariables[PV->RHO][cellIdG2] = CV->rhoInfinity;
3122 }
3123 }
3124}
3125
3137template <MBool isRans>
3139 const MInt NU_T = 5;
3140 const MInt SIJSIJ = 6;
3141 const MInt LENGTH_SCALE = 7;
3142 const MInt FLUC_UU = 8;
3143 const MInt FLUC_VV = 9;
3144 const MInt FLUC_WW = 10;
3145 const MInt FLUC_UV = 11;
3146 const MInt FLUC_VW = 12;
3147 const MInt FLUC_UW = 13;
3148 const MInt FLUC_U = 14;
3149 const MInt FLUC_V = 15;
3150 const MInt FLUC_W = 16;
3151 const MInt LENGTH_X = 17;
3152 const MInt LENGTH_Y = 18;
3153 const MInt LENGTH_Z = 19;
3154
3155 const MFloat gamma = m_solver->m_gamma;
3156 const MFloat gammaMinusOne = gamma - 1.0;
3157
3158 MInt* start = m_physicalBCMap[bcId]->start1;
3159 MInt* end = m_physicalBCMap[bcId]->end1;
3160
3161 // Initalization of variables that will be used
3162 MFloat SijSij, Vb;
3163 MInt I, IBC;
3164 const MInt ii = 1;
3165 const MInt nran = m_solver->m_stgMaxNoEddies;
3166
3167 // Arrays for MPI operations
3168 MFloatScratchSpace maxValsLocal(4, AT_, "maxValsLocal");
3169 MFloatScratchSpace maxValsGlobal(4, AT_, "maxValsGlobal");
3170 maxValsLocal.fill(F0);
3171 maxValsGlobal.fill(F0);
3172
3173 MFloatScratchSpace eddyBcastBuffer(nran * m_solver->m_stgNoEddieProperties, AT_, "eddyBcastBuffer");
3174 eddyBcastBuffer.fill(F0);
3175
3177 // Value initialization for some variables
3179
3180 I = cellIndex(start[0], start[1], start[2]);
3181 const MFloat fre = 1.0 / m_solver->m_Re0;
3182
3183 // Limiters
3184 const MFloat epss = 1e-34;
3185 const MFloat eps = 1e-16;
3186 const MFloat epsl = 1e-13;
3187
3188 // Box volume must be specified manually and is sign sensitive
3189 const MFloat delta_in = m_solver->m_stgDelta99Inflow;
3190
3191 const MFloat BLT1 = abs(m_stgVbEnd[0] - m_stgVbStart[0]);
3192 const MFloat BLT2 = abs(m_stgVbEnd[1] - m_stgVbStart[1]);
3193 const MFloat BLT3 = abs(m_stgVbEnd[2] - m_stgVbStart[2]);
3194
3195 // Manual parameters
3196 const MFloat c_mu = 0.09;
3197 const MFloat a1 = 1 / sqrt(c_mu);
3198
3199 const MFloat timsm = 0.3; // Smoothing factor for new eddies (in time)
3200 const MFloat aniso = 1.0; // Anisotropic, clustered eddies
3201 const MFloat exple = m_solver->m_stgExple; // to scale length of eddies
3202
3203 Vb = 0.0; // Initial box volume
3204
3205 MInt I1 = cellIndexBC(ii, start[1] + m_noGhostLayers, start[2] + m_noGhostLayers);
3206
3207 MFloat rhoRANSI1 = m_cells->stg_fq[PV->RHO][I1];
3208 MFloat pressure1 = m_cells->stg_fq[PV->P][I1];
3209
3210 const MFloat temp = m_solver->m_gamma * pressure1 / rhoRANSI1;
3211 const MFloat xmu = SUTHERLANDLAW(temp);
3212
3213 // get delta0 boundary layer thickness:
3214 if(globalTimeStep % 250 == 0 && m_solver->m_RKStep == 0) {
3215 MInt bndryLayerIndex = 0;
3216 MFloat u99_0 = F0, u99_1 = F0;
3217 for(MInt j = start[1] + m_noGhostLayers; j < end[1] - m_noGhostLayers; j++) {
3218 if(m_cells->stg_fq[PV->U][cellIndexBC(0, j, 2)] >= 0.99 * PV->UInfinity
3219 && m_cells->stg_fq[PV->U][cellIndexBC(0, j - 1, 2)] < 0.99 * PV->UInfinity) {
3220 u99_0 = m_cells->stg_fq[PV->U][cellIndexBC(0, j - 1, 2)];
3221 u99_1 = m_cells->stg_fq[PV->U][cellIndexBC(0, j, 2)];
3222 bndryLayerIndex = j - 1;
3223 break;
3224 }
3225 }
3226 MFloat bndryLayerThicknessLocal = 0.0;
3227 MFloat bndryLayerThicknessGlobal = 0.0;
3228
3229 if(bndryLayerIndex > 0) {
3230 bndryLayerThicknessLocal = m_cells->coordinates[1][cellIndex(0, bndryLayerIndex, 2)]
3231 + (0.99 * PV->UInfinity - u99_0) / (u99_1 - u99_0)
3232 * (m_cells->coordinates[1][cellIndex(0, bndryLayerIndex + 1, 2)]
3233 - m_cells->coordinates[1][cellIndex(0, bndryLayerIndex, 2)]);
3234 }
3235 MPI_Allreduce(&bndryLayerThicknessLocal, &bndryLayerThicknessGlobal, 1, MPI_DOUBLE, MPI_MAX, m_solver->m_commStg,
3236 AT_, "bndryLayerThicknessLocal", "bndryLayerThicknessGlobal");
3237 if(m_solver->m_stgMyRank == m_solver->m_commStgRoot) {
3238 cout << "Boundary Layer thickness delta99: " << bndryLayerThicknessGlobal << endl;
3239 }
3240 }
3241
3242 // this solver is only executed at the beginning as the RANS profile doesn't vary
3243 if((globalTimeStep <= m_solver->m_restartTimeStep)
3244 || ((m_solver->m_restartTimeStep == 0 && globalTimeStep < 2) && (m_solver->m_RKStep == 0))
3245 || (m_solver->m_zonal && (globalTimeStep % m_solver->m_zonalExchangeInterval == 0) && (m_solver->m_RKStep == 0))) {
3246 // Initialize max values
3247 MFloat utaumax = F0, umax = F0, vmax = F0, wmax = F0, minLengthLocal = F0;
3248
3249 if(m_solver->m_stgMyRank == m_solver->m_commStgRoot) {
3250 cout << "STG - Computing Reynolds Tensor Components and Length Scales..." << endl;
3251 }
3252
3253 for(MInt k = start[2] + 1; k < end[2] - 1; k++) {
3254 for(MInt j = start[1] + 1; j < end[1] - 1; j++) {
3256 // This is the metrics / strain tensor / max shear part
3258
3259 MInt IPJK, IMJK, IJPK, IJMK, IJKP, IJKM;
3260
3261 I = cellIndex(ii, j, k);
3262 IPJK = cellIndex(ii + 1, j, k);
3263 IMJK = cellIndex(ii - 1, j, k);
3264 IJPK = cellIndex(ii, j + 1, k);
3265 IJMK = cellIndex(ii, j - 1, k);
3266 IJKP = cellIndex(ii, j, k + 1);
3267 IJKM = cellIndex(ii, j, k - 1);
3268
3269
3270 const MFloat dxdi = F1B2 * (m_cells->coordinates[0][IPJK] - m_cells->coordinates[0][IMJK]);
3271 const MFloat dxdj = F1B2 * (m_cells->coordinates[0][IJPK] - m_cells->coordinates[0][IJMK]);
3272 const MFloat dxdk = F1B2 * (m_cells->coordinates[0][IJKP] - m_cells->coordinates[0][IJKM]);
3273 const MFloat dydi = F1B2 * (m_cells->coordinates[1][IPJK] - m_cells->coordinates[1][IMJK]);
3274 const MFloat dydj = F1B2 * (m_cells->coordinates[1][IJPK] - m_cells->coordinates[1][IJMK]);
3275 const MFloat dydk = F1B2 * (m_cells->coordinates[1][IJKP] - m_cells->coordinates[1][IJKM]);
3276 const MFloat dzdi = F1B2 * (m_cells->coordinates[2][IPJK] - m_cells->coordinates[2][IMJK]);
3277 const MFloat dzdj = F1B2 * (m_cells->coordinates[2][IJPK] - m_cells->coordinates[2][IJMK]);
3278 const MFloat dzdk = F1B2 * (m_cells->coordinates[2][IJKP] - m_cells->coordinates[2][IJKM]);
3279
3280 const MFloat dxl = sqrt(dxdi * dxdi + dydi * dydi + dzdi * dzdi);
3281 const MFloat dyl = sqrt(dxdj * dxdj + dydj * dydj + dzdj * dzdj);
3282 const MFloat dzl = sqrt(dxdk * dxdk + dydk * dydk + dzdk * dzdk);
3283
3284 const MFloat dxidx = (1. / max(m_cells->cellJac[I], epss)) * m_cells->cellMetrics[0][I];
3285 const MFloat dxidy = (1. / max(m_cells->cellJac[I], epss)) * m_cells->cellMetrics[1][I];
3286 const MFloat dxidz = (1. / max(m_cells->cellJac[I], epss)) * m_cells->cellMetrics[2][I];
3287
3288 const MFloat detadx = (1. / max(m_cells->cellJac[I], epss)) * m_cells->cellMetrics[3 + 0][I];
3289 const MFloat detady = (1. / max(m_cells->cellJac[I], epss)) * m_cells->cellMetrics[3 + 1][I];
3290 const MFloat detadz = (1. / max(m_cells->cellJac[I], epss)) * m_cells->cellMetrics[3 + 2][I];
3291
3292 const MFloat dzetadx = (1. / max(m_cells->cellJac[I], epss)) * m_cells->cellMetrics[6 + 0][I];
3293 const MFloat dzetady = (1. / max(m_cells->cellJac[I], epss)) * m_cells->cellMetrics[6 + 1][I];
3294 const MFloat dzetadz = (1. / max(m_cells->cellJac[I], epss)) * m_cells->cellMetrics[6 + 2][I];
3295
3296 IBC = cellIndexBC(ii, j, k);
3297 IPJK = cellIndexBC(ii + 1, j, k);
3298 IMJK = cellIndexBC(ii - 1, j, k);
3299 IJPK = cellIndexBC(ii, j + 1, k);
3300 IJMK = cellIndexBC(ii, j - 1, k);
3301 IJKP = cellIndexBC(ii, j, k + 1);
3302 IJKM = cellIndexBC(ii, j, k - 1);
3303
3304 const MFloat frho = 1.0 / m_cells->stg_fq[PV->RHO][IBC];
3305
3306 // dud?
3307 const MFloat dudxi = F1B2 * (m_cells->stg_fq[PV->U][IPJK] - m_cells->stg_fq[PV->U][IMJK]);
3308 const MFloat dudeta = F1B2 * (m_cells->stg_fq[PV->U][IJPK] - m_cells->stg_fq[PV->U][IJMK]);
3309 const MFloat dudzeta = F1B2 * (m_cells->stg_fq[PV->U][IJKP] - m_cells->stg_fq[PV->U][IJKM]);
3310
3311 // dvd?
3312 const MFloat dvdxi = F1B2 * (m_cells->stg_fq[PV->V][IPJK] - m_cells->stg_fq[PV->V][IMJK]);
3313 const MFloat dvdeta = F1B2 * (m_cells->stg_fq[PV->V][IJPK] - m_cells->stg_fq[PV->V][IJMK]);
3314 const MFloat dvdzeta = F1B2 * (m_cells->stg_fq[PV->V][IJKP] - m_cells->stg_fq[PV->V][IJKM]);
3315
3316 // dwd?
3317 const MFloat dwdxi = F1B2 * (m_cells->stg_fq[PV->W][IPJK] - m_cells->stg_fq[PV->W][IMJK]);
3318 const MFloat dwdeta = F1B2 * (m_cells->stg_fq[PV->W][IJPK] - m_cells->stg_fq[PV->W][IJMK]);
3319 const MFloat dwdzeta = F1B2 * (m_cells->stg_fq[PV->W][IJKP] - m_cells->stg_fq[PV->W][IJKM]);
3320
3321 const MFloat dudx = dudxi * dxidx + dudeta * detadx + dudzeta * dzetadx;
3322 const MFloat dudy = dudxi * dxidy + dudeta * detady + dudzeta * dzetady;
3323 const MFloat dudz = dudxi * dxidz + dudeta * detadz + dudzeta * dzetadz;
3324
3325 const MFloat dvdx = dvdxi * dxidx + dvdeta * detadx + dvdzeta * dzetadx;
3326 const MFloat dvdy = dvdxi * dxidy + dvdeta * detady + dvdzeta * dzetady;
3327 const MFloat dvdz = dvdxi * dxidz + dvdeta * detadz + dvdzeta * dzetadz;
3328
3329 const MFloat dwdx = dwdxi * dxidx + dwdeta * detadx + dwdzeta * dzetadx;
3330 const MFloat dwdy = dwdxi * dxidy + dwdeta * detady + dwdzeta * dzetady;
3331 const MFloat dwdz = dwdxi * dxidz + dwdeta * detadz + dwdzeta * dzetadz;
3332
3333
3334 const MFloat s11 = 2.0 * dudx;
3335 const MFloat s12 = dvdx + dudy;
3336 const MFloat s13 = dwdx + dudz;
3337
3338 const MFloat s21 = dudy + dvdx;
3339 const MFloat s22 = 2.0 * dvdy;
3340 const MFloat s23 = dwdy + dvdz;
3341
3342 const MFloat s31 = dudz + dwdx;
3343 const MFloat s32 = dvdz + dwdy;
3344 const MFloat s33 = 2.0 * dwdz;
3345
3346 // Strain tensor
3347 SijSij = F1B4
3348 * (s11 * s11 + s12 * s12 + s13 * s13 + s21 * s21 + s22 * s22 + s23 * s23 + s31 * s31 + s32 * s32
3349 + s33 * s33);
3350
3351 if(std::isnan(SijSij)) {
3352 cout << " dudxi : " << dudxi << " dudeta : " << dudeta << " dudzeta: " << dudzeta << " dvdxi : " << dvdxi
3353 << " dvdeta : " << dvdeta << " dvdzeta: " << dvdzeta << " dwdxi : " << dwdxi << " dwdeta : " << dwdeta
3354 << " dwdzeta: " << dwdzeta << endl;
3355 }
3356
3357
3358 //>marian: in TFS code this isn't SQRT
3359 m_cells->stg_fq[SIJSIJ][cellIndexBC(ii, j, k)] = SijSij;
3360
3361 // Assume a one-, or two equation turbulence model
3362 // Assume a simplified directivity:
3363
3364 // Read from RANS profile
3365 MFloat nu_t = m_cells->stg_fq[NU_T][cellIndexBC(m_noGhostLayers, j, k)];
3366
3367
3368 const MFloat sr1 = (s12 + s21) * (s12 + s21);
3369 const MFloat sr2 = (s23 + s32) * (s23 + s32);
3370 const MFloat sr3 = (s13 + s31) * (s13 + s31);
3371 const MFloat srt = max(sqrt(sr1 + sr2 + sr3), epsl);
3372
3373 const MFloat rr1 = sqrt(sr1) / srt;
3374 const MFloat rr2 = sqrt(sr2) / srt;
3375 const MFloat rr3 = sqrt(sr3) / srt;
3376
3377 const MFloat uv = -sqrt(2.0 * SijSij) * rr1 * nu_t * fre;
3378 const MFloat vw = -sqrt(2.0 * SijSij) * rr2 * nu_t * fre;
3379 const MFloat uw = -sqrt(2.0 * SijSij) * rr3 * nu_t * fre;
3380 const MFloat uu = a1 * abs(uv) * m_solver->m_stgRSTFactors[0];
3381 const MFloat vv = a1 * abs(uv) * m_solver->m_stgRSTFactors[1];
3382 const MFloat ww = a1 * abs(uv) * m_solver->m_stgRSTFactors[2];
3383
3384 m_cells->stg_fq[FLUC_UU][cellIndexBC(ii, j, k)] = uu;
3385 m_cells->stg_fq[FLUC_VV][cellIndexBC(ii, j, k)] = vv;
3386 m_cells->stg_fq[FLUC_WW][cellIndexBC(ii, j, k)] = ww;
3387 m_cells->stg_fq[FLUC_UV][cellIndexBC(ii, j, k)] = uv;
3388 m_cells->stg_fq[FLUC_VW][cellIndexBC(ii, j, k)] = vw;
3389 m_cells->stg_fq[FLUC_UW][cellIndexBC(ii, j, k)] = uw;
3390
3391 // Get utau using laminar viscosity
3392 const MFloat utau2 = sqrt(fre * sqrt(2.0 * SijSij) * xmu * frho);
3393
3394 // Save values if they are the new maximum
3395 if(utau2 >= utaumax) {
3396 minLengthLocal = pow((dxl * dyl * dzl), 0.33);
3397 utaumax = max(utau2, utaumax);
3398 }
3399
3400 // In which direction aims the maximum averaged velocity?
3401 const MFloat u = m_cells->stg_fq[PV->U][IBC];
3402 const MFloat v = m_cells->stg_fq[PV->V][IBC];
3403 const MFloat w = m_cells->stg_fq[PV->W][IBC];
3404
3405 umax = max(u, umax);
3406 vmax = max(v, vmax);
3407 wmax = max(w, wmax);
3408
3409 // We need a global length scale to compare
3410 m_cells->stg_fq[LENGTH_SCALE][cellIndexBC(ii, j, k)] = pow(sqrt(max(2.0 * SijSij, epss)), -exple);
3411
3413 // Zero gradient extrapolation of boundary values
3415 MInt noSTGVariables = 14;
3416
3417 if(k == start[2] + 1) {
3418 // 1st layer
3419 for(MInt var = 6; var < noSTGVariables; var++) {
3420 m_cells->stg_fq[var][cellIndexBC(ii, j, k - 1)] = m_cells->stg_fq[var][IBC];
3421 }
3422 } else if(k == end[2] - m_noGhostLayers) {
3423 // 1st layer
3424 for(MInt var = 6; var < noSTGVariables; var++) {
3425 m_cells->stg_fq[var][cellIndexBC(ii, j, k + 1)] = m_cells->stg_fq[var][IBC];
3426 }
3427 }
3428
3429 if(j == start[1] + 1) {
3430 for(MInt var = 6; var < noSTGVariables; var++) {
3431 m_cells->stg_fq[var][cellIndexBC(ii, j - 1, k)] = m_cells->stg_fq[var][IBC];
3432 }
3433 } else if(j == end[1] - m_noGhostLayers) {
3434 for(MInt var = 6; var < noSTGVariables; var++) {
3435 m_cells->stg_fq[var][cellIndexBC(ii, j + 1, k)] = m_cells->stg_fq[var][IBC];
3436 }
3437 }
3438
3440 // Storage of values
3442
3443 // Save max direction vector and max tau
3444 maxValsLocal[0] = umax;
3445 maxValsLocal[1] = vmax;
3446 maxValsLocal[2] = wmax;
3447 maxValsLocal[3] = utaumax;
3448 }
3449 }
3450
3452 // Communication: Exchange min and max values
3454
3455 MFloat minLengthGlobal = 0.0;
3456 MPI_Allreduce(maxValsLocal.begin(), maxValsGlobal.begin(), 4, MPI_DOUBLE, MPI_MAX, m_solver->m_commStg, AT_,
3457 "maxValsLocal.begin()", "maxValsGlobal.begin()");
3458 MPI_Allreduce(&minLengthLocal, &minLengthGlobal, 1, MPI_DOUBLE, MPI_MIN, m_solver->m_commStg, AT_, "minLengthLocal",
3459 "minLengthGlobal");
3460
3461
3462 // Maximum convection velocities at inflow
3463 m_stgMaxVel[0] = maxValsGlobal[0];
3464 m_stgMaxVel[1] = maxValsGlobal[1];
3465 m_stgMaxVel[2] = maxValsGlobal[2];
3466 const MFloat utaux = maxValsGlobal[3];
3467
3468 for(MInt k = start[2]; k < end[2]; k++) {
3469 for(MInt j = start[1]; j < end[1]; j++) {
3470 I = cellIndex(ii, j, k);
3471 IBC = cellIndexBC(ii, j, k);
3472
3473 // Length scale in main flow direction
3474 const MFloat xlength =
3475 max(min(m_solver->m_stgLengthFactors[0]
3476 * max(m_cells->stg_fq[LENGTH_SCALE][IBC] * delta_in * pow(utaux / delta_in, exple), eps),
3477 delta_in * 1.0),
3478 minLengthGlobal);
3479
3480 // Length scale in the direction of main shear
3481 const MFloat ylength =
3482 max(min(m_solver->m_stgLengthFactors[1]
3483 * max(m_cells->stg_fq[LENGTH_SCALE][IBC] * delta_in * pow(utaux / delta_in, exple), eps),
3484 delta_in * 0.66),
3485 minLengthGlobal);
3486
3487 // Length scale in the direction perpendicular of x and y
3488 const MFloat zlength =
3489 max(min(m_solver->m_stgLengthFactors[2]
3490 * max(m_cells->stg_fq[LENGTH_SCALE][IBC] * delta_in * pow(utaux / delta_in, exple), eps),
3491 delta_in * 1.0),
3492 minLengthGlobal);
3493
3494 //>marian
3495 m_cells->stg_fq[LENGTH_X][IBC] = xlength;
3496 m_cells->stg_fq[LENGTH_Y][IBC] = ylength;
3497 m_cells->stg_fq[LENGTH_Z][IBC] = zlength;
3498 //<marian
3499 }
3500 }
3501 }
3502
3503 if(m_solver->m_RKStep == 0) {
3505 // The virtual box part - executed by Master Solver at the inflow
3507
3508 if(m_solver->m_stgMyRank == m_solver->m_commStgRoot) {
3509 MFloat epsik1 = 0.0, epsik2 = 0.0, epsik3 = 0.0;
3510
3511 for(MInt n = 0; n < nran; n++) {
3512 MFloat xk1t = m_solver->m_stgEddies[n][0];
3513 MFloat xk2t = m_solver->m_stgEddies[n][1];
3514 MFloat xk3t = m_solver->m_stgEddies[n][2];
3515
3516 // Check if the eddie has left the Virtual Box
3517 if(xk1t > m_stgVbEnd[0] || xk1t < m_stgVbStart[0] || xk2t > m_stgVbEnd[1] || xk2t < m_stgVbStart[1]
3518 || xk3t > m_stgVbEnd[2] || xk3t < m_stgVbStart[2]) {
3519 // Get coordinates of eddie cores and their signs
3520 // cout << "Old eddie with position: " << xk1t << " , " << xk2t << " , " << xk3t << endl;
3521 xk1t = m_stgVbStart[0];
3522 xk2t = m_stgVbStart[1] + generate_rand_weighted() * BLT2;
3523 xk3t = m_stgVbStart[2] + generate_rand() * BLT3;
3524 // cout << "Creating new eddie with position: " << xk1t << " , " << xk2t << " , " << xk3t << endl;
3525 epsik1 = 2.0 * generate_rand() - 1.0;
3526 epsik1 = epsik1 / max(abs(epsik1), eps);
3527 epsik2 = 2.0 * generate_rand() - 1.0;
3528 epsik2 = epsik2 / max(abs(epsik2), eps);
3529 epsik3 = 2.0 * generate_rand() - 1.0;
3530 epsik3 = epsik3 / max(abs(epsik3), eps);
3531 } else {
3532 xk1t = m_stgMaxVel[0] * m_solver->m_timeStep + m_solver->m_stgEddies[n][0];
3533 xk2t = m_stgMaxVel[1] * m_solver->m_timeStep + m_solver->m_stgEddies[n][1];
3534 xk3t = m_stgMaxVel[2] * m_solver->m_timeStep + m_solver->m_stgEddies[n][2];
3535
3536 epsik1 = m_solver->m_stgEddies[n][3];
3537 epsik2 = m_solver->m_stgEddies[n][4];
3538 epsik3 = m_solver->m_stgEddies[n][5];
3539 }
3540
3541 eddyBcastBuffer[n + nran * 0] = xk1t;
3542 eddyBcastBuffer[n + nran * 1] = xk2t;
3543 eddyBcastBuffer[n + nran * 2] = xk3t;
3544 eddyBcastBuffer[n + nran * 3] = epsik1;
3545 eddyBcastBuffer[n + nran * 4] = epsik2;
3546 eddyBcastBuffer[n + nran * 5] = epsik3;
3547 }
3548 }
3549
3550 // Broadcast the new/updated eddies to all relevant processes
3551 MPI_Bcast(eddyBcastBuffer.begin(), nran * m_solver->m_stgNoEddieProperties, MPI_DOUBLE, m_solver->m_commStgRoot,
3552 m_solver->m_commStg, AT_, "eddyBcastBuffer.begin()");
3553
3554 // Copy data into m_FQeddie vector
3555 for(MInt n = 0; n < nran; n++) {
3556 for(MInt p = 0; p < m_solver->m_stgNoEddieProperties; p++) {
3557 m_solver->m_stgEddies[n][p] = eddyBcastBuffer[n + nran * p];
3558 }
3559 }
3560
3561 Vb = BLT2 * BLT3 * BLT1;
3562
3563 // Summary of synth turb parameters
3564 if(m_solver->m_stgMyRank == m_solver->m_commStgRoot && globalTimeStep == m_solver->m_restartTimeStep) {
3565 cout << "**************************" << endl
3566 << "Synthetic turbulence:" << endl
3567 << "zones: 1" << endl
3568 << "nr. eddies: " << nran << endl
3569 << "conv. vel: " << sqrt(POW2(m_stgMaxVel[0]) + POW2(m_stgMaxVel[1]) + POW2(m_stgMaxVel[2])) << endl
3570 << "umax = " << m_stgMaxVel[0] << endl
3571 << "vmax = " << m_stgMaxVel[1] << endl
3572 << "wmax = " << m_stgMaxVel[2] << endl
3573 << "virtual box volume: " << Vb << endl
3574 << "Vb/nran = " << Vb / nran << endl
3575 << "**************************" << endl;
3576 }
3577
3579 // Calculation of the fluctuation induced by all eddies on each cell
3581
3582 // only compute fluctuations for second
3583 const MFloat vbFactor = sqrt(Vb / nran);
3584 const MInt iStart = 1, iEnd = 2;
3585
3586 for(MInt k = start[2]; k < end[2]; k++) {
3587 for(MInt j = start[1]; j < end[1]; j++) {
3588 for(MInt i = iStart; i < iEnd; i++) {
3589 MFloat help1 = F0, help2 = F0, help3 = F0, help4 = F0, help5 = F0, help6 = F0;
3590
3591 const MFloat umax = m_stgMaxVel[0];
3592 const MFloat vmax = m_stgMaxVel[1];
3593 const MFloat wmax = m_stgMaxVel[2];
3594
3595 // the tensor components and xyzlengths are only saved in one row (ii = 1)
3596 const MInt cellIdBC = cellIndexBC(i, j, k);
3597 const MInt cellIdBCFirst = cellIndexBC(ii, j, k);
3598 const MInt cellId = cellIndex(ii, j, k);
3599
3600 const MFloat uu = m_cells->stg_fq[FLUC_UU][cellIdBCFirst];
3601 const MFloat vv = m_cells->stg_fq[FLUC_VV][cellIdBCFirst];
3602 const MFloat ww = m_cells->stg_fq[FLUC_WW][cellIdBCFirst];
3603 const MFloat uv = m_cells->stg_fq[FLUC_UV][cellIdBCFirst];
3604 const MFloat vw = m_cells->stg_fq[FLUC_VW][cellIdBCFirst];
3605 const MFloat uw = m_cells->stg_fq[FLUC_UW][cellIdBCFirst];
3606
3607 // Cholesky decomposition of the Reynolds stress tensor
3608 const MFloat a11 = sqrt(max(uu, epsl));
3609 const MFloat a21 = uv / a11;
3610 const MFloat a31 = uw / a11;
3611 const MFloat a22 = sqrt(max((vv - a21 * a21), epsl));
3612 const MFloat a32 = (vw - a21 * a31) / a22;
3613 const MFloat a33 = sqrt(max((ww - a31 * a31 - a32 * a32), epsl));
3614
3615 const MFloat xLb1 = m_cells->stg_fq[LENGTH_X][cellIdBCFirst];
3616 const MFloat xLb2 = m_cells->stg_fq[LENGTH_Y][cellIdBCFirst];
3617 const MFloat xLb3 = m_cells->stg_fq[LENGTH_Z][cellIdBCFirst];
3618
3619 const MFloat fxLb1 = 1.0 / xLb1;
3620 const MFloat fxLb2 = 1.0 / xLb2;
3621 const MFloat fxLb3 = 1.0 / xLb3;
3622
3623 const MFloat fsqrtxLb1 = 1.0 / sqrt(xLb1);
3624 const MFloat fsqrtxLb2 = 1.0 / sqrt(xLb2);
3625 const MFloat fsqrtxLb3 = 1.0 / sqrt(xLb3);
3626
3627 const MFloat fsqrtPixLb1 = 1.0 / sqrt(3.141 * xLb1);
3628 const MFloat fsqrtPixLb2 = 1.0 / sqrt(3.141 * xLb2);
3629 const MFloat fsqrtPixLb3 = 1.0 / sqrt(3.141 * xLb3);
3630
3631 for(MInt n = 0; n < nran; n++) {
3632 // Tent function to determine the symmetric function to model the
3633 // decay of the fluctuations
3634 const MFloat xk1t = m_solver->m_stgEddies[n][0];
3635 const MFloat xk2t = m_solver->m_stgEddies[n][1];
3636 const MFloat xk3t = m_solver->m_stgEddies[n][2];
3637
3638 const MFloat distX = m_cells->coordinates[0][cellId] - xk1t;
3639 const MFloat distY = m_cells->coordinates[1][cellId] - xk2t;
3640 const MFloat distZ = m_cells->coordinates[2][cellId] - xk3t;
3641
3642 const MFloat aDistX = fabs(distX);
3643 const MFloat aDistY = fabs(distY);
3644 const MFloat aDistZ = fabs(distZ);
3645
3646 // only compute contribution if eddie is in vicinity, i.e.,
3647 // if it is within 4 eddy lengthscales
3648 if(aDistX < 4.0 * xLb1 && aDistY < 4.0 * xLb2 && aDistZ < 4.0 * xLb3) {
3649 const MFloat zacfq1 = distX / aDistX;
3650 const MFloat rol1H = zacfq1 * min(aDistX * fxLb1, 1.0);
3651
3652 const MFloat zacfq2 = distY / aDistY;
3653 const MFloat rol2H = zacfq2 * min(aDistY * fxLb2, 1.0);
3654
3655 const MFloat zacfq3 = distZ / aDistZ;
3656 const MFloat rol3H = zacfq3 * min(aDistZ * fxLb3, 1.0);
3657
3658 const MFloat fl1 = 2.0 * fsqrtPixLb1 * exp(-((distX)*2 * fxLb1) * ((distX)*2 * fxLb1));
3659 const MFloat fl2 = 2.0 * fsqrtPixLb2 * exp(-((distY)*2 * fxLb2) * ((distY)*2 * fxLb2));
3660 const MFloat fl3 = 2.0 * fsqrtPixLb3 * exp(-((distZ)*2 * fxLb3) * ((distZ)*2 * fxLb3));
3661
3662
3663 // Normalization factor cannot be chosen as Pamies did... or we...
3664 MFloat fH1 = (F1 - cos(2.0 * 3.141 * rol1H)) / (2.0 * 3.141 * rol1H * 0.44);
3665 MFloat fH2 = (F1 - cos(2.0 * 3.141 * rol2H)) / (2.0 * 3.141 * rol2H * 0.44);
3666 MFloat fH3 = (F1 - cos(2.0 * 3.141 * rol3H)) / (2.0 * 3.141 * rol3H * 0.44);
3667
3668 fH1 = aniso * fH1 * fsqrtxLb1 + fabs(aniso - 1.0) * fl1;
3669 fH2 = aniso * fH2 * fsqrtxLb2 + fabs(aniso - 1.0) * fl2;
3670 fH3 = aniso * fH3 * fsqrtxLb3 + fabs(aniso - 1.0) * fl3;
3671
3672 const MFloat epsik1 = m_solver->m_stgEddies[n][3];
3673 const MFloat epsik2 = m_solver->m_stgEddies[n][4];
3674 const MFloat epsik3 = m_solver->m_stgEddies[n][5];
3675
3676 help4 += vbFactor * epsik1 * fl1 * fl2 * fH3;
3677 help5 += vbFactor * epsik2 * fl1 * fl2 * fH3;
3678 help6 += vbFactor * epsik3 * fl1 * fH2 * fl3;
3679 }
3680 }
3681
3683 // Use Cholesky-Trafo to scale random fluctuations
3685
3686 help1 = help4 * a11; // Fluctuation u'
3687 help2 = help4 * a21 + help5 * a22; // Fluctuation v'
3688 help3 = help4 * a31 + help5 * a32 + help6 * a33; // Fluctuation w'
3689
3690 const MFloat velmax = sqrt(umax * umax + vmax * vmax + wmax * wmax);
3691
3692 const MFloat ufluc = min(max(help1, -0.3 * velmax), 0.3 * velmax);
3693 const MFloat vfluc = min(max(help2, -0.3 * velmax), 0.3 * velmax);
3694 const MFloat wfluc = min(max(help3, -0.3 * velmax), 0.3 * velmax);
3695
3696
3697 m_cells->stg_fq[FLUC_U][cellIdBC] += timsm * (ufluc - m_cells->stg_fq[FLUC_U][cellIdBC]);
3698 m_cells->stg_fq[FLUC_V][cellIdBC] += timsm * (vfluc - m_cells->stg_fq[FLUC_V][cellIdBC]);
3699 m_cells->stg_fq[FLUC_W][cellIdBC] += timsm * (wfluc - m_cells->stg_fq[FLUC_W][cellIdBC]);
3700 }
3701 }
3702 }
3703 } // RKStep end if
3704
3708 // Now comes the BC stuff that we need to do every RK step
3709 for(MInt j = start[1]; j < end[1]; j++) {
3710 for(MInt k = start[2]; k < end[2]; k++) {
3711 const MInt cellIdG1 = cellIndex(m_noGhostLayers - 1, j, k);
3712 IBC = cellIndexBC(m_noGhostLayers - 1, j, k);
3713 const MInt cellIdA1 = cellIndex(m_noGhostLayers, j, k);
3714
3715 MFloat dxidx = m_cells->cellMetrics[0][cellIdA1];
3716 MFloat dxidy = m_cells->cellMetrics[1][cellIdA1];
3717 MFloat dxidz = m_cells->cellMetrics[2][cellIdA1];
3718
3719 MFloat gradxi = -F1 / sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz);
3720
3721 MFloat dxHelp = dxidx * gradxi;
3722 MFloat dyHelp = dxidy * gradxi;
3723 MFloat dzHelp = dxidz * gradxi;
3724
3725 const MFloat rhoBC = m_cells->pvariables[PV->RHO][cellIdG1];
3726 const MFloat pBC = m_cells->pvariables[PV->P][cellIdG1];
3727 const MFloat fRhoBC = F1 / rhoBC;
3728 const MFloat aBC = sqrt(gamma * pBC * fRhoBC);
3729 const MFloat uBC = m_cells->pvariables[PV->U][cellIdG1];
3730 const MFloat vBC = m_cells->pvariables[PV->V][cellIdG1];
3731 const MFloat wBC = m_cells->pvariables[PV->W][cellIdG1];
3732
3733 const MFloat maBC = (dxHelp * uBC + dyHelp * vBC + dzHelp * wBC) / aBC;
3734
3735 // get mean values from the rans
3736 const MFloat rhoRANS = m_cells->stg_fq[PV->RHO][IBC];
3737 const MFloat uRANS = m_cells->stg_fq[PV->U][IBC];
3738 const MFloat vRANS = m_cells->stg_fq[PV->V][IBC];
3739 const MFloat wRANS = m_cells->stg_fq[PV->W][IBC];
3740 const MFloat pRANS = m_cells->stg_fq[PV->P][IBC];
3741
3742 // fluctuation values from the STG
3743 const MFloat u_prime = m_cells->stg_fq[FLUC_U][IBC];
3744 const MFloat v_prime = m_cells->stg_fq[FLUC_V][IBC];
3745 const MFloat w_prime = m_cells->stg_fq[FLUC_W][IBC];
3746
3747 // superpose onto mean RANS variables
3748 const MFloat uSTG = max(uRANS + u_prime, epsl);
3749 const MFloat vSTG = vRANS + v_prime;
3750 const MFloat wSTG = wRANS + w_prime;
3751
3752 // compute correct density
3753 const MFloat u9a = PV->UInfinity;
3754 const MFloat u9ff = u_prime;
3755 const MFloat alok = sqrt(gamma * PV->PInfinity / CV->rhoInfinity);
3756 const MFloat flucc = u9ff / u9a * POW2((PV->UInfinity / alok)) * gammaMinusOne * m_cells->stg_fq[PV->RHO][IBC];
3757 const MFloat zdir = flucc / max(fabs(flucc), 0.0000001);
3758 const MFloat rhoSTG = rhoRANS + zdir * min(fabs(flucc), 0.1 * rhoRANS);
3759
3760 // get field values inside the integration domain
3761 const MFloat pField = m_cells->pvariables[PV->P][cellIdA1];
3762 const MFloat rhoField = m_cells->pvariables[PV->RHO][cellIdA1];
3763 const MFloat uField = m_cells->pvariables[PV->U][cellIdA1];
3764 const MFloat vField = m_cells->pvariables[PV->V][cellIdA1];
3765 const MFloat wField = m_cells->pvariables[PV->W][cellIdA1];
3766 const MFloat aField = sqrt(gamma * pField / rhoField);
3767
3771 const MFloat pSub =
3772 F1B2
3773 * (pField + pRANS
3774 + rhoField * aField * (+dxHelp * (uField - uSTG) + dyHelp * (vField - vSTG) + dzHelp * (wField - wSTG)));
3775 const MFloat rhoSub = rhoSTG + (pSub - pRANS) / (POW2(aField));
3776 const MFloat rhoSubHelp = (pSub - pRANS) / (rhoField * aField);
3777
3778 // Multiply velocities with density
3779 const MFloat uSub = uSTG + dxHelp * rhoSubHelp;
3780 const MFloat vSub = vSTG + dyHelp * rhoSubHelp;
3781 const MFloat wSub = wSTG + dzHelp * rhoSubHelp;
3782
3786 const MFloat rhoSup = rhoSTG;
3787 const MFloat uSup = uSTG;
3788 const MFloat vSup = vSTG;
3789 const MFloat wSup = wSTG;
3790 const MFloat pSup = pRANS;
3791
3795
3796 // by default the subsonic formulation is used
3797 // switch on "stgSubSup" to get the mixed formulation
3798 // or "stgSupersonic" to use the pure supersonic formulation
3799 MFloat xSub = F1;
3800 MFloat xSup = F0;
3801
3802 if(m_solver->m_stgSubSup) {
3803 const MFloat maBCAbs = fabs(maBC);
3804 const MFloat alpha = 14.0;
3805 const MFloat b = 0.95;
3806 const MFloat count = alpha * (maBCAbs - b);
3807 const MFloat denom = (F1 - 0.99 * b) * maBCAbs + b;
3808 const MFloat ratio = count / denom;
3809 const MFloat wfun = F1B2 * (F1 + tanh(ratio) / tanh(alpha));
3810
3811 xSub = fabs(wfun - F1);
3812 xSup = fabs(wfun);
3813 } else if(m_solver->m_stgSupersonic) {
3814 xSub = F0;
3815 xSup = F1;
3816 }
3817
3818 m_cells->pvariables[PV->RHO][cellIdG1] = rhoSub * xSub + rhoSup * xSup;
3819 m_cells->pvariables[PV->U][cellIdG1] = uSub * xSub + uSup * xSup;
3820 m_cells->pvariables[PV->V][cellIdG1] = vSub * xSub + vSup * xSup;
3821 m_cells->pvariables[PV->W][cellIdG1] = wSub * xSub + wSup * xSup;
3822 m_cells->pvariables[PV->P][cellIdG1] = pSub * xSub + pSup * xSup;
3823
3824
3828 const MInt cellIdG2 = cellIndex(0, j, k);
3829 // extrapolate into second ghost cell
3830 for(MInt var = 0; var < PV->noVariables; var++) {
3831 m_cells->pvariables[var][cellIdG2] =
3832 F2 * m_cells->pvariables[var][cellIdG1] - m_cells->pvariables[var][cellIdA1];
3833 }
3834 }
3835 }
3836}
3837//<marian
3838
3839
3850// Inlet station
3851template <MBool isRans>
3853 (void)bcId;
3854 // Communication between the Recycling and Inlet station.
3855 //___COMMGr(oup)______________________
3856 //|______________|_________________| |
3857 //|Inlet station |Recycling station| |
3858 //| | | |
3859 //|______________|_________________| |
3860 //|__________________________________|
3861 //
3862 // infographic of the Groups
3863
3864 // MFloat delta_inMax = delta_in+2.5*delta_in; //limit the integration height
3865 const MFloat gamma = m_solver->m_gamma;
3866 const MFloat gammaMinusOne = gamma - F1;
3867
3868 const MFloat rescalEPS = pow(10, -16.0);
3869 const MFloat alpha = 4.0;
3870 const MFloat b = 0.2;
3871 const MFloat rc = pow(m_solver->m_Pr, F1B3);
3872 const MFloat ctema = F1B2 * gammaMinusOne * POW2(m_solver->m_Ma) * rc;
3873 const MFloat maxIntegrationHeight = 2.0 * m_rescalingBLT;
3874
3875 // van Driest constant & transformed velocity
3876 const MFloat b_vd = sqrt(ctema / (F1 + ctema));
3877 const MFloat uvd8 = PV->UInfinity * asin(b_vd) / b_vd;
3878
3879 // compute the momentum thickness at the inlet (i==x, j==y, k==z)
3880 const MInt i = m_noGhostLayers - 1;
3881
3882
3886
3887 // allocate space in k direction (all k-Cells)
3888 MFloatScratchSpace thetaLocal(2, AT_, "thetaLocalIn");
3889 thetaLocal.fill(F0); // initialize scratch space
3890
3891 MFloatScratchSpace thetaGlobal(2, AT_, "thetaGlobalIn");
3892 thetaGlobal.fill(F0);
3893
3894 // the offest position in k-direction is the offset
3895 const MInt thetaLocalOffset = m_solver->m_nOffsetCells[0];
3896
3897 // compute the local moment thickness j=direction of integration
3898 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
3899 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; ++j) {
3900 const MInt cellId = cellIndex(i, j, k);
3901 const MInt pointIdM1 = getPointIdFromCell(i, j, k);
3902 const MInt pointIdP1 = getPointIdfromPoint(pointIdM1, 0, 1, 0);
3903
3904 if(m_grid->m_coordinates[1][pointIdM1] > maxIntegrationHeight) {
3905 continue;
3906 }
3907
3908 const MFloat urat = m_cells->pvariables[PV->U][cellId] / PV->UInfinity;
3909 const MFloat momThick =
3910 (m_cells->pvariables[PV->U][cellId] * m_cells->pvariables[PV->RHO][cellId] * fabs(F1 - urat))
3911 / (CV->rhoUInfinity);
3912
3913 // integrate normal to the wall
3914 const MFloat ydist = m_grid->m_coordinates[1][pointIdP1] - m_grid->m_coordinates[1][pointIdM1];
3915 thetaLocal(0) += momThick * ydist;
3916 }
3917 }
3918
3919 MPI_Allreduce(thetaLocal.begin(), thetaGlobal.begin(), 2, MPI_DOUBLE, MPI_SUM, m_solver->m_rescalingCommGrComm, AT_,
3920 "thetaLocal.begin()", "thetaGlobal.begin()");
3921
3922 // determine spanwise average: we assume equally spaced in z-direction
3923 for(MInt ii = 0; ii < 2; ++ii) {
3924 thetaGlobal(ii) /= (m_grid->getMyBlockNoCells(0));
3925 }
3926
3927 if(globalTimeStep % 50 == 0 && m_solver->m_RKStep == 0
3928 && m_solver->domainId() == m_solver->m_rescalingCommGrRootGlobal) {
3929 cout << "ThetaInflow: " << thetaGlobal(0) << " ThetaRecyclingStation: " << thetaGlobal(1) << endl;
3930
3931 FILE* f_channel;
3932 f_channel = fopen("./theta_inflow.dat", "a+");
3933 fprintf(f_channel, "%d", globalTimeStep);
3934 fprintf(f_channel, " %f", m_solver->m_physicalTime);
3935 fprintf(f_channel, " %f", m_solver->m_time);
3936 fprintf(f_channel, " %f", m_solver->m_timeStep);
3937 fprintf(f_channel, " %f", thetaGlobal[0]);
3938 fprintf(f_channel, " %f", thetaGlobal[1]);
3939 fprintf(f_channel, "\n");
3940 fclose(f_channel);
3941 }
3942
3946 const MInt noVar = 2; // for more variables if wanted
3947 MFloatScratchSpace wallPropertiesLocal(m_grid->getMyBlockNoCells(0), noVar, AT_, "wallPropertiesLocalInlet");
3948 MFloatScratchSpace wallProperties(m_grid->getMyBlockNoCells(0), noVar, AT_, "wallPropertiesInlet");
3949 wallPropertiesLocal.fill(F0);
3950 wallProperties.fill(F0);
3951
3952 MPI_Allreduce(wallPropertiesLocal.begin(), wallProperties.begin(), m_grid->getMyBlockNoCells(0) * noVar, MPI_DOUBLE,
3953 MPI_SUM, m_solver->m_rescalingCommGrComm, AT_, "wallPropertiesLocal.begin()", "wallProperties.begin()");
3954
3958 MFloatScratchSpace utauIn(m_nCells[0], AT_, "u_tauIn");
3959 MFloatScratchSpace gams(m_nCells[0], AT_, "gams");
3960
3961 MInt kStart = 0;
3962 MInt kEnd = m_nCells[0];
3963
3964 if(m_solver->m_nOffsetCells[0] == 0) {
3965 kStart = m_noGhostLayers;
3966 }
3967 if(m_solver->m_nOffsetCells[0] + m_solver->m_nActiveCells[0] == m_grid->getMyBlockNoCells(0)) {
3968 kEnd = m_nCells[0] - m_noGhostLayers;
3969 }
3970
3971 for(MInt k = kStart; k < kEnd; ++k) {
3972 const MFloat utauRe = wallProperties(thetaLocalOffset + (k - m_noGhostLayers), 0);
3973
3974 // estimate the friction velocity at the inlet
3975 // according to standard power law approximations
3976 // utau_in = utau_re*(theta_re/theta_in)**(1/2*(n-1))
3977 // where theta is the momentum thickness
3978 // see Thomas S. Lund, p241
3979
3980 // when take into account the variance of wall density
3981 // utau_in = utau_re*(rho_wall_re/rho_wall_in)**0.5
3982 //* (theta_re/theta_in)**(1/2*(n-1))
3983 // here n = 5
3984
3985 gams(k) = pow(thetaGlobal(1) / fabs(thetaGlobal(0)), F1B8);
3986 utauIn(k) = utauRe * min(max(gams(k), F1), 2.5);
3987 }
3988
3989 MFloatScratchSpace coordInInner(m_nCells[0] * m_nCells[1], AT_, "coordInInner");
3990 MFloatScratchSpace coordInOuter(m_nCells[0] * m_nCells[1], AT_, "coordInOuter");
3991
3992 for(MInt k = 0; k < m_nCells[0]; ++k) {
3993 for(MInt j = 0; j < m_nCells[1]; ++j) {
3994 const MInt cellId = cellIndex(i, j, k);
3995 const MInt faceId = j + k * m_nCells[1];
3996 const MFloat rho = m_cells->pvariables[PV->RHO][cellId];
3997 const MFloat frho = F1 / rho;
3998 const MFloat p = m_cells->pvariables[PV->P][cellId];
3999 const MFloat temp = p * gamma * frho;
4000 const MFloat mu = SUTHERLANDLAW(temp);
4001
4002 coordInInner(faceId) = utauIn(k) * rho * m_cells->coordinates[1][cellId] / (mu * sqrt(m_solver->m_Re0));
4003 coordInOuter(faceId) = m_cells->coordinates[1][cellId] * rho / (m_rescalingBLT * CV->rhoInfinity);
4004 }
4005 }
4006
4010 const MInt noVariables = 6;
4011 const MInt totalCells[2] = {m_grid->getMyBlockNoCells(0), m_grid->getMyBlockNoCells(1) + 1};
4012 MFloatScratchSpace varSliceLocal(noVariables, totalCells[0] * totalCells[1], AT_, "varSliceLocal");
4013 MFloatScratchSpace varSlice(noVariables, totalCells[0] * totalCells[1], AT_, "varSlice");
4014
4015 // we are at the inlet, only fill with zeros
4016 varSlice.fill(F0);
4017 varSliceLocal.fill(F0);
4018
4019 MPI_Allreduce(varSliceLocal.begin(), varSlice.begin(), noVariables * totalCells[0] * totalCells[1], MPI_DOUBLE,
4020 MPI_SUM, m_solver->m_rescalingCommGrComm, AT_, "varSliceLocal.begin()", "varSlice.begin()");
4021
4022
4026
4027 MInt jStart = 0;
4028 MInt jEnd = m_nCells[1];
4029
4030 if(m_solver->m_nOffsetCells[1] == 0) {
4031 jStart = m_noGhostLayers;
4032 }
4033 if(m_solver->m_nOffsetCells[1] + m_solver->m_nActiveCells[1] == m_grid->getMyBlockNoCells(1)) {
4034 jEnd = m_nCells[1] - m_noGhostLayers;
4035 }
4036
4037 for(MInt k = kStart; k < kEnd; ++k) {
4038 const MFloat ctem1 = (F1 + ctema) * (F1 - POW2(gams(k)));
4039 const MFloat ctem2 = F2 * ctema * gams(k) * (F1 - gams(k));
4040 const MFloat ctem3 = (F1 - gams(k)) * (F1 + gams(k) + F2 * ctema * gams(k));
4041
4042 for(MInt j = jStart; j < jEnd; ++j) {
4043 const MInt faceId = j + k * m_nCells[1];
4044 // const MInt faceIdM1 = (j-1)+k*m_nCells[1];
4045 const MInt cellId = cellIndex(i, j, k);
4046
4047 if(coordInOuter(faceId) < 1.05) {
4048 MFloat uInner = F0, vInner = F0, wInner = F0, TInner = F0;
4049 MFloat uOuter = F0, vOuter = F0, wOuter = F0, TOuter = F0;
4050 const MFloat count = alpha * (coordInOuter(faceId) - b);
4051 const MFloat denom = (F1 - F2 * b) * coordInOuter(faceId) + b;
4052 const MFloat ratio = count / denom;
4053 const MFloat wfun = F1B2 * (F1 + tanh(ratio) / tanh(alpha));
4054
4055 for(MInt jj = 0; jj < totalCells[1] - 1; ++jj) {
4056 const MInt localId = jj + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4057 const MInt localIdP1 = (jj + 1) + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4058
4059 const MFloat yInnerRe = varSlice(4, localId);
4060 const MFloat yInnerReP1 = varSlice(4, localIdP1);
4061
4062 if((yInnerRe - coordInInner(faceId)) < rescalEPS && yInnerReP1 > coordInInner(faceId)) {
4063 const MFloat dy1 = coordInInner(faceId) - yInnerRe;
4064 const MFloat dy2 = yInnerReP1 - coordInInner(faceId);
4065 const MFloat dy = yInnerReP1 - yInnerRe;
4066
4067 const MFloat u = varSlice(0, localId);
4068 const MFloat uP1 = varSlice(0, localIdP1);
4069 const MFloat v = varSlice(1, localId);
4070 const MFloat vP1 = varSlice(1, localIdP1);
4071 const MFloat w = varSlice(2, localId);
4072 const MFloat wP1 = varSlice(2, localIdP1);
4073 const MFloat t = varSlice(3, localId);
4074 const MFloat tP1 = varSlice(3, localIdP1);
4075 uInner = (uP1 * dy1 + u * dy2) / dy;
4076 vInner = (vP1 * dy1 + v * dy2) / dy;
4077 wInner = (wP1 * dy1 + w * dy2) / dy;
4078 TInner = (tP1 * dy1 + t * dy2) / dy;
4079 }
4080 }
4081
4082 // outer region
4083 for(MInt jj = 0; jj < totalCells[1] - 1; ++jj) {
4084 const MInt localId = jj + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4085 const MInt localIdP1 = (jj + 1) + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4086
4087 const MFloat yOuterRe = varSlice(5, localId);
4088 const MFloat yOuterReP1 = varSlice(5, localIdP1);
4089
4090 if((yOuterRe - coordInOuter(faceId)) < rescalEPS && yOuterReP1 > coordInOuter(faceId)) {
4091 const MFloat dy1 = coordInOuter(faceId) - yOuterRe;
4092 const MFloat dy2 = yOuterReP1 - coordInOuter(faceId);
4093 const MFloat dy = yOuterReP1 - yOuterRe;
4094
4095 const MFloat u = varSlice(0, localId);
4096 const MFloat uP1 = varSlice(0, localIdP1);
4097 const MFloat v = varSlice(1, localId);
4098 const MFloat vP1 = varSlice(1, localIdP1);
4099 const MFloat w = varSlice(2, localId);
4100 const MFloat wP1 = varSlice(2, localIdP1);
4101 const MFloat t = varSlice(3, localId);
4102 const MFloat tP1 = varSlice(3, localIdP1);
4103 uOuter = (uP1 * dy1 + u * dy2) / dy;
4104 vOuter = (vP1 * dy1 + v * dy2) / dy;
4105 wOuter = (wP1 * dy1 + w * dy2) / dy;
4106 TOuter = (tP1 * dy1 + t * dy2) / dy;
4107 }
4108 }
4109
4110 const MFloat TInnerA = POW2(gams(k)) * TInner + ctem1 * PV->TInfinity;
4111 const MFloat TOuterA = POW2(gams(k)) * TOuter - (ctem2 * (uOuter / PV->UInfinity) - ctem3) * PV->TInfinity;
4112
4113 // van Driest transformation
4114 const MFloat uvdInner = PV->UInfinity * asin(b_vd * uInner / PV->UInfinity) / b_vd;
4115 const MFloat uvdOuter = PV->UInfinity * asin(b_vd * uOuter / PV->UInfinity) / b_vd;
4116
4117 // scaling of transformed inner and outer velocities
4118 uInner = gams(k) * uvdInner;
4119 uOuter = gams(k) * uvdOuter + (F1 - gams(k)) * uvd8;
4120 uInner = PV->UInfinity * sin(b_vd * uInner / PV->UInfinity) / b_vd;
4121 uOuter = PV->UInfinity * sin(b_vd * uOuter / PV->UInfinity) / b_vd;
4122
4123 const MFloat pres = PV->PInfinity;
4124 const MFloat uMean = uInner * (F1 - wfun) + uOuter * wfun;
4125 const MFloat vMean = vInner * (F1 - wfun) + vOuter * wfun;
4126 const MFloat wMean = (wInner * (F1 - wfun) + wOuter * wfun) * gams(k);
4127 const MFloat tMean = TInnerA * (F1 - wfun) + TOuterA * wfun;
4128 const MFloat rhoIn = gamma * pres / tMean;
4129
4130 // //clebanoff factor is optional
4131 // const MFloat clebf = 6.1;
4132 // const MFloat blt = m_rescalingBLT;
4133 // const MFloat cleb = F1/(F1+pow((m_cells->coordinates[1][cellId]/(clebf*blt)), 6.0));
4134
4135 m_cells->pvariables[PV->RHO][cellId] = rhoIn;
4136 m_cells->pvariables[PV->U][cellId] = uMean;
4137 m_cells->pvariables[PV->V][cellId] = vMean;
4138 m_cells->pvariables[PV->W][cellId] = wMean;
4139 m_cells->pvariables[PV->P][cellId] = pres;
4140 } else {
4141 // if(!edgePointIsSet(k)) {
4142 // edgePointJ(k) = j;
4143 // edgePointIsSet(k) = 1;
4144 // }
4145
4146 const MFloat pres = PV->PInfinity;
4147 const MFloat rhoIn = gamma * pres / PV->TInfinity;
4148
4149 const MFloat uMean = PV->UInfinity;
4150 const MFloat vMean = PV->VInfinity;
4151 const MFloat wMean = PV->WInfinity;
4152
4153 m_cells->pvariables[PV->RHO][cellId] = rhoIn;
4154 m_cells->pvariables[PV->U][cellId] = uMean;
4155 m_cells->pvariables[PV->V][cellId] = vMean;
4156 m_cells->pvariables[PV->W][cellId] = wMean;
4157 m_cells->pvariables[PV->P][cellId] = pres;
4158 }
4159 }
4160 }
4161
4162 for(MInt k = kStart; k < kEnd; ++k) {
4163 for(MInt j = 0; j < m_nCells[1]; ++j) {
4164 // extrapolation for second GC
4165 const MInt cellId = cellIndex(1, j, k);
4166 const MInt cellIdM1 = cellIndex(0, j, k);
4167 const MInt cellIdadj = cellIndex(2, j, k);
4168
4169 for(MInt var = 0; var < PV->noVariables; var++) {
4170 m_cells->pvariables[var][cellIdM1] =
4171 2.0 * m_cells->pvariables[var][cellId] - m_cells->pvariables[var][cellIdadj];
4172 }
4173 }
4174 }
4175}
4176
4177
4178// Recycling station
4179template <MBool isRans>
4181 MInt* start = m_physicalBCMap[bcId]->start1;
4182
4183 const MFloat gamma = m_solver->m_gamma;
4184
4185 // things to move to init or elsewhere
4186 MFloat F727 = 72.0 / 7.0;
4187 const MInt i = start[0]; // position at which recycle is taken
4188 const MFloat yWall = F0; // this has been fixed else method does not work
4189 const MFloat maxIntegrationHeight = 2.0 * m_rescalingBLT;
4190
4194
4195 // thetaLocal.fill(F0); //initialize scratch space to zero // only for parallel use
4196 MFloatScratchSpace thetaLocal(2, AT_, "thetaLocalRe");
4197 MFloatScratchSpace thetaGlobal(2, AT_, "thetaGlobalRe");
4198 thetaLocal.fill(F0);
4199 thetaGlobal.fill(F0);
4200
4201 // the offest position in k-direction is the offset
4202 const MInt thetaLocalOffset = m_solver->m_nOffsetCells[0];
4203
4204 // compute the local moment thickness j=direction of integration
4205 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
4206 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; ++j) {
4207 const MInt cellId = cellIndex(i, j, k);
4208 const MInt pointIdM1 = getPointIdFromCell(i, j, k);
4209 const MInt pointIdP1 = getPointIdfromPoint(pointIdM1, 0, 1, 0);
4210
4211 if(m_grid->m_coordinates[1][pointIdM1] > maxIntegrationHeight) {
4212 continue;
4213 }
4214
4215 const MFloat urat = m_cells->pvariables[PV->U][cellId] / PV->UInfinity;
4216 const MFloat momThick =
4217 (m_cells->pvariables[PV->U][cellId] * m_cells->pvariables[PV->RHO][cellId] * fabs(F1 - urat))
4218 / (CV->rhoUInfinity);
4219
4220 // integrate normal to the wall
4221 const MFloat ydist = m_grid->m_coordinates[1][pointIdP1] - m_grid->m_coordinates[1][pointIdM1];
4222 thetaLocal(1) += momThick * ydist;
4223 }
4224 }
4225
4226 // communicate the Thickness across the plane
4227 MPI_Allreduce(thetaLocal.begin(), thetaGlobal.begin(), 2, MPI_DOUBLE, MPI_SUM, m_solver->m_rescalingCommGrComm, AT_,
4228 "thetaLocal.begin()", "thetaGlobal.begin()");
4229
4230 // determine spanwise average: we assume equally spaced in z-direction
4231 for(MInt ii = 0; ii < 2; ++ii) {
4232 thetaGlobal(ii) /= (m_grid->getMyBlockNoCells(0));
4233 }
4234
4238
4239 const MFloat delta = F727 * thetaGlobal(1);
4240 const MInt noVar = 2; // for more variables if wanted
4241 const MInt wallLocalOffset = m_solver->m_nOffsetCells[1]; // Offset in j-direction
4242
4243 MFloatScratchSpace wallPropertiesLocal(m_grid->getMyBlockNoCells(0), noVar, AT_, "wallPropertiesLocalRe");
4244 MFloatScratchSpace wallProperties(m_grid->getMyBlockNoCells(0), noVar, AT_, "wallPropertiesRe");
4245 wallPropertiesLocal.fill(F0);
4246 wallProperties.fill(F0);
4247
4248 // determine the wall stuff if wall is contained whithin the partition
4249 if(wallLocalOffset == 0 && m_solver->m_nActiveCells[1] >= m_noGhostLayers) {
4250 for(MInt k = m_noGhostLayers; k < m_solver->m_nCells[0] - m_noGhostLayers; ++k) {
4251 const MInt cellId = cellIndex(i, m_noGhostLayers, k);
4252 const MInt localId = m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers);
4253 const MFloat rho = m_cells->pvariables[PV->RHO][cellId];
4254 const MFloat p = m_cells->pvariables[PV->P][cellId];
4255 const MFloat t = p * gamma / rho;
4256 const MFloat mu = SUTHERLANDLAW(t);
4257 const MFloat uWall = fabs(m_cells->pvariables[PV->U][cellId]);
4258 const MFloat ydist = m_cells->coordinates[1][cellId] - yWall;
4259 const MFloat uTau = sqrt(uWall * mu / (ydist * rho));
4260
4261 wallPropertiesLocal(localId, 0) = uTau;
4262 wallPropertiesLocal(localId, 1) = rho;
4263 }
4264 }
4265
4266 MPI_Allreduce(wallPropertiesLocal.begin(), wallProperties.begin(), noVar * m_grid->getMyBlockNoCells(0), MPI_DOUBLE,
4267 MPI_SUM, m_solver->m_rescalingCommGrComm, AT_, "wallPropertiesLocal.begin()", "wallProperties.begin()");
4268
4272
4273 const MInt totalCells[2] = {m_grid->getMyBlockNoCells(0), m_grid->getMyBlockNoCells(1) + 1};
4274
4275 MFloatScratchSpace varSliceLocal(6, totalCells[0] * totalCells[1], AT_, "varSliceLocal");
4276 MFloatScratchSpace varSlice(6, totalCells[0] * totalCells[1], AT_, "varSlice");
4277
4278 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
4279 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; ++j) {
4280 const MInt cellId = cellIndex(i, j, k);
4281 const MInt localId = (m_solver->m_nOffsetCells[1] + (j - m_noGhostLayers) + 1)
4282 + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4283 const MFloat rho = m_cells->pvariables[PV->RHO][cellId];
4284 const MFloat frho = F1 / rho;
4285 const MFloat p = m_cells->pvariables[PV->P][cellId];
4286 const MFloat temp = p * gamma * frho;
4287 const MFloat mu = SUTHERLANDLAW(temp);
4288 const MFloat uTauRe = wallProperties(thetaLocalOffset + (k - m_noGhostLayers), 0);
4289 const MFloat yIn = (m_cells->coordinates[1][cellId] - yWall) * uTauRe * rho / (mu * sqrt(m_solver->m_Re0));
4290 const MFloat yOut = (m_cells->coordinates[1][cellId] - yWall) * rho / (delta * CV->rhoInfinity);
4291 const MFloat u = m_cells->pvariables[PV->U][cellId];
4292 const MFloat v = m_cells->pvariables[PV->V][cellId];
4293 const MFloat w = m_cells->pvariables[PV->W][cellId];
4294
4295 // save the variables u,v,w,t,yI,yO
4296 varSliceLocal(0, localId) = u;
4297 varSliceLocal(1, localId) = v;
4298 varSliceLocal(2, localId) = w;
4299 varSliceLocal(3, localId) = temp;
4300 varSliceLocal(4, localId) = yIn;
4301 varSliceLocal(5, localId) = yOut;
4302 }
4303
4304 // set first value at the wall manually
4305 if(m_solver->m_nOffsetCells[0] == 0) {
4306 const MInt localId = 0 + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4307 const MInt localIdP1 = 1 + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4308 varSliceLocal(0, localId) = 0.0; // u
4309 varSliceLocal(1, localId) = 0.0; // v
4310 varSliceLocal(2, localId) = 0.0; // w
4311 varSliceLocal(3, localId) = varSliceLocal(3, localIdP1); // t
4312 varSliceLocal(4, localId) = 0.0; // yIn
4313 varSliceLocal(5, localId) = 0.0; // yOut
4314 }
4315 }
4316
4317 // communicate the slice
4318 MPI_Allreduce(varSliceLocal.begin(), varSlice.begin(), 6 * totalCells[0] * totalCells[1], MPI_DOUBLE, MPI_SUM,
4319 m_solver->m_rescalingCommGrComm, AT_, "varSliceLocal.begin()", "varSlice.begin()");
4320
4321 // participate in communication but only fill with zeros
4322 // MFloatScratchSpace blEdgeVValueLocal(m_solver->m_totalGridBlockDim[0][0]-1,AT_, "blEdgeVValueLocal");
4323 // MFloatScratchSpace blEdgeVValueGlobal(m_solver->m_totalGridBlockDim[0][0]-1,AT_, "blEdgeVValueLocal");
4324 // blEdgeVValueLocal.fill(F0);
4325 // blEdgeVValueGlobal.fill(F0);
4326
4327 // MPI_Allreduce(blEdgeVValueLocal.begin(),blEdgeVValueGlobal.begin(), m_solver->m_totalGridBlockDim[0][0]-1,
4328 // MPI_DOUBLE, MPI_SUM, m_solver->m_rescalingCommGrComm, AT_, "blEdgeVValueLocal.begin()",
4329 // "blEdgeVValueGlobal.begin()" );
4330}
4331
4332
4333// Inlet station for RANS
4334template <MBool isRans>
4336 (void)bcId;
4337
4338 cout.precision(8);
4339 // MInt* start = m_physicalBCMap[bcId]->start1;
4340 // MInt* end = m_physicalBCMap[bcId]->end1;
4341 // Communication between the Recycling and Inlet station.
4342 //___COMMGr(oup)______________________
4343 //|______________|_________________| |
4344 //|Inlet station |Recycling station| |
4345 //| | | |
4346 //|______________|_________________| |
4347 //|__________________________________|
4348 //
4349 // infographic of the Groups
4350
4351 // MFloat delta_inMax = delta_in+2.5*delta_in; //limit the integration height
4352 const MFloat gamma = m_solver->m_gamma;
4353 const MFloat gammaMinusOne = gamma - F1;
4354
4355 const MFloat rescalEPS = pow(10, -16.0);
4356 const MFloat alpha = 4.0;
4357 const MFloat b = 0.2;
4358 const MFloat rc = pow(m_solver->m_Pr, F1B3);
4359 const MFloat ctema = F1B2 * gammaMinusOne * POW2(m_solver->m_Ma) * rc;
4360
4361 // van Driest constant & transformed velocity
4362 const MFloat b_vd = sqrt(ctema / (F1 + ctema));
4363 const MFloat uvd8 = PV->UInfinity * asin(b_vd) / b_vd;
4364 const MInt i = m_noGhostLayers - 1;
4365
4369
4370 // allocate space in k direction (all k-Cells)
4371 MFloatScratchSpace thetaLocal(2, AT_, "thetaLocalIn");
4372 thetaLocal.fill(F0); // initialize scratch space
4373
4374 MFloatScratchSpace thetaGlobal(2, AT_, "thetaGlobalIn");
4375 thetaGlobal.fill(F0);
4376
4377 // the offest position in k-direction is the offset
4378 const MInt thetaLocalOffset = m_solver->m_nOffsetCells[0];
4379 // compute the local moment thickness j=direction of integration
4380 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
4381 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; ++j) {
4382 const MInt cellId = cellIndex(i, j, k);
4383 const MInt pointIdM1 = getPointIdFromCell(i, j, k);
4384 const MInt pointIdP1 = getPointIdfromPoint(pointIdM1, 0, 1, 0);
4385
4386 const MFloat urat = m_cells->pvariables[PV->U][cellId] / PV->UInfinity;
4387 const MFloat momThick =
4388 (m_cells->pvariables[PV->U][cellId] * m_cells->pvariables[PV->RHO][cellId] * fabs(F1 - urat))
4389 / (CV->rhoUInfinity);
4390 // integrate normal to the wall
4391 const MFloat ydist = m_grid->m_coordinates[1][pointIdP1] - m_grid->m_coordinates[1][pointIdM1];
4392 thetaLocal(0) += momThick * ydist;
4393 }
4394 }
4395
4396 MPI_Allreduce(thetaLocal.begin(), thetaGlobal.begin(), 2, MPI_DOUBLE, MPI_SUM, m_solver->m_rescalingCommGrComm, AT_,
4397 "thetaLocal.begin()", "thetaGlobal.begin()");
4398
4399 // determine spanwise average: we assume equally spaced in z-direction
4400 for(MInt ii = 0; ii < 2; ++ii) {
4401 thetaGlobal(ii) /= m_grid->getMyBlockNoCells(0);
4402 }
4403
4404 if(globalTimeStep % 5 == 0 && m_solver->m_RKStep == 0
4405 && m_solver->domainId() == m_solver->m_rescalingCommGrRootGlobal) {
4406 cout << m_solver->domainId() << " ThetaInflow " << thetaGlobal(0) << " ThetaRecyclingStation " << thetaGlobal(1)
4407 << endl;
4408
4409 FILE* f_channel;
4410 f_channel = fopen("./theta_inflow.dat", "a+");
4411 fprintf(f_channel, "%d", globalTimeStep);
4412 fprintf(f_channel, " %f", m_solver->m_physicalTime);
4413 fprintf(f_channel, " %f", m_solver->m_time);
4414 fprintf(f_channel, " %f", m_solver->m_timeStep);
4415 fprintf(f_channel, " %f", thetaGlobal[0]);
4416 fprintf(f_channel, " %f", thetaGlobal[1]);
4417 fprintf(f_channel, "\n");
4418 fclose(f_channel);
4419 }
4420
4424 const MInt noWallProperties = 3;
4425 MFloatScratchSpace wallPropertiesLocal(m_grid->getMyBlockNoCells(0), noWallProperties, AT_,
4426 "wallPropertiesLocalInlet");
4427 MFloatScratchSpace wallProperties(m_grid->getMyBlockNoCells(0), noWallProperties, AT_, "wallPropertiesInlet");
4428 wallPropertiesLocal.fill(F0);
4429 wallProperties.fill(F0);
4430
4431 MPI_Allreduce(wallPropertiesLocal.begin(), wallProperties.begin(), m_grid->getMyBlockNoCells(0) * noWallProperties,
4432 MPI_DOUBLE, MPI_SUM, m_solver->m_rescalingCommGrComm, AT_, "wallPropertiesLocal.begin()",
4433 "wallProperties.begin()");
4434
4438
4439 MFloatScratchSpace utauIn(m_solver->m_nActiveCells[0], 2, AT_, "u_tauIn");
4440 MFloatScratchSpace gams(m_solver->m_nActiveCells[0], 2, AT_, "gams");
4441
4442 for(MInt k = 0; k < m_solver->m_nActiveCells[0]; ++k) {
4443 MFloat utauRe = wallProperties(thetaLocalOffset + (k), 0);
4444
4445 // estimate the friction velocity at the inlet
4446 // according to standard power law approximations
4447 // utau_in = utau_re*(theta_re/theta_in)**(1/2*(n-1))
4448 // where theta is the momentum thichness
4449 // see Thomas S. Lund, p241
4450
4451 // when take into account the variance of wall density
4452 // utau_in = utau_re*(rho_wall_re/rho_wall_in)**0.5
4453 //* (theta_re/theta_in)**(1/2*(n-1))
4454 // here n = 5
4455 const MFloat n = 5.0;
4456 const MFloat facc = F1 / (F2 * (n - F1));
4457
4458 gams(k, i) = pow(thetaGlobal(1) / fabs(thetaGlobal(0)), facc);
4459 utauIn(k, i) = utauRe * min(max(gams(k, i), F1), 2.5);
4460 }
4461
4462 MFloatScratchSpace coordInInner(m_nCells[0] * m_nCells[1], 2, AT_, "coordInInner");
4463 MFloatScratchSpace coordInOuter(m_nCells[0] * m_nCells[1], 2, AT_, "coordInOuter");
4464
4465 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
4466 for(MInt j = 0; j < m_nCells[1]; ++j) {
4467 const MInt cellId = cellIndex(i, j, k);
4468 const MInt localId = j + (k - m_noGhostLayers) * m_nCells[1];
4469 const MFloat rho = m_cells->pvariables[PV->RHO][cellId];
4470 const MFloat frho = F1 / rho;
4471 const MFloat p = m_cells->pvariables[PV->P][cellId];
4472 const MFloat temp = p * gamma * frho;
4473 const MFloat mu = SUTHERLANDLAW(temp);
4474
4475 coordInInner(localId, i) =
4476 utauIn(k - m_noGhostLayers, i) * rho * m_cells->coordinates[1][cellId] / (mu * sqrt(m_solver->m_Re0));
4477 coordInOuter(localId, i) = m_cells->coordinates[1][cellId] * rho / (m_rescalingBLT * CV->rhoInfinity);
4478 }
4479 }
4480
4481 const MInt wallLocalOffset = m_solver->m_nOffsetCells[1]; // Offset in j-direction
4482 MFloatScratchSpace tempWallInletLocal(m_grid->getMyBlockNoCells(0), AT_, "tempWallInletLocal");
4483 MFloatScratchSpace tempWallInletGlobal(m_grid->getMyBlockNoCells(0), AT_, "tempWallInletGlobal");
4484 tempWallInletLocal.fill(F0);
4485 tempWallInletGlobal.fill(F0);
4486 // determine the wall stuff if wall is contained whithin the partition
4487 if(wallLocalOffset == 0 && m_solver->m_nActiveCells[1] >= m_noGhostLayers) {
4488 for(MInt k = m_noGhostLayers; k < m_solver->m_nCells[0] - m_noGhostLayers; ++k) {
4489 const MInt cellId = cellIndex(1, m_noGhostLayers, k);
4490 const MInt localId = m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers);
4491 tempWallInletLocal(localId) = temperature(cellId);
4492 }
4493 }
4494
4495 MPI_Allreduce(tempWallInletLocal.begin(), tempWallInletGlobal.begin(), m_grid->getMyBlockNoCells(0), MPI_DOUBLE,
4496 MPI_SUM, m_solver->m_rescalingCommGrComm, AT_, "tempWallInletLocal.begin()",
4497 "tempWallInletGlobal.begin()");
4498
4499
4503 const MInt noVariables = PV->noVariables + 1;
4504 MInt totalCells[2] = {m_grid->getMyBlockNoCells(0), m_grid->getMyBlockNoCells(1)};
4505 MFloatScratchSpace varSliceLocal(noVariables, totalCells[0] * totalCells[1], AT_, "varSliceLocal");
4506 MFloatScratchSpace varSlice(noVariables, totalCells[0] * totalCells[1], AT_, "varSlice");
4507
4508 // we are at the inlet, only fill with zeros
4509 varSlice.fill(F0);
4510 varSliceLocal.fill(F0);
4511
4512 MPI_Allreduce(varSliceLocal.begin(), varSlice.begin(), noVariables * totalCells[0] * totalCells[1], MPI_DOUBLE,
4513 MPI_SUM, m_solver->m_rescalingCommGrComm, AT_, "varSliceLocal.begin()", "varSlice.begin()");
4514
4515 if(globalTimeStep % 5 == 0 && m_solver->m_RKStep == 0
4516 && m_solver->domainId() == m_solver->m_rescalingCommGrRootGlobal) {
4517 cout << m_solver->domainId() << " ThetaInflow " << thetaGlobal(0) << " ThetaRecyclingStation " << thetaGlobal(1)
4518 << endl;
4519 }
4520
4524
4525 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
4526 const MFloat ctem1 = (F1 + ctema) * (F1 - POW2(gams(k - m_noGhostLayers, i)));
4527 const MFloat ctem2 = F2 * ctema * gams(k - m_noGhostLayers, i) * (F1 - gams(k - m_noGhostLayers, i));
4528 const MFloat ctem3 = (F1 - gams(k - m_noGhostLayers, i))
4529 * (F1 + gams(k - m_noGhostLayers, i) + F2 * ctema * gams(k - m_noGhostLayers, i));
4530
4531
4532 MInt jStart = 0;
4533 MInt jEnd = m_nCells[1];
4534
4535 if(m_solver->m_nOffsetCells[1] == 0) {
4536 jStart = m_noGhostLayers;
4537 }
4538 if(m_solver->m_nOffsetCells[1] + m_solver->m_nActiveCells[1] == m_grid->getMyBlockNoCells(1)) {
4539 jEnd = m_nCells[1] - m_noGhostLayers;
4540 }
4541
4542 for(MInt j = jStart; j < jEnd; ++j) {
4543 const MInt faceId = j + (k - m_noGhostLayers) * m_nCells[1];
4544 const MInt cellId = cellIndex(i, j, k);
4545
4546 if(coordInOuter(faceId, i) < 1.05) {
4547 MFloat uInner = F0, vInner = F0, wInner = F0, TInner = F0, mutInner = F0;
4548 MFloat uOuter = F0, vOuter = F0, wOuter = F0, TOuter = F0, mutOuter = F0;
4549 const MFloat count = alpha * (coordInOuter(faceId, i) - b);
4550 const MFloat denom = (F1 - F2 * b) * coordInOuter(faceId, i) + b;
4551 const MFloat ratio = count / denom;
4552 const MFloat wfun = F1B2 * (F1 + tanh(ratio) / tanh(alpha));
4553
4554 for(MInt jj = 0; jj < totalCells[1] - 1; ++jj) {
4555 const MInt localId = jj + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4556 const MInt localIdP1 = jj + 1 + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4557
4558 const MFloat yInnerRe = varSlice(4, localId);
4559 const MFloat yInnerReP1 = varSlice(4, localIdP1);
4560
4561 if((yInnerRe - coordInInner(faceId, i)) < rescalEPS && yInnerReP1 > coordInInner(faceId, i)) {
4562 const MFloat dy1 = coordInInner(faceId, i) - yInnerRe;
4563 const MFloat dy2 = yInnerReP1 - coordInInner(faceId, i);
4564 const MFloat dy = yInnerReP1 - yInnerRe;
4565
4566 const MFloat u = varSlice(0, localId);
4567 const MFloat uP1 = varSlice(0, localIdP1);
4568 const MFloat v = varSlice(1, localId);
4569 const MFloat vP1 = varSlice(1, localIdP1);
4570 const MFloat w = varSlice(2, localId);
4571 const MFloat wP1 = varSlice(2, localIdP1);
4572 const MFloat t = varSlice(3, localId);
4573 const MFloat tP1 = varSlice(3, localIdP1);
4574 const MFloat mut = varSlice(6, localId);
4575 const MFloat mutP1 = varSlice(6, localIdP1);
4576 uInner = (uP1 * dy1 + u * dy2) / dy;
4577 vInner = (vP1 * dy1 + v * dy2) / dy;
4578 wInner = (wP1 * dy1 + w * dy2) / dy;
4579 TInner = (tP1 * dy1 + t * dy2) / dy;
4580 mutInner = (mutP1 * dy1 + mut * dy2) / dy;
4581 }
4582 }
4583
4584 //>marian: catch those cells that didn't pass the if-clause (where TInner is still zero)
4585 if(TInner < 0.5) {
4586 for(MInt jj = 0; jj < totalCells[1] - 1; ++jj) {
4587 const MInt localId = jj + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4588 const MInt localIdP1 = jj + 1 + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4589
4590 const MFloat yInnerRe = varSlice(4, localId);
4591 const MFloat yInnerReP1 = varSlice(4, localIdP1);
4592 const MFloat diffPercent = (abs(yInnerRe - coordInInner(faceId, i)) / coordInInner(faceId, i)) * 100.0;
4593
4594 if((diffPercent < 10.0) && yInnerReP1 > coordInInner(faceId, i)) {
4595 const MFloat dy1 = coordInInner(faceId, i) - yInnerRe;
4596 const MFloat dy2 = yInnerReP1 - coordInInner(faceId, i);
4597 const MFloat dy = yInnerReP1 - yInnerRe;
4598
4599 const MFloat u = varSlice(0, localId);
4600 const MFloat uP1 = varSlice(0, localIdP1);
4601 const MFloat v = varSlice(1, localId);
4602 const MFloat vP1 = varSlice(1, localIdP1);
4603 const MFloat w = varSlice(2, localId);
4604 const MFloat wP1 = varSlice(2, localIdP1);
4605 const MFloat t = varSlice(3, localId);
4606 const MFloat tP1 = varSlice(3, localIdP1);
4607 const MFloat mut = varSlice(6, localId);
4608 const MFloat mutP1 = varSlice(6, localIdP1);
4609 uInner = (uP1 * dy1 + u * dy2) / dy;
4610 vInner = (vP1 * dy1 + v * dy2) / dy;
4611 wInner = (wP1 * dy1 + w * dy2) / dy;
4612 TInner = (tP1 * dy1 + t * dy2) / dy;
4613 mutInner = (mutP1 * dy1 + mut * dy2) / dy;
4614 }
4615 }
4616 }
4617 //<marian
4618
4619 // outer region
4620 for(MInt jj = 0; jj < totalCells[1] - 1; ++jj) {
4621 const MInt localId = jj + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4622 const MInt localIdP1 = jj + 1 + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4623
4624 const MFloat yOuterRe = varSlice(5, localId);
4625 const MFloat yOuterReP1 = varSlice(5, localIdP1);
4626
4627 if((yOuterRe - coordInOuter(faceId, i)) < rescalEPS && yOuterReP1 > coordInOuter(faceId, i)) {
4628 const MFloat dy1 = coordInOuter(faceId, i) - yOuterRe;
4629 const MFloat dy2 = yOuterReP1 - coordInOuter(faceId, i);
4630 const MFloat dy = yOuterReP1 - yOuterRe;
4631
4632
4633 const MFloat u = varSlice(0, localId);
4634 const MFloat uP1 = varSlice(0, localIdP1);
4635 const MFloat v = varSlice(1, localId);
4636 const MFloat vP1 = varSlice(1, localIdP1);
4637 const MFloat w = varSlice(2, localId);
4638 const MFloat wP1 = varSlice(2, localIdP1);
4639 const MFloat t = varSlice(3, localId);
4640 const MFloat tP1 = varSlice(3, localIdP1);
4641 const MFloat mut = varSlice(6, localId);
4642 const MFloat mutP1 = varSlice(6, localIdP1);
4643 uOuter = (uP1 * dy1 + u * dy2) / dy;
4644 vOuter = (vP1 * dy1 + v * dy2) / dy;
4645 wOuter = (wP1 * dy1 + w * dy2) / dy;
4646 TOuter = (tP1 * dy1 + t * dy2) / dy;
4647 mutOuter = (mutP1 * dy1 + mut * dy2) / dy;
4648 }
4649 }
4650
4651 const MFloat TInnerA = POW2(gams(k - m_noGhostLayers, i)) * TInner + ctem1 * PV->TInfinity;
4652 const MFloat TOuterA =
4653 POW2(gams(k - m_noGhostLayers, i)) * TOuter - (ctem2 * (uOuter / PV->UInfinity) - ctem3) * PV->TInfinity;
4654
4655 // van Driest transformation
4656 const MFloat uvdInner = PV->UInfinity * asin(b_vd * uInner / PV->UInfinity) / b_vd;
4657 const MFloat uvdOuter = PV->UInfinity * asin(b_vd * uOuter / PV->UInfinity) / b_vd;
4658
4659 // scaling of transformed inner and outer velocities
4660 uInner = gams(k - m_noGhostLayers, i) * uvdInner;
4661 uOuter = gams(k - m_noGhostLayers, i) * uvdOuter + (F1 - gams(k - m_noGhostLayers, i)) * uvd8;
4662
4663 uInner = PV->UInfinity * sin(b_vd * uInner / PV->UInfinity) / b_vd;
4664 uOuter = PV->UInfinity * sin(b_vd * uOuter / PV->UInfinity) / b_vd;
4665
4666 const MFloat pres = PV->PInfinity;
4667
4668 const MFloat uMean = uInner * (F1 - wfun) + uOuter * wfun;
4669 const MFloat vMean = vInner * (F1 - wfun) + vOuter * wfun;
4670 const MFloat wMean = (wInner * (F1 - wfun) + wOuter * wfun) * gams(k - m_noGhostLayers, i);
4671 const MFloat tMean = TInnerA * (F1 - wfun) + TOuterA * wfun;
4672 const MFloat rhoIn = gamma * pres / tMean;
4673
4674 // turbulent viscosity
4675 const MFloat tempWallInlet = tempWallInletGlobal(thetaLocalOffset + (k - m_noGhostLayers));
4676 const MFloat tempWallRecycling = wallProperties(thetaLocalOffset + (k - m_noGhostLayers), 2);
4677
4678 const MFloat viscWallInlet = SUTHERLANDLAW(tempWallInlet);
4679 const MFloat viscWallRecycling = SUTHERLANDLAW(tempWallRecycling);
4680 const MFloat thetaInlet = thetaGlobal(0);
4681 const MFloat thetaRecycling = thetaGlobal(1);
4682 mutInner = mutInner * (viscWallInlet / viscWallRecycling);
4683 mutOuter = mutOuter * gams(k - m_noGhostLayers, i) * (thetaInlet / thetaRecycling);
4684
4685 MFloat mutMean = mutInner * (F1 - wfun) + mutOuter * wfun;
4686 const MFloat clebf = 6.6;
4687 const MFloat blt = m_rescalingBLT;
4688 const MFloat cleb = F1 / (F1 + pow((m_cells->coordinates[1][cellId] / (clebf * blt)), 6.0));
4689
4690 m_cells->pvariables[PV->RHO][cellId] = rhoIn * cleb;
4691 m_cells->pvariables[PV->U][cellId] = uMean * cleb;
4692 m_cells->pvariables[PV->V][cellId] = vMean * cleb;
4693 m_cells->pvariables[PV->W][cellId] = wMean * cleb;
4694
4695 m_cells->pvariables[PV->P][cellId] = pres;
4696 m_cells->pvariables[PV->RANS_VAR[0]][cellId] = mutMean / rhoIn;
4697
4698 } else {
4699 // const MFloat pres = pressure(cellIndex(m_noGhostLayers,j,k)); //for supersonic PV->PInfinity
4700 const MFloat pres = PV->PInfinity;
4701 const MFloat rhoIn = gamma * pres / PV->TInfinity;
4702
4703 const MFloat uMean = PV->UInfinity;
4704 const MFloat vMean = PV->VInfinity;
4705 const MFloat wMean = PV->WInfinity;
4706
4707 m_cells->pvariables[PV->RHO][cellId] = rhoIn;
4708 m_cells->pvariables[PV->U][cellId] = uMean;
4709 m_cells->pvariables[PV->V][cellId] = vMean;
4710 m_cells->pvariables[PV->W][cellId] = wMean;
4711 m_cells->pvariables[PV->P][cellId] = pres;
4712 m_cells->pvariables[PV->RANS_VAR[0]][cellId] = PV->ransInfinity[0];
4713 }
4714 }
4715 }
4716
4717 for(MInt k = 0; k < m_nCells[0]; ++k) {
4718 for(MInt j = 0; j < m_nCells[1]; ++j) {
4719 // extrapolation for second GC
4720 const MInt cellId = cellIndex(1, j, k);
4721 const MInt cellIdM1 = cellIndex(0, j, k);
4722 const MInt cellIdadj = cellIndex(2, j, k);
4723
4724 for(MInt var = 0; var < PV->noVariables; var++) {
4725 m_cells->pvariables[var][cellIdM1] =
4726 2.0 * m_cells->pvariables[var][cellId] - m_cells->pvariables[var][cellIdadj];
4727 }
4728 }
4729 }
4730}
4731
4732
4733// Recycling station for RANS
4734template <MBool isRans>
4736 MInt* start = m_physicalBCMap[bcId]->start1;
4737 cout.precision(8);
4738
4739 // scaling between delta0 and delta2
4740 const MFloat F727 = 72.0 / 8.0;
4741 const MInt i = start[0]; // position at which recycle is taken
4742 const MFloat yWall = F0; // this has been fixed else method does not works
4743
4747
4748 // thetaLocal.fill(F0); //initialize scratch space to zero // only for parallel use
4749 MFloatScratchSpace thetaLocal(2, AT_, "thetaLocalRe");
4750 MFloatScratchSpace thetaGlobal(2, AT_, "thetaGlobalRe");
4751 thetaLocal.fill(F0); // initialize scratch space
4752 thetaGlobal.fill(F0);
4753
4754 // the offest position in k-direction is the offset
4755 const MInt thetaLocalOffset = m_solver->m_nOffsetCells[0];
4756 // compute the local moment thickness j=direction of integration
4757 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
4758 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; ++j) {
4759 const MInt cellId = cellIndex(i, j, k);
4760 const MInt pointIdM1 = getPointIdFromCell(i, j, k);
4761 const MInt pointIdP1 = getPointIdfromPoint(pointIdM1, 0, 1, 0);
4762
4763 const MFloat urat = m_cells->pvariables[PV->U][cellId] / PV->UInfinity;
4764 const MFloat momThick =
4765 (m_cells->pvariables[PV->U][cellId] * m_cells->pvariables[PV->RHO][cellId] * fabs(F1 - urat))
4766 / (CV->rhoUInfinity);
4767
4768 // integrate normal to the wall
4769 const MFloat ydist = m_grid->m_coordinates[1][pointIdP1] - m_grid->m_coordinates[1][pointIdM1];
4770 thetaLocal(1) += momThick * ydist;
4771 }
4772 }
4773
4774
4775 // communicate the Thickness across the plane
4776 MPI_Allreduce(thetaLocal.begin(), thetaGlobal.begin(), 2, MPI_DOUBLE, MPI_SUM, m_solver->m_rescalingCommGrComm, AT_,
4777 "thetaLocal.begin()", "thetaGlobal.begin()");
4778
4779 thetaGlobal(1) /= m_grid->getMyBlockNoCells(0); // we have now the averaged momentum thi
4780
4784
4785 const MFloat delta = F727 * thetaGlobal(1);
4786 const MInt noVar = 3; // for more variables if wanted
4787 const MInt wallLocalOffset = m_solver->m_nOffsetCells[1]; // Offset in j-direction
4788
4789 MFloatScratchSpace wallPropertiesLocal(m_grid->getMyBlockNoCells(0), noVar, AT_, "wallPropertiesLocalRe");
4790 MFloatScratchSpace wallProperties(m_grid->getMyBlockNoCells(0), noVar, AT_, "wallPropertiesRe");
4791 wallPropertiesLocal.fill(F0);
4792 wallProperties.fill(F0);
4793
4794 // determine the wall stuff if wall is contained whithin the partition
4795 if(wallLocalOffset == 0 && m_solver->m_nActiveCells[1] >= m_noGhostLayers) {
4796 for(MInt k = m_noGhostLayers; k < m_solver->m_nCells[0] - m_noGhostLayers; ++k) {
4797 const MInt cellId = cellIndex(i, m_noGhostLayers, k);
4798 const MFloat rho = m_cells->pvariables[PV->RHO][cellId];
4799 const MFloat t = temperature(cellId);
4800 const MFloat nu = SUTHERLANDLAW(t);
4801 const MFloat uWall = fabs(m_cells->pvariables[PV->U][cellId]);
4802 const MFloat ydist = m_cells->coordinates[1][cellId] - yWall;
4803 const MFloat uTau = sqrt(uWall * nu / (ydist * rho));
4804 const MInt localId = m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers);
4805
4806 wallPropertiesLocal(localId, 0) = uTau;
4807 wallPropertiesLocal(localId, 1) = rho;
4808 wallPropertiesLocal(localId, 2) = t;
4809 }
4810 }
4811
4812
4813 MPI_Allreduce(wallPropertiesLocal.begin(), wallProperties.begin(), noVar * m_grid->getMyBlockNoCells(0), MPI_DOUBLE,
4814 MPI_SUM, m_solver->m_rescalingCommGrComm, AT_, "wallPropertiesLocal.begin()", "wallProperties.begin()");
4815
4816 MFloatScratchSpace tempWallInletLocal(m_grid->getMyBlockNoCells(0), AT_, "tempWallInletLocal");
4817 MFloatScratchSpace tempWallInletGlobal(m_grid->getMyBlockNoCells(0), AT_, "tempWallInletGlobal");
4818 tempWallInletLocal.fill(F0);
4819 tempWallInletGlobal.fill(F0);
4820
4821 MPI_Allreduce(tempWallInletLocal.begin(), tempWallInletGlobal.begin(), m_grid->getMyBlockNoCells(0), MPI_DOUBLE,
4822 MPI_SUM, m_solver->m_rescalingCommGrComm, AT_, "tempWallInletLocal.begin()",
4823 "tempWallInletGlobal.begin()");
4824
4828
4829 MInt totalCells[2] = {m_grid->getMyBlockNoCells(0), m_grid->getMyBlockNoCells(1)};
4830
4831 const MInt noVariables = PV->noVariables + 1;
4832 MFloatScratchSpace varSliceLocal(noVariables, totalCells[0] * totalCells[1], AT_, "varSliceLocal");
4833 MFloatScratchSpace varSlice(noVariables, totalCells[0] * totalCells[1], AT_, "varSlice");
4834
4835
4836 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
4837 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; ++j) {
4838 const MInt cellId = cellIndex(i, j, k);
4839 const MFloat rho = m_cells->pvariables[PV->RHO][cellId];
4840 const MFloat temp = temperature(cellId);
4841 const MFloat nu = SUTHERLANDLAW(temp);
4842 const MFloat uTauRe = wallProperties(thetaLocalOffset + (k - m_noGhostLayers), 0);
4843 const MFloat yIn = (m_cells->coordinates[1][cellId] - yWall) * uTauRe * rho / (nu * sqrt(m_solver->m_Re0));
4844 const MFloat yOut = (m_cells->coordinates[1][cellId] - yWall) * rho / (delta * CV->rhoInfinity);
4845 const MFloat u = m_cells->pvariables[PV->U][cellId];
4846 const MFloat v = m_cells->pvariables[PV->V][cellId];
4847 const MFloat w = m_cells->pvariables[PV->W][cellId];
4848 //>RANS
4849 const MFloat nut = m_cells->pvariables[PV->RANS_VAR[0]][cellId];
4850 //<RANS
4851
4852 const MInt localId = m_solver->m_nOffsetCells[1] + (j - m_noGhostLayers)
4853 + (m_solver->m_nOffsetCells[0] + (k - m_noGhostLayers)) * totalCells[1];
4854
4855 // save the variables u,v,w,t,yI,yO
4856 varSliceLocal(0, localId) = u;
4857 varSliceLocal(1, localId) = v;
4858 varSliceLocal(2, localId) = w;
4859 varSliceLocal(3, localId) = temp;
4860 varSliceLocal(4, localId) = yIn;
4861 varSliceLocal(5, localId) = yOut;
4862 varSliceLocal(6, localId) = nut;
4863 }
4864 }
4865
4866 // communicate the slice
4867 MPI_Allreduce(varSliceLocal.begin(), varSlice.begin(), noVariables * totalCells[0] * totalCells[1], MPI_DOUBLE,
4868 MPI_SUM, m_solver->m_rescalingCommGrComm, AT_, "varSliceLocal.begin()", "varSlice.begin()");
4869}
4870
4875template <MBool isRans>
4877 MInt* start = m_physicalBCMap[bcId]->start1;
4878 MInt* end = m_physicalBCMap[bcId]->end1;
4879
4880 switch(m_physicalBCMap[bcId]->face) {
4881 case 0: {
4882 for(MInt k = start[2]; k < end[2]; k++) {
4883 for(MInt j = end[1] - 1; j >= start[1]; j--) {
4884 const MInt cellIdG1 = cellIndex(start[0] + 1, j, k);
4885 const MInt cellIdG2 = cellIndex(start[0] + 0, j, k);
4886 const MInt cellIdA1 = cellIndex(start[0] + 2, j, k);
4887 const MFloat y_max = F1; // channel height
4888
4889 const MFloat x = m_cells->coordinates[0][cellIdG1];
4890 const MFloat y = m_cells->coordinates[1][cellIdG1];
4891 const MFloat pG1 =
4892 PV->PInfinity
4893 - F3 * (x + 15.0) * SUTHERLANDLAW(PV->TInfinity) * PV->UInfinity * POW2(F2 / y_max) / m_solver->m_Re0;
4894
4895 m_cells->pvariables[PV->RHO][cellIdG1] = CV->rhoInfinity;
4896 m_cells->pvariables[PV->U][cellIdG1] =
4897 (-(F3 / F2) * PV->UInfinity * (POW2(y - y_max / F2) - POW2(y_max / F2)) / POW2(y_max / F2));
4898 m_cells->pvariables[PV->V][cellIdG1] = F0;
4899 m_cells->pvariables[PV->W][cellIdG1] = F0;
4900 m_cells->pvariables[PV->P][cellIdG1] = pG1;
4901
4902 // extrapolate into second ghost cell
4903 for(MInt var = 0; var < PV->noVariables; var++) {
4904 m_cells->pvariables[var][cellIdG2] =
4905 F2 * m_cells->pvariables[var][cellIdG1] - m_cells->pvariables[var][cellIdA1];
4906 }
4907 }
4908 }
4909 break;
4910 }
4911 default: {
4912 cout << "bc2020: face not implemented" << endl;
4913 }
4914 }
4915}
4916
4924template <MBool isRans>
4926 MInt* start = m_physicalBCMap[bcId]->start1;
4927 MInt* end = m_physicalBCMap[bcId]->end1;
4928
4929 switch(m_physicalBCMap[bcId]->face) {
4930 case 0: {
4931 for(MInt i = start[0]; i < end[0]; i++) {
4932 for(MInt j = start[1]; j < end[1]; j++) {
4933 for(MInt k = start[2]; k < end[2]; k++) {
4934 const MInt cellId = cellIndex(m_noGhostLayers - 1 - i, j, k);
4935 const MInt cellIdadj = cellIndex(m_noGhostLayers - i, j, k);
4936
4937 // extrapolate pressure to ghost cells
4938 m_cells->pvariables[PV->P][cellId] = m_cells->pvariables[PV->P][cellIdadj];
4939 }
4940 }
4941 }
4942 break;
4943 }
4944 case 1: {
4945 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
4946 const MFloat gamma = m_solver->m_gamma;
4947
4948 // Here we find out the normal direction of the
4949 // boundary and the two tangential directions.
4950 // This way we can make a general formulation of
4951 // the boundary condition
4952 const MInt face = m_physicalBCMap[bcId]->face;
4953 const MInt normalDir = face / 2;
4954 const MInt firstTangentialDir = (normalDir + 1) % nDim;
4955 const MInt secondTangentialDir = (normalDir + 2) % nDim;
4956 const MInt normalDirStart = start[normalDir];
4957 const MInt firstTangentialStart = start[firstTangentialDir];
4958 const MInt firstTangentialEnd = end[firstTangentialDir];
4959 const MInt secondTangentialStart = start[secondTangentialDir];
4960 const MInt secondTangentialEnd = end[secondTangentialDir];
4961 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
4962
4963 const MInt n = (face % 2) * 2 - 1; //-1,+1
4964 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
4965 const MInt g2 = normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n)); // 0,+1
4966 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
4967 const MInt a2 = normalDirStart + (MInt)(0.5 - (2.5 * (MFloat)n)); //+3,-2
4968
4969 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
4970 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
4971 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
4972 const MInt cellIdG2 = g2 * inc[0] + t1 * inc[1] + t2 * inc[2];
4973 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
4974 const MInt cellIdA2 = a2 * inc[0] + t1 * inc[1] + t2 * inc[2];
4975 const MInt cellIdBc =
4976 g1 - normalDirStart + (t1 + t2 * m_solver->m_bc2600noCells[1]) * m_solver->m_bc2600noCells[2];
4977
4978 const MFloat dxidx = m_cells->surfaceMetrics[normalDir * nDim + 0][cellIdA1];
4979 const MFloat dxidy = m_cells->surfaceMetrics[normalDir * nDim + 1][cellIdA1];
4980 const MFloat dxidz = m_cells->surfaceMetrics[normalDir * nDim + 2][cellIdA1];
4981 // multiply with n, so it will be -1 or +1 depending if we enter
4982 // or leave the domain of integration in positive direction
4983 const MFloat gradxi = n * F1 / sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz);
4984
4985 const MFloat dxHelp = dxidx * gradxi;
4986 const MFloat dyHelp = dxidy * gradxi;
4987 const MFloat dzHelp = dxidz * gradxi;
4988
4989 const MFloat cBC =
4990 sqrt(gamma * m_cells->pvariables[PV->P][cellIdG1] / m_cells->pvariables[PV->RHO][cellIdG1]);
4991 const MFloat rhoBC = m_cells->pvariables[PV->RHO][cellIdG1];
4992
4993 const MFloat rhoInner = m_cells->pvariables[PV->RHO][cellIdA1];
4994 const MFloat uInner = m_cells->pvariables[PV->U][cellIdA1];
4995 const MFloat vInner = m_cells->pvariables[PV->V][cellIdA1];
4996 const MFloat wInner = m_cells->pvariables[PV->W][cellIdA1];
4997 const MFloat pInner = m_cells->pvariables[PV->P][cellIdA1];
4998
4999 const MFloat u2600 = m_solver->m_bc2600Variables[PV->U][cellIdBc];
5000 const MFloat v2600 = m_solver->m_bc2600Variables[PV->V][cellIdBc];
5001 const MFloat w2600 = m_solver->m_bc2600Variables[PV->W][cellIdBc];
5002 const MFloat rho2600 = m_solver->m_bc2600Variables[PV->RHO][cellIdBc];
5003 const MFloat p2600 = m_solver->m_bc2600Variables[PV->P][cellIdBc];
5004 const MFloat rans2600 = m_solver->m_bc2600Variables[PV->RANS_VAR[0]][cellIdBc];
5005
5006 const MFloat maContravariant =
5007 (dxidx * uInner + dxidy * vInner + dxidz * wInner - m_cells->dxt[normalDir][cellIdA1]) * gradxi;
5008
5009 if(maContravariant < F0) {
5010 // inflow
5011 const MFloat p =
5012 F1B2
5013 * (pInner + p2600
5014 + rhoBC * cBC * (dxHelp * (uInner - u2600) + dyHelp * (vInner - v2600) + dzHelp * (wInner - w2600)));
5015
5016 const MFloat rho = rho2600 + (p - p2600) / POW2(cBC);
5017 const MFloat help = (p - p2600) / (rhoBC * cBC);
5018
5019 m_cells->pvariables[PV->RHO][cellIdG1] = rho;
5020 m_cells->pvariables[PV->U][cellIdG1] = (u2600 + help * dxHelp);
5021 m_cells->pvariables[PV->V][cellIdG1] = (u2600 + help * dyHelp);
5022 m_cells->pvariables[PV->W][cellIdG1] = (u2600 + help * dzHelp);
5023 m_cells->pvariables[PV->P][cellIdG1] = p;
5024 if(isRans) {
5025 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG1] = rans2600;
5026 }
5027 } else {
5028 // outflow
5029 MFloat p = p2600; // PV->PInfinity;
5030 // if(m_solver->m_restartTimeStep+globalTimeStep <= 1000000) {
5031 // p = PV->PInfinity +
5032 // (p2600-PV->PInfinity)*(((MFloat)(m_solver->m_restartTimeStep+globalTimeStep))/1000000.0);
5033 // } else {
5034 // p = p2600;
5035 // }
5036
5037 const MFloat rho = rhoInner + (p - pInner) / POW2(cBC);
5038 const MFloat help = (p - pInner) / (rhoBC * cBC);
5039
5040 m_cells->pvariables[PV->RHO][cellIdG1] = rho;
5041 m_cells->pvariables[PV->U][cellIdG1] = (uInner - help * dxHelp);
5042 m_cells->pvariables[PV->V][cellIdG1] = (vInner - help * dyHelp);
5043 m_cells->pvariables[PV->W][cellIdG1] = (wInner - help * dzHelp);
5044 m_cells->pvariables[PV->P][cellIdG1] = p;
5045 if(isRans) {
5046 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG1] = (F2 * m_cells->pvariables[PV->RANS_VAR[0]][cellIdA1]
5047 - m_cells->pvariables[PV->RANS_VAR[0]][cellIdA2]);
5048 }
5049 }
5050
5051 // extrapolate into second ghost cell
5052 for(MInt var = 0; var < PV->noVariables; var++) {
5053 m_cells->pvariables[var][cellIdG2] =
5054 F2 * m_cells->pvariables[var][cellIdG1] - m_cells->pvariables[var][cellIdA1];
5055 }
5056 }
5057 }
5058 break;
5059 }
5060 default: {
5061 mTerm(1, AT_, "Face not implemented");
5062 break;
5063 }
5064 }
5065}
5066
5067
5075template <MBool isRans>
5077 MInt* start = m_physicalBCMap[bcId]->start1;
5078 MInt* end = m_physicalBCMap[bcId]->end1;
5079
5080 MFloat theta100000 = 0.002065747418;
5081 MFloat rexPosQuad = 0.014452;
5082 MFloat gammaEpsilon = m_solver->m_bc2601GammaEpsilon;
5083
5084 if(m_solver->m_rans) {
5085 theta100000 = 0.002171197777811;
5086 rexPosQuad = 0.14452;
5087 }
5088
5089 const MFloat lengthFactor = theta100000 * rexPosQuad;
5090
5091 MFloatScratchSpace effConst(m_2601noPos, m_2601noCoeff, AT_, "effConst");
5092 effConst.fill(F0);
5093
5094
5095 switch(m_physicalBCMap[bcId]->face) {
5096 case 2: {
5097 for(MInt k = start[2]; k < end[2]; k++) {
5101 // manipulate time with spanwise coordinate
5102 const MInt spanCell = cellIndex(m_noGhostLayers, m_noGhostLayers, k);
5103 const MFloat spanCoord = m_cells->coordinates[2][spanCell];
5104 const MFloat waveSpeed = 0.015795;
5105 const MFloat timeShift = spanCoord / waveSpeed;
5106 const MFloat t = m_solver->m_time + m_solver->m_timeStep * m_solver->m_RKalpha[m_solver->m_RKStep] - timeShift;
5107
5111
5112 // interpolate between time values
5113 for(MInt pos = 0; pos < m_2601noPos; pos++) {
5114 effConst(pos, 0) = m_2601streamwisePos[pos];
5115 for(MInt iter = 0; iter < m_2601noSteps - 1; iter++) {
5116 if(m_2601effConst[0][pos * m_2601noCoeff + 0] >= t) {
5117 effConst(pos, 1) = m_2601effConst[0][pos * m_2601noCoeff + 1];
5118 effConst(pos, 2) = m_2601effConst[0][pos * m_2601noCoeff + 2];
5119 effConst(pos, 3) = m_2601effConst[0][pos * m_2601noCoeff + 3];
5120 effConst(pos, 4) = m_2601effConst[0][pos * m_2601noCoeff + 4];
5121 break;
5122 } else if(m_2601effConst[iter][pos * m_2601noCoeff + 0] < t
5123 && t <= m_2601effConst[iter + 1][pos * m_2601noCoeff + 0]) {
5124 for(MInt var = 1; var < 5; var++) {
5125 // linear interpolation between two time values
5126 effConst(pos, var) = m_2601effConst[iter][pos * m_2601noCoeff + var]
5127 + (t - m_2601effConst[iter][pos * m_2601noCoeff + 0])
5128 / (m_2601effConst[iter + 1][pos * m_2601noCoeff + 0]
5129 - m_2601effConst[iter][pos * m_2601noCoeff + 0])
5130 * (m_2601effConst[iter + 1][pos * m_2601noCoeff + var]
5131 - m_2601effConst[iter][pos * m_2601noCoeff + var]);
5132 }
5133 break;
5134 } else {
5135 effConst(pos, 1) = m_2601effConst[iter][pos * m_2601noCoeff + 1];
5136 effConst(pos, 2) = m_2601effConst[iter][pos * m_2601noCoeff + 2];
5137 effConst(pos, 3) = m_2601effConst[iter][pos * m_2601noCoeff + 3];
5138 effConst(pos, 4) = m_2601effConst[iter][pos * m_2601noCoeff + 4];
5139 }
5140 }
5141 }
5142
5143 for(MInt pos = 0; pos < m_2601noPos; pos++) {
5144 effConst(pos, 0) = (effConst(pos, 0) - rexPosQuad) / lengthFactor + 36.57;
5145 }
5146
5150
5151 for(MInt i = start[0]; i < end[0]; i++) {
5152 const MInt cellId = cellIndex(i, 1, k);
5153
5154 MInt cellIdG2 = cellIndex(i, 0, k); // ghost
5155 MInt cellIdG1 = cellIndex(i, 1, k); // ghost
5156 MInt cellIdA1 = cellIndex(i, 2, k); // field
5157 MInt cellIdA2 = cellIndex(i, 3, k); // field
5158
5159 const MInt cellIdBcG1 = i + (1 + k * m_noGhostLayers) * m_solver->m_nCells[2];
5160 const MInt cellIdBcG2 = i + (0 + k * m_noGhostLayers) * m_solver->m_nCells[2];
5161
5162 const MFloat rho_zerothG1 = m_solver->m_bc2601ZerothOrderSolution[PV->RHO][cellIdBcG1];
5163 const MFloat u_zerothG1 = m_solver->m_bc2601ZerothOrderSolution[PV->U][cellIdBcG1];
5164 const MFloat v_zerothG1 = m_solver->m_bc2601ZerothOrderSolution[PV->V][cellIdBcG1];
5165 const MFloat w_zerothG1 = m_solver->m_bc2601ZerothOrderSolution[PV->W][cellIdBcG1];
5166
5167 // const MFloat rho_zerothG2 = m_solver->m_bc2601ZerothOrderSolution[PV->RHO][cellIdBcG2];
5168 const MFloat u_zerothG2 = m_solver->m_bc2601ZerothOrderSolution[PV->U][cellIdBcG2];
5169 const MFloat v_zerothG2 = m_solver->m_bc2601ZerothOrderSolution[PV->V][cellIdBcG2];
5170 const MFloat w_zerothG2 = m_solver->m_bc2601ZerothOrderSolution[PV->W][cellIdBcG2];
5171
5172 const MFloat uInfQuad = 1.029342800042823e+02;
5173 const MFloat rhoInfQuad = 1.209633989123;
5174 // const MFloat heightG1 = m_cells->coordinates[1][cellIdG1];
5175 // const MFloat heightG2 = m_cells->coordinates[1][cellIdG2];
5176 const MFloat xPos = m_cells->coordinates[0][cellId];
5177
5178 MFloat uFactor = F0;
5179 MFloat vFactor = F0;
5180 MFloat wFactor = F0;
5181 MFloat rhoFactor = F0;
5182
5183 // interpolated from the actuated solution
5184 MFloat uActuated = F0, vActuated = F0, wActuated = F0;
5185
5186 // space interpolation
5187 if(xPos < effConst(0, 0)) {
5188 const MFloat relPos = (xPos - effConst(0, 0)) / (effConst(1, 0) - effConst(0, 0));
5189 uFactor = effConst(0, 1) + relPos * (effConst(1, 1) - effConst(0, 1));
5190 vFactor = effConst(0, 2) + relPos * (effConst(1, 2) - effConst(0, 2));
5191 wFactor = effConst(0, 3) + relPos * (effConst(1, 3) - effConst(0, 3));
5192 rhoFactor = effConst(0, 4) + relPos * (effConst(1, 4) - effConst(0, 4));
5193 } else if(effConst(0, 0) <= xPos && xPos < effConst(m_2601noPos - 1, 0)) {
5194 for(MInt pos = 0; pos < m_2601noPos - 1; pos++) {
5195 if(effConst(pos, 0) <= xPos && xPos < effConst(pos + 1, 0)) {
5196 const MFloat relPos = (xPos - effConst(pos, 0)) / (effConst(pos + 1, 0) - effConst(pos, 0));
5197 uFactor = effConst(pos, 1) + relPos * (effConst(pos + 1, 1) - effConst(pos, 1));
5198 vFactor = effConst(pos, 2) + relPos * (effConst(pos + 1, 2) - effConst(pos, 2));
5199 wFactor = effConst(pos, 3) + relPos * (effConst(pos + 1, 3) - effConst(pos, 3));
5200 rhoFactor = effConst(pos, 4) + relPos * (effConst(pos + 1, 4) - effConst(pos, 4));
5201 break;
5202 }
5203 }
5204 } else {
5205 const MFloat relPos =
5206 (xPos - effConst(m_2601noPos - 2, 0)) / (effConst(m_2601noPos - 1, 0) - effConst(m_2601noPos - 2, 0));
5207 uFactor =
5208 effConst(m_2601noPos - 2, 1) + relPos * (effConst(m_2601noPos - 1, 1) - effConst(m_2601noPos - 2, 1));
5209 vFactor =
5210 effConst(m_2601noPos - 2, 2) + relPos * (effConst(m_2601noPos - 1, 2) - effConst(m_2601noPos - 2, 2));
5211 wFactor =
5212 effConst(m_2601noPos - 2, 3) + relPos * (effConst(m_2601noPos - 1, 3) - effConst(m_2601noPos - 2, 3));
5213 rhoFactor =
5214 effConst(m_2601noPos - 2, 4) + relPos * (effConst(m_2601noPos - 1, 4) - effConst(m_2601noPos - 2, 4));
5215 }
5216
5217 // //for now take uniform distribution
5218 // uFactor = effConst(0,1);
5219 // vFactor = effConst(0,2);
5220 // rhoFactor = effConst(0,4);
5221
5222 // MFloat u_correctedG1 = u_zerothG1 + heightG1*lengthFactor*(uFactor)*(PV->UInfinity/uInfQuad);
5223 // MFloat u_correctedG2 = u_zerothG2 + heightG2*lengthFactor*(uFactor)*(PV->UInfinity/uInfQuad);
5224
5225
5226 MFloat u_zerothBC = u_zerothG1 + F1B2 * (u_zerothG1 - u_zerothG2);
5227 MFloat u_correctedBC = u_zerothBC + gammaEpsilon * lengthFactor * (uFactor) * (PV->UInfinity / uInfQuad);
5228 MFloat v_zerothBC = v_zerothG1 + F1B2 * (v_zerothG1 - v_zerothG2);
5229 MFloat v_correctedBC = v_zerothBC + gammaEpsilon * lengthFactor * (vFactor) * (PV->UInfinity / uInfQuad);
5230 MFloat w_zerothBC = w_zerothG1 + F1B2 * (w_zerothG1 - w_zerothG2);
5231 MFloat w_correctedBC =
5232 w_zerothBC + gammaEpsilon * lengthFactor * (wFactor) * (PV->UInfinity / uInfQuad); // + wActuated;
5233 MFloat rho_correctedG1 =
5234 rho_zerothG1 + gammaEpsilon * lengthFactor * (rhoFactor) * (CV->rhoInfinity / rhoInfQuad);
5235
5236 if(m_solver->m_nOffsetCells[2] + i - 2 == 80 && m_solver->m_nOffsetCells[0] + k - 2 == 50) {
5237 if(globalTimeStep % 20 == 0 && m_solver->m_RKStep == 0) {
5238 cout.precision(7);
5239 cout << "globalTimeStep: " << globalTimeStep << " time: " << t << " gammaEpsilon: " << gammaEpsilon
5240 << " uZeroth: " << u_zerothBC << " u_correctedBC: " << u_correctedBC << " vZeroth: " << v_zerothBC
5241 << " v_correctedBC: " << v_correctedBC << " rhoZeroth: " << rho_zerothG1
5242 << " rho_correctedG1: " << rho_correctedG1 << " vActuated: " << vActuated << endl;
5243
5244
5245 FILE* f_effective;
5246 f_effective = fopen("./effective_boundary.dat", "a+");
5247 fprintf(f_effective, "%d", globalTimeStep);
5248 fprintf(f_effective, " %f", m_solver->m_physicalTime);
5249 fprintf(f_effective, " %f", m_solver->m_time);
5250 fprintf(f_effective, " %f", m_solver->m_timeStep);
5251 fprintf(f_effective, " %f", u_zerothBC);
5252 fprintf(f_effective, " %f", u_correctedBC);
5253 fprintf(f_effective, " %f", v_zerothBC);
5254 fprintf(f_effective, " %f", v_correctedBC);
5255 fprintf(f_effective, " %f", w_zerothBC);
5256 fprintf(f_effective, " %f", w_correctedBC);
5257 fprintf(f_effective, " %f", rho_zerothG1);
5258 fprintf(f_effective, " %f", rho_correctedG1);
5259 fprintf(f_effective, " %f", uActuated);
5260 fprintf(f_effective, " %f", vActuated);
5261 fprintf(f_effective, " %f", wActuated);
5262 fprintf(f_effective, "\n");
5263 fclose(f_effective);
5264 }
5265 }
5266
5267 const MFloat u_uncorrectedBC = u_zerothG1 + F1B2 * (u_zerothG1 - u_zerothG2);
5268 const MFloat v_uncorrectedBC = v_zerothG1 + F1B2 * (v_zerothG1 - v_zerothG2);
5269 const MFloat w_uncorrectedBC = w_zerothG1 + F1B2 * (w_zerothG1 - w_zerothG2);
5270 const MFloat rho_uncorrectedG1 = rho_zerothG1;
5271
5272 MFloat u_appliedBC = F0, v_appliedBC = F0, w_appliedBC = F0, rho_appliedG1 = F0;
5273
5274 if(m_cells->coordinates[0][cellId] < 12.4) {
5275 u_appliedBC = u_uncorrectedBC;
5276 v_appliedBC = v_uncorrectedBC;
5277 w_appliedBC = w_uncorrectedBC;
5278 rho_appliedG1 = rho_uncorrectedG1;
5279 } else if(m_cells->coordinates[0][cellId] >= 12.4 && m_cells->coordinates[0][cellId] < 15.4) {
5280 const MFloat fader = (m_cells->coordinates[0][cellId] - 12.4) / 3.0;
5281 u_appliedBC = u_uncorrectedBC * (1.0 - fader) + u_correctedBC * fader;
5282 v_appliedBC = v_uncorrectedBC * (1.0 - fader) + v_correctedBC * fader;
5283 w_appliedBC = w_uncorrectedBC * (1.0 - fader) + w_correctedBC * fader;
5284 rho_appliedG1 = rho_uncorrectedG1 * (1.0 - fader) + rho_correctedG1 * fader;
5285 } else if(m_cells->coordinates[0][cellId] >= 15.4 && m_cells->coordinates[0][cellId] < 60.0) {
5286 u_appliedBC = u_correctedBC;
5287 v_appliedBC = v_correctedBC;
5288 w_appliedBC = w_correctedBC;
5289 rho_appliedG1 = rho_correctedG1;
5290 } else if(m_cells->coordinates[0][cellId] >= 60.0 && m_cells->coordinates[0][cellId] < 63.0) {
5291 const MFloat fader = (m_cells->coordinates[0][cellId] - 60.0) / 3.0;
5292 u_appliedBC = u_uncorrectedBC * (fader) + u_correctedBC * (1.0 - fader);
5293 v_appliedBC = v_uncorrectedBC * (fader) + v_correctedBC * (1.0 - fader);
5294 w_appliedBC = w_uncorrectedBC * (fader) + w_correctedBC * (1.0 - fader);
5295 rho_appliedG1 = rho_uncorrectedG1 * (fader) + rho_correctedG1 * (1.0 - fader);
5296 } else {
5297 u_appliedBC = u_uncorrectedBC;
5298 v_appliedBC = v_uncorrectedBC;
5299 w_appliedBC = w_uncorrectedBC;
5300 rho_appliedG1 = rho_uncorrectedG1;
5301 }
5302
5303 // if(m_cells->coordinates[0][cellId] < 15.4) {
5304 // u_appliedBC = u_uncorrectedBC;
5305 // v_appliedBC = v_uncorrectedBC;
5306 // w_appliedBC = w_uncorrectedBC;
5307 // rho_appliedG1 = rho_uncorrectedG1;
5308 // } else if(m_cells->coordinates[0][cellId] >= 15.4 && m_cells->coordinates[0][cellId] < 60.0) {
5309 // u_appliedBC = u_correctedBC;
5310 // v_appliedBC = v_correctedBC;
5311 // w_appliedBC = w_correctedBC;
5312 // rho_appliedG1 = rho_correctedG1;
5313 // } else {
5314 // u_appliedBC = u_uncorrectedBC;
5315 // v_appliedBC = v_uncorrectedBC;
5316 // w_appliedBC = w_uncorrectedBC;
5317 // rho_appliedG1 = rho_uncorrectedG1;
5318 // }
5319
5320 // const MFloat rho_correctedG2 = rho_zerothG2 +
5321 // heightG2*lengthFactor*(rhoFactor)*(CV->rhoInfinity/rhoInfQuad); const MFloat rho_correctedBC =
5322 // rho_correctedG1 + F1B2*(rho_correctedG1-rho_correctedG2);
5323 const MFloat pField = pressure(cellIndex(i, m_noGhostLayers, k));
5324
5325
5326 const MFloat u1 = m_cells->pvariables[PV->U][cellIdA1];
5327 const MFloat v1 = m_cells->pvariables[PV->V][cellIdA1];
5328 const MFloat w1 = m_cells->pvariables[PV->W][cellIdA1];
5329 const MFloat rho1 = m_cells->pvariables[PV->RHO][cellIdA1];
5330
5331 const MFloat u2 = m_cells->pvariables[PV->U][cellIdA2];
5332 const MFloat v2 = m_cells->pvariables[PV->V][cellIdA2];
5333 const MFloat w2 = m_cells->pvariables[PV->W][cellIdA2];
5334 // MFloat rho2 = m_cells->pvariables[PV->RHO][cellIdA2];
5335
5336 const MFloat uG1 = F2 * u_appliedBC - u1;
5337 const MFloat vG1 = F2 * v_appliedBC - v1;
5338 const MFloat wG1 = F2 * w_appliedBC - w1;
5339
5340 const MFloat uG2 = F2 * u_appliedBC - u2;
5341 const MFloat vG2 = F2 * v_appliedBC - v2;
5342 const MFloat wG2 = F2 * w_appliedBC - w2;
5343
5344 const MFloat rhoG1 = rho_appliedG1; // F2*rho_correctedBC-rho1;
5345 const MFloat rhoG2 = F2 * rho_appliedG1 - rho1;
5346
5347 m_cells->pvariables[PV->RHO][cellIdG1] = rhoG1;
5348 m_cells->pvariables[PV->U][cellIdG1] = uG1;
5349 m_cells->pvariables[PV->V][cellIdG1] = vG1;
5350 m_cells->pvariables[PV->W][cellIdG1] = wG1;
5351 m_cells->pvariables[PV->P][cellIdG1] = pField;
5352
5353 m_cells->pvariables[PV->RHO][cellIdG2] = rhoG2;
5354 m_cells->pvariables[PV->U][cellIdG2] = uG2;
5355 m_cells->pvariables[PV->V][cellIdG2] = vG2;
5356 m_cells->pvariables[PV->W][cellIdG2] = wG2;
5357 m_cells->pvariables[PV->P][cellIdG2] = pField;
5358
5359 if(m_solver->m_rans) {
5360 const MFloat nutilde_zerothG1 = m_solver->m_bc2601ZerothOrderSolution[PV->RANS_VAR[0]][cellIdBcG1];
5361 const MFloat nutilde_zerothG2 = m_solver->m_bc2601ZerothOrderSolution[PV->RANS_VAR[0]][cellIdBcG2];
5362 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG1] = nutilde_zerothG1;
5363 m_cells->pvariables[PV->RANS_VAR[0]][cellIdG2] = nutilde_zerothG2;
5364 }
5365 }
5366 }
5367 break;
5368 }
5369 default: {
5370 mTerm(1, AT_, "Face not implemented");
5371 break;
5372 }
5373 }
5374}
5375
5381template <MBool isRans>
5383 MInt* start = m_physicalBCMap[bcId]->start1;
5384 MInt* end = m_physicalBCMap[bcId]->end1;
5385 const MFloat gamma = m_solver->m_gamma;
5386 const MFloat time = m_solver->m_time;
5387 MFloat velocity[3] = {F0, F0, F0};
5388
5389 switch(m_physicalBCMap[bcId]->face) {
5390 case 0:
5391 case 3: {
5392 for(MInt k = start[2]; k < end[2]; k++) {
5393 for(MInt j = start[1]; j < end[1]; j++) {
5394 for(MInt i = start[0]; i < end[0]; i++) {
5395 MInt cellId = cellIndex(i, j, k);
5396 MFloat rho = CV->rhoInfinity;
5397 for(MInt dim = 0; dim < nDim; dim++) {
5398 velocity[dim] = PV->VVInfinity[dim];
5399 }
5400 MFloat p = PV->PInfinity;
5401
5402 // add the modes
5403 for(MInt mode = 0; mode < m_modes; mode++) {
5404 // 1. pressure
5405 const MFloat pressure_f =
5406 gamma * m_solver->m_Ma * PV->PInfinity * m_modeAmp[mode] * (MFloat)(m_modeType[mode]);
5407
5408 // 2. density
5409 MFloat density_f;
5410 const MFloat a = sqrt(PV->TInfinity);
5411 if(m_modeType[mode])
5412 density_f = pressure_f / POW2(a);
5413 else
5414 density_f = m_modeAmp[mode] * CV->rhoInfinity * m_solver->m_Ma;
5415
5416 // 3. velocity
5417 MFloat K = F0;
5418 for(MInt dim = 0; dim < nDim; dim++) {
5419 K += pow(m_modeK[mode][dim], 2);
5420 }
5421
5422 K = sqrt(K);
5423 const MFloat acImp = a * CV->rhoInfinity;
5424 const MFloat modeVelocity = (MFloat)(m_modeType[mode]) * pressure_f / acImp;
5425 MFloat velocity_f[3];
5426 for(MInt dim = 0; dim < nDim; dim++) {
5427 velocity_f[dim] = (m_modeK[mode][dim] * modeVelocity) / K;
5428 }
5429
5430 // 1. calculate cell dependant trigonometry
5431 MFloat trigTerm = F0;
5432 for(MInt dim = 0; dim < nDim; dim++) {
5433 trigTerm += m_modeK[mode][dim] * m_cells->coordinates[dim][cellId];
5434 }
5435
5436 trigTerm -= m_modeOmega[mode] * (time); // time;
5437 trigTerm += m_modePhi[mode];
5438 trigTerm = sin(trigTerm);
5439
5440 rho += trigTerm * density_f;
5441 for(MInt dim = 0; dim < nDim; dim++) {
5442 velocity[dim] += trigTerm * velocity_f[0];
5443 }
5444 p += trigTerm * pressure_f;
5445 }
5446
5447 // conservatives:
5448 m_cells->pvariables[PV->RHO][cellId] = rho;
5449 m_cells->pvariables[PV->U][cellId] = velocity[PV->U];
5450 m_cells->pvariables[PV->V][cellId] = velocity[PV->V];
5451 m_cells->pvariables[PV->W][cellId] = velocity[PV->W];
5452 m_cells->pvariables[PV->P][cellId] = p;
5453 }
5454 }
5455 }
5456 break;
5457 }
5458 default: {
5459 mTerm(1, AT_, "Face direction not implemented)");
5460 }
5461 }
5462}
5463
5464
5465// Jet Freund Inlet
5466template <MBool isRans>
5468 MInt* start = m_physicalBCMap[bcId]->start1;
5469 MInt* end = m_physicalBCMap[bcId]->end1;
5470 switch(m_physicalBCMap[bcId]->face) {
5471 case 0: {
5472 MInt cellId = -1;
5473 MInt cellIdadj = -1;
5474 MInt pIJK = 0, pIJPK = 0, pIJKP = 0, pIJPKP = 0;
5475 // fully new bc
5476 MInt i = end[0] - 1;
5477 MFloat pBC = F0, rho = F0, u = F0, v = F0, w = F0;
5478 MFloat drho = F0, du = F0, dv = F0, dw = F0, dp = F0;
5479 MFloat xBC = F0;
5480 // pBC=PV->PInfinity;
5481 MFloat pInner = F0, c02 = F0, distance = F0;
5482 for(MInt k = start[2]; k < end[2]; k++) {
5483 for(MInt j = start[1]; j < end[1]; j++) {
5484 cellId = cellIndex(i, j, k);
5485 cellIdadj = cellIndex(i + 1, j, k);
5486 // to determine the face coordinates!!!!!!
5487 pIJK = getPointIdFromCell(i + 1, j, k);
5488 pIJPK = getPointIdfromPoint(pIJK, 0, 1, 0);
5489 pIJKP = getPointIdfromPoint(pIJK, 0, 0, 1);
5490 pIJPKP = getPointIdfromPoint(pIJK, 0, 1, 1);
5491 MFloat r = sqrt(POW2(m_cells->coordinates[0][cellId]) + POW2(m_cells->coordinates[1][cellId])
5492 + POW2(m_cells->coordinates[2][cellId]));
5493 MFloat uInf = F1B2 * (F1 - tanh(12.5 * (fabs(r / 0.5) - fabs(0.5 / r)))) * PV->VVInfinity[0];
5494 MFloat vInf = 0;
5495 MFloat wInf = 0;
5496
5497 // values at the inner point
5498 pInner = m_cells->pvariables[PV->P][cellIdadj];
5499 c02 = sqrt(m_solver->m_gamma * pInner / m_cells->pvariables[PV->RHO][cellIdadj]);
5500 u = m_cells->pvariables[PV->U][cellIdadj];
5501 v = m_cells->pvariables[PV->V][cellIdadj];
5502 w = m_cells->pvariables[PV->W][cellIdadj];
5503
5504 MFloat dxidx = m_cells->surfaceMetrics[0][cellId];
5505 MFloat dxidy = m_cells->surfaceMetrics[1][cellId];
5506 MFloat dxidz = m_cells->surfaceMetrics[2][cellId];
5507
5508 // values at the boundary
5509 pBC = F1B2
5510 * (pInner + PV->PInfinity
5511 - m_cells->pvariables[PV->RHO][cellIdadj] * c02
5512 * (dxidx * (uInf - u) + dxidy * (vInf - v) + dxidz * (wInf - w)));
5513 rho = CV->rhoInfinity + ((pBC - PV->PInfinity) / (c02 * c02));
5514
5515 u = uInf - dxidx * (PV->PInfinity - pBC) / (m_cells->pvariables[PV->RHO][cellIdadj] * c02);
5516 v = vInf - dxidy * (PV->PInfinity - pBC) / (m_cells->pvariables[PV->RHO][cellIdadj] * c02);
5517 w = wInf - dxidz * (PV->PInfinity - pBC) / (m_cells->pvariables[PV->RHO][cellIdadj] * c02);
5518
5519 // extrapolate the variables into the ghost cells
5520 // gradients
5521
5522 xBC = F1B4
5523 * (m_grid->m_coordinates[0][pIJK] + m_grid->m_coordinates[0][pIJPK] + m_grid->m_coordinates[0][pIJKP]
5524 + m_grid->m_coordinates[0][pIJPKP]);
5525
5526
5527 distance = (xBC - m_cells->coordinates[0][cellIdadj]);
5528
5529 drho = (rho - m_cells->pvariables[PV->RHO][cellIdadj]) / distance;
5530 du = (u - m_cells->pvariables[PV->U][cellIdadj]) / distance;
5531 dv = (v - m_cells->pvariables[PV->V][cellIdadj]) / distance;
5532 dw = (w - m_cells->pvariables[PV->W][cellIdadj]) / distance;
5533 dp = (pBC - m_cells->pvariables[PV->P][cellIdadj]) / distance;
5534
5535 // extrapolate:
5536 for(MInt ii = start[0]; ii < end[0]; ++ii) {
5537 cellId = cellIndex(ii, j, k);
5538 distance = (m_cells->coordinates[0][cellId] - m_cells->coordinates[0][cellIdadj]);
5539 m_cells->pvariables[PV->RHO][cellId] = m_cells->pvariables[PV->RHO][cellIdadj] + drho * distance;
5540 m_cells->pvariables[PV->U][cellId] = m_cells->pvariables[PV->U][cellIdadj] + du * distance;
5541 m_cells->pvariables[PV->V][cellId] = m_cells->pvariables[PV->V][cellIdadj] + dv * distance;
5542 m_cells->pvariables[PV->W][cellId] = m_cells->pvariables[PV->W][cellIdadj] + dw * distance;
5543 m_cells->pvariables[PV->P][cellId] = m_cells->pvariables[PV->P][cellIdadj] + dp * distance;
5544 }
5545 }
5546 }
5547 break;
5548 }
5549 default: {
5550 mTerm(1, AT_, "Face not implemented");
5551 break;
5552 }
5553 }
5554}
5555
5556template <MBool isRans>
5558 cout << "applying bc " << bcId << endl;
5559}
5560
5561// Works equally for conversion of fluid state into porous and vice versa
5562// Only works for LES
5563template <MBool isRans>
5565 TRACE();
5566
5567 const MInt IJK[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
5568 MInt* start = m_physicalBCMap[bcId]->start1;
5569 MInt* end = m_physicalBCMap[bcId]->end1;
5570
5571 constexpr MFloat eps = 1e-8;
5572 const MFloat gamma = m_solver->m_gamma;
5573 const MFloat gammaOverGammaMinusOne = gamma / (gamma - 1);
5574
5575 if(m_physicalBCMap[bcId]->Nstar == -1) {
5576 // Here we find out the normal direction of the
5577 // boundary and the tangential direction.
5578 // This way we can make a general formulation of
5579 // the boundary condition
5580 const MInt face = m_physicalBCMap[bcId]->face;
5581 const MInt normalDir = face / 2;
5582 const MInt firstTangentialDir = (normalDir + 1) % nDim;
5583 const MInt secondTangentialDir = (normalDir + 2) % nDim;
5584 const MInt normalDirStart = start[normalDir];
5585 const MInt firstTangentialStart = start[firstTangentialDir];
5586 const MInt firstTangentialEnd = end[firstTangentialDir];
5587 const MInt secondTangentialStart = start[secondTangentialDir];
5588 const MInt secondTangentialEnd = end[secondTangentialDir];
5589 const MInt inc[nDim] = {IJK[normalDir], IJK[firstTangentialDir], IJK[secondTangentialDir]};
5590
5591 // determine indices for direction help
5592 const MInt n = (face % 2) * 2 - 1; //-1,+1
5593 const MInt g[2] = {normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)), //+1,0
5594 normalDirStart + (MInt)(0.5 + (0.5 * (MFloat)n))}; // 0,+1
5595 const MInt a1 = normalDirStart + (MInt)(0.5 - (1.5 * (MFloat)n)); //+2,-1
5596
5597 // convention: index x is unknown and y is known
5598 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
5599 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
5600 const MInt cellIdG1 = g[0] * inc[0] + t1 * inc[1] + t2 * inc[2];
5601 const MFloat normalVec[nDim] = {m_cells->fq[FQ->NORMAL[0]][cellIdG1], m_cells->fq[FQ->NORMAL[1]][cellIdG1],
5602 m_cells->fq[FQ->NORMAL[2]][cellIdG1]};
5603 const MInt cellIdA1 = a1 * inc[0] + t1 * inc[1] + t2 * inc[2];
5604 const MFloat por_x = m_cells->fq[FQ->POROSITY][cellIdA1];
5605 for(MInt i = 0; i < 2 /*m_noGhostLayers*/; ++i) {
5606 const MInt cellIdG = g[i] * inc[0] + t1 * inc[1] + t2 * inc[2];
5607
5608 const MFloat por_y = m_cells->fq[FQ->POROSITY][cellIdG];
5609 const MFloat rho_y = m_cells->pvariables[PV->RHO][cellIdG];
5610 const MFloat p_y = m_cells->pvariables[PV->P][cellIdG];
5611 const MFloat u_y = m_cells->pvariables[PV->U][cellIdG];
5612 const MFloat v_y = m_cells->pvariables[PV->V][cellIdG];
5613 const MFloat w_y = m_cells->pvariables[PV->W][cellIdG];
5614
5615 // Compute normal and tangential velocity components
5616 const MFloat U_y = u_y * normalVec[0] + v_y * normalVec[1] + w_y * normalVec[2];
5617 const MFloat VW_y[nDim] = {u_y - U_y * normalVec[0], v_y - U_y * normalVec[1], w_y - U_y * normalVec[2]};
5618
5619 //
5620 const MFloat auxconst1 = gammaOverGammaMinusOne * p_y / pow(rho_y, gamma);
5621 const MFloat auxconst2 = 0; // only important in RANS
5622 const MFloat auxconst3 = -(gammaOverGammaMinusOne * p_y / rho_y + 0.5 * POW2(U_y));
5623 const MFloat auxconst4 = 0.5 * POW2(por_y / por_x * rho_y * U_y);
5624
5625 // TODO_SS labels:FV Later take a more sufficient initial value
5626 MFloat rho_x = rho_y;
5627
5628 MFloat res = auxconst1 * pow(rho_x, gamma + 1) + auxconst2 * rho_x + auxconst3 * POW2(rho_x) + auxconst4;
5629
5630 MInt testcounter = 0;
5631 while(res > eps) {
5632 // TODO_SS labels:FV,totest Check if it is divided by zero
5633 const MFloat dresdrho = (gamma + 1) * auxconst1 * pow(rho_x, gamma) + auxconst2 + 2 * auxconst3 * rho_x;
5634 const MFloat deltarho_x = -res / dresdrho;
5635 rho_x += deltarho_x;
5636
5637 res = auxconst1 * pow(rho_x, gamma + 1) + auxconst2 * rho_x + auxconst3 * POW2(rho_x) + auxconst4;
5638
5639 ++testcounter;
5640 }
5641
5642 if(testcounter > 10) {
5643 cout << "Loop in BC6002 took " << testcounter << " steps!"
5644 << "cell: " << g[i] << "|" << t1 << " res=" << res << " (x|y)=" << m_cells->coordinates[0][cellIdG]
5645 << "|" << m_cells->coordinates[1][cellIdG] << endl;
5646 mTerm(1, "testcounter > 10 in BC6002 loop");
5647 }
5648
5649 // Compute remaining variables
5650 const MFloat temp = por_y * rho_y / (por_x * rho_x);
5651 const MFloat p_x = p_y * pow(rho_x / rho_y, gamma);
5652 const MFloat U_x = temp * U_y;
5653 const MFloat u_x = U_x * normalVec[0] + VW_y[0] /*=VW_x*/;
5654 const MFloat v_x = U_x * normalVec[1] + VW_y[1] /*=VW_x*/;
5655 const MFloat w_x = U_x * normalVec[2] + VW_y[2] /*=VW_x*/;
5656
5657 // Assign solution to pvariables
5658 m_cells->pvariables[PV->RHO][cellIdG] = rho_x;
5659 m_cells->pvariables[PV->P][cellIdG] = p_x;
5660 m_cells->pvariables[PV->U][cellIdG] = u_x;
5661 m_cells->pvariables[PV->V][cellIdG] = v_x;
5662 m_cells->pvariables[PV->W][cellIdG] = w_x;
5663 }
5664 }
5665 }
5666 } else {
5667 mTerm(1, "This is not tested in 3D yet!");
5668 const MInt singularId = m_physicalBCMap[bcId]->SingularId;
5669 const auto& singularity = m_solver->m_singularity[singularId];
5670
5671 // Check
5672 const MInt* start2 = singularity.start;
5673 const MInt* end2 = singularity.end;
5674 for(MInt d = 0; d < nDim; ++d) {
5675 if(end[d] - start[d] != end2[d] - start2[d]) mTerm(1, "SCHEISSE");
5676 }
5677
5678 // cout << globalTimeStep<< ": SINGULARITY BC d=" << m_solver->domainId() << " start=" << start[0] << "|" <<
5679 // start[1] << " start2=" << start2[0] << "|" << start2[1] << " end=" << end[0] << "|" << end[1] << " end2=" <<
5680 // end2[0] << "|" << end2[1] << endl;
5681
5682 // TODO_SS labels:FV,totest Check if we maybe need to add +2 and -2 respectively in the tangential direction,
5683 // because those cells may
5684 // be needed in viscousFluxCorrection
5685 for(MInt k = start[2], kk = start2[2]; k < end[2]; k++, kk++) {
5686 for(MInt j = start[1], jj = start2[1]; j < end[1]; j++, jj++) {
5687 for(MInt i = start[0], ii = start2[0]; i < end[0]; i++, ii++) {
5688 const MInt cellIdG = cellIndex(i, j, k);
5689 const MInt cellIdA1 = cellIndex(ii, jj, kk);
5690 const MFloat normalVec[nDim] = {m_cells->fq[FQ->NORMAL[0]][cellIdG], m_cells->fq[FQ->NORMAL[1]][cellIdG],
5691 m_cells->fq[FQ->NORMAL[2]][cellIdG]};
5692 const MFloat por_x = m_cells->fq[FQ->POROSITY][cellIdA1];
5693
5694 const MFloat por_y = m_cells->fq[FQ->POROSITY][cellIdG];
5695 const MFloat rho_y = m_cells->pvariables[PV->RHO][cellIdG];
5696 const MFloat p_y = m_cells->pvariables[PV->P][cellIdG];
5697 const MFloat u_y = m_cells->pvariables[PV->U][cellIdG];
5698 const MFloat v_y = m_cells->pvariables[PV->V][cellIdG];
5699 const MFloat w_y = m_cells->pvariables[PV->W][cellIdG];
5700
5701 // Compute normal and tangential velocity components
5702 const MFloat U_y = u_y * normalVec[0] + v_y * normalVec[1] + w_y * normalVec[2];
5703 const MFloat VW_y[nDim] = {u_y - U_y * normalVec[0], v_y - U_y * normalVec[1], w_y - U_y * normalVec[2]};
5704
5705 //
5706 const MFloat auxconst1 = gammaOverGammaMinusOne * p_y / pow(rho_y, gamma);
5707 const MFloat auxconst2 = 0; // only important in RANS
5708 const MFloat auxconst3 = -(gammaOverGammaMinusOne * p_y / rho_y + 0.5 * POW2(U_y));
5709 const MFloat auxconst4 = 0.5 * POW2(por_y / por_x * rho_y * U_y);
5710
5711 // TODO_SS labels:FV Later take a more sufficient initial value
5712 MFloat rho_x = rho_y;
5713
5714 MFloat res = auxconst1 * pow(rho_x, gamma + 1) + auxconst2 * rho_x + auxconst3 * POW2(rho_x) + auxconst4;
5715
5716 MInt testcounter = 0;
5717 while(res > eps) {
5718 // TODO_SS labels:FV,totest Check if it is divided by zero
5719 const MFloat dresdrho = (gamma + 1) * auxconst1 * pow(rho_x, gamma) + auxconst2 + 2 * auxconst3 * rho_x;
5720 const MFloat deltarho_x = -res / dresdrho;
5721 rho_x += deltarho_x;
5722
5723 res = auxconst1 * pow(rho_x, gamma + 1) + auxconst2 * rho_x + auxconst3 * POW2(rho_x) + auxconst4;
5724
5725 ++testcounter;
5726 }
5727
5728 if(testcounter > 10) {
5729 cout << "Loop in BC6002 took " << testcounter << " steps!"
5730 << " domainId=" << m_solver->domainId() << " cellId: " << cellIdG << " res=" << res
5731 << " (x|y)=" << m_cells->coordinates[0][cellIdG] << "|" << m_cells->coordinates[1][cellIdG] << por_y
5732 << " " << rho_y << " " << p_y << " " << u_y << " " << v_y << endl;
5733 }
5734
5735 // Compute remaining variables
5736 const MFloat temp = por_y * rho_y / (por_x * rho_x);
5737 const MFloat p_x = p_y * pow(rho_x / rho_y, gamma);
5738 const MFloat U_x = temp * U_y;
5739 const MFloat u_x = U_x * normalVec[0] + VW_y[0] /*=VW_x*/;
5740 const MFloat v_x = U_x * normalVec[1] + VW_y[1] /*=VW_x*/;
5741 const MFloat w_x = U_x * normalVec[2] + VW_y[2] /*=VW_x*/;
5742
5743 // Assign solution to pvariables
5744 m_cells->pvariables[PV->RHO][cellIdG] = rho_x;
5745 m_cells->pvariables[PV->P][cellIdG] = p_x;
5746 m_cells->pvariables[PV->U][cellIdG] = u_x;
5747 m_cells->pvariables[PV->V][cellIdG] = v_x;
5748 m_cells->pvariables[PV->W][cellIdG] = w_x;
5749 }
5750 }
5751 }
5752 }
5753}
5754
5755
5756template <MBool isRans>
5758 TRACE();
5759
5760 MInt* start = m_physicalBCMap[bcId]->start1;
5761 MInt* end = m_physicalBCMap[bcId]->end1;
5762
5763 // first we need the average pressure and Temperature
5764 //==> calculate from the field
5765 //==> average over the surface
5766 //==> store in variable
5767
5768 MInt Id = m_channelSurfaceIndexMap[bcId];
5769 MInt* startface = &m_solver->m_windowInfo->channelSurfaceIndices[Id]->start1[0];
5770 MInt* endface = &m_solver->m_windowInfo->channelSurfaceIndices[Id]->end1[0];
5771 MInt cellId = 0;
5772 // global Pressure and Temperature at in-/outlet
5773 MFloat globalTin[2] = {F0, F0};
5774 MFloat globalTout[2] = {F0, F0};
5775 MFloat globalPin[2] = {F0, F0};
5776 MFloat globalPout[2] = {F0, F0};
5777 cout.precision(10);
5778
5779 // find out which face it is
5780 switch(m_physicalBCMap[bcId]->face) {
5781 case 0: {
5782 // average the pressure
5783 // use values from the inside to determine the pressure at the face!!!
5784 MFloat surface = F0;
5785 MFloat localPin[2] = {F0, F0};
5786 MFloat localTin[2] = {F0, F0};
5787 MFloat localVel = F0, globalVel = F0;
5788 MFloat localMassFlux = F0, globalMassFlux = F0;
5789
5790 for(MInt k = startface[2]; k < endface[2]; k++) {
5791 for(MInt j = startface[1]; j < endface[1]; j++) {
5792 MInt ii = end[0] - 1;
5793 MInt cellIdP1 = cellIndex(ii + 1, j, k);
5794 MInt cellIdP2 = cellIndex(ii + 2, j, k);
5795
5796 surface = sqrt(POW2(m_cells->surfaceMetrics[0][cellIdP1]) + POW2(m_cells->surfaceMetrics[1][cellIdP1])
5797 + POW2(m_cells->surfaceMetrics[2][cellIdP1]));
5798 localPin[0] += surface * m_cells->pvariables[PV->P][cellIdP1];
5799 localPin[1] += surface * m_cells->pvariables[PV->P][cellIdP2];
5800 localTin[0] += surface * temperature(cellIdP1);
5801 localTin[1] += surface * temperature(cellIdP2);
5802 localVel += surface * (m_cells->pvariables[PV->U][cellIdP1]);
5803 localMassFlux += surface * (m_cells->pvariables[PV->U][cellIdP1] * m_cells->pvariables[PV->RHO][cellIdP1]);
5804 }
5805 }
5806
5807 // next now that the pressure and temperature are known:
5808 // make it a global variable for the complete inflow plane
5809 MPI_Allreduce(localPin, globalPin, 2, MPI_DOUBLE, MPI_SUM, m_solver->m_commChannelIn, AT_, "localPin",
5810 "globalPin");
5811 MPI_Allreduce(localTin, globalTin, 2, MPI_DOUBLE, MPI_SUM, m_solver->m_commChannelIn, AT_, "localTin",
5812 "globalTin");
5813 MPI_Allreduce(&localMassFlux, &globalMassFlux, 1, MPI_DOUBLE, MPI_SUM, m_solver->m_commChannelIn, AT_,
5814 "localMassFlux", "globalMassFlux");
5815 MPI_Allreduce(&localVel, &globalVel, 1, MPI_DOUBLE, MPI_SUM, m_solver->m_commChannelIn, AT_, "localVel",
5816 "globalVel");
5817
5818 MPI_Barrier(m_solver->m_commChannelIn, AT_);
5819 globalPin[0] /= m_channelSurfaceIn;
5820 globalTin[0] /= m_channelSurfaceIn;
5821 globalPin[1] /= m_channelSurfaceIn;
5822 globalTin[1] /= m_channelSurfaceIn;
5823 globalMassFlux /= m_channelSurfaceIn;
5824 globalVel /= m_channelSurfaceIn;
5825 MFloat currentRe = m_solver->m_Re / PV->UInfinity * globalVel;
5826
5827 // set a Barrier to ensure that all domains having a channel side are at same time level
5828 // now make the variables known everywhere in the channel world
5829 MPI_Barrier(m_solver->m_commChannelWorld, AT_);
5830 MPI_Bcast(globalTin, 2, MPI_DOUBLE, m_solver->m_channelRoots[2], m_solver->m_commChannelWorld, AT_, "globalTin");
5831 MPI_Bcast(globalPin, 2, MPI_DOUBLE, m_solver->m_channelRoots[2], m_solver->m_commChannelWorld, AT_, "globalPin");
5832 MPI_Bcast(globalTout, 2, MPI_DOUBLE, m_solver->m_channelRoots[3], m_solver->m_commChannelWorld, AT_,
5833 "globalTout");
5834 MPI_Bcast(globalPout, 2, MPI_DOUBLE, m_solver->m_channelRoots[3], m_solver->m_commChannelWorld, AT_,
5835 "globalPout");
5836 // now every value is known and can be used to apply the BC !!!!
5837 // cannot take values from above at here the window is extended to the ghost layers
5838
5839 if(globalTimeStep > 1 && globalTimeStep % 50 == 0) {
5840 if(m_channelInflowRank == 0 && globalTimeStep % m_solver->m_residualInterval == 0 && m_solver->m_RKStep == 0) {
5841 cout.precision(6);
5842
5843 FILE* f_channel;
5844 f_channel = fopen("./massflow.dat", "a+");
5845 fprintf(f_channel, "%d", globalTimeStep);
5846 fprintf(f_channel, " %f", m_solver->m_physicalTime);
5847 fprintf(f_channel, " %f", m_solver->m_time);
5848 fprintf(f_channel, " %f", m_solver->m_timeStep);
5849 fprintf(f_channel, " %f", currentRe);
5850 fprintf(f_channel, " %f", globalMassFlux);
5851 fprintf(f_channel, " %f", globalPin[0]);
5852 fprintf(f_channel, " %f", globalPin[1]);
5853 fprintf(f_channel, " %f", globalTin[0]);
5854 fprintf(f_channel, " %f", globalTout[0]);
5855 fprintf(f_channel, " %f", globalPout[0]);
5856 fprintf(f_channel, " %f", globalPout[1]);
5857 fprintf(f_channel, " %f", (globalTin[0] - globalTout[1]));
5858 fprintf(f_channel, "\n");
5859 fclose(f_channel);
5860 }
5861 }
5862
5863 for(MInt k = start[2]; k < end[2]; k++) {
5864 for(MInt j = start[1]; j < end[1]; j++) {
5865 MInt i = 1;
5866 cellId = cellIndex(i, j, k);
5867
5868 MFloat pressureFluctuation = m_cells->pvariables[PV->P][cellId] - globalPout[1];
5869 MFloat x = m_cells->coordinates[0][cellId];
5870 MFloat pressureInflowMean =
5871 m_solver->m_deltaP / m_solver->m_channelLength * (x - m_solver->m_channelInflowPlaneCoordinate)
5872 + PV->PInfinity;
5873 MFloat pressureNew = pressureInflowMean + pressureFluctuation;
5874 MFloat temperatureFlucOutflow = temperature(cellId) - globalTout[1];
5875 MFloat temperatureNew = PV->TInfinity + temperatureFlucOutflow;
5876 MFloat rhoNew = m_solver->m_gamma * pressureNew / temperatureNew;
5877
5878 m_cells->pvariables[PV->RHO][cellId] = rhoNew;
5879 m_cells->pvariables[PV->P][cellId] = pressureNew;
5880
5881 for(MInt var = 0; var < PV->noVariables; var++) {
5882 m_cells->pvariables[var][cellIndex(start[0], j, k)] =
5883 2.0 * m_cells->pvariables[var][cellIndex(start[0] + 1, j, k)]
5884 - m_cells->pvariables[var][cellIndex(start[0] + 2, j, k)];
5885 }
5886 }
5887 }
5888 break;
5889 }
5890 case 1: {
5891 // average the pressure
5892 // use values from the inside to determine the pressure at the face!!!
5893 MFloat surface = F0;
5894 MFloat localPout[] = {F0, F0};
5895 MFloat localTout[] = {F0, F0};
5896 for(MInt k = startface[2]; k < endface[2]; k++) {
5897 for(MInt j = startface[1]; j < endface[1]; j++) {
5898 MInt ii = start[0];
5899 MInt cellIdM1 = cellIndex(ii - 1, j, k);
5900 MInt cellIdM2 = cellIndex(ii - 2, j, k);
5901 surface = sqrt(POW2(m_cells->surfaceMetrics[0][cellIdM1]) + POW2(m_cells->surfaceMetrics[1][cellIdM1])
5902 + POW2(m_cells->surfaceMetrics[2][cellIdM1]));
5903 localPout[0] += surface * m_cells->pvariables[PV->P][cellIdM2];
5904 localPout[1] += surface * m_cells->pvariables[PV->P][cellIdM1];
5905 localTout[0] += surface * temperature(cellIdM2);
5906 localTout[1] += surface * temperature(cellIdM1);
5907 }
5908 }
5909
5910 // next now that the pressure and temperature are known:
5911 // make it a global variable for the complete outflow plane
5912 MPI_Allreduce(localPout, globalPout, 2, MPI_DOUBLE, MPI_SUM, m_solver->m_commChannelOut, AT_, "localPout",
5913 "globalPout");
5914 MPI_Allreduce(localTout, globalTout, 2, MPI_DOUBLE, MPI_SUM, m_solver->m_commChannelOut, AT_, "localTout",
5915 "globalTout");
5916
5917 MPI_Barrier(m_solver->m_commChannelOut, AT_);
5918 globalPout[0] /= m_channelSurfaceOut;
5919 globalTout[0] /= m_channelSurfaceOut;
5920 globalPout[1] /= m_channelSurfaceOut;
5921 globalTout[1] /= m_channelSurfaceOut;
5922 // set a Barrier to ensure that all domains having a channel side are at same time level
5923 // now make the variables known everywhere in the channel world
5924 MPI_Barrier(m_solver->m_commChannelWorld, AT_);
5925 MPI_Bcast(globalTin, 2, MPI_DOUBLE, m_solver->m_channelRoots[2], m_solver->m_commChannelWorld, AT_, "globalTin");
5926 MPI_Bcast(globalPin, 2, MPI_DOUBLE, m_solver->m_channelRoots[2], m_solver->m_commChannelWorld, AT_, "globalPin");
5927 MPI_Bcast(globalTout, 2, MPI_DOUBLE, m_solver->m_channelRoots[3], m_solver->m_commChannelWorld, AT_,
5928 "globalTout");
5929 MPI_Bcast(globalPout, 2, MPI_DOUBLE, m_solver->m_channelRoots[3], m_solver->m_commChannelWorld, AT_,
5930 "globalPout");
5931 // now every value is known and can be used to apply the BC !!!!
5932 // cannot take values from above at here the window is extended to the ghost layers
5933
5934 for(MInt k = start[2]; k < end[2]; k++) {
5935 for(MInt j = start[1]; j < end[1]; j++) {
5936 MInt i = start[0];
5937 cellId = cellIndex(i, j, k);
5938
5939 MFloat pressureFluctuation = m_cells->pvariables[PV->P][cellId] - globalPin[0];
5940 MFloat x = m_cells->coordinates[0][cellId];
5941 MFloat pressureOutflowMean =
5942 m_solver->m_deltaP / m_solver->m_channelLength * (x - m_solver->m_channelInflowPlaneCoordinate)
5943 + PV->PInfinity;
5944 MFloat pressureNew = pressureOutflowMean + pressureFluctuation;
5945 MFloat deltaT = (globalTin[0] - globalTout[1]);
5946 MFloat temperatureInflow = temperature(cellId);
5947 MFloat temperatureNew = temperatureInflow - deltaT;
5948 MFloat rhoNew = m_solver->m_gamma * pressureNew / temperatureNew;
5949
5950 m_cells->pvariables[PV->RHO][cellId] = rhoNew;
5951 m_cells->pvariables[PV->P][cellId] = pressureNew;
5952
5953 for(MInt var = 0; var < PV->noVariables; var++) {
5954 m_cells->pvariables[var][cellIndex(start[0] + 1, j, k)] =
5955 2.0 * m_cells->pvariables[var][cellIndex(start[0], j, k)]
5956 - m_cells->pvariables[var][cellIndex(start[0] - 1, j, k)];
5957 }
5958 }
5959 }
5960 break;
5961 }
5962 default: {
5963 mTerm(1, AT_, "Face not implemented");
5964 break;
5965 }
5966 }
5967}
5968
5969
5970template <MBool isRans>
5972 return m_cells->pvariables[PV->P][cellId];
5973}
5974
5975template <MBool isRans>
5977 const MFloat gamma = m_solver->m_gamma;
5978 MFloat t = gamma * m_cells->pvariables[PV->P][cellId] / m_cells->pvariables[PV->RHO][cellId];
5979 return t;
5980}
5981
5982template <MBool isRans>
5984 MInt cellId = cellIndex(i, j, k);
5985 return pressure(cellId);
5986}
5987
5988template <MBool isRans>
5990 return i + (j + k * m_nPoints[1]) * m_nPoints[2];
5991}
5992
5993template <MBool isRans>
5995 return i + (j + k * m_nPoints[1]) * m_nPoints[2];
5996}
5997
5998template <MBool isRans>
6000 return origin + incI + incJ * m_nPoints[2] + incK * m_nPoints[2] * m_nPoints[1];
6001}
6002
6009template <MBool isRans>
6010template <MBool computePower>
6012 // cf=mue*du/dy/(rho*u_8*u_8*0.5)
6013 // cp=2*(p-p_8)/(rho8*u_8*u_8*0.5)
6014
6015 const MInt noForceCoefs = m_solver->m_noForceDataFields;
6016
6017 // References for convenience
6018 auto& m_forceCoef = m_solver->m_forceCoef;
6019
6020 const MFloat fre0 = F1 / (m_solver->m_Re0);
6021 const MFloat UT = m_solver->m_Ma * sqrt(PV->TInfinity);
6022 const MFloat fstagnationPressure = F1 / (CV->rhoInfinity * F1B2 * POW2(UT));
6023 const MFloat fstagnationEnergy = F1 / (CV->rhoInfinity * F1B2 * POW3(UT));
6024
6025 // Only those for which auxData is requested in the property file; not those which are required
6026 // because of k-epsilon rans model
6027 const MInt noWalls = m_solver->m_windowInfo->m_auxDataWindowIds.size();
6028
6029 // reset values to zero for the calculation
6030 for(MInt i = 0; i < (MInt)(noForceCoefs * noWalls); ++i) {
6031 m_forceCoef[i] = F0;
6032 }
6033
6034 // loop over all maps
6035 for(MInt map = 0; map < (MInt)m_auxDataMap.size(); ++map) {
6036 //
6037 if(auxDataWindows) {
6038 MBool takeIt = false;
6039 for(auto& m : m_solver->m_windowInfo->m_auxDataWindowIds) {
6040 if(m_auxDataMap[map]->Id2 == m.second) {
6041 takeIt = true;
6042 break;
6043 }
6044 }
6045 if(!takeIt) continue;
6046 }
6047
6048 const MInt mapOffsetCf = m_cells->cfOffsets[map];
6049 const MInt mapOffsetCp = m_cells->cpOffsets[map];
6050 const MInt mapOffsetPower = m_cells->powerOffsets[map];
6051 MInt* start = m_auxDataMap[map]->start1;
6052 MInt* end = m_auxDataMap[map]->end1;
6053
6054 MInt n = 0;
6055 MInt normal = 0;
6056 MFloat area = F0;
6057 MFloat cf[6] = {F0, F0, F0, F0, F0, F0};
6058 MFloat cp[3] = {F0, F0, F0};
6059 MFloat powerp[3] = {F0, F0, F0};
6060 MFloat powerv[3] = {F0, F0, F0};
6061
6062 const MInt pCoordDir[3][9] = {
6063 {0, 1, 0, 0, 0, 1, 0, 1, 1}, {1, 0, 0, 0, 0, 1, 1, 0, 1}, {1, 0, 0, 0, 1, 0, 1, 1, 0}};
6064
6065 // indices
6066 MInt n10[3] = {0, 0, 0};
6067 MInt n01[3] = {0, 0, 0};
6068 MInt n1m1[3] = {0, 0, 0};
6069 MInt firstTangential = -1, secondTangential = -1;
6070 MInt i = 0, k = 0, j = 0;
6071 MInt jj = 0, kk = 0;
6072 MInt *reali = nullptr, *realj = nullptr, *realk = nullptr;
6073 MInt *realjj = nullptr, *realkk = nullptr;
6074 MInt sizeJ = 0, sizeK = 0;
6075
6076 // determine the wall
6077 if((m_auxDataMap[map]->face) % 2 == 0) {
6078 n = -1; // bottom wall
6079 normal = m_auxDataMap[map]->face / 2;
6080 i = start[normal];
6081 } else {
6082 n = 1; // top wall
6083 normal = (m_auxDataMap[map]->face - 1) / 2;
6084 i = end[normal] - 1;
6085 }
6086 // determine the normals
6087 n1m1[normal] = -1 * n;
6088 n10[normal] = (MInt)(0.5 + (0.5 * (MFloat)n));
6089 n01[normal] = (MInt)(-0.5 + (0.5 * (MFloat)n));
6090
6091 switch(normal) {
6092 case 0: {
6093 if(m_solver->m_forceAveragingDir == 2) {
6094 firstTangential = 2;
6095 secondTangential = 1;
6096 // pointers to the correct direction counter
6097 reali = &i;
6098 realj = &k;
6099 realk = &j;
6100 realjj = &kk;
6101 realkk = &jj;
6102 } else if(m_solver->m_forceAveragingDir == 1) {
6103 firstTangential = 1;
6104 secondTangential = 2;
6105
6106 reali = &i;
6107 realj = &j;
6108 realk = &k;
6109 realjj = &jj;
6110 realkk = &kk;
6111 } else {
6112 mTerm(1, AT_, "Cant average in normal direction");
6113 }
6114 // Saves normal directions for three other points of surface
6115
6116 // determine the sizes
6117 sizeJ = end[1] - start[1];
6118 sizeK = end[2] - start[2];
6119 break;
6120 }
6121 case 1: {
6122 if(m_solver->m_forceAveragingDir == 2) {
6123 firstTangential = 2;
6124 secondTangential = 0;
6125 reali = &k;
6126 realj = &i;
6127 realk = &j;
6128 realjj = &kk;
6129 realkk = &jj;
6130 } else if(m_solver->m_forceAveragingDir == 0) {
6131 firstTangential = 0;
6132 secondTangential = 2;
6133 reali = &j;
6134 realj = &i;
6135 realk = &k;
6136 realjj = &jj;
6137 realkk = &kk;
6138 } else {
6139 mTerm(1, AT_, "Cant average in normal direction");
6140 }
6141
6142 sizeJ = end[0] - start[0];
6143 sizeK = end[2] - start[2];
6144
6145
6146 break;
6147 }
6148 case 2: {
6149 if(m_solver->m_forceAveragingDir == 1) {
6150 firstTangential = 1;
6151 secondTangential = 0;
6152
6153 reali = &k;
6154 realj = &j;
6155 realk = &i;
6156 realjj = &kk;
6157 realkk = &jj;
6158 } else if(m_solver->m_forceAveragingDir == 0) {
6159 firstTangential = 0;
6160 secondTangential = 1;
6161
6162 reali = &j;
6163 realj = &k;
6164 realk = &i;
6165 realjj = &jj;
6166 realkk = &kk;
6167 } else {
6168 mTerm(1, AT_, "Cant average in normal direction");
6169 }
6170
6171
6172 sizeJ = end[0] - start[0];
6173 sizeK = end[1] - start[1];
6174 break;
6175 }
6176 default: {
6177 mTerm(1, AT_, "Normal direction not implemented");
6178 }
6179 }
6180
6181 // main loop over the two tangential directions of the wall
6182 for(k = start[secondTangential]; k < end[secondTangential]; k++) {
6183 jj = 0;
6184
6185 // this loop always goes into the line averaging direction
6186 for(j = start[firstTangential]; j < end[firstTangential]; j++) {
6187 // get id of boundary cell and cell above that one for extrapolation
6188 const MInt cellId = cellIndex(*reali, *realj, *realk);
6189 const MInt cellIdP1 = cellIndex(*reali + n1m1[0], *realj + n1m1[1], *realk + n1m1[2]);
6190
6191 // get point id and ids of three other surface corners
6192 const MInt pIJK = getPointIdFromCell(*reali + n10[0], *realj + n10[1], *realk + n10[2]);
6193 const MInt pIJPK = getPointIdfromPoint(pIJK, pCoordDir[normal][0], pCoordDir[normal][1], pCoordDir[normal][2]);
6194 const MInt pIJKP = getPointIdfromPoint(pIJK, pCoordDir[normal][3], pCoordDir[normal][4], pCoordDir[normal][5]);
6195 const MInt pIJPKP = getPointIdfromPoint(pIJK, pCoordDir[normal][6], pCoordDir[normal][7], pCoordDir[normal][8]);
6196
6197 // first get the position of the wall (reference!!)
6198 // x is always used as coordinate in normal direction
6199 const MFloat xRef = F1B4
6200 * (m_grid->m_coordinates[0][pIJK] + m_grid->m_coordinates[0][pIJPK]
6201 + m_grid->m_coordinates[0][pIJKP] + m_grid->m_coordinates[0][pIJPKP]);
6202 const MFloat yRef = F1B4
6203 * (m_grid->m_coordinates[1][pIJK] + m_grid->m_coordinates[1][pIJPK]
6204 + m_grid->m_coordinates[1][pIJKP] + m_grid->m_coordinates[1][pIJPKP]);
6205 const MFloat zRef = F1B4
6206 * (m_grid->m_coordinates[2][pIJK] + m_grid->m_coordinates[2][pIJPK]
6207 + m_grid->m_coordinates[2][pIJKP] + m_grid->m_coordinates[2][pIJPKP]);
6208
6209 MFloat uWall = F0, vWall = F0, wWall = F0;
6210 if(m_solver->m_movingGrid) {
6211 uWall = F1B4
6212 * (m_grid->m_velocity[0][pIJK] + m_grid->m_velocity[0][pIJPK] + m_grid->m_velocity[0][pIJKP]
6213 + m_grid->m_velocity[0][pIJPKP]);
6214 vWall = F1B4
6215 * (m_grid->m_velocity[1][pIJK] + m_grid->m_velocity[1][pIJPK] + m_grid->m_velocity[1][pIJKP]
6216 + m_grid->m_velocity[1][pIJPKP]);
6217 wWall = F1B4
6218 * (m_grid->m_velocity[2][pIJK] + m_grid->m_velocity[2][pIJPK] + m_grid->m_velocity[2][pIJKP]
6219 + m_grid->m_velocity[2][pIJPKP]);
6220 }
6221
6222 // get the distcance
6223 const MFloat dx2 = sqrt(POW2(m_cells->coordinates[0][cellIdP1] - m_cells->coordinates[0][cellId])
6224 + POW2(m_cells->coordinates[1][cellIdP1] - m_cells->coordinates[1][cellId])
6225 + POW2(m_cells->coordinates[2][cellIdP1] - m_cells->coordinates[2][cellId]));
6226 const MFloat dx1 =
6227 sqrt(POW2(m_cells->coordinates[0][cellId] - xRef) + POW2(m_cells->coordinates[1][cellId] - yRef)
6228 + POW2(m_cells->coordinates[2][cellId] - zRef));
6229 // pressures
6230 const MFloat p1 = m_cells->pvariables[PV->P][cellId];
6231 const MFloat p2 = m_cells->pvariables[PV->P][cellIdP1];
6232 // extrapolation to the face
6233 const MFloat pW = ((p1 - p2) / dx2) * dx1 + p1;
6234 const MFloat cpn = (pW - PV->PInfinity) * fstagnationPressure;
6235
6236 // save pressure to map
6237 m_cells->cp[mapOffsetCp + (*realjj) + (*realkk) * sizeJ] = cpn;
6238
6239
6240 // compute the skin-friction coefficient
6241 //-->
6242 // compute orthogonal distance surface-plane to cell center
6243 MFloat supportVec[3] = {F0, F0, F0};
6244 MFloat firstVec[3] = {F0, F0, F0};
6245 MFloat secondVec[3] = {F0, F0, F0};
6246 MFloat normalVec[3] = {F0, F0, F0};
6247 MFloat cellVec[3] = {F0, F0, F0};
6248
6249 for(MInt dim = 0; dim < nDim; dim++) {
6250 supportVec[dim] = m_grid->m_coordinates[dim][pIJK];
6251 firstVec[dim] = m_grid->m_coordinates[dim][pIJPK] - m_grid->m_coordinates[dim][pIJK];
6252 secondVec[dim] = m_grid->m_coordinates[dim][pIJKP] - m_grid->m_coordinates[dim][pIJK];
6253 cellVec[dim] = m_cells->coordinates[dim][cellId];
6254 }
6255
6256 crossProduct(normalVec, firstVec, secondVec);
6257 const MFloat normalLength = sqrt(POW2(normalVec[0]) + POW2(normalVec[1]) + POW2(normalVec[2]));
6258
6259 const MFloat nn[3] = {normalVec[0] / normalLength, normalVec[1] / normalLength, normalVec[2] / normalLength};
6260 MFloat orthDist = F0;
6261
6262 for(MInt dim = 0; dim < nDim; dim++) {
6263 orthDist += (cellVec[dim] - supportVec[dim]) * normalVec[dim];
6264 }
6265
6266 orthDist = fabs(orthDist / normalLength);
6267
6268 // extrapolate the Temperature to the wall
6269 const MFloat T1 = temperature(cellId);
6270 const MFloat T2 = temperature(cellIdP1);
6271
6272 // extrapolation to the face
6273 const MFloat tBc = ((T1 - T2) / dx2) * dx1 + T1;
6274 const MFloat mue = SUTHERLANDLAW(tBc);
6275
6276 // velocities
6277 const MFloat u1 = m_cells->pvariables[PV->U][cellId];
6278 const MFloat v1 = m_cells->pvariables[PV->V][cellId];
6279 const MFloat w1 = m_cells->pvariables[PV->W][cellId];
6280
6281 // compute gradient
6282 MFloat dudeta = (u1 - uWall) / orthDist;
6283 MFloat dvdeta = (v1 - vWall) / orthDist;
6284 MFloat dwdeta = (w1 - wWall) / orthDist;
6285
6286 // using taylor expansion a second-order approximation
6287 // of du/dn can be achieved at the wall
6288 if(m_solver->m_forceSecondOrder) {
6289 const MFloat u2 = m_cells->pvariables[PV->U][cellIdP1];
6290 const MFloat v2 = m_cells->pvariables[PV->V][cellIdP1];
6291 const MFloat w2 = m_cells->pvariables[PV->W][cellIdP1];
6292 const MFloat dx3 = dx1 + dx2;
6293 dudeta =
6294 (u1 * dx3 * dx3 + (dx1 * dx1 - dx3 * dx3) * uWall - u2 * dx1 * dx1) / (dx1 * dx3 * dx3 - dx1 * dx1 * dx3);
6295 dvdeta =
6296 (v1 * dx3 * dx3 + (dx1 * dx1 - dx3 * dx3) * vWall - v2 * dx1 * dx1) / (dx1 * dx3 * dx3 - dx1 * dx1 * dx3);
6297 dwdeta =
6298 (w1 * dx3 * dx3 + (dx1 * dx1 - dx3 * dx3) * wWall - w2 * dx1 * dx1) / (dx1 * dx3 * dx3 - dx1 * dx1 * dx3);
6299 }
6300
6301 // the compressible contribution to the stress tensor
6302 const MFloat comp = F1B3 * (dudeta * nn[0] + dvdeta * nn[1] + dwdeta * nn[2]);
6303
6304 // friction coefficient in computational space
6305 const MFloat taux = mue * dudeta * fre0;
6306 const MFloat tauy = mue * dvdeta * fre0;
6307 const MFloat tauz = mue * dwdeta * fre0;
6308
6309 const MFloat cfx = taux * fstagnationPressure;
6310 const MFloat cfy = tauy * fstagnationPressure;
6311 const MFloat cfz = tauz * fstagnationPressure;
6312
6313 const MFloat taux_c = mue * comp * nn[0] * fre0;
6314 const MFloat tauy_c = mue * comp * nn[1] * fre0;
6315 const MFloat tauz_c = mue * comp * nn[2] * fre0;
6316
6317 const MFloat cfx_c = taux_c * fstagnationPressure;
6318 const MFloat cfy_c = tauy_c * fstagnationPressure;
6319 const MFloat cfz_c = tauz_c * fstagnationPressure;
6320
6321 // save to map
6322 // skin-friction
6323 m_cells->cf[mapOffsetCf + 0 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = cfx + cfx_c;
6324 m_cells->cf[mapOffsetCf + 1 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = cfy + cfy_c;
6325 m_cells->cf[mapOffsetCf + 2 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = cfz + cfz_c;
6326 //<-- finished computation of skin-friction
6327
6328
6329 MFloat considerValue = F1;
6330 if(m_solver->m_auxDataCoordinateLimits) {
6331 if(m_solver->m_auxDataLimits[0] <= xRef && xRef <= m_solver->m_auxDataLimits[1]
6332 && m_solver->m_auxDataLimits[2] <= zRef && zRef <= m_solver->m_auxDataLimits[3]) {
6333 considerValue = F1;
6334 } else {
6335 considerValue = F0;
6336 }
6337 }
6338
6339 // sum up all lengths and all cps with their surface width contribution
6340 const MFloat dxidx =
6341 m_cells->surfaceMetrics[nDim * normal + 0][cellIndex(*reali + n01[0], *realj + n01[1], *realk + n01[2])];
6342 const MFloat dxidy =
6343 m_cells->surfaceMetrics[nDim * normal + 1][cellIndex(*reali + n01[0], *realj + n01[1], *realk + n01[2])];
6344 const MFloat dxidz =
6345 m_cells->surfaceMetrics[nDim * normal + 2][cellIndex(*reali + n01[0], *realj + n01[1], *realk + n01[2])];
6346 const MFloat dA = sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz);
6347
6348 cp[0] += (-1.0) * cpn * dxidx * considerValue;
6349 cp[1] += (-1.0) * cpn * dxidy * considerValue;
6350 cp[2] += (-1.0) * cpn * dxidz * considerValue;
6351 // cf
6352 cf[0] += cfx * dA * considerValue;
6353 cf[1] += cfy * dA * considerValue;
6354 cf[2] += cfz * dA * considerValue;
6355
6356 cf[3] += cfx_c * dA * considerValue;
6357 cf[4] += cfy_c * dA * considerValue;
6358 cf[5] += cfz_c * dA * considerValue;
6359 // area
6360 area += dA * considerValue;
6361
6362 if(computePower) {
6363 // compute the power (p*v)
6364 const MFloat dp = (pW - PV->PInfinity);
6365
6366 // this is power without area contribution, i.e.: P/A
6367 const MFloat P_px = (-1.0) * dp * uWall * fstagnationEnergy;
6368 const MFloat P_py = (-1.0) * dp * vWall * fstagnationEnergy;
6369 const MFloat P_pz = (-1.0) * dp * wWall * fstagnationEnergy;
6370
6371 // save power due to pressure to map
6372 m_cells->powerPres[mapOffsetPower + 0 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = P_px;
6373 m_cells->powerPres[mapOffsetPower + 1 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = P_py;
6374 m_cells->powerPres[mapOffsetPower + 2 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = P_pz;
6375
6376 // Power due to viscous forces in the computational space ( tau_w*n*u)
6377 const MFloat P_cfx = (taux + taux_c) * uWall * fstagnationEnergy;
6378 const MFloat P_cfy = (tauy + tauy_c) * vWall * fstagnationEnergy;
6379 const MFloat P_cfz = (tauz + tauz_c) * wWall * fstagnationEnergy;
6380
6381 // save power to map
6382 m_cells->powerVisc[mapOffsetPower + 0 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = P_cfx;
6383 m_cells->powerVisc[mapOffsetPower + 1 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = P_cfy;
6384 m_cells->powerVisc[mapOffsetPower + 2 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = P_cfz;
6385
6386 // compute pressurepower*area -> P = (P/A) * A
6387 powerp[0] += P_px * dxidx * considerValue;
6388 powerp[1] += P_py * dxidy * considerValue;
6389 powerp[2] += P_pz * dxidz * considerValue;
6390 // viscous power
6391 powerv[0] += P_cfx * (sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz)) * considerValue;
6392 powerv[1] += P_cfy * (sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz)) * considerValue;
6393 powerv[2] += P_cfz * (sqrt(dxidx * dxidx + dxidy * dxidy + dxidz * dxidz)) * considerValue;
6394 }
6395
6396 if(m_solver->m_detailAuxData) {
6397 // save surface contributions
6398 m_cells->cf[mapOffsetCf + 3 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = dxidx;
6399 m_cells->cf[mapOffsetCf + 4 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = dxidy;
6400 m_cells->cf[mapOffsetCf + 5 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = dxidz;
6401
6402 // save surface coordinates
6403 m_cells->cf[mapOffsetCf + 6 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = xRef;
6404 m_cells->cf[mapOffsetCf + 7 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = yRef;
6405 m_cells->cf[mapOffsetCf + 8 * sizeJ * sizeK + (*realjj) + (*realkk) * sizeJ] = zRef;
6406 }
6407
6408 ++jj;
6409 }
6410
6411 ++kk;
6412 }
6413
6414 // now add to force coefficients
6415 MInt count = 0;
6416 for(auto it = m_solver->m_windowInfo->m_auxDataWindowIds.cbegin();
6417 it != m_solver->m_windowInfo->m_auxDataWindowIds.cend();
6418 ++it) {
6419 if(m_auxDataMap[map]->Id2 == it->second) {
6420 m_forceCoef[count * noForceCoefs + 0] += cf[0];
6421 m_forceCoef[count * noForceCoefs + 1] += cf[1];
6422 m_forceCoef[count * noForceCoefs + 2] += cf[2];
6423 m_forceCoef[count * noForceCoefs + 3] += cf[3];
6424 m_forceCoef[count * noForceCoefs + 4] += cf[4];
6425 m_forceCoef[count * noForceCoefs + 5] += cf[5];
6426 m_forceCoef[count * noForceCoefs + 6] += cp[0];
6427 m_forceCoef[count * noForceCoefs + 7] += cp[1];
6428 m_forceCoef[count * noForceCoefs + 8] += cp[2];
6429 m_forceCoef[count * noForceCoefs + 9] += area;
6430
6431 if(computePower) {
6432 m_forceCoef[count * noForceCoefs + 10] += powerv[0];
6433 m_forceCoef[count * noForceCoefs + 11] += powerv[1];
6434 m_forceCoef[count * noForceCoefs + 12] += powerv[2];
6435 m_forceCoef[count * noForceCoefs + 13] += powerp[0];
6436 m_forceCoef[count * noForceCoefs + 14] += powerp[1];
6437 m_forceCoef[count * noForceCoefs + 15] += powerp[2];
6438 }
6439 }
6440
6441 count++;
6442 }
6443 }
6444}
6449
6450
6454template <MBool isRans>
6456
6457template <MBool isRans>
6459 result[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
6460 result[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
6461 result[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
6462}
6463
6464template <MBool isRans>
6466 const MInt i_new = m_reverseCellIdGC[face * 3 + 0] * (m_noGhostLayers - 1) + m_reverseCellIdDim[face * 3 + 0] * i;
6467 const MInt j_new = m_reverseCellIdGC[face * 3 + 1] * (m_noGhostLayers - 1) + m_reverseCellIdDim[face * 3 + 1] * j;
6468 const MInt k_new = m_reverseCellIdGC[face * 3 + 2] * (m_noGhostLayers - 1) + m_reverseCellIdDim[face * 3 + 2] * k;
6469 return cellIndex(i_new, j_new, k_new);
6470}
6471
6472template <MBool isRans>
6474 static const MInt cellShift[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
6475 const MInt n = 1 - 2 * (face % 2);
6476 const MInt dim = face / 2;
6477 const MInt nghbrId = cellId + n * cellShift[dim];
6478 return nghbrId;
6479}
6480
6481template <MBool isRans>
6483 const MInt cellShift[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
6484 const MInt gcPos[6] = {m_noGhostLayers, m_nCells[2] - m_noGhostLayers - 1,
6485 m_noGhostLayers, m_nCells[1] - m_noGhostLayers - 1,
6486 m_noGhostLayers, m_nCells[0] - m_noGhostLayers - 1};
6487 const MInt ijk_new[3] = {
6488 m_reverseCellIdGC[face * 3 + 0] * (m_noGhostLayers - 1) + m_reverseCellIdDim[face * 3 + 0] * i,
6489 m_reverseCellIdGC[face * 3 + 1] * (m_noGhostLayers - 1) + m_reverseCellIdDim[face * 3 + 1] * j,
6490 m_reverseCellIdGC[face * 3 + 2] * (m_noGhostLayers - 1) + m_reverseCellIdDim[face * 3 + 2] * k};
6491 const MInt dim = face / 2;
6492 const MInt n = 1 - 2 * (face % 2);
6493 const MInt mirror = ((gcPos[face] - ijk_new[dim]) * 2 - n);
6494 const MInt cellId = cellIndex(ijk_new[0], ijk_new[1], ijk_new[2]);
6495 return make_pair(cellId, cellId + mirror * cellShift[dim]);
6496}
6497
6498// instantanisation of the class
6499template class StructuredBndryCnd3D<true>;
6500template class StructuredBndryCnd3D<false>;
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 MInt propertyLength(const MString &name, MInt solverId=m_noSolvers)
Returns the number of elements of a property.
Definition: context.cpp:538
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
Definition: context.cpp:494
3D structured solver class
Base class of the structured solver.
MInt timer(const MInt timerId) const
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
iterator begin()
Definition: scratch.h:273
Class for the 3D stuctured boundary conditions.
void initBc2500(MInt)
Rescaling inflow.
void initBc7909(MInt)
Synthetic Turbulence Generation.
void bc2730(MInt)
Simple outflow with pressure gradient for FSC boundary layer.
void bc1006(MInt)
Moving rigid isothermal wall functions.
void bc1004(MInt)
Moving rigid wall functions.
void initBc2004(MInt)
Initialize with standard pressure extrapolation at inflow or prescribe p_inf at outflow.
void initBc2009(MInt)
Characteristic boundary condition supersonic after shock.
void bc2097(MInt)
Subsonic Inflow for a plenum.
virtual void bc6002(MInt) override
void bc2601(MInt)
Prescribe given profile BC.
void bc2999(MInt)
Blasius bl inflow boundary condition.
void computeFrictionPressureCoef_(const MBool auxDataWindows=false)
New function to compute the skin friction and pressure coefficient and the part for the force coeffic...
MInt cellIndexBC(MInt i, MInt j, MInt k)
FvStructuredSolver3D * m_solver
MFloat generate_rand()
Random number generator.
void bc2002(MInt)
Supersonic Inflow.
MInt getPointIdfromPoint(MInt origin, MInt incI, MInt incJ, MInt incK)
void crossProduct(MFloat *, MFloat *, MFloat *)
MFloat generate_rand_weighted()
Weighted random number generator.
void bc1007(MInt)
Oscillating wall.
MInt getPointIdFromCell(MInt i, MInt j, MInt k)
void bc2020(MInt)
Laminar Poiseuille inflow.
void bc2888(MInt)
Falkner-Skan-Cooke inflow boundary condition.
void bc2099(MInt)
Subsonic Inflow with u=(y/delta)^(1/7)
void bc3001(MInt)
Streamline symmetry.
void initBc2601(MInt)
Prescribe profile BC.
MInt pointIndex(MInt i, MInt j, MInt k)
MInt cellIndex(MInt i, MInt j, MInt k)
void bc2700(MInt)
supersonic inflow with imposed acoustic or entropy waves
std::pair< MInt, MInt > getMirrorCellIdPair(MInt i, MInt j, MInt k, MInt face)
MFloat temperature(MInt cellId)
void initBc2600(MInt)
Prescribe profile BC.
void bc2600(MInt)
Prescribe given profile BC.
void bc2001(MInt)
Subsonic Inflow.
void bc2003(MInt)
Subsonic in/outflow simple.
StructuredBndryCnd3D(FvStructuredSolver< 3 > *solver, StructuredGrid< 3 > *grid)
Constructor of the 3D boundary conditions class.
void bc2014(MInt)
Subsonic rotational inflow.
MFloat dist(MFloat *a, MFloat *b)
MInt getReverseCellId(MInt i, MInt j, MInt k, MInt face)
void bc2009(MInt)
Outflow condition after shock.
void initBc2402(MInt)
Channel flow / Pipe Flow.
void bc2500(MInt)
Rescaling Boundary Conditions.
void initBc2700(MInt)
Init for the acoustic and entropy waves.
void bc7909(MInt)
Reformulated Synthetic Turbulence Generation.
MInt getExtrNghbrId(MInt cellId, MInt face)
void bc2005(MInt)
Supersonic outflow.
Base class of the structured boundary conditions.
Structured grid class.
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
constexpr Real POW3(const Real x)
Definition: functions.h:123
constexpr Real POW2(const Real x)
Definition: functions.h:119
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 globalTimeStep
void printAllocatedMemory(const MLong oldAllocatedBytes, const MString &solverName, const MPI_Comm comm)
Prints currently allocated memory.
InfoOutFile m_log
int32_t MInt
Definition: maiatypes.h:62
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
MInt id
Definition: maiatypes.h:71
int MPI_Barrier(MPI_Comm comm, const MString &name)
same as MPI_Barrier
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
const MInt PIO_READ
Definition: parallelio.h:40
Definition: kdtree.h:73
MInt nearest(Point< DIM > pt, MFloat &dist)
Definition: kdtree.h:199
Definition: pointbox.h:20
Definition: contexttypes.h:19
define array structures