MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
fvstructuredsolver3d.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
8#include <cmath>
9#include "COMM/mpioverride.h"
11#include "IO/parallelio_hdf5.h"
12#include "UTIL/parallelfor.h"
13#include "globals.h"
14
15using namespace std;
16
18 const MPI_Comm comm)
19 : FvStructuredSolver<3>(solverId, grid_, propertiesGroups, comm) {
20 TRACE();
21 const MLong oldAllocatedBytes = allocatedBytes();
22
23 // count the no of necessary FQ fields and allocate
25
26 // compute the cell center coordinates from point coordinates
27 m_grid->computeCellCenterCoordinates();
28
29 if(m_rans) {
30 m_structuredBndryCnd = make_unique<StructuredBndryCnd3D<true>>(this, m_grid);
31 } else {
32 m_structuredBndryCnd = make_unique<StructuredBndryCnd3D<false>>(this, m_grid);
33 }
34
36
37 // allocate memory for aux data maps (cf,cp)
39
40 // assign coordinates to all ghost points
42
43 // if we are RANS we should allocate a new RANS solver
44 if(m_rans == true) {
45 m_ransSolver = make_unique<FvStructuredSolver3DRans>(this);
46 }
47
49
50 m_grid->computeCellCenterCoordinates();
51 RECORD_TIMER_START(m_timers[Timers::ComputeMetrics]);
52 m_grid->computeMetrics();
53 RECORD_TIMER_STOP(m_timers[Timers::ComputeMetrics]);
54 RECORD_TIMER_START(m_timers[Timers::ComputeJacobian]);
55 m_grid->computeJacobian();
56 RECORD_TIMER_STOP(m_timers[Timers::ComputeJacobian]);
57
58 // TODO_SS labels:FV,totest By now I am not sure if Code performs correctly for wrongly oriented meshes
59 for(MInt k = 0; k < m_nCells[0]; k++) {
60 for(MInt j = 0; j < m_nCells[1]; j++) {
61 for(MInt i = 0; i < m_nCells[2]; i++) {
62 const MInt cellId = cellIndex(i, j, k);
63 if(m_cells->cellJac[cellId] < 0.0) mTerm(1, "Negative Jacobian found! Check first if code can cope this!");
64 }
65 }
66 }
67
68 m_convergence = false;
69
70 if(m_zonal) {
72 }
73
74 // Assign handlers to the correct boundary conditions
76
77 // Computation of modified wall distance in porous computation requires to set the porosity,
78 // Da-number etc. first; on the other hand we need to wait for initializeFQField to be called
79 if(m_porous) {
80 initPorous();
81 // exchange6002();
82 }
83
84 if(m_zonal || m_rans) {
86 m_structuredBndryCnd->computeWallDistances();
87 }
88 }
89
92 }
93
96 }
97
98 printAllocatedMemory(oldAllocatedBytes, "FvStructuredSolver3D", m_StructuredComm);
99
100 RECORD_TIMER_STOP(m_timers[Timers::Constructor]);
101}
102
104
106 if(!m_rans) {
107 // do a spanwise average of the pressure in
108 // all LES zones
109 m_zonalSpanwiseAvgVars.push_back(m_cells->fq[FQ->AVG_P]);
110 }
111
115 const MInt noZonalBCMaps = m_windowInfo->m_zonalBCMaps.size();
116 m_zonalBC.resize(noZonalBCMaps);
117
121 if(domainId() == 0) {
122 cout << "///////////////////////////////////////////////////////////////////" << endl
123 << "Starting zonal bc creation for " << noZonalBCMaps << " zonal bc maps" << endl;
124 }
125
126 for(MInt id = 0; id < noZonalBCMaps; id++) {
127 if(domainId() == 0) {
128 cout << "///////////////////////////////////////////////////////////////////" << endl;
129 cout << "//////////// ZONAL BC " << id << " ///////////////////////////////////////////" << endl;
130 cout << "///////////////////////////////////////////////////////////////////" << endl;
131 }
132
133 m_zonalBC[id] = make_unique<StructuredZonalBC>();
134 m_zonalBC[id]->receiverBlockId = m_windowInfo->m_zonalBCMaps[id]->Id1;
135
136 if(domainId() == 0) {
137 cout << "Zonal BC" << id << ": Initialization ..." << endl;
138 }
139
140 // set up the data of the zonal domain and noCellsBC
141 MIntScratchSpace noZonalCells(noDomains(), AT_, "noZonalCells");
142 MInt hasRcvDomain = 0;
143 m_zonalBC[id]->noZonalVariables = 6;
144 m_zonalBC[id]->hasSTG = false;
145 m_zonalBC[id]->noCellsGlobalBC = 0;
146 m_zonalBC[id]->noCellsLocalBC = 0;
147 m_zonalBC[id]->hasLocalBCMap = false;
148
149 for(MInt bcId = 0; bcId < abs((MInt)m_windowInfo->physicalBCMap.size()); ++bcId) {
150 m_zonalBC[id]->hasLocalBCMap =
151 m_windowInfo->checkZonalBCMaps(m_windowInfo->m_zonalBCMaps[id], m_windowInfo->physicalBCMap[bcId]);
152
153 MInt stgIP = 0;
154 if(m_zonalBC[id]->hasLocalBCMap) {
155 if(m_windowInfo->physicalBCMap[bcId]->BC == 2221) {
156 stgIP = 1; // in this case use one more cell, required for STG
157 m_zonalBC[id]->hasSTG = true;
158 }
159
160 MInt* start = m_structuredBndryCnd->m_physicalBCMap[bcId]->start1;
161 MInt* end = m_structuredBndryCnd->m_physicalBCMap[bcId]->end1;
162 m_zonalBC[id]->noCellsLocalBC += (end[0] + stgIP - start[0]) * (end[1] - start[1]) * (end[2] - start[2]);
163 m_zonalBC[id]->start[0] = start[0];
164 m_zonalBC[id]->start[1] = start[1];
165 m_zonalBC[id]->start[2] = start[2];
166 m_zonalBC[id]->end[0] = end[0] + stgIP;
167 m_zonalBC[id]->end[1] = end[1];
168 m_zonalBC[id]->end[2] = end[2];
169 hasRcvDomain = 1;
170 break;
171 }
172 }
173
174 if(domainId() == 0) {
175 cout << "Zonal BC" << id << ": Initialization ... Finished!" << endl;
176 cout << "Zonal BC" << id << ": Collecting local coordinates ... " << endl;
177 }
178
179 MFloatScratchSpace localCoordinatesBC(nDim, std::max(1, m_zonalBC[id]->noCellsLocalBC), AT_, "localCoordinatesBC");
180 MIntScratchSpace localReceiverIds(std::max(1, m_zonalBC[id]->noCellsLocalBC), AT_, "localReceiverIds");
181 MIntScratchSpace localMapCellIds(std::max(1, m_zonalBC[id]->noCellsLocalBC), AT_, "m_localMapCellIds");
182
183 if(m_zonalBC[id]->hasLocalBCMap) {
184 MInt bcCellId = 0;
185 for(MInt k = m_zonalBC[id]->start[2]; k < m_zonalBC[id]->end[2]; k++) {
186 for(MInt j = m_zonalBC[id]->start[1]; j < m_zonalBC[id]->end[1]; j++) {
187 for(MInt i = m_zonalBC[id]->start[0]; i < m_zonalBC[id]->end[0]; i++) {
188 const MInt cellId = cellIndex(i, j, k);
189
190 if(m_zonalBC[id]->hasSTG) {
191 localMapCellIds[bcCellId] = bcCellId;
192 } else {
193 localMapCellIds[bcCellId] = cellId;
194 }
195
196 for(MInt dim = 0; dim < nDim; ++dim) {
197 localCoordinatesBC(dim, bcCellId) = m_cells->coordinates[dim][cellId];
198 }
199
200 localReceiverIds[bcCellId] = domainId();
201 ++bcCellId;
202 }
203 }
204 }
205 }
206
207 if(domainId() == 0) {
208 cout << "Zonal BC" << id << ": Collecting local coordinates ... Finished!" << endl;
209 cout << "Zonal BC" << id << ": Exchanging information about local coordinates ..." << endl;
210 }
211
212 MPI_Allreduce(&m_zonalBC[id]->noCellsLocalBC, &m_zonalBC[id]->noCellsGlobalBC, 1, MPI_INT, MPI_SUM,
213 m_StructuredComm, AT_, "m_zonalBC[id]->noCellsLocalBC", "m_zonalBC[id]->noCellsGlobalBC");
214 MPI_Allgather(&m_zonalBC[id]->noCellsLocalBC, 1, MPI_INT, &noZonalCells[0], 1, MPI_INT, m_StructuredComm, AT_,
215 "m_zonalBC[id]->noCellsLocalBC", "noZonalCells[0]");
216
217 if(domainId() == 0) {
218 cout << "Zonal BC" << id << ": Exchanging information about local coordinates ... Finished!" << endl;
219 }
220
224 if(domainId() == 0) {
225 MInt noCells = 0;
226 for(MInt i = 0; i < noDomains(); i++) {
227 noCells += noZonalCells[i];
228 }
229 cout << "Zonal BC" << id << ": Gathering coordinates for " << noCells << " cells on all partitions..." << endl;
230 }
231
232 MIntScratchSpace noCellsBCOffsets(noDomains(), AT_, "noCellsBCOffsets");
233 mAlloc(m_zonalBC[id]->coordinatesGlobalBC, 3, std::max(1, m_zonalBC[id]->noCellsGlobalBC), "coordinatesGlobalBC",
234 0.0, AT_);
235 mAlloc(m_zonalBC[id]->globalLocalMapCellIds, std::max(1, m_zonalBC[id]->noCellsGlobalBC), "globalLocalMapCellIds",
236 -1, AT_);
237 mAlloc(m_zonalBC[id]->globalReceiverIds, std::max(1, m_zonalBC[id]->noCellsGlobalBC), "globalReceiverIds", -1, AT_);
238
239 noCellsBCOffsets[0] = 0;
240 for(MInt i = 1; i < noDomains(); i++) {
241 noCellsBCOffsets[i] = noCellsBCOffsets[i - 1] + noZonalCells[i - 1];
242 }
243
244
245 // Distribute all zonal cell information (all coordinates, cellIds, domainIds) to all domains
246 for(MInt dim = 0; dim < nDim; ++dim) {
247 MPI_Allgatherv(&localCoordinatesBC(dim, 0), noZonalCells[domainId()], MPI_DOUBLE,
248 &m_zonalBC[id]->coordinatesGlobalBC[dim][0], &noZonalCells[0], &noCellsBCOffsets[0], MPI_DOUBLE,
249 m_StructuredComm, AT_, "localCoordinatesBC(0,0)", "coordinatesGlobalBC[0][0]");
250 }
251 MPI_Allgatherv(&localReceiverIds[0], noZonalCells[domainId()], MPI_INT, &m_zonalBC[id]->globalReceiverIds[0],
252 &noZonalCells[0], &noCellsBCOffsets[0], MPI_INT, m_StructuredComm, AT_, "localReceiverIds[0]",
253 "m_zonalBC[id]->globalReceiverIds[0]");
254 MPI_Allgatherv(&localMapCellIds[0], noZonalCells[domainId()], MPI_INT, &m_zonalBC[id]->globalLocalMapCellIds[0],
255 &noZonalCells[0], &noCellsBCOffsets[0], MPI_INT, m_StructuredComm, AT_, "localMapCellIds[0]",
256 "m_zonalBC[id]->globalLocalMapCellIds[0]");
257
258 if(domainId() == 0) {
259 MInt noCells = 0;
260 for(MInt i = 0; i < noDomains(); i++) {
261 noCells += noZonalCells[i];
262 }
263 cout << "Zonal BC" << id << ": Gathering coordinates for " << noCells << " cells on all partitions... Finished!"
264 << endl;
265 cout << "Zonal BC" << id << ": Searching for suitable interpolation partners..." << endl;
266 }
270 MIntScratchSpace hasPartnerLocalBC(m_zonalBC[id]->noCellsGlobalBC, AT_, "hasPartnerLocalBC");
271 MBool hasInterpolationPartnerDomain = true;
272
273 if(m_blockId == m_zonalBC[id]->receiverBlockId) {
274 hasInterpolationPartnerDomain = false;
275 }
276
277 m_zonalBC[id]->interpolation =
278 make_unique<StructuredInterpolation<nDim>>(m_nCells, m_cells->coordinates, m_StructuredComm);
279
280 m_zonalBC[id]->interpolation->prepareZonalInterpolation(m_zonalBC[id]->noCellsGlobalBC,
281 m_zonalBC[id]->coordinatesGlobalBC,
282 hasPartnerLocalBC.begin(),
283 hasInterpolationPartnerDomain);
284
285 if(domainId() == 0) {
286 cout << "Zonal BC" << id << ": Searching for suitable interpolation partners... Finished!" << endl;
287 cout << "Zonal BC" << id << ": Creating sending and receiving information..." << endl;
288 }
289
293 // to find out which domains will be rcvDomains
294
295 m_zonalBC[id]->noGlobalRcvDomains = 0;
296 MPI_Allreduce(&hasRcvDomain, &m_zonalBC[id]->noGlobalRcvDomains, 1, MPI_INT, MPI_SUM, m_StructuredComm, AT_,
297 "hasRcvDomain", "m_zonalBC[id]->noGlobalRcvDomains");
298
299 mAlloc(m_zonalBC[id]->globalRcvDomainIds, std::max(1, m_zonalBC[id]->noGlobalRcvDomains), "m_globalRcvDomainIds",
300 -1, AT_);
301
302 MInt pos = 0;
303 for(MInt j = 0; j < noDomains(); j++) {
304 if(noZonalCells[j] > 0) {
305 m_zonalBC[id]->globalRcvDomainIds[pos] = j;
306 ++pos;
307 }
308 }
309
310 // to find out which domains will be sndDomains
311 MInt hasSndDomain = false;
312 for(MInt cellIdBC = 0; cellIdBC < m_zonalBC[id]->noCellsGlobalBC; cellIdBC++) {
313 if(hasPartnerLocalBC[cellIdBC]) {
314 hasSndDomain = true;
315 break;
316 }
317 }
318
319 m_zonalBC[id]->noGlobalSndDomains = 0;
320 MPI_Allreduce(&hasSndDomain, &m_zonalBC[id]->noGlobalSndDomains, 1, MPI_INT, MPI_SUM, m_StructuredComm, AT_,
321 "hasSndDomain", "m_zonalBC[id]->noGlobalSndDomains");
322
323
324 MIntScratchSpace hasSndDomainInfo(noDomains(), AT_, "hasSndDomainInfo");
325 MPI_Allgather(&hasSndDomain, 1, MPI_INT, &hasSndDomainInfo[0], 1, MPI_INT, m_StructuredComm, AT_, "hasSndDomain",
326 "hasSndDomainInfo[0]");
327
328 mAlloc(m_zonalBC[id]->globalSndDomainIds, std::max(1, m_zonalBC[id]->noGlobalSndDomains), "m_globalSndDomainIds",
329 -1, AT_);
330
331 pos = 0;
332 for(MInt j = 0; j < noDomains(); j++) {
333 if(hasSndDomainInfo[j] > 0) {
334 m_zonalBC[id]->globalSndDomainIds[pos] = j;
335 pos++;
336 }
337 }
341 // compute no of cells which our domain can interpolate and has to send
342 m_zonalBC[id]->noBufferSndSize = 0;
343 for(MInt cellIdBC = 0; cellIdBC < m_zonalBC[id]->noCellsGlobalBC; cellIdBC++) {
344 if(hasPartnerLocalBC[cellIdBC]) {
345 m_zonalBC[id]->noBufferSndSize++;
346 }
347 }
348
349 mAlloc(m_zonalBC[id]->localCommReceiverIds, std::max(1, m_zonalBC[id]->noBufferSndSize), "localCommReceiverIds",
350 AT_);
351 mAlloc(m_zonalBC[id]->localBufferMapCellIds, std::max(1, m_zonalBC[id]->noBufferSndSize), "localCommReceiverIds",
352 AT_);
353 mAlloc(m_zonalBC[id]->localBufferIndexCellIds, std::max(1, m_zonalBC[id]->noBufferSndSize), "localCommReceiverIds",
354 AT_);
355
356 // collect the receiver domainIds for each cell that our domain can interpolate
357 pos = 0;
358 for(MInt cellIdBC = 0; cellIdBC < m_zonalBC[id]->noCellsGlobalBC; cellIdBC++) {
359 if(hasPartnerLocalBC[cellIdBC]) {
360 m_zonalBC[id]->localCommReceiverIds[pos] = m_zonalBC[id]->globalReceiverIds[cellIdBC];
361 pos++;
362 }
363 }
364
365 // count to how many different domains our domain needs to send data
366 m_zonalBC[id]->noSndNghbrDomains = 0;
367 for(MInt i = 0; i < m_zonalBC[id]->noGlobalSndDomains; i++) {
368 if(m_zonalBC[id]->globalSndDomainIds[i] == domainId()) {
369 for(MInt d = 0; d < noDomains(); d++) {
370 for(MInt j = 0; j < m_zonalBC[id]->noBufferSndSize; j++) {
371 if(m_zonalBC[id]->localCommReceiverIds[j] == d) {
372 m_zonalBC[id]->noSndNghbrDomains++;
373 break;
374 }
375 }
376 }
377 }
378 }
379
380 MIntScratchSpace localRcvId(std::max(1, m_zonalBC[id]->noSndNghbrDomains), AT_, "localRcvId");
381 MIntScratchSpace localBufferSndSize(std::max(1, m_zonalBC[id]->noSndNghbrDomains), AT_, "localBufferSndSize");
382
383 // save each receiving domainId in localRcvId
384 pos = 0;
385 for(MInt i = 0; i < m_zonalBC[id]->noGlobalSndDomains; i++) {
386 if(m_zonalBC[id]->globalSndDomainIds[i] == domainId()) {
387 for(MInt d = 0; d < noDomains(); d++) {
388 for(MInt j = 0; j < m_zonalBC[id]->noBufferSndSize; j++) {
389 if(m_zonalBC[id]->localCommReceiverIds[j] == d) {
390 localRcvId[pos] = d;
391 pos++;
392 break;
393 }
394 }
395 }
396 }
397 }
398
399
400 // save the cellId and mapCellId (the cellId of the receiving cell on the nghbr Domain)
401 pos = 0;
402 for(MInt cellIdBC = 0; cellIdBC < m_zonalBC[id]->noCellsGlobalBC; cellIdBC++) {
403 if(hasPartnerLocalBC[cellIdBC]) {
404 const MInt mapCellId = m_zonalBC[id]->globalLocalMapCellIds[cellIdBC];
405 m_zonalBC[id]->localBufferMapCellIds[pos] = mapCellId;
406 m_zonalBC[id]->localBufferIndexCellIds[pos] = cellIdBC; // this is needed to get InterpolatedVars in zonalGather
407 pos++;
408 }
409 }
410
411 // compute the buffer size for each domain our domain needs to send data to
412 for(MInt i = 0; i < m_zonalBC[id]->noSndNghbrDomains; i++) {
413 for(MInt j = 0; j < m_zonalBC[id]->noBufferSndSize; j++) {
414 if(localRcvId[i] == m_zonalBC[id]->localCommReceiverIds[j]) {
415 localBufferSndSize[i]++;
416 }
417 }
418 }
419
420 // get m_zonalBC[id]->noRcvNghbrDomains and SndId
421 MIntScratchSpace sndBufferRcvSize(noDomains(), AT_, "sndBufferRcvSize");
422
423 for(MInt noRcv = 0; noRcv < m_zonalBC[id]->noGlobalRcvDomains; noRcv++) {
424 MInt bufferRcvSize = 0;
425 for(MInt cellIdBC = 0; cellIdBC < m_zonalBC[id]->noCellsGlobalBC; cellIdBC++) {
426 if(m_zonalBC[id]->globalRcvDomainIds[noRcv] == m_zonalBC[id]->globalReceiverIds[cellIdBC]) {
427 if(hasPartnerLocalBC[cellIdBC]) {
428 bufferRcvSize++;
429 }
430 }
431 }
432
433 // get the bufferSndSize
434 sndBufferRcvSize[m_zonalBC[id]->globalRcvDomainIds[noRcv]] = bufferRcvSize;
435 }
436
437 MIntScratchSpace rcvBufferRcvSize(noDomains(), AT_, "rcvBufferRcvSize");
438 MPI_Alltoall(&sndBufferRcvSize[0], 1, MPI_INT, &rcvBufferRcvSize[0], 1, MPI_INT, m_StructuredComm, AT_,
439 "sndBufferRcvSize[0]", "rcvBufferRcvSize[0]");
440
441 // get m_zonalBC[id]->noRcvNghbrDomains, localSndId, localbufferRcvSize.
442 // These are from which domains each rcvDoamin will receive
443 // and how much size it is.
444 m_zonalBC[id]->noRcvNghbrDomains = 0;
445 if(m_zonalBC[id]->hasLocalBCMap) {
446 for(MInt i = 0; i < noDomains(); i++) {
447 if(rcvBufferRcvSize[i] > 0) { // get noRcvNghbrDoamins
448 m_zonalBC[id]->noRcvNghbrDomains++;
449 }
450 }
451 }
452
453 MIntScratchSpace localSndId(std::max(1, m_zonalBC[id]->noRcvNghbrDomains), AT_, "localSndId");
454 MIntScratchSpace localBufferRcvSize(std::max(1, m_zonalBC[id]->noRcvNghbrDomains), AT_, "localBufferRcvSize");
455
456 // get localSndId from which domains each rcvDoamin will receive data
457 pos = 0;
458 if(m_zonalBC[id]->hasLocalBCMap) {
459 for(MInt i = 0; i < noDomains(); i++) {
460 if(rcvBufferRcvSize[i] > 0) { // sndId is the info the receiver Domains have from which domains I will receive
461 localSndId[pos] = i;
462 pos++;
463 }
464 }
465 }
466 // get localbufferRcvSize
467 pos = 0;
468 if(m_zonalBC[id]->hasLocalBCMap) {
469 for(MInt i = 0; i < noDomains(); i++) {
470 if(rcvBufferRcvSize[i] > 0) {
471 localBufferRcvSize[pos] = rcvBufferRcvSize[i];
472 pos++;
473 }
474 }
475 }
476
480
481 mAlloc(m_zonalBC[id]->sndRequest, std::max(1, m_zonalBC[id]->noSndNghbrDomains), "sndRequest", AT_);
482 mAlloc(m_zonalBC[id]->sndStatus, std::max(1, m_zonalBC[id]->noSndNghbrDomains), "sndStatus", AT_);
483 mAlloc(m_zonalBC[id]->rcvRequest, std::max(1, m_zonalBC[id]->noRcvNghbrDomains), "rcvRequest", AT_);
484 mAlloc(m_zonalBC[id]->rcvStatus, std::max(1, m_zonalBC[id]->noRcvNghbrDomains), "rcvStatus", AT_);
485
486
487 for(MInt i = 0; i < m_zonalBC[id]->noSndNghbrDomains; i++) {
488 unique_ptr<StructuredZonalComm> sndCommPtr =
489 make_unique<StructuredZonalComm>(localBufferSndSize[i], localRcvId[i], m_zonalBC[id]->noZonalVariables);
490 m_zonalBC[id]->sndComm.push_back(std::move(sndCommPtr));
491 m_zonalBC[id]->sndRequest[i] = MPI_REQUEST_NULL;
492 }
493
494 for(MInt i = 0; i < m_zonalBC[id]->noRcvNghbrDomains; i++) {
495 unique_ptr<StructuredZonalComm> rcvCommPtr =
496 make_unique<StructuredZonalComm>(localBufferRcvSize[i], localSndId[i], m_zonalBC[id]->noZonalVariables);
497 m_zonalBC[id]->rcvComm.push_back(std::move(rcvCommPtr));
498 m_zonalBC[id]->rcvRequest[i] = MPI_REQUEST_NULL;
499 }
500
501
505
506 for(MInt noSnd = 0; noSnd < m_zonalBC[id]->noSndNghbrDomains; noSnd++) {
507 pos = 0;
508
509 for(MInt cellId = 0; cellId < m_zonalBC[id]->noBufferSndSize; cellId++) {
510 if(m_zonalBC[id]->localCommReceiverIds[cellId] == m_zonalBC[id]->sndComm[noSnd]->localId) {
511 m_zonalBC[id]->sndComm[noSnd]->mapCellId[pos] = m_zonalBC[id]->localBufferMapCellIds[cellId];
512 pos++;
513 }
514 }
515
516 MInt err = MPI_Isend((void*)m_zonalBC[id]->sndComm[noSnd]->mapCellId, m_zonalBC[id]->sndComm[noSnd]->bufferSize,
517 MPI_INT, m_zonalBC[id]->sndComm[noSnd]->localId, 0, m_StructuredComm,
518 &m_zonalBC[id]->sndRequest[noSnd], AT_, "m_zonalBC[id]->sndComm[noSnd]->intBbuffer");
519 if(err)
520 cout << "rank " << domainId() << " zonal sending to " << m_zonalBC[id]->sndComm[noSnd]->localId
521 << " throws error " << endl;
522 }
523
524 for(MInt noRcv = 0; noRcv < m_zonalBC[id]->noRcvNghbrDomains; noRcv++) {
525 MInt err =
526 MPI_Irecv((void*)&m_zonalBC[id]->rcvComm[noRcv]->mapCellId[0], m_zonalBC[id]->rcvComm[noRcv]->bufferSize,
527 MPI_INT, m_zonalBC[id]->rcvComm[noRcv]->localId, 0, m_StructuredComm,
528 &m_zonalBC[id]->rcvRequest[noRcv], AT_, "(void*)&m_zonalBC[id]->rcvComm[noRcv]->mapCellId");
529 if(err)
530 cout << "rank " << domainId() << " zonal sending to " << m_zonalBC[id]->sndComm[noRcv]->localId
531 << " throws error " << endl;
532 }
533
534 MPI_Waitall(m_zonalBC[id]->noSndNghbrDomains, m_zonalBC[id]->sndRequest, m_zonalBC[id]->sndStatus, AT_);
535 MPI_Waitall(m_zonalBC[id]->noRcvNghbrDomains, m_zonalBC[id]->rcvRequest, m_zonalBC[id]->rcvStatus, AT_);
536
538
539 if(domainId() == 0) {
540 cout << "Zonal BC" << id << ": Creating sending and receiving information... Finished!" << endl;
541 cout << "Zonal BC" << id << ": Completed!" << endl;
542 }
543 }
544}
545
547 zonalGather();
548 zonalSend();
549 zonalReceive();
550 zonalScatter();
551}
552
553
555 // gather sending variables in buffer
556 for(auto const& zBC : m_zonalBC) {
557 for(MInt noSnd = 0; noSnd < zBC->noSndNghbrDomains; noSnd++) {
558 const MInt noCells = zBC->sndComm[noSnd]->bufferSize;
559 MInt pos = 0;
560 for(MInt cellId = 0; cellId < zBC->noBufferSndSize; cellId++) {
561 if(zBC->localCommReceiverIds[cellId] == zBC->sndComm[noSnd]->localId) {
562 const MInt cellIdBC = zBC->localBufferIndexCellIds[cellId];
563 if(m_rans) {
564 zBC->sndComm[noSnd]->buffer[pos + 0 * noCells] =
565 zBC->interpolation->interpolateVariableZonal(m_cells->pvariables[PV->U], cellIdBC);
566 zBC->sndComm[noSnd]->buffer[pos + 1 * noCells] =
567 zBC->interpolation->interpolateVariableZonal(m_cells->pvariables[PV->V], cellIdBC);
568 zBC->sndComm[noSnd]->buffer[pos + 2 * noCells] =
569 zBC->interpolation->interpolateVariableZonal(m_cells->pvariables[PV->W], cellIdBC);
570 zBC->sndComm[noSnd]->buffer[pos + 3 * noCells] =
571 zBC->interpolation->interpolateVariableZonal(m_cells->pvariables[PV->RHO], cellIdBC);
572 zBC->sndComm[noSnd]->buffer[pos + 4 * noCells] =
573 zBC->interpolation->interpolateVariableZonal(m_cells->pvariables[PV->P], cellIdBC);
574 zBC->sndComm[noSnd]->buffer[pos + 5 * noCells] =
575 zBC->interpolation->interpolateVariableZonal(m_cells->fq[FQ->NU_T], cellIdBC);
576 } else {
577 zBC->sndComm[noSnd]->buffer[pos + 0 * noCells] =
578 zBC->interpolation->interpolateVariableZonal(m_cells->fq[FQ->AVG_U], cellIdBC);
579 zBC->sndComm[noSnd]->buffer[pos + 1 * noCells] =
580 zBC->interpolation->interpolateVariableZonal(m_cells->fq[FQ->AVG_V], cellIdBC);
581 zBC->sndComm[noSnd]->buffer[pos + 2 * noCells] =
582 zBC->interpolation->interpolateVariableZonal(m_cells->fq[FQ->AVG_W], cellIdBC);
583 zBC->sndComm[noSnd]->buffer[pos + 3 * noCells] =
584 zBC->interpolation->interpolateVariableZonal(m_cells->fq[FQ->AVG_RHO], cellIdBC);
585 zBC->sndComm[noSnd]->buffer[pos + 4 * noCells] =
586 zBC->interpolation->interpolateVariableZonal(m_cells->fq[FQ->AVG_P], cellIdBC);
587 zBC->sndComm[noSnd]->buffer[pos + 5 * noCells] =
588 zBC->interpolation->interpolateVariableZonal(m_cells->fq[FQ->NU_T], cellIdBC);
589 }
590 pos++;
591 }
592 }
593 }
594 }
595}
596
598 for(auto const& zBC : m_zonalBC) {
599 // access only sndDomains
600 for(MInt i = 0; i < zBC->noGlobalSndDomains; i++) {
601 if(zBC->globalSndDomainIds[i] == domainId()) {
602 for(MInt noSnd = 0; noSnd < zBC->noSndNghbrDomains; noSnd++) {
603 MInt err = MPI_Isend(&zBC->sndComm[noSnd]->buffer[0], zBC->sndComm[noSnd]->bufferSize * zBC->noZonalVariables,
604 MPI_DOUBLE, zBC->sndComm[noSnd]->localId, 0, m_StructuredComm, &zBC->sndRequest[noSnd],
605 AT_, "zBC->buffer[noSnd][0]");
606 if(err) cout << "rank " << domainId() << " zonal sending throws error " << endl;
607 }
608 }
609 }
610 }
611}
612
614 for(auto const& zBC : m_zonalBC) {
615 for(MInt i = 0; i < zBC->noGlobalRcvDomains; i++) {
616 // access only rcvDomains
617 if(zBC->globalRcvDomainIds[i] == domainId()) {
618 for(MInt noRcv = 0; noRcv < zBC->noRcvNghbrDomains; noRcv++) {
619 MInt err = MPI_Irecv(&zBC->rcvComm[noRcv]->buffer[0], zBC->rcvComm[noRcv]->bufferSize * zBC->noZonalVariables,
620 MPI_DOUBLE, zBC->rcvComm[noRcv]->localId, 0, m_StructuredComm, &zBC->rcvRequest[noRcv],
621 AT_, "&zBC->bufferRcvZonal[noRcv][0]");
622 if(err) cout << "rank " << domainId() << " zonal receiving throws error " << endl;
623 }
624 }
625 }
626 MPI_Waitall(zBC->noSndNghbrDomains, zBC->sndRequest, zBC->sndStatus, AT_);
627 MPI_Waitall(zBC->noRcvNghbrDomains, zBC->rcvRequest, zBC->rcvStatus, AT_);
628 }
629}
630
631
633 for(auto const& zBC : m_zonalBC) {
634 for(MInt noRcv = 0; noRcv < zBC->noRcvNghbrDomains; noRcv++) {
635 const MInt noCells = zBC->rcvComm[noRcv]->bufferSize;
636 for(MInt i = 0; i < noCells; i++) {
637 const MInt localMapCellIds = zBC->rcvComm[noRcv]->mapCellId[i];
638 if(zBC->hasSTG) {
639 m_cells->stg_fq[PV->U][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[0 * noCells + i];
640 m_cells->stg_fq[PV->V][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[1 * noCells + i];
641 m_cells->stg_fq[PV->W][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[2 * noCells + i];
642 m_cells->stg_fq[PV->RHO][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[3 * noCells + i];
643 m_cells->stg_fq[PV->P][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[4 * noCells + i];
644 m_cells->stg_fq[FQ->NU_T][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[5 * noCells + i];
645 } else {
646 m_cells->fq[FQ->AVG_U][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[0 * noCells + i];
647 m_cells->fq[FQ->AVG_V][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[1 * noCells + i];
648 m_cells->fq[FQ->AVG_W][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[2 * noCells + i];
649 m_cells->fq[FQ->AVG_RHO][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[3 * noCells + i];
650 m_cells->fq[FQ->AVG_P][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[4 * noCells + i];
651 m_cells->fq[FQ->NU_T][localMapCellIds] = zBC->rcvComm[noRcv]->buffer[5 * noCells + i];
652 }
653 }
654 }
655 }
656}
657
658
660 // choose the convective flux method
661 // for performance issues, it is templated
662 //(we do not need to write the muscl stuff too often
663 // we need to put the limiter also into the template
664 // in order to reduce this function!!
665 if(m_rans == true) {
668 } else {
669 viscFluxMethod = &FvStructuredSolver3D::viscousFluxLES<>;
670 // check if limiter
671 if(m_limiter) {
673 case VENKATAKRISHNAN_MOD: {
686 m_venkFactor = Context::getSolverProperty<MFloat>("venkFactor", m_solverId,
687 AT_); // reads the customizable parameter from properties
688
689 m_log << "Using VENKATAKRISHNAN MOD limiter with VENK factor of " << m_venkFactor << " !" << endl;
692 break;
693 }
694
695 case VENKATAKRISHNAN: {
696 m_log << "Using VENKATAKRISHNAN limiter!" << endl;
699 break;
700 }
701
702 case BARTH_JESPERSON: {
703 m_log << "Using BARTH JESPERSON limiter!" << endl;
706 break;
707 }
708 case MINMOD: {
709 m_log << "Using MINMOD limiter!" << endl;
711 break;
712 }
713 case ALBADA: {
714 m_log << "Using VAN ALBADA limiter!" << endl;
716 break;
717 }
718 default: {
719 stringstream errorMessage;
720 errorMessage << "Limiter function " << m_limiterMethod << " not implemented!" << endl;
721 mTerm(1, AT_, errorMessage.str());
722 }
723 }
724 } else if(m_musclScheme == "Standard") {
725 m_log << "Using unlimited MUSCL! (standard Formulation)" << endl;
726 if(m_ausmScheme == "Standard") {
727 m_log << "Using standard AUSM central" << endl;
728 m_dsIsComputed = false;
729 switch(CV->noVariables) {
730 case 5: {
731 reconstructSurfaceData = &FvStructuredSolver3D::Muscl_AusmLES<5>;
732 break;
733 }
734 case 6: {
735 reconstructSurfaceData = &FvStructuredSolver3D::Muscl_AusmLES<6>;
736 break;
737 }
738 case 7: {
739 reconstructSurfaceData = &FvStructuredSolver3D::Muscl_AusmLES<7>;
740 break;
741 }
742 default: {
743 stringstream errorMessage;
744 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
745 mTerm(1, AT_);
746 }
747 }
748 } else if(m_ausmScheme == "PTHRC") {
749 m_log << "Using AUSM PTHRC" << endl;
750 m_dsIsComputed = false;
751 switch(CV->noVariables) {
752 case 5: {
753 reconstructSurfaceData = &FvStructuredSolver3D::Muscl_AusmLES_PTHRC<5>;
754 break;
755 }
756 case 6: {
757 reconstructSurfaceData = &FvStructuredSolver3D::Muscl_AusmLES_PTHRC<6>;
758 break;
759 }
760 case 7: {
761 reconstructSurfaceData = &FvStructuredSolver3D::Muscl_AusmLES_PTHRC<7>;
762 break;
763 }
764 default: {
765 stringstream errorMessage;
766 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
767 mTerm(1, AT_);
768 }
769 }
770 } else if(m_ausmScheme == "AUSMDV") {
771 m_log << "Using AUSMDV" << endl;
772 m_dsIsComputed = false;
773 switch(CV->noVariables) {
774 case 5: {
775 reconstructSurfaceData = &FvStructuredSolver3D::Muscl_AusmDV<5>;
776 break;
777 }
778 case 6: {
779 reconstructSurfaceData = &FvStructuredSolver3D::Muscl_AusmDV<6>;
780 break;
781 }
782 case 7: {
783 reconstructSurfaceData = &FvStructuredSolver3D::Muscl_AusmDV<7>;
784 break;
785 }
786 default: {
787 stringstream errorMessage;
788 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
789 mTerm(1, AT_);
790 }
791 }
792 }
793 } else if(m_musclScheme == "Stretched") {
794 m_log << "Using unlimited MUSCL (streched Grids)";
795 mAlloc(m_cells->cellLength, nDim, m_noCells, "m_cells->cellLength", -F1, AT_);
797 m_log << "Using standard AUSM central" << endl;
798 if(m_ausmScheme == "Standard") {
799 switch(CV->noVariables) {
800 case 5: {
801 reconstructSurfaceData = &FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES, 5>;
802 break;
803 }
804 case 6: {
805 reconstructSurfaceData = &FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES, 6>;
806 break;
807 }
808 case 7: {
809 reconstructSurfaceData = &FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES, 7>;
810 break;
811 }
812 default: {
813 stringstream errorMessage;
814 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
815 mTerm(1, AT_);
816 }
817 }
818 } else if(m_ausmScheme == "PTHRC") {
819 m_log << "Using AUSM PTHRC" << endl;
820 switch(CV->noVariables) {
821 case 5: {
822 reconstructSurfaceData = &FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES_PTHRC, 5>;
823 break;
824 }
825 case 6: {
826 reconstructSurfaceData = &FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES_PTHRC, 6>;
827 break;
828 }
829 case 7: {
830 reconstructSurfaceData = &FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES_PTHRC, 7>;
831 break;
832 }
833 default: {
834 stringstream errorMessage;
835 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
836 mTerm(1, AT_);
837 }
838 }
839 } else if(m_ausmScheme == "AUSMDV") {
840 m_log << "Using AUSMDV" << endl;
841 switch(CV->noVariables) {
842 case 5: {
843 reconstructSurfaceData = &FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmDV, 5>;
844 break;
845 }
846 case 6: {
847 reconstructSurfaceData = &FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmDV, 6>;
848 break;
849 }
850 case 7: {
851 reconstructSurfaceData = &FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmDV, 7>;
852 break;
853 }
854 default: {
855 stringstream errorMessage;
856 errorMessage << "Number of Variables " << CV->noVariables << " not implemented in template AUSM!" << endl;
857 mTerm(1, AT_);
858 }
859 }
860 }
861 }
862 }
863}
864
865
867 // this function can be moved into the MusclSchemeStreched later but for testing it is easier
868 // REMEMBER: FOR MOVINg GRIDS THIS NEEDS TO BE CALLED EACH TIME
869
870 MInt P1 = -1, P2 = -1, P3 = -1, P4 = -1, P5 = -1, P6 = -1, P7 = -1, P8 = -1;
871 MFloat f1x = F0, f1y = F0, f1z = F0, f2x = F0, f2y = F0, f2z = F0;
872 for(MInt k = 0; k < m_nCells[0]; k++) {
873 for(MInt j = 0; j < m_nCells[1]; j++) {
874 for(MInt i = 0; i < m_nCells[2]; i++) {
875 const MInt cellId = cellIndex(i, j, k);
876 P1 = getPointIdFromCell(i, j, k);
877 P2 = getPointIdfromPoint(P1, 1, 0, 0);
878 P3 = getPointIdfromPoint(P1, 1, 1, 0);
879 P4 = getPointIdfromPoint(P1, 1, 0, 1);
880 P5 = getPointIdfromPoint(P1, 1, 1, 1);
881 P6 = getPointIdfromPoint(P1, 0, 1, 0);
882 P7 = getPointIdfromPoint(P1, 0, 1, 1);
883 P8 = getPointIdfromPoint(P1, 0, 0, 1);
884 //----------Idirection
885 // face 1
886 f1x = F1B4
887 * (m_grid->m_coordinates[0][P1] + m_grid->m_coordinates[0][P6] + m_grid->m_coordinates[0][P7]
888 + m_grid->m_coordinates[0][P8]);
889 f1y = F1B4
890 * (m_grid->m_coordinates[1][P1] + m_grid->m_coordinates[1][P6] + m_grid->m_coordinates[1][P7]
891 + m_grid->m_coordinates[1][P8]);
892 f1z = F1B4
893 * (m_grid->m_coordinates[2][P1] + m_grid->m_coordinates[2][P6] + m_grid->m_coordinates[2][P7]
894 + m_grid->m_coordinates[2][P8]);
895 // face 2
896 f2x = F1B4
897 * (m_grid->m_coordinates[0][P2] + m_grid->m_coordinates[0][P3] + m_grid->m_coordinates[0][P4]
898 + m_grid->m_coordinates[0][P5]);
899 f2y = F1B4
900 * (m_grid->m_coordinates[1][P2] + m_grid->m_coordinates[1][P3] + m_grid->m_coordinates[1][P4]
901 + m_grid->m_coordinates[1][P5]);
902 f2z = F1B4
903 * (m_grid->m_coordinates[2][P2] + m_grid->m_coordinates[2][P3] + m_grid->m_coordinates[2][P4]
904 + m_grid->m_coordinates[2][P5]);
905 m_cells->cellLength[0][cellId] = sqrt(POW2(f2x - f1x) + POW2(f2y - f1y) + POW2(f2z - f1z));
906 //----------Jdirection
907 // face 1
908 f1x = F1B4
909 * (m_grid->m_coordinates[0][P1] + m_grid->m_coordinates[0][P2] + m_grid->m_coordinates[0][P4]
910 + m_grid->m_coordinates[0][P8]);
911 f1y = F1B4
912 * (m_grid->m_coordinates[1][P1] + m_grid->m_coordinates[1][P2] + m_grid->m_coordinates[1][P4]
913 + m_grid->m_coordinates[1][P8]);
914 f1z = F1B4
915 * (m_grid->m_coordinates[2][P1] + m_grid->m_coordinates[2][P2] + m_grid->m_coordinates[2][P4]
916 + m_grid->m_coordinates[2][P8]);
917 // face 2
918 f2x = F1B4
919 * (m_grid->m_coordinates[0][P3] + m_grid->m_coordinates[0][P5] + m_grid->m_coordinates[0][P6]
920 + m_grid->m_coordinates[0][P7]);
921 f2y = F1B4
922 * (m_grid->m_coordinates[1][P3] + m_grid->m_coordinates[1][P5] + m_grid->m_coordinates[1][P6]
923 + m_grid->m_coordinates[1][P7]);
924 f2z = F1B4
925 * (m_grid->m_coordinates[2][P3] + m_grid->m_coordinates[2][P5] + m_grid->m_coordinates[2][P6]
926 + m_grid->m_coordinates[2][P7]);
927 m_cells->cellLength[1][cellId] = sqrt(POW2(f2x - f1x) + POW2(f2y - f1y) + POW2(f2z - f1z));
928 //----------Kdirection
929 // face 1
930 f1x = F1B4
931 * (m_grid->m_coordinates[0][P1] + m_grid->m_coordinates[0][P2] + m_grid->m_coordinates[0][P3]
932 + m_grid->m_coordinates[0][P6]);
933 f1y = F1B4
934 * (m_grid->m_coordinates[1][P1] + m_grid->m_coordinates[1][P2] + m_grid->m_coordinates[1][P3]
935 + m_grid->m_coordinates[1][P6]);
936 f1z = F1B4
937 * (m_grid->m_coordinates[2][P1] + m_grid->m_coordinates[2][P2] + m_grid->m_coordinates[2][P3]
938 + m_grid->m_coordinates[2][P6]);
939 // face 2
940 f2x = F1B4
941 * (m_grid->m_coordinates[0][P4] + m_grid->m_coordinates[0][P5] + m_grid->m_coordinates[0][P7]
942 + m_grid->m_coordinates[0][P8]);
943 f2y = F1B4
944 * (m_grid->m_coordinates[1][P4] + m_grid->m_coordinates[1][P5] + m_grid->m_coordinates[1][P7]
945 + m_grid->m_coordinates[1][P8]);
946 f2z = F1B4
947 * (m_grid->m_coordinates[2][P5] + m_grid->m_coordinates[2][P5] + m_grid->m_coordinates[2][P7]
948 + m_grid->m_coordinates[2][P8]);
949 m_cells->cellLength[2][cellId] = sqrt(POW2(f2x - f1x) + POW2(f2y - f1y) + POW2(f2z - f1z));
950 }
951 }
952 }
953}
954
956 const MInt P1 = getPointIdFromCell(i, j, k);
957 const MInt P2 = getPointIdfromPoint(P1, 1, 0, 0);
958 const MInt P3 = getPointIdfromPoint(P1, 1, 1, 0);
959 const MInt P4 = getPointIdfromPoint(P1, 1, 0, 1);
960 const MInt P5 = getPointIdfromPoint(P1, 1, 1, 1);
961 const MInt P6 = getPointIdfromPoint(P1, 0, 1, 0);
962 const MInt P7 = getPointIdfromPoint(P1, 0, 1, 1);
963 const MInt P8 = getPointIdfromPoint(P1, 0, 0, 1);
964
965 const MFloat lowerY = F1B4
966 * (m_grid->m_coordinates[1][P1] + m_grid->m_coordinates[1][P2] + m_grid->m_coordinates[1][P4]
967 + m_grid->m_coordinates[1][P8]);
968 const MFloat upperY = F1B4
969 * (m_grid->m_coordinates[1][P3] + m_grid->m_coordinates[1][P5] + m_grid->m_coordinates[1][P6]
970 + m_grid->m_coordinates[1][P7]);
971
972 return upperY - lowerY;
973}
974
976
977
979 TRACE();
980
981 std::ignore = mode;
982
983 // Compute infinity values from property file
984 // and (if no restart) fill cells according
985 // to the initialCondition property
987
990 } else if(m_restart) {
992 }
993
994 // timestep will be computed and
995 // set if globalTimeStep == 0 or
996 // constantTimeStep = 0
997 setTimeStep();
998
999 // initialize moving grid
1000 // functions and move grid
1001 // to correct position
1002 if(m_movingGrid) {
1003 RECORD_TIMER_START(m_timers[Timers::MovingGrid]);
1004 RECORD_TIMER_START(m_timers[Timers::MGMoveGrid]);
1006 RECORD_TIMER_STOP(m_timers[Timers::MGMoveGrid]);
1007 RECORD_TIMER_STOP(m_timers[Timers::MovingGrid]);
1008 }
1009
1010 if(m_bodyForce) {
1011 initBodyForce();
1012 }
1013
1014 if(m_useSandpaperTrip) {
1016 }
1017
1018 // Get the correct values
1019 // in the exchange ghostcells
1020 exchange();
1021
1022 if(m_rans) {
1023 m_ransSolver->computeTurbViscosity();
1024 }
1025
1026 if(m_zonal) {
1029 zonalExchange();
1030 }
1031
1032 // Call the init function of each BC
1033 initBndryCnds();
1034
1035 // Apply boundary conditions
1036 // and fill the non-exchange ghostcells
1038
1039 if(m_rans) {
1040 m_ransSolver->computeTurbViscosity();
1041 }
1042
1043 // Check for NaNs
1044 checkNans();
1045
1047}
1048
1059 m_structuredInterpolation = make_unique<StructuredInterpolation<3>>(m_StructuredComm);
1060 m_structuredInterpolation->prepareInterpolationField(m_nCells, m_cells->coordinates);
1061
1062 if(m_zonal) {
1063 for(MInt var = 0; var < m_maxNoVariables; var++) {
1064 m_structuredInterpolation->interpolateField(m_pvariableNames[var], m_cells->pvariables[var]);
1065 }
1066
1067 m_structuredInterpolation->interpolateField(FQ->fqNames[FQ->NU_T], m_cells->fq[FQ->NU_T]);
1068 } else {
1069 MBool donorConservative = false;
1070 if(Context::propertyExists("donorConservative", m_solverId)) {
1071 donorConservative = Context::getSolverProperty<MBool>("donorConservative", false, AT_);
1072 }
1073
1074 if(donorConservative) {
1075 for(MInt var = 0; var < CV->noVariables; var++) {
1076 m_structuredInterpolation->interpolateField(m_variableNames[var], m_cells->variables[var]);
1077 }
1079 } else {
1080 for(MInt var = 0; var < PV->noVariables; var++) {
1081 m_structuredInterpolation->interpolateField(m_pvariableNames[var], m_cells->pvariables[var]);
1082 }
1083 }
1084
1085 // interpolate NU_T for STG if this is an initial start (otherwise not needed)
1087 m_structuredInterpolation->interpolateField(FQ->fqNames[FQ->NU_T], m_cells->fq[FQ->NU_T]);
1088 }
1089 }
1090
1091 if(m_useSponge && m_spongeLayerType == 2) {
1092 m_structuredInterpolation->interpolateField("rho", m_cells->fq[FQ->SPONGE_RHO]);
1093 m_structuredInterpolation->interpolateField("rhoE", m_cells->fq[FQ->SPONGE_RHO_E]);
1094 }
1095
1096 if(m_useSponge && m_spongeLayerType == 4) {
1097 m_structuredInterpolation->interpolateField("rho", m_cells->fq[FQ->SPONGE_RHO]);
1098 }
1099
1101}
1102
1103
1113 TRACE();
1114 const MFloat gammaMinusOne = m_gamma - 1.0;
1115 MFloat UT;
1116 MFloat pressureCH = F0;
1117
1118 PV->TInfinity = 1.0 / (1.0 + F1B2 * gammaMinusOne * POW2(m_Ma));
1119 UT = m_Ma * sqrt(PV->TInfinity);
1120 PV->UInfinity = UT * cos(m_angle[0]) * cos(m_angle[1]);
1121 PV->VInfinity = UT * sin(m_angle[0]) * cos(m_angle[1]);
1122 PV->WInfinity = UT * sin(m_angle[1]);
1123 PV->VVInfinity[0] = PV->UInfinity;
1124 PV->VVInfinity[1] = PV->VInfinity;
1125 PV->VVInfinity[2] = PV->WInfinity;
1126 PV->PInfinity = pow(PV->TInfinity, (m_gamma / gammaMinusOne)) / m_gamma;
1127
1128 // compute conservative variables
1129 CV->rhoInfinity = pow(PV->TInfinity, (1.0 / gammaMinusOne));
1130 CV->rhoUInfinity = CV->rhoInfinity * PV->UInfinity;
1131 CV->rhoVInfinity = CV->rhoInfinity * PV->VInfinity;
1132 CV->rhoWInfinity = CV->rhoInfinity * PV->WInfinity;
1133 CV->rhoVVInfinity[0] = CV->rhoUInfinity;
1134 CV->rhoVVInfinity[1] = CV->rhoVInfinity;
1135 CV->rhoVVInfinity[2] = CV->rhoWInfinity;
1136 CV->rhoEInfinity = PV->PInfinity / gammaMinusOne + CV->rhoInfinity * (F1B2 * POW2(UT));
1137
1138 // internal Reynolds number Re0 = Re / ( rho8*M*sqrt(T8)/T8^F072)
1139 m_Re0 = m_Re * SUTHERLANDLAW(PV->TInfinity) / (CV->rhoInfinity * m_Ma * sqrt(PV->TInfinity));
1140
1141 // reference enthalpies (needed for combustion computations)
1142 m_hInfinity = PV->PInfinity / CV->rhoInfinity * m_gamma / gammaMinusOne;
1143
1144 // reference time (convection time)
1146
1147 m_deltaP = F0;
1148 // pressure loss per unit length dp = rho_00 u_tau^2 L / D ) here: D=1.0, L=1;
1149 // channel: dp = rho_00 u_tau^2 L / D )
1150 // m_deltaP = POW2( m_Ma * m_ReTau * sqrt(PV->TInfinity) / m_Re ) * CV->rhoInfinity / m_referenceLength;x
1151 // result is obtained by making deltap dimensionless with a_0^2 and rho_0
1152 // pipe: dp = lambda * L/D * rho/2 * u^2, lambda = 0.3164 Re^(-1/4) (Blasius)
1153
1154 if(m_rans) {
1155 const MFloat lamVisc = SUTHERLANDLAW(PV->TInfinity);
1156 const MFloat chi = 0.1;
1157 CV->ransInfinity[0] = chi * (lamVisc);
1158 PV->ransInfinity[0] = chi * (lamVisc / CV->rhoInfinity);
1159 }
1160
1161 m_log << "=================================================" << endl;
1162 m_log << " INITIAL CONDITION SUMMARY" << endl;
1163 m_log << "=================================================" << endl;
1164 m_log << "Re = " << m_Re << endl;
1165 m_log << "Re0 = " << m_Re0 << endl;
1166 m_log << "Ma = " << m_Ma << endl;
1167 m_log << "TInfinity = " << PV->TInfinity << endl;
1168 m_log << "UInfinity = " << PV->UInfinity << endl;
1169 m_log << "VInfinity = " << PV->VInfinity << endl;
1170 m_log << "WInfinity = " << PV->WInfinity << endl;
1171 m_log << "PInfinity = " << PV->PInfinity << endl;
1172 m_log << "rhoInfinity = " << CV->rhoInfinity << endl;
1173 m_log << "rhoEInfinity = " << CV->rhoEInfinity << endl;
1174 m_log << "referenceTime = " << m_timeRef << endl;
1175
1176 if(domainId() == 0) {
1177 cout << "////////////////////////////////////////////////" << endl;
1178 cout << "////////// Initial Condition summary ///////////" << endl;
1179 cout << "////////////////////////////////////////////////" << endl;
1180 cout << "Re = " << m_Re << endl;
1181 cout << "Re0 = " << m_Re0 << endl;
1182 cout << "Ma = " << m_Ma << endl;
1183 cout << "TInfinity = " << PV->TInfinity << endl;
1184 cout << "UInfinity = " << PV->UInfinity << endl;
1185 cout << "VInfinity = " << PV->VInfinity << endl;
1186 cout << "WInfinity = " << PV->WInfinity << endl;
1187 cout << "Angle = " << m_angle[0] << " " << m_angle[1] << endl;
1188 cout << "PInfinity = " << PV->PInfinity << endl;
1189 cout << "rhoInfinity = " << CV->rhoInfinity << endl;
1190 cout << "rhoEInfinity = " << CV->rhoEInfinity << endl;
1191 cout << "referenceTime = " << m_timeRef << endl;
1192 cout << " zonal = " << m_zonal << endl;
1193 }
1194
1195 if(!m_restart) {
1196 // inflow condition
1197 // ----------------
1198 switch(m_initialCondition) {
1199 case 0: {
1200 // parallel inflow field
1201 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
1202 // go through every cell
1203 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity;
1204 for(MInt i = 0; i < nDim; i++) {
1205 m_cells->pvariables[PV->VV[i]][cellid] = PV->VVInfinity[i];
1206 }
1207
1208 m_cells->pvariables[PV->P][cellid] = PV->PInfinity;
1209
1210 if(m_rans) {
1211 m_cells->pvariables[PV->RANS_VAR[0]][cellid] = PV->ransInfinity[0];
1212 }
1213 }
1214
1215 break;
1216 }
1217 case 43: {
1218 // parallel inflow field with pressure peak in the middle of the domain
1219 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
1220 // go through every cell
1221 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity;
1222 for(MInt i = 0; i < nDim; i++) {
1223 m_cells->pvariables[PV->VV[i]][cellid] = F0;
1224 }
1225
1226 m_cells->pvariables[PV->P][cellid] = PV->PInfinity;
1227
1228 MFloat radius =
1229 sqrt(POW2(m_cells->coordinates[0][cellid] - 0.5) + POW2(m_cells->coordinates[1][cellid] - 0.5));
1230
1231 // impose pressure peak in the middle of the domain
1232 if(radius <= 0.05) {
1233 MFloat pAmp = 0.005;
1234 MFloat pressureSignal = sin(radius / 0.05 * PI) * pAmp + PV->PInfinity;
1235 m_cells->pvariables[PV->P][cellid] = pressureSignal;
1236 }
1237 }
1238 break;
1239 }
1240 case 333: {
1241 // parallel inflow field
1242 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
1243 // go through every cell
1244 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity;
1245 for(MInt i = 0; i < nDim; i++) {
1246 m_cells->pvariables[PV->VV[i]][cellid] = PV->VVInfinity[i];
1247 }
1248
1249 m_cells->pvariables[PV->P][cellid] = PV->PInfinity;
1250
1251 // impose pressure peak in the middle of the domain
1252 if(m_cells->coordinates[0][cellid] > 0.4 && m_cells->coordinates[0][cellid] < 0.5) {
1253 MFloat pAmp = 0.005;
1254 MFloat xCoordinate = m_cells->coordinates[0][cellid] - 0.4;
1255 MFloat pressureSignal = sin(xCoordinate / 0.1 * PI) * pAmp + PV->PInfinity;
1256 m_cells->pvariables[PV->P][cellid] = pressureSignal;
1257 }
1258 }
1259 break;
1260 }
1261 case 314: // stagnating flow field
1262 {
1263 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
1264 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity;
1265 for(MInt i = 0; i < nDim; i++) {
1266 m_cells->pvariables[PV->VV[i]][cellid] = F0;
1267 }
1268
1269 m_cells->pvariables[PV->P][cellid] = PV->PInfinity;
1270 }
1271 cout << "I.C. stagnating flow field was applied! " << endl;
1272 break;
1273 }
1274 case 315: // Poiseuille flow
1275 {
1276 MFloat x = F0, y = F0; // p=F0, T=F0, T0=F0;
1277 MFloat y_max = F1; // channel height
1278
1279 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
1280 x = m_cells->coordinates[0][cellid];
1281 y = m_cells->coordinates[1][cellid];
1282
1283 for(MInt i = 0; i < nDim; i++) {
1284 m_cells->pvariables[PV->VV[i]][cellid] = F0;
1285 }
1286 // all velocity components are 0 except u, Poiseuille distribution:
1287 m_cells->pvariables[PV->VV[0]][cellid] =
1288 -(F3 / F2) * PV->UInfinity * (POW2(y - y_max / F2) - POW2(y_max / F2)) / POW2(y_max / F2);
1289
1290 // the pressure is defined through the axial pressure gradient:
1291 m_cells->pvariables[PV->P][cellid] =
1292 PV->PInfinity - F3 * (x + 15.0) * SUTHERLANDLAW(PV->TInfinity) * PV->UInfinity * POW2(F2 / y_max) / m_Re0;
1293
1294 // compressible Poiseuille Temperature distribution
1295 // T = T0 - (m_gamma-F1)*m_Pr * POW2(PV->UInfinity*F3/F2) * (F1B2*(F1+ pow( (y-y_max/F2)/(y_max/F2), F4 )
1296 // )-POW2((y-y_max/F2)/(y_max/F2)));
1297 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity; // m_gamma * m_cells->variables[ PV->P ][cellid] /
1298 // T;//
1299 }
1300
1301 break;
1302 }
1303 case 101: // TAYLOR_GREEN_VORTEX
1304 {
1305 // domain boundaries are all 2*pi
1306 // rho=1.0;
1307 // u=A*SIN(x)*COS(y)*COS(z)
1308 // v=- A*COS(x)*SIN(y)*COS(z)
1309 // w=0.0
1310 // p=A*A*rho*( 1./(Ms*Ms*kappa) + 1./16.*(COS(2*x)*COS(2.*z)+ 2.*COS(2.*y) +2.*COS(2.*x) +COS(2*y)*COS(2.*z)))
1311 // Ms =0.1 maximum Mach number
1312 // A= speed magnitude set to 1.0
1313 MInt cellId = 0;
1314 MFloat A = PV->UInfinity;
1315 MFloat x = F0;
1316 MFloat y = F0;
1317 MFloat z = F0;
1318 for(MInt k = 0; k < m_nCells[0]; k++) {
1319 for(MInt j = 0; j < m_nCells[1]; j++) {
1320 for(MInt i = 0; i < m_nCells[2]; i++) {
1321 cellId = cellIndex(i, j, k);
1322 x = m_cells->coordinates[0][cellId];
1323 y = m_cells->coordinates[1][cellId];
1324 z = m_cells->coordinates[2][cellId];
1325 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1326 m_cells->pvariables[PV->VV[0]][cellId] = A * sin(x) * cos(y) * cos(z);
1327 m_cells->pvariables[PV->VV[1]][cellId] = -A * cos(x) * sin(y) * cos(z);
1328 m_cells->pvariables[PV->VV[2]][cellId] = 0.0;
1329 m_cells->pvariables[PV->P][cellId] =
1330 PV->PInfinity
1331 + F1B16 * (POW2(A) * CV->rhoInfinity) * (cos(2.0 * x) + cos(2.0 * y)) * (2.0 + cos(2.0 * z));
1332 }
1333 }
1334 }
1335 break;
1336 }
1337 case 1234: {
1338 // laminar channel flow
1339 MInt cellId = 0;
1340 m_channelHeight = 2.0;
1341 m_channelLength = 6.2831;
1342 // m_deltaP=32.0*SUTHERLANDLAW(PV->TInfinity)*m_Ma*sqrt(PV->TInfinity)*m_channelLength/(m_Re0*m_channelHeight);
1343 m_deltaP =
1344 -12.0 * PV->UInfinity * SUTHERLANDLAW(PV->TInfinity) * m_channelLength / (POW2(m_channelHeight) * m_Re0);
1345
1346 m_channelPresInlet = PV->PInfinity;
1347 m_channelPresOutlet = PV->PInfinity + m_deltaP;
1348 MFloat u =
1349 PV->UInfinity; // POW2(m_channelHeight)*m_deltaP*m_Re0*m_referenceLength*m_referenceLength/m_channelLength;
1350 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
1351 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
1352 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
1353 cellId = cellIndex(i, j, k);
1354
1355 // channel height is in j direction
1356 // so prescribe a mean profile in u(y)
1357 MFloat x = m_cells->coordinates[0][cellId];
1359 // density:
1360 MFloat rho = pressureCH * m_gamma / PV->TInfinity;
1361 m_cells->pvariables[PV->RHO][cellId] = rho;
1362 m_cells->pvariables[PV->U][cellId] = u;
1363 m_cells->pvariables[PV->V][cellId] = F0;
1364 m_cells->pvariables[PV->W][cellId] = F0;
1365 m_cells->pvariables[PV->P][cellId] = pressureCH;
1366 }
1367 }
1368 }
1369
1370 break;
1371 }
1372 case 1233: {
1373 // turbulent channel with perturbations
1374 // calculate the Pressure loss;
1375
1376 // for the law of the wall
1377 const MFloat C1 = m_channelC1;
1378 const MFloat C2 = m_channelC2;
1379 const MFloat C3 = m_channelC3;
1380 const MFloat C4 = m_channelC4;
1382 MInt cellId = 0;
1383 MFloat yplus = F0;
1384 MFloat uTau = m_ReTau * m_Ma * sqrt(PV->TInfinity) / m_Re;
1385 MFloat prefactor = m_ReTau; // uTau*m_Re0/SUTHERLANDLAW(PV->TInfinity);
1386
1387 m_deltaP = -CV->rhoInfinity * POW2(uTau) * F2 * (m_channelLength) / m_channelHeight;
1388
1389 m_log << "uTau: " << uTau << " channelLength: " << m_channelLength << endl;
1390 // mean velocity profile
1391 m_channelPresInlet = PV->PInfinity;
1393 PV->PInfinity - CV->rhoInfinity * POW2(uTau) * F2 * (xINIT + m_channelLength) / m_channelHeight;
1395 MFloat cfTheo = 2 * POW2(uTau / PV->UInfinity);
1396 MFloat cdTheo = cfTheo * 2.0 * m_channelWidth * m_channelLength;
1397 m_log << "deltaP: " << deltaP << " cfTheoretisch: " << cfTheo << " cdTheo: " << cdTheo << endl;
1398
1399
1400 for(MInt k = 0; k < m_nCells[0]; k++) {
1401 for(MInt j = 0; j < m_nCells[1]; j++) {
1402 for(MInt i = 0; i < m_nCells[2]; i++) {
1403 // channel height is in j direction
1404 // so prescribe a mean profile in u(y)
1405 cellId = cellIndex(i, j, k);
1406 // channel starts at x=0 or we need to prescribe an offset
1407 MFloat y = m_cells->coordinates[1][cellId];
1408 MFloat x = m_cells->coordinates[0][cellId];
1409 pressureCH =
1411
1412 MFloat rho = pressureCH * m_gamma / PV->TInfinity;
1413 MFloat velFactor = 2.0;
1414 if(y < m_channelHeight / 2) {
1415 yplus = prefactor * y;
1416 } else {
1417 yplus = prefactor * (m_channelHeight - y);
1418 }
1419
1420 // C1 etc are defined in maiaconstants.h
1421 if(yplus <= 5.0) {
1422 m_cells->pvariables[PV->U][cellId] = 0.5 * uTau * yplus * velFactor;
1423 } else if(yplus <= 30 && yplus > 5.0) {
1424 m_cells->pvariables[PV->U][cellId] = 0.5 * uTau * (C1 * log(yplus) + C2) * velFactor;
1425 } else if(yplus > 30) {
1426 m_cells->pvariables[PV->U][cellId] = 0.5 * uTau * (C3 * log(yplus) + C4) * velFactor;
1427 }
1428
1429 m_cells->pvariables[PV->RHO][cellId] = rho;
1430 m_cells->pvariables[PV->V][cellId] = F0;
1431 m_cells->pvariables[PV->W][cellId] = F0;
1432 m_cells->pvariables[PV->P][cellId] = pressureCH;
1433 }
1434 }
1435 }
1436 // create the fluctuations:
1437
1438
1439 // this way of creating the
1440 // fluctuations is only possible for
1441 // quite small mounts of cells
1442 // if too large this approach will not work anymore
1443 // 125000000 is a random integer number which has to be tested
1444 // else the approach with white noise will be employed
1445 const MInt totalBlockCells =
1446 (m_grid->getMyBlockNoCells(0) * m_grid->getMyBlockNoCells(1) * m_grid->getMyBlockNoCells(2));
1447
1448 if(totalBlockCells <= 12500000) {
1449 fftw_complex *uPhysField, *vPhysField, *wPhysField;
1450
1451 // we need the total number of points
1452 MInt lx = m_grid->getMyBlockNoCells(2), ly = m_grid->getMyBlockNoCells(1), lz = m_grid->getMyBlockNoCells(0);
1453
1454 // field of velocities from positve frequencies
1455 uPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
1456 vPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
1457 wPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
1458
1459 // no real parallel computation is done
1460 // should be implemented later !!!!
1461
1462 if(noDomains() > 1) {
1463 MFloatScratchSpace sendRecvBufferU(lx * ly * lz, AT_, "sendRecvBufferU");
1464 MFloatScratchSpace sendRecvBufferV(lx * ly * lz, AT_, "sendRecvBufferV");
1465 MFloatScratchSpace sendRecvBufferW(lx * ly * lz, AT_, "sendRecvBufferW");
1466 if(domainId() == 0) {
1467 MInt m_noPeakModes = 100;
1468 initFFTW(uPhysField, vPhysField, wPhysField, lx, ly, lz, m_noPeakModes);
1469 // copy values into the sendRCVbuffer
1470
1471 for(MInt id = 0; id < lz * ly * lz; id++) {
1472 sendRecvBufferU[id] = uPhysField[id][0];
1473 sendRecvBufferV[id] = vPhysField[id][0];
1474 sendRecvBufferW[id] = wPhysField[id][0];
1475 }
1476 }
1477 MPI_Bcast(&sendRecvBufferU[0], lx * ly * lz, MPI_DOUBLE, 0, m_StructuredComm, AT_, "sendRecvBufferU[0]");
1478 MPI_Bcast(&sendRecvBufferV[0], lx * ly * lz, MPI_DOUBLE, 0, m_StructuredComm, AT_, "sendRecvBufferV[0]");
1479 MPI_Bcast(&sendRecvBufferW[0], lx * ly * lz, MPI_DOUBLE, 0, m_StructuredComm, AT_, "sendRecvBufferW[0]");
1480
1481 if(domainId() != 0) {
1482 for(MInt id = 0; id < lz * ly * lz; id++) {
1483 uPhysField[id][0] = sendRecvBufferU[id];
1484 vPhysField[id][0] = sendRecvBufferV[id];
1485 wPhysField[id][0] = sendRecvBufferW[id];
1486 }
1487 }
1488 } else {
1489 // create velocity field
1490 MInt m_noPeakModes = 100;
1491 initFFTW(uPhysField, vPhysField, wPhysField, lx, ly, lz, m_noPeakModes);
1492 }
1493 // now we need to distribute the
1494 } else {
1495 MFloat amp = 0.15;
1496 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
1497 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
1498 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
1499 cellId = cellIndex(i, j, k);
1500 m_cells->pvariables[PV->V][cellId] +=
1501 amp * 2.0 * (0.5 - (1.0 * rand() / (RAND_MAX + 1.0))) * m_cells->pvariables[PV->U][cellId];
1502 m_cells->pvariables[PV->W][cellId] +=
1503 amp * 2.0 * (0.5 - (1.0 * rand() / (RAND_MAX + 1.0))) * m_cells->pvariables[PV->U][cellId];
1504 m_cells->pvariables[PV->U][cellId] +=
1505 amp * 2.0 * (0.5 - (1.0 * rand() / (RAND_MAX + 1.0))) * m_cells->pvariables[PV->U][cellId];
1506 }
1507 }
1508 }
1509 }
1510
1511 break;
1512 }
1513 case 1236: {
1514 // pipe with perturbations
1515 // calculate the Pressure loss;
1516 // for the law of the wall
1517 // const MFloat C1 = m_channelC1;
1518 // const MFloat C2 = m_channelC2;
1519 const MFloat C3 = m_channelC3;
1520 const MFloat C4 = m_channelC4;
1521 MInt cellId = 0;
1522 MFloat uTau = m_ReTau * m_Ma * sqrt(PV->TInfinity) / m_Re;
1523 // MFloat prefactor=m_ReTau;//uTau*m_Re0/SUTHERLANDLAW(PV->TInfinity);
1524
1525 m_deltaP = -4.0 * CV->rhoInfinity * POW2(uTau) * (m_channelLength) / m_channelHeight;
1526 m_channelPresInlet = PV->PInfinity;
1527 m_channelPresOutlet = PV->PInfinity + m_deltaP;
1528 const MFloat bulkVel = uTau * (C3 * log(m_ReTau / 2) + C4);
1529
1530 m_log << "=========== Turb. Pipe Flow Inital Condition Summary =========== " << endl;
1531 m_log << "-->Turbulent pipe flow deltaP: " << m_deltaP << endl;
1532 m_log << "-->pipe friciton velocity: " << uTau << endl;
1533 m_log << "-->pipe pressure inflow: " << m_channelPresInlet << endl;
1534 m_log << "-->pipe pressure outflow: " << m_channelPresOutlet << endl;
1535 m_log << "--> bulk velocity (u_max)" << bulkVel << endl;
1536 m_log << "=========== Turb. Pipe Flow Initial Condition Summary Finished =========== " << endl;
1537
1538 for(MInt k = 0; k < m_nCells[0]; k++) {
1539 for(MInt j = 0; j < m_nCells[1]; j++) {
1540 for(MInt i = 0; i < m_nCells[2]; i++) {
1541 // IMPORTANT PIPE LENGTH HAS TO GO INTO X-DIRECTION
1542 // so prescribe a mean profile in u(r)
1543 // centerline is assumed at y=0.0,z=0.0
1544
1545 cellId = cellIndex(i, j, k);
1546 // determine the radius
1547 MFloat r = sqrt(POW2(m_cells->coordinates[1][cellId]) + POW2(m_cells->coordinates[2][cellId]));
1548
1549 MFloat x = m_cells->coordinates[0][cellId];
1550 // determine the pressure drop
1551 pressureCH = m_deltaP / m_channelLength * (x - m_channelInflowPlaneCoordinate) + PV->PInfinity;
1552 MFloat rho = pressureCH * m_gamma / PV->TInfinity;
1553 // important: viscous sublayer is not build explicitly. The flow has to build it by itself
1554 MFloat vel = bulkVel + C3 * log(F1 - min(((F2 * r) / m_channelHeight), 0.999999999)) * uTau;
1555 m_cells->pvariables[PV->RHO][cellId] = rho;
1556 m_cells->pvariables[PV->U][cellId] = vel;
1557 m_cells->pvariables[PV->V][cellId] = F0;
1558 m_cells->pvariables[PV->W][cellId] = F0;
1559 m_cells->pvariables[PV->P][cellId] = pressureCH;
1560 }
1561 }
1562 }
1563
1564 // create the fluctuations:
1565 // this way of creating the
1566 // fluctuations is only possible for
1567 // quite small mounts of cells
1568 // if too large this approach will not work anymore
1569 // 125000000 is a random integer number which has to be tested
1570 // else the approach with white noise will be employed
1571 const MInt totalBlockCells =
1572 (m_grid->getMyBlockNoCells(0) * m_grid->getMyBlockNoCells(1) * m_grid->getMyBlockNoCells(2));
1573
1574 if(totalBlockCells <= 12500000) {
1575 fftw_complex *uPhysField, *vPhysField, *wPhysField;
1576
1577 // we need the total number of points
1578 MInt lx = m_grid->getMyBlockNoCells(2), ly = m_grid->getMyBlockNoCells(1), lz = m_grid->getMyBlockNoCells(0);
1579
1580 // field of velocities from positve frequencies
1581 uPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
1582 vPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
1583 wPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
1584
1585 // no real parallel computation is done
1586 // should be implemented later !!!!
1587
1588 if(noDomains() > 1) {
1589 MFloatScratchSpace sendRecvBufferU(lx * ly * lz, AT_, "sendRecvBufferU");
1590 MFloatScratchSpace sendRecvBufferV(lx * ly * lz, AT_, "sendRecvBufferV");
1591 MFloatScratchSpace sendRecvBufferW(lx * ly * lz, AT_, "sendRecvBufferW");
1592 if(domainId() == 0) {
1593 MInt m_noPeakModes = 100;
1594 initFFTW(uPhysField, vPhysField, wPhysField, lx, ly, lz, m_noPeakModes);
1595 // copy values into the sendRCVbuffer
1596
1597 for(MInt id = 0; id < lz * ly * lz; id++) {
1598 sendRecvBufferU[id] = uPhysField[id][0];
1599 sendRecvBufferV[id] = vPhysField[id][0];
1600 sendRecvBufferW[id] = wPhysField[id][0];
1601 }
1602 }
1603 MPI_Bcast(&sendRecvBufferU[0], lx * ly * lz, MPI_DOUBLE, 0, m_StructuredComm, AT_, "sendRecvBufferU[0]");
1604 MPI_Bcast(&sendRecvBufferV[0], lx * ly * lz, MPI_DOUBLE, 0, m_StructuredComm, AT_, "sendRecvBufferV[0]");
1605 MPI_Bcast(&sendRecvBufferW[0], lx * ly * lz, MPI_DOUBLE, 0, m_StructuredComm, AT_, "sendRecvBufferW[0]");
1606
1607 if(domainId() != 0) {
1608 for(MInt id = 0; id < lz * ly * lz; id++) {
1609 uPhysField[id][0] = sendRecvBufferU[id];
1610 vPhysField[id][0] = sendRecvBufferV[id];
1611 wPhysField[id][0] = sendRecvBufferW[id];
1612 }
1613 }
1614 } else {
1615 // create velocity field
1616 MInt m_noPeakModes = 100;
1617 initFFTW(uPhysField, vPhysField, wPhysField, lx, ly, lz, m_noPeakModes);
1618 }
1619 // now we need to distribute the
1620 } else {
1621 MFloat amp = 0.15;
1622 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
1623 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
1624 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
1625 cellId = cellIndex(i, j, k);
1626 m_cells->pvariables[PV->V][cellId] +=
1627 amp * 2.0 * (0.5 - (1.0 * rand() / (RAND_MAX + 1.0))) * m_cells->pvariables[PV->U][cellId];
1628 m_cells->pvariables[PV->W][cellId] +=
1629 amp * 2.0 * (0.5 - (1.0 * rand() / (RAND_MAX + 1.0))) * m_cells->pvariables[PV->U][cellId];
1630 m_cells->pvariables[PV->U][cellId] +=
1631 amp * 2.0 * (0.5 - (1.0 * rand() / (RAND_MAX + 1.0))) * m_cells->pvariables[PV->U][cellId];
1632 }
1633 }
1634 }
1635 }
1636
1637 break;
1638 }
1639 case 79092: {
1640 // approximate mean turbulent boundary layer profile
1641 const MFloat epss = 1e-10;
1642 const MFloat reTheta = 1000.000;
1643 const MFloat theta = 1.0;
1644 const MFloat delta0 = 72.0 / 7.0 * theta;
1645 const MFloat kappa = 0.4;
1646 const MFloat C1 = 3.573244189003983;
1647 const MFloat PI1 = 0.55;
1648 const MFloat cf = 0.024 / pow(reTheta, 0.25);
1649 const MFloat uTau = sqrt(cf / 2.0) * PV->UInfinity;
1650 const MFloat nu = SUTHERLANDLAW(PV->TInfinity);
1651 for(MInt k = 0; k < m_nCells[0]; k++) {
1652 for(MInt j = 0; j < m_nCells[1]; j++) {
1653 for(MInt i = 0; i < m_nCells[2]; i++) {
1654 const MInt cellId = cellIndex(i, j, k);
1655 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1656 const MFloat y = m_cells->coordinates[1][cellId];
1657 MFloat yPlus = mMax(uTau * y * m_Re0 / nu, F0);
1658
1659 if(y > delta0) {
1660 m_cells->pvariables[PV->U][cellId] = PV->UInfinity;
1661 } else if(yPlus <= 10.0) {
1662 m_cells->pvariables[PV->U][cellId] = yPlus * uTau;
1663 } else if(yPlus <= 30 && yPlus > 10.0) {
1664 m_cells->pvariables[PV->U][cellId] = uTau * ((F1 / kappa) * log(max(yPlus, epss)) + C1);
1665 } else if(yPlus > 30.0 && y <= delta0) {
1666 m_cells->pvariables[PV->U][cellId] =
1667 uTau
1668 * ((F1 / kappa) * log(max(yPlus, epss)) + C1 + 2 * (PI1 / kappa) * (3 * y * y - 2 * y * y * y));
1669 }
1670
1671 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
1672 m_cells->pvariables[PV->W][cellId] = PV->WInfinity;
1673 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1674 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
1675
1676 if(m_rans) {
1677 m_cells->pvariables[PV->RANS_VAR[0]][cellId] = PV->ransInfinity[0];
1678 }
1679 }
1680 }
1681 }
1682
1683 break;
1684 }
1685
1686 case 79091: // Turbulent plate
1687 {
1688 const MFloat epss = 1e-10;
1689 const MFloat reTheta = 1000.0;
1690 const MFloat theta = 1.0;
1691 const MFloat delta0 = 72.0 / 7.0 * theta;
1692 const MFloat K = 0.4;
1693 const MFloat C1 = 3.573244189003983; // With coles
1694 const MFloat PI1 = 0.55;
1695 const MFloat cf = 0.024 / pow(reTheta, 0.25);
1696
1697 for(MInt k = 0; k < m_nCells[0]; k++) {
1698 for(MInt j = 0; j < m_nCells[1]; j++) {
1699 for(MInt i = 0; i < m_nCells[2]; i++) {
1700 const MInt cellId = cellIndex(i, j, k);
1701 const MFloat mu = SUTHERLANDLAW(PV->TInfinity);
1702 const MFloat utau = sqrt(cf / 2.0) * m_Ma * sqrt(PV->TInfinity);
1703 const MFloat yplus = m_cells->coordinates[1][cellId] * sqrt(cf / 2.) * CV->rhoUInfinity / mu * m_Re0;
1704 const MFloat eta = m_cells->coordinates[1][cellId] / delta0; // y/delta
1705
1706 // 1-7th profile
1707 // log-law + wake
1708 if(m_cells->coordinates[1][cellId] > delta0) {
1709 m_cells->pvariables[PV->U][cellId] = PV->UInfinity; // Outside BL
1710 } else if(yplus < 10) {
1711 m_cells->pvariables[PV->U][cellId] = utau * yplus;
1712 } else {
1713 m_cells->pvariables[PV->U][cellId] = mMin(
1714 utau
1715 * ((1. / K) * log(max(yplus, epss)) + C1 + 2 * PI1 / K * (3 * eta * eta - 2 * eta * eta * eta)),
1716 PV->UInfinity);
1717 }
1718
1719 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
1720 m_cells->pvariables[PV->W][cellId] = PV->WInfinity;
1721 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1722 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
1723
1724 if(m_rans) {
1725 m_cells->pvariables[PV->RANS_VAR[0]][cellId] = PV->ransInfinity[0];
1726 }
1727 }
1728 }
1729 }
1730
1731 break;
1732 }
1733 case 11: // point source in the middle
1734 {
1735 // contain an initial perturbation in the middle
1736 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
1737 // go through every cell
1738 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity;
1739 for(MInt i = 0; i < nDim; i++) {
1740 m_cells->pvariables[PV->VV[i]][cellid] = PV->VVInfinity[i];
1741 }
1742
1743 MFloat amp = 0.0001;
1744 MFloat x = m_cells->coordinates[0][cellid];
1745 MFloat y = m_cells->coordinates[1][cellid];
1746 MFloat z = m_cells->coordinates[2][cellid];
1747 MFloat r = 0.025;
1748 MFloat a1 = POW2(x - 0.5);
1749 MFloat a2 = POW2(y - 0.5);
1750 MFloat a3 = POW2(z - 0.5);
1751 MFloat disturb = amp * exp(-(a1 + a2 + a3) / POW2(r) / 2.0);
1752 m_cells->pvariables[PV->P][cellid] = PV->PInfinity + disturb;
1753 }
1754 break;
1755 }
1756 /* TESTCASE from C. Bogey, C. Bailly, Three-dimensional non-reflective boundary conditions
1757 * for acoustic simulations: far field formulation and validation test cases
1758 * Acta acustica united with acustica Volume 88 (2002), 463-471
1759 */
1760 case 111: {
1761 MFloat amp = 0.01;
1762 MFloat alpha = log(2) / 9;
1763 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
1764 // go through every cell
1765 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity;
1766 MFloat x = m_cells->coordinates[0][cellid];
1767 MFloat y = m_cells->coordinates[1][cellid];
1768 MFloat z = m_cells->coordinates[2][cellid];
1769 MFloat fluc = amp * exp(-alpha * (POW2(x) + POW2(y) + POW2(z)));
1770 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity + fluc;
1771 m_cells->pvariables[PV->P][cellid] = (PV->PInfinity + fluc);
1772 for(MInt i = 0; i < nDim; i++) {
1773 m_cells->pvariables[PV->VV[i]][cellid] = PV->VVInfinity[i];
1774 }
1775 }
1776 break;
1777 }
1778 /* TESTCASE from C. Bogey, C. Bailly, Three-dimensional non-reflective boundary conditions
1779 * for acoustic simulations: far field formulation and validation test cases
1780 * Acta acustica united with acustica Volume 88 (2002), 463-471 the vortex
1781 */
1782 case 112: {
1783 MFloat amp = 0.003;
1784 MFloat b = 0.025;
1785 MFloat alpha = log(2) / POW2(b);
1786 MFloat r0 = 0.1; // changed!!!
1787 MFloat r = F0;
1788 MFloat phi = F0;
1789 MFloat v = F0;
1790 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
1791 // go through every cell
1792 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1793 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
1794 m_cells->pvariables[PV->U][cellId] = PV->UInfinity;
1795 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
1796 m_cells->pvariables[PV->W][cellId] = PV->WInfinity;
1797 MFloat x = m_cells->coordinates[0][cellId] - 0.5;
1798 MFloat y = m_cells->coordinates[1][cellId] - 0.5;
1799 MFloat z = m_cells->coordinates[2][cellId] - 0.25;
1800 r = sqrt(POW2(y) + POW2(z));
1801 phi = atan(z / y);
1802 m_cells->pvariables[PV->U][cellId] +=
1803 amp * (r0 / r) * (r - r0) * exp(-1.0 * alpha * (POW2(x) + POW2(r - r0)));
1804 v = -1.0 * amp * (r0 / r) * x * exp(-1.0 * alpha * (POW2(x) + POW2(r - r0)));
1805 m_cells->pvariables[PV->V][cellId] += v * r * sin(phi);
1806 m_cells->pvariables[PV->W][cellId] += v * r * cos(phi);
1807 }
1808 break;
1809 }
1810 case 113: {
1811 MFloat amp = 0.003;
1812 MFloat b = 0.25 / 4;
1813 MFloat alpha = log(2) / POW2(b);
1814 MFloat r0 = 0.25; // changed!!!
1815 MFloat r = F0;
1816 MFloat phi = F0;
1817 MFloat v = F0;
1818 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
1819 // go through every cell
1820 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1821 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
1822 m_cells->pvariables[PV->U][cellId] = PV->UInfinity;
1823 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
1824 m_cells->pvariables[PV->W][cellId] = PV->WInfinity;
1825 MFloat x = m_cells->coordinates[0][cellId] + 0.5;
1826 MFloat y = m_cells->coordinates[1][cellId];
1827 MFloat z = m_cells->coordinates[2][cellId] - 0.25;
1828 r = sqrt(POW2(y) + POW2(z));
1829 phi = atan(z / y);
1830 m_cells->pvariables[PV->U][cellId] +=
1831 amp * (r0 / r) * (r - r0) * exp(-1.0 * alpha * (POW2(x) + POW2(r - r0)));
1832 v = -1.0 * amp * (r0 / r) * x * exp(-1.0 * alpha * (POW2(x) + POW2(r - r0)));
1833 m_cells->pvariables[PV->V][cellId] += v * r * sin(phi);
1834 m_cells->pvariables[PV->W][cellId] += v * r * cos(phi);
1835 }
1836 break;
1837 }
1838 case 2: // shear flow is prescribed
1839 {
1840 MInt cellId = 0;
1841 MFloat x = F0;
1842 for(MInt k = 0; k < m_nCells[0]; k++) {
1843 for(MInt j = 0; j < m_nCells[1]; j++) {
1844 for(MInt i = 0; i < m_nCells[2]; i++) {
1845 cellId = cellIndex(i, j, k);
1846 x = m_cells->coordinates[0][cellId];
1847 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1848 if(x < 0.5) {
1849 m_cells->pvariables[PV->U][cellId] = F0;
1850 m_cells->pvariables[PV->V][cellId] = 0.5 * PV->UInfinity;
1851 m_cells->pvariables[PV->W][cellId] = F0;
1852 } else {
1853 m_cells->pvariables[PV->U][cellId] = F0;
1854 m_cells->pvariables[PV->V][cellId] = PV->UInfinity;
1855 m_cells->pvariables[PV->W][cellId] = F0;
1856 }
1857 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
1858 }
1859 }
1860 }
1861 break;
1862 }
1863 case 900: { // jet Freund
1864 for(MInt k = 0; k < m_nCells[0]; k++) {
1865 for(MInt j = 0; j < m_nCells[1]; j++) {
1866 for(MInt i = 0; i < m_nCells[2]; i++) {
1867 MInt cellId = cellIndex(i, j, k);
1868 MFloat r = sqrt(POW2(m_cells->coordinates[0][cellId]) + POW2(m_cells->coordinates[1][cellId])
1869 + POW2(m_cells->coordinates[2][cellId]));
1870 MFloat u = F1B2 * (F1 - tanh(12.5 * (fabs(r / 0.5) - fabs(0.5 / r)))) * PV->VVInfinity[0];
1871 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1872 m_cells->pvariables[PV->U][cellId] = u;
1873 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
1874 m_cells->pvariables[PV->W][cellId] = PV->WInfinity;
1875 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
1876 }
1877 }
1878 }
1879 break;
1880 }
1881 case 4001: { // test periodic rotation boundary conditions
1882 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
1883 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; ++j) {
1884 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; ++i) {
1885 MInt cellId = cellIndex(i, j, k);
1886 // MFloat x= m_cells->coordinates[0][cellId];
1887 MFloat y = m_cells->coordinates[1][cellId];
1888 MFloat z = m_cells->coordinates[2][cellId];
1889 MFloat phi = atan2(y, z);
1890 MFloat r = sqrt(POW2(y) + POW2(z));
1891 MFloat rmax = 10.0;
1892 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1893 m_cells->pvariables[PV->U][cellId] = PV->UInfinity;
1894 m_cells->pvariables[PV->V][cellId] = -(r / rmax) * cos(phi) * 0.1 * PV->UInfinity;
1895 m_cells->pvariables[PV->W][cellId] = (r / rmax) * sin(phi) * 0.1 * PV->UInfinity;
1896 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
1897 }
1898 }
1899 }
1900 break;
1901 }
1902 case 42: {
1903 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
1904 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1905 m_cells->pvariables[PV->V][cellId] = F0;
1906 m_cells->pvariables[PV->W][cellId] = F0;
1907
1908 if(m_cells->coordinates[1][cellId] < 0.5) {
1909 m_cells->pvariables[PV->U][cellId] = 1.001 * PV->UInfinity;
1910 } else {
1911 m_cells->pvariables[PV->U][cellId] = 0.999 * PV->UInfinity;
1912 }
1913
1914 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
1915 }
1916 break;
1917 }
1918 case 44: {
1919 MFloat amp = 0.003;
1920 MFloat b = 0.25 / 4;
1921 MFloat alpha = log(2) / POW2(b);
1922 MFloat r0 = 0.25; // changed!!!
1923 MFloat r = F0;
1924 MFloat phi = F0;
1925 MFloat v = F0;
1926 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
1927 // go through every cell
1928 m_cells->pvariables[PV->RHO][cellId] = CV->rhoInfinity;
1929 m_cells->pvariables[PV->P][cellId] = PV->PInfinity;
1930 m_cells->pvariables[PV->U][cellId] = PV->UInfinity;
1931 m_cells->pvariables[PV->V][cellId] = PV->VInfinity;
1932 m_cells->pvariables[PV->W][cellId] = PV->WInfinity;
1933 MFloat x = m_cells->coordinates[0][cellId] - 0.61;
1934 MFloat y = m_cells->coordinates[1][cellId] - 0.55;
1935 MFloat z = m_cells->coordinates[2][cellId] - 0.43;
1936 r = sqrt(POW2(y) + POW2(z));
1937 phi = atan(z / y);
1938 m_cells->pvariables[PV->U][cellId] +=
1939 amp * (r0 / mMax(r, 0.00001)) * (r - r0) * exp(-1.0 * alpha * (POW2(x) + POW2(r - r0)));
1940 v = -1.0 * amp * (r0 / mMax(r, 0.00001)) * x * exp(-1.0 * alpha * (POW2(x) + POW2(r - r0)));
1941 m_cells->pvariables[PV->V][cellId] += v * r * sin(phi);
1942 m_cells->pvariables[PV->W][cellId] += v * r * cos(phi);
1943 }
1944 break;
1945 }
1946 case 777: {
1947 // fsc
1948 m_log << "falkner skan cooke initial condition (incompressible)" << endl;
1949 if(!m_fsc) mTerm(1, "property fsc not set. Refer to the description of the property");
1950 if(true && !domainId()) {
1951 ofstream fscf;
1952 // write pressure to file
1953 fscf.open("pressure.dat", ios::trunc);
1954 if(fscf) {
1955 fscf << "#x_maia x_fsc p" << endl;
1956 for(MInt i = 0; i < 95; i++) {
1957 const MFloat x = i * F1;
1958 fscf << x << " " << m_fsc_x0 + x << " " << getFscPressure(x) / PV->PInfinity << endl;
1959 }
1960 fscf.close();
1961 }
1962 // write velocity to file
1963 fscf.open("velocity_x0.dat", ios::trunc);
1964 if(fscf) {
1965 fscf << "#y eta u v w" << endl;
1966 for(MInt i = 0; i < 200; i++) {
1967 // coord
1968 const MFloat y = i * 0.05;
1969 fscf << y << " " << getFscEta(F0, y);
1970 // velocity
1971 MFloat vel[nDim];
1972 getFscVelocity(F0, y, vel);
1973 for(MInt dim = 0; dim < nDim; dim++)
1974 fscf << " " << vel[dim] / PV->UInfinity;
1975 fscf << endl;
1976 }
1977
1978 fscf.close();
1979 }
1980 }
1981
1982 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
1983 MFloat vel[nDim];
1984 getFscVelocity(cellid, vel);
1985 for(MInt i = 0; i < nDim; i++) {
1986 m_cells->pvariables[PV->VV[i]][cellid] = vel[i];
1987 }
1988 m_cells->pvariables[PV->P][cellid] = getFscPressure(cellid);
1989 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity;
1990 }
1991
1992 break;
1993 }
1994 case 999: {
1995 // blasius laminar bl
1996 m_log << "Blasius initial condition (incompressible)" << endl;
1997 if(!m_useBlasius) mTerm(1, "property Blasius not set. Refer to the description of the property");
1998 if(domainId() == 0) {
1999 ofstream blasiusf;
2000 // write velocity to file
2001 blasiusf.open("velocity_x0.dat", ios::trunc);
2002 if(blasiusf) {
2003 blasiusf << "#y eta u v" << endl;
2004 MFloat d0 = 0.0;
2005 MFloat d1 = 0.0;
2006 MFloat d2 = 0.0;
2007 MBool d0Set = false;
2008
2009 for(MInt i = 0; i < m_blasius_noPoints; i++) {
2010 // coord
2011 const MFloat y = i * 0.05;
2012 blasiusf << y << " " << getBlasiusEta(F0, y);
2013 // velocity
2014 MFloat vel[nDim];
2015 getBlasiusVelocity(F0, y, vel);
2016 for(MInt dim = 0; dim < nDim; dim++)
2017 blasiusf << " " << vel[dim] / PV->UInfinity;
2018 blasiusf << endl;
2019
2020 if(!d0Set && vel[0] >= 0.99 * PV->UInfinity) {
2021 d0 = y;
2022 d0Set = true;
2023 }
2024
2025 if(y < 10.0) {
2026 d1 += (1 - vel[0] / PV->UInfinity) * 0.05;
2027 d2 += vel[0] / PV->UInfinity * (1 - vel[0] / PV->UInfinity) * 0.05;
2028 }
2029 }
2030 blasiusf.close();
2031
2032 cout << "x0: " << m_blasius_x0 << endl;
2033 cout << "d0: " << d0 << " d1: " << d1 << " d2: " << d2 << endl;
2034 }
2035 }
2036
2037 for(MInt cellid = 0; cellid < m_noCells; cellid++) {
2038 MFloat vel[nDim];
2039 getBlasiusVelocity(cellid, vel);
2040 for(MInt i = 0; i < nDim; i++) {
2041 m_cells->pvariables[PV->VV[i]][cellid] = vel[i];
2042 }
2043 m_cells->pvariables[PV->P][cellid] = PV->PInfinity;
2044 m_cells->pvariables[PV->RHO][cellid] = CV->rhoInfinity;
2045 }
2046
2047 break;
2048 }
2049 default: {
2050 // put the parallel flow field input in here
2051 // force output that no specific initial condition was chosen
2052 mTerm(1, AT_, "No (correct) initial Condition is given!");
2053 break;
2054 }
2055 }
2056 }
2057}
2058
2059
2064 TRACE();
2065 if(!m_movingGrid) {
2067 make_unique<StructuredInterpolation<3>>(m_nCells, m_cells->coordinates, m_cells->pvariables, m_StructuredComm);
2068 // allocate domains points of the lines
2072 MPI_SUM, m_StructuredComm, AT_, "m_intpPointsHasPartnerLocal", "m_intpPointsHasPartnerGlobal");
2073 }
2074}
2075
2076
2078 TRACE();
2079 if(!m_movingGrid) {
2081 make_unique<StructuredInterpolation<3>>(m_nCells, m_cells->coordinates, m_cells->pvariables, m_StructuredComm);
2082
2083 // allocate domains points of the lines
2087 MPI_SUM, m_StructuredComm, AT_, "m_pointsToAsciiHasPartnerLocal", "m_pointsToAsciiHasPartnerGlobal");
2088
2089 for(MInt pointId = 0; pointId < m_pointsToAsciiNoPoints; pointId++) {
2090 cout << "domainId: " << domainId() << " pointId: " << pointId
2091 << " hasPartnerLocal: " << m_pointsToAsciiHasPartnerLocal[pointId]
2092 << " hasPartnerGlobal: " << m_pointsToAsciiHasPartnerGlobal[pointId]
2093 << " x: " << m_pointsToAsciiCoordinates[0][pointId] << " y: " << m_pointsToAsciiCoordinates[1][pointId]
2094 << " z: " << m_pointsToAsciiCoordinates[2][pointId] << endl;
2095 }
2096 }
2097}
2098
2099
2109 if(m_movingGrid) {
2110 for(MInt pointId = 0; pointId < m_pointsToAsciiNoPoints; pointId++) {
2111 m_intpPointsHasPartnerLocal[pointId] = 0;
2112 m_intpPointsHasPartnerGlobal[pointId] = 0;
2113 for(MInt var = 0; var < PV->noVariables; var++) {
2114 m_intpPointsVarsLocal[var][pointId] = F0;
2115 m_intpPointsVarsGlobal[var][pointId] = F0;
2116 }
2117 }
2118
2119 m_pointsToAsciiInterpolation = make_unique<StructuredInterpolation<3>>(m_nCells, m_cells->coordinates,
2121 // allocate domains points of the lines
2125 MPI_SUM, m_StructuredComm, AT_, "m_pointsToAsciiHasPartnerLocal",
2126 "m_pointsToAsciiHasPartnerGlobal");
2127 }
2128
2129 // calculation of interpolated variables only for the points in domain
2130 for(MInt pointId = 0; pointId < m_pointsToAsciiNoPoints; pointId++) {
2132 if(m_pointsToAsciiHasPartnerLocal[pointId]) {
2134 m_pointsToAsciiInterpolation->getInterpolatedVariable(pointId, m_pointsToAsciiVarId);
2135 }
2136 }
2137
2139 MPI_SUM, m_StructuredComm, AT_, "m_pointsToAsciiVars[0][0]", "m_pointsToAsciiVars[0][0]");
2140
2141 for(MInt pointId = 0; pointId < m_pointsToAsciiNoPoints; pointId++) {
2142 if(m_pointsToAsciiHasPartnerGlobal[pointId] > 1) {
2144 }
2145 }
2146
2150
2153 }
2154
2155
2158 if(domainId() == 0) {
2159 cout << "globalTimeStep: " << globalTimeStep << " writing point data out to ascii file" << endl;
2160 MString filename = "./pointVars.dat";
2161 FILE* f_forces;
2162 f_forces = fopen(filename.c_str(), "a+");
2163
2164 for(MInt j = 0; j < m_pointsToAsciiCounter; j++) {
2165 fprintf(f_forces, "%d", (MInt)m_pointsToAsciiVars[j][0]);
2166 fprintf(f_forces, " %.8f", m_pointsToAsciiVars[j][1]);
2167 fprintf(f_forces, " %.8f", m_pointsToAsciiVars[j][2]);
2168 for(MInt i = 0; i < m_pointsToAsciiNoPoints; i++) {
2169 fprintf(f_forces, " %.8f", m_pointsToAsciiVars[j][3 + i]);
2170 }
2171 fprintf(f_forces, "\n");
2172 }
2173 fclose(f_forces);
2174 }
2175
2178 }
2179}
2180
2181
2203 MBool interpolationCorrection = false;
2204 if(Context::propertyExists("interpolationCorrection", m_solverId)) {
2205 interpolationCorrection =
2206 Context::getSolverProperty<MBool>("interpolationCorrection", m_solverId, AT_, &interpolationCorrection);
2207 }
2208 if(m_nOffsetCells[1] == 0 && m_rans && interpolationCorrection) {
2209 cout << "Correcting interpolation" << endl;
2210 for(MInt i = 0; i < m_nCells[2]; i++) {
2211 for(MInt k = 0; k < m_nCells[0]; k++) {
2212 MInt cellIdA1 = cellIndex(i, 2, k);
2213 MInt cellIdA2 = cellIndex(i, 3, k);
2214 MInt cellIdA3 = cellIndex(i, 4, k);
2215
2216 for(MInt var = 0; var < PV->noVariables; var++) {
2217 m_cells->pvariables[var][cellIdA1] =
2218 m_cells->pvariables[var][cellIdA2]
2219 + (m_cells->coordinates[1][cellIdA1] - m_cells->coordinates[1][cellIdA2])
2220 / (m_cells->coordinates[1][cellIdA2] - m_cells->coordinates[1][cellIdA3])
2221 * (m_cells->variables[var][cellIdA2] - m_cells->pvariables[var][cellIdA3]);
2222 }
2223 }
2224 }
2225 }
2226}
2227
2228
2234 TRACE();
2235 static MBool deviateAvailable = false; // flag
2236 static float storedDeviate; // deviate from previous calculation
2237 MFloat polar, rsquared, var1, var2;
2238
2239 // If no deviate has been stored, the polar Box-Muller transformation is
2240 // performed, producing two independent normally-distributed random
2241 // deviates. One is stored for the next round, and one is returned.
2242 if(!deviateAvailable) {
2243 // choose pairs of uniformly distributed deviates, discarding those
2244 // that don't fall within the unit circle
2245 do {
2246 var1 = 2.0 * (MFloat(rand()) / MFloat(RAND_MAX)) - 1.0;
2247 var2 = 2.0 * (MFloat(rand()) / MFloat(RAND_MAX)) - 1.0;
2248 rsquared = var1 * var1 + var2 * var2;
2249 } while(rsquared >= 1.0 || approx(rsquared, F0, m_eps));
2250
2251 // calculate polar tranformation for each deviate
2252 polar = sqrt(-2.0 * log(rsquared) / rsquared);
2253
2254 // store first deviate and set flag
2255 storedDeviate = var1 * polar;
2256 deviateAvailable = true;
2257
2258 // return second deviate
2259 return var2 * polar * sigma + mu;
2260
2261 // If a deviate is available from a previous call to this function, it is
2262 // eturned, and the flag is set to false.
2263 } else {
2264 deviateAvailable = false;
2265 return storedDeviate * sigma + mu;
2266 }
2267}
2268
2270 TRACE();
2271 m_structuredBndryCnd->applyNonReflectingBC();
2272}
2273
2275 TRACE();
2276 // treat Dirichlet and Neumann BC in one go!!!
2277 m_structuredBndryCnd->applyDirichletNeumannBC();
2278}
2279
2280
2282
2283
2285 TRACE();
2286 // stencil identifier
2287 const MInt IJK[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
2288 // switch for order
2289 const MInt sword = 2;
2290
2291 // reduce to onedimensional arrays
2292 MFloat* __restrict x = &m_cells->coordinates[0][0];
2293 MFloat* __restrict y = &m_cells->coordinates[1][0];
2294 MFloat* __restrict z = &m_cells->coordinates[2][0];
2295 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
2296
2297 const MUint noCells = m_noCells;
2298 const MFloat* const RESTRICT cellVariables = ALIGNED_F(m_cells->pvariables[0]);
2299
2300 for(MInt dim = 0; dim < nDim; ++dim) {
2301 for(MInt k = m_noGhostLayers - 1; k < m_nCells[0] - m_noGhostLayers; ++k) {
2302 for(MInt j = m_noGhostLayers - 1; j < m_nCells[1] - m_noGhostLayers; ++j) {
2303 for(MInt i = m_noGhostLayers - 1; i < m_nCells[2] - m_noGhostLayers; ++i) {
2304 // cell ids
2305 const MInt I = cellIndex(i, j, k);
2306 const MInt IP1 = I + IJK[dim];
2307 const MInt IM1 = I - IJK[dim];
2308 const MInt IP2 = I + 2 * IJK[dim];
2309
2310 // distances q_i+1 - q_i
2311 const MFloat DS = sqrt(POW2(x[IP1] - x[I]) + POW2(y[IP1] - y[I]) + POW2(z[IP1] - z[I]));
2312 // distances q_i - q_i-1
2313 const MFloat DSM1 = sqrt(POW2(x[I] - x[IM1]) + POW2(y[I] - y[IM1]) + POW2(z[I] - z[IM1]));
2314 const MFloat DSP1 = sqrt(POW2(x[IP2] - x[IP1]) + POW2(y[IP2] - y[IP1]) + POW2(z[IP2] - z[IP1]));
2315 const MFloat DSP = DS / POW2(DSP1 + DS);
2316 const MFloat DSM = DS / POW2(DSM1 + DS);
2317
2318 if(sword == 2) {
2319 for(MInt var = 0; var < PV->noVariables; ++var) {
2320 const MUint offset = var * noCells;
2321 const MFloat* const RESTRICT vars = ALIGNED_F(cellVariables + offset);
2322
2323 const MFloat DQ = vars[IP1] - vars[I];
2324 const MFloat DQP1 = vars[IP2] - vars[IP1];
2325 const MFloat DQM1 = vars[I] - vars[IM1];
2326
2327 const MFloat ri = DQM1 / DQ;
2328 const MFloat rip = DQ / DQP1;
2329
2330 const MFloat phii = mMax(F0, mMin(F1, ri));
2331 const MFloat phiip = mMax(F0, mMin(F1, rip));
2332
2333 m_QLeft[var] = vars[I] + (DQ * DSM1 + DQM1 * DS) * DSM * phii;
2334 m_QRight[var] = vars[IP1] - (DQP1 * DS + DQ * DSP1) * DSP * phiip;
2335 }
2336 }
2337
2338 AusmLES(m_QLeft, m_QRight, dim, I);
2339 }
2340 }
2341 }
2342
2343 // FLUX BALANCE
2344 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
2345 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; ++j) {
2346 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; ++i) {
2347 const MInt I = cellIndex(i, j, k);
2348 const MInt IM1 = I - IJK[dim];
2349
2350 for(MInt v = 0; v < CV->noVariables; ++v) {
2351 m_cells->rightHandSide[v][I] += flux[v][IM1] - flux[v][I];
2352 }
2353 }
2354 }
2355 }
2356 }
2357}
2358
2359// Muscl reconstruction with Albada limiter
2361 TRACE();
2362 // stencil identifier
2363 const MInt IJK[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
2364
2365 // reduce to onedimensional arrays
2366 MFloat* RESTRICT x = &m_cells->coordinates[0][0];
2367 MFloat* RESTRICT y = &m_cells->coordinates[1][0];
2368 MFloat* RESTRICT z = &m_cells->coordinates[2][0];
2369 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
2370 MFloat** RESTRICT pvars = m_cells->pvariables;
2371
2373 // MFloat epsi=F1;
2374 // MFloat kappa=F1B3;
2376 for(MInt dim = 0; dim < nDim; dim++) {
2377 for(MInt k = m_noGhostLayers - 1; k < m_nCells[0] - m_noGhostLayers; k++) {
2378 for(MInt j = m_noGhostLayers - 1; j < m_nCells[1] - m_noGhostLayers; j++) {
2379 for(MInt i = m_noGhostLayers - 1; i < m_nCells[2] - m_noGhostLayers; i++) {
2380 // cell ids
2381 const MInt I = cellIndex(i, j, k);
2382 const MInt IP1 = I + IJK[dim];
2383 const MInt IM1 = I - IJK[dim];
2384 const MInt IP2 = I + 2 * IJK[dim];
2385
2386 // distances q_i+1 - q_i
2387 const MFloat DS = sqrt(POW2(x[IP1] - x[I]) + POW2(y[IP1] - y[I]) + POW2(z[IP1] - z[I]));
2388 // distances q_i - q_i-1
2389 const MFloat DSM1 = sqrt(POW2(x[I] - x[IM1]) + POW2(y[I] - y[IM1]) + POW2(z[I] - z[IM1]));
2390 const MFloat DSP1 = sqrt(POW2(x[IP2] - x[IP1]) + POW2(y[IP2] - y[IP1]) + POW2(z[IP2] - z[IP1]));
2391 const MFloat DSP = DS / POW2(DSP1 + DS);
2392 const MFloat DSM = DS / POW2(DSM1 + DS);
2393
2394 const MFloat pIM2 = pvars[PV->P][IM1];
2395 const MFloat pIM1 = pvars[PV->P][I];
2396 const MFloat pIP2 = pvars[PV->P][IP2];
2397 const MFloat pIP1 = pvars[PV->P][IP1];
2398
2399 const MFloat smps = DS * DSP1;
2400 const MFloat dummy = fabs(pIM2 - F2 * pIM1 + pIP1) / (pIM2 + F2 * pIM1 + pIP1);
2401 const MFloat dummy1 = fabs(pIM1 - F2 * pIP1 + pIP2) / (pIM1 + F2 * pIP1 + pIP2);
2402 const MFloat psi = mMin(F1, F6 * mMax(dummy, dummy1));
2403 const MFloat epsLim = mMax(m_eps, pow(F1B2 * smps, F5));
2404
2405 for(MInt var = 0; var < PV->noVariables; ++var) {
2406 const MFloat DQ = pvars[var][IP1] - pvars[var][I];
2407 const MFloat DQP1 = pvars[var][IP2] - pvars[var][IP1];
2408 const MFloat DQM1 = pvars[var][I] - pvars[var][IM1];
2409 const MFloat phi =
2410 F1B2
2411 - (F1B2
2412 - mMax(F0, (DQP1 * DQM1 * smps + F1B2 * epsLim) / (POW2(DQP1 * DS) + POW2(DQM1 * DSP1) + epsLim)))
2413 * psi;
2414
2415 m_QLeft[var] = pvars[var][I] + DSM * (DSM1 * DQ + DS * DQM1) * phi;
2416 m_QRight[var] = pvars[var][IP1] - DSP * (DS * DQP1 + DSP1 * DQ) * phi;
2417 }
2418
2419 AusmLES(m_QLeft, m_QRight, dim, I); // Flux balance in AUSM
2420 }
2421 }
2422 }
2423
2424 // FLUX BALANCE
2425 for(MInt v = 0; v < CV->noVariables; v++) {
2426 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
2427 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
2428 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
2429 const MInt I = cellIndex(i, j, k);
2430 const MInt IM1 = I - IJK[dim];
2431 m_cells->rightHandSide[v][I] += flux[v][IM1] - flux[v][I];
2432 }
2433 }
2434 }
2435 }
2436 }
2437}
2438
2439
2453 TRACE();
2454 const MUint noCells = m_noCells;
2455 const MInt IJK[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
2456 // reduce to onedimensional arrays
2457 const MFloat* const RESTRICT x = ALIGNED_F(m_cells->coordinates[0]);
2458 const MFloat* const RESTRICT y = ALIGNED_F(m_cells->coordinates[1]);
2459 const MFloat* const RESTRICT z = ALIGNED_F(m_cells->coordinates[2]);
2460 const MFloat* const RESTRICT cellVariables = ALIGNED_F(m_cells->pvariables[0]);
2461 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
2462
2463 MFloatScratchSpace QLeft(m_noCells, PV->noVariables, 3, AT_, "QLeft");
2464 MFloatScratchSpace QRight(m_noCells, PV->noVariables, 3, AT_, "QRight");
2465 MFloatScratchSpace minPhi(PV->noVariables, 2, AT_, "minPhi");
2466
2467 QLeft.fill(F0);
2468 QRight.fill(F0);
2469
2470 for(MInt k = m_noGhostLayers - 1; k < m_nCells[0] - m_noGhostLayers; k++) {
2471 for(MInt j = m_noGhostLayers - 1; j < m_nCells[1] - m_noGhostLayers; j++) {
2472 for(MInt i = m_noGhostLayers - 1; i < m_nCells[2] - m_noGhostLayers; i++) {
2473 for(MInt var = 0; var < nDim + 2; var++) {
2474 const MUint offset = var * noCells;
2475 const MFloat* const RESTRICT pvars = ALIGNED_F(cellVariables + offset);
2476
2477 MFloat minNghbrDelta = F0;
2478 MFloat maxNghbrDelta = F0;
2479 MFloat effNghbrDelta = F0;
2480
2481 // 1. get the abs min value of the max and min value from the reconstruction neighbours
2482 for(MInt dim1 = 0; dim1 < nDim; dim1++) {
2483 for(MInt rcnstructnNghbr = 0; rcnstructnNghbr < 2; rcnstructnNghbr++) {
2484 const MInt cellId = cellIndex(i, j, k);
2485 const MInt IP1 = cellId + IJK[dim1];
2486 const MInt IM1 = cellId - IJK[dim1];
2487
2488 MFloat rcnstrctnNghbrValue = F0;
2489 if(rcnstructnNghbr == 0) {
2490 rcnstrctnNghbrValue = pvars[IP1]; //(i/j/k)+1
2491 } else {
2492 rcnstrctnNghbrValue = pvars[IM1]; //(i/j/k)-1
2493 }
2494
2495 const MFloat tmpDelta = rcnstrctnNghbrValue - pvars[cellId]; // i
2496 maxNghbrDelta = mMax(maxNghbrDelta, tmpDelta);
2497 minNghbrDelta = mMin(minNghbrDelta, tmpDelta);
2498 }
2499 }
2500
2501 effNghbrDelta = mMin(maxNghbrDelta, abs(minNghbrDelta));
2502
2503 MFloat srfcDelta = F0;
2504 MFloat dxEpsSqr = F1;
2505 for(MInt dim1 = 0; dim1 < nDim; dim1++) {
2506 const MInt cellId = cellIndex(i, j, k);
2507 const MInt IP1 = cellId + IJK[dim1];
2508 const MInt IM1 = cellId - IJK[dim1];
2509
2510 const MFloat DS = sqrt(POW2(x[IP1] - x[cellId]) + POW2(y[IP1] - y[cellId]) + POW2(z[IP1] - z[cellId]));
2511 // distances q_i - q_i-1
2512 const MFloat DSM1 = sqrt(POW2(x[cellId] - x[IM1]) + POW2(y[cellId] - y[IM1]) + POW2(z[cellId] - z[IM1]));
2513 const MFloat DSM = DS / POW2(DSM1 + DS);
2514
2515 // 2. get srfcDelta and compute the minimum phi
2516 const MFloat dx1 =
2517 DSM
2518 * (DSM1 * sqrt(POW2(x[IP1] - x[cellId]) + POW2(y[IP1] - y[cellId]) + POW2(z[IP1] - z[cellId]))
2519 + DS * sqrt(POW2(x[cellId] - x[IM1]) + POW2(y[cellId] - y[IM1]) + POW2(z[cellId] - z[IM1])));
2520 const MFloat DQ =
2521 (pvars[IP1] - pvars[IM1]) / sqrt(POW2(x[IP1] - x[IM1]) + POW2(y[IP1] - y[IM1]) + POW2(z[IP1] - z[IM1]));
2522 srfcDelta += abs(DQ * dx1);
2523 dxEpsSqr *= dx1;
2524 }
2525
2526 MInt cellPos = 0;
2527
2528 // calling limiter function
2529 (this->*Venkatakrishnan_function)(effNghbrDelta, srfcDelta, dxEpsSqr, cellPos, var, minPhi);
2530
2531 minNghbrDelta = F0;
2532 maxNghbrDelta = F0;
2533 effNghbrDelta = F0;
2534
2535 // 1. get the abs min value of the max and min value from the reconstruction neighbours
2536 for(MInt dim1 = 0; dim1 < nDim; dim1++) {
2537 for(MInt rcnstructnNghbr = 0; rcnstructnNghbr < 2; rcnstructnNghbr++) {
2538 const MInt cellId = cellIndex(i, j, k);
2539 const MInt IP1 = cellId + IJK[dim1];
2540 const MInt IP2 = cellId + 2 * IJK[dim1];
2541
2542 MFloat rcnstrctnNghbrValue = F0;
2543 if(rcnstructnNghbr == 0) {
2544 rcnstrctnNghbrValue = pvars[IP2]; //(i/j/k)+2
2545 } else {
2546 rcnstrctnNghbrValue = pvars[cellId]; //(i/j/k)
2547 }
2548
2549 const MFloat tmpDelta = rcnstrctnNghbrValue - pvars[IP1]; //(i/j/k)+1
2550
2551 maxNghbrDelta = mMax(maxNghbrDelta, tmpDelta);
2552 minNghbrDelta = mMin(minNghbrDelta, tmpDelta);
2553 }
2554 }
2555
2556 effNghbrDelta = mMin(maxNghbrDelta, abs(minNghbrDelta));
2557
2558 srfcDelta = F0;
2559 dxEpsSqr = F1;
2560 for(MInt dim1 = 0; dim1 < nDim; dim1++) {
2561 const MInt cellId = cellIndex(i, j, k);
2562 const MInt IP1 = cellId + IJK[dim1];
2563 const MInt IP2 = cellId + 2 * IJK[dim1];
2564
2565 const MFloat DS = sqrt(POW2(x[IP1] - x[cellId]) + POW2(y[IP1] - y[cellId]) + POW2(z[IP1] - z[cellId]));
2566 // distances q_i - q_i-1
2567 const MFloat DSP1 = sqrt(POW2(x[IP2] - x[IP1]) + POW2(y[IP2] - y[IP1]) + POW2(z[IP2] - z[IP1]));
2568 const MFloat DSP = DS / POW2(DSP1 + DS);
2569
2570 // 2. get srfcDelta and compute the minimum phi
2571
2572 const MFloat dx2 =
2573 DSP
2574 * (DS * sqrt(POW2(x[IP2] - x[IP1]) + POW2(y[IP2] - y[IP1]) + POW2(z[IP2] - z[IP1]))
2575 + DSP1 * sqrt(POW2(x[IP1] - x[cellId]) + POW2(y[IP1] - y[cellId]) + POW2(z[IP1] - z[cellId])));
2576 const MFloat DQ = (pvars[IP2] - pvars[cellId])
2577 / sqrt(POW2(x[IP2] - x[cellId]) + POW2(y[IP2] - y[cellId]) + POW2(z[IP2] - z[cellId]));
2578
2579 srfcDelta += abs(DQ * dx2);
2580 dxEpsSqr *= dx2;
2581 }
2582
2583 cellPos = 1;
2584 (this->*Venkatakrishnan_function)(effNghbrDelta, srfcDelta, dxEpsSqr, cellPos, var, minPhi); // calling Venk
2585
2586 for(MInt dim1 = 0; dim1 < nDim; dim1++) {
2587 const MInt cellId = cellIndex(i, j, k);
2588 const MInt IP1 = cellId + IJK[dim1];
2589 const MInt IM1 = cellId - IJK[dim1];
2590 const MInt IP2 = cellId + 2 * IJK[dim1];
2591
2592 const MFloat DS = sqrt(POW2(x[IP1] - x[cellId]) + POW2(y[IP1] - y[cellId]) + POW2(z[IP1] - z[cellId]));
2593 // distances q_i - q_i-1
2594 const MFloat DSM1 = sqrt(POW2(x[cellId] - x[IM1]) + POW2(y[cellId] - y[IM1]) + POW2(z[cellId] - z[IM1]));
2595 const MFloat DSP1 = sqrt(POW2(x[IP2] - x[IP1]) + POW2(y[IP2] - y[IP1]) + POW2(z[IP2] - z[IP1]));
2596 const MFloat DSP = DS / POW2(DSP1 + DS);
2597 const MFloat DSM = DS / POW2(DSM1 + DS);
2598
2599 QLeft(cellId, var, dim1) =
2600 pvars[cellId]
2601 + DSM * (DSM1 * (pvars[IP1] - pvars[cellId]) + DS * (pvars[cellId] - pvars[IM1])) * minPhi(var, 0);
2602 QRight(cellId, var, dim1) =
2603 pvars[IP1]
2604 - DSP * (DS * (pvars[IP2] - pvars[IP1]) + DSP1 * (pvars[IP1] - pvars[cellId])) * minPhi(var, 1);
2605 }
2606 }
2607 }
2608 }
2609 }
2610
2612 for(MInt dim = 0; dim < nDim; dim++) {
2613 for(MInt k = m_noGhostLayers - 1; k < m_nCells[0] - m_noGhostLayers; k++) {
2614 for(MInt j = m_noGhostLayers - 1; j < m_nCells[1] - m_noGhostLayers; j++) {
2615 for(MInt i = m_noGhostLayers - 1; i < m_nCells[2] - m_noGhostLayers; i++) {
2616 // cell ids
2617 const MInt cellId = cellIndex(i, j, k);
2618
2619 for(MInt v = 0; v < PV->noVariables; v++) {
2620 m_QLeft[v] = QLeft(cellId, v, dim);
2621 m_QRight[v] = QRight(cellId, v, dim);
2622 }
2623
2624 AusmLES(m_QLeft, m_QRight, dim, cellId);
2625 }
2626 }
2627 }
2628
2629
2630 // FLUX BALANCE
2631 for(MInt v = 0; v < CV->noVariables; v++) {
2632 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
2633 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
2634 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
2635 const MInt I = cellIndex(i, j, k);
2636 const MInt IM1 = I - IJK[dim];
2637 m_cells->rightHandSide[v][I] += flux[v][IM1] - flux[v][I];
2638 }
2639 }
2640 }
2641 }
2642 }
2643}
2644
2645
2653 MInt cellPos, MInt var, MFloatScratchSpace& minPhi) {
2654 MFloat epsSqr = pow(m_venkFactor, F3) * dxEpsSqr;
2655 minPhi(var, cellPos) = (pow(effNghbrDelta, F2) + epsSqr + F2 * effNghbrDelta * srfcDelta)
2656 / (pow(effNghbrDelta, F2) + F2 * pow(srfcDelta, F2) + effNghbrDelta * srfcDelta + epsSqr);
2657}
2658
2664void FvStructuredSolver3D::VENKATAKRISHNAN_FCT(MFloat effNghbrDelta, MFloat srfcDelta, MFloat dxEpsSqr, MInt cellPos,
2665 MInt var, MFloatScratchSpace& minPhi) {
2666 (void)dxEpsSqr;
2667 const MFloat eps = 1e-12;
2668 MFloat yps1 = effNghbrDelta / (srfcDelta + eps);
2669 minPhi(var, cellPos) = mMin((yps1 * yps1 + F2 * yps1) / (yps1 * yps1 + yps1 + F2), F1);
2670}
2671
2677void FvStructuredSolver3D::BARTH_JESPERSON_FCT(MFloat effNghbrDelta, MFloat srfcDelta, MFloat dxEpsSqr, MInt cellPos,
2678 MInt var, MFloatScratchSpace& minPhi) {
2679 (void)dxEpsSqr;
2680 const MFloat eps = 1e-12;
2681 MFloat phi_max = effNghbrDelta / (srfcDelta + eps);
2682 minPhi(var, cellPos) = mMin(phi_max, F1);
2683}
2684
2690// inline void FvStructuredSolver3D::AusmNew(MFloat* QLeft, MFloat* QRight, const MInt dim, const MInt
2691// cellId)
2692inline void FvStructuredSolver3D::AusmLES(MFloat* RESTRICT QLeft, MFloat* RESTRICT QRight, const MInt dim,
2693 const MInt I) {
2694 // MFloat pFactor[3]={F0,F0,F0};
2695 const MFloat gamma = m_gamma;
2696 const MFloat gammaMinusOne = gamma - 1.0;
2697 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
2698
2699 const MFloat surf0 = m_cells->surfaceMetrics[dim * 3 + 0][I];
2700 const MFloat surf1 = m_cells->surfaceMetrics[dim * 3 + 1][I];
2701 const MFloat surf2 = m_cells->surfaceMetrics[dim * 3 + 2][I];
2702
2703 const MFloat dxdtau = m_cells->dxt[dim][I];
2704
2705 // calculate pressure
2706 const MFloat PL = QLeft[PV->P];
2707 const MFloat UL = QLeft[PV->U];
2708 const MFloat VL = QLeft[PV->V];
2709 const MFloat WL = QLeft[PV->W];
2710 const MFloat RHOL = QLeft[PV->RHO];
2711
2712 const MFloat PR = QRight[PV->P];
2713 const MFloat UR = QRight[PV->U];
2714 const MFloat VR = QRight[PV->V];
2715 const MFloat WR = QRight[PV->W];
2716 const MFloat RHOR = QRight[PV->RHO];
2717
2718 // compute lenght of metric vector for normalization
2719 const MFloat metricLength = sqrt(POW2(surf0) + POW2(surf1) + POW2(surf2));
2720 const MFloat fMetricLength = F1 / metricLength;
2721
2722 // scale by metric length to get velocity in the new basis (get normalized basis vectors)
2723 const MFloat UUL = ((UL * surf0 + VL * surf1 + WL * surf2) - dxdtau) * fMetricLength;
2724
2725
2726 const MFloat UUR = ((UR * surf0 + VR * surf1 + WR * surf2) - dxdtau) * fMetricLength;
2727
2728
2729 // speed of sound
2730 const MFloat AL = sqrt(gamma * mMax(m_eps, PL / mMax(m_eps, RHOL)));
2731 const MFloat AR = sqrt(gamma * mMax(m_eps, PR / mMax(m_eps, RHOR)));
2732
2733 const MFloat MAL = UUL / AL;
2734 const MFloat MAR = UUR / AR;
2735
2736 const MFloat MALR = F1B2 * (MAL + MAR);
2737 const MFloat PLR = PL * (F1B2 + m_chi * MAL) + PR * (F1B2 - m_chi * MAR);
2738
2739 const MFloat RHO_AL = RHOL * AL;
2740 const MFloat RHO_AR = RHOR * AR;
2741
2742 const MFloat PLfRHOL = PL / RHOL;
2743 const MFloat PRfRHOR = PR / RHOR;
2744
2745 const MFloat e0 = PLfRHOL * FgammaMinusOne + 0.5 * (POW2(UL) + POW2(VL) + POW2(WL)) + PLfRHOL;
2746 const MFloat e1 = PRfRHOR * FgammaMinusOne + 0.5 * (POW2(UR) + POW2(VR) + POW2(WR)) + PRfRHOR;
2747
2748 const MFloat RHOU = F1B2 * (MALR * (RHO_AL + RHO_AR) + fabs(MALR) * (RHO_AL - RHO_AR)) * metricLength;
2749 const MFloat RHOU2 = F1B2 * RHOU;
2750 // multiply by metric length to take surface area into account
2751 const MFloat AbsRHO_U2 = fabs(RHOU2);
2752
2753 //==>fluxes:
2754 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
2755 flux[CV->RHO_U][I] = RHOU2 * (UL + UR) + AbsRHO_U2 * (UL - UR) + PLR * surf0;
2756 flux[CV->RHO_V][I] = RHOU2 * (VL + VR) + AbsRHO_U2 * (VL - VR) + PLR * surf1;
2757 flux[CV->RHO_W][I] = RHOU2 * (WL + WR) + AbsRHO_U2 * (WL - WR) + PLR * surf2;
2758 flux[CV->RHO_E][I] = RHOU2 * (e0 + e1) + AbsRHO_U2 * (e0 - e1) + PLR * dxdtau;
2759 flux[CV->RHO][I] = RHOU;
2760}
2761
2762
2771inline void FvStructuredSolver3D::AusmLES_PTHRC(MFloat* QLeft, MFloat* QRight, MInt dim, MInt I) {
2772 const MFloat gamma = m_gamma;
2773 const MFloat FgammaMinusOne = m_fgammaMinusOne;
2774
2775 const MFloat surf0 = m_cells->surfaceMetrics[dim * 3 + 0][I];
2776 const MFloat surf1 = m_cells->surfaceMetrics[dim * 3 + 1][I];
2777 const MFloat surf2 = m_cells->surfaceMetrics[dim * 3 + 2][I];
2778
2779 const MFloat* const RESTRICT p = ALIGNED_F(m_cells->pvariables[PV->P]);
2780
2781 const MFloat dxdtau = m_cells->dxt[dim][I];
2782
2783 // calculate pressure
2784 const MFloat PL = QLeft[PV->P];
2785 const MFloat UL = QLeft[PV->U];
2786 const MFloat VL = QLeft[PV->V];
2787 const MFloat WL = QLeft[PV->W];
2788 const MFloat RHOL = QLeft[PV->RHO];
2789
2790 const MFloat PR = QRight[PV->P];
2791 const MFloat UR = QRight[PV->U];
2792 const MFloat VR = QRight[PV->V];
2793 const MFloat WR = QRight[PV->W];
2794 const MFloat RHOR = QRight[PV->RHO];
2795
2796 // compute lenght of metric vector for normalization
2797 const MFloat metricLength = sqrt(POW2(surf0) + POW2(surf1) + POW2(surf2));
2798 const MFloat fMetricLength = F1 / metricLength;
2799
2800 // scale by metric length to get velocity in the new basis (get normalized basis vectors)
2801 const MFloat UUL = ((UL * surf0 + VL * surf1 + WL * surf2) - dxdtau) * fMetricLength;
2802
2803
2804 const MFloat UUR = ((UR * surf0 + VR * surf1 + WR * surf2) - dxdtau) * fMetricLength;
2805
2806 // speed of sound
2807 const MFloat AL = sqrt(gamma * mMax(m_eps, PL / mMax(m_eps, RHOL)));
2808 const MFloat AR = sqrt(gamma * mMax(m_eps, PR / mMax(m_eps, RHOR)));
2809
2810 const MFloat MAL = UUL / AL;
2811 const MFloat MAR = UUR / AR;
2812
2813 const MFloat MALR = F1B2 * (MAL + MAR);
2814
2815 // 4th order pressure damping
2816 const MInt IPJK = getCellIdfromCell(I, 1, 0, 0);
2817 const MInt IMJK = getCellIdfromCell(I, -1, 0, 0);
2818 const MInt IP2JK = getCellIdfromCell(I, 2, 0, 0);
2819 const MInt IM2JK = getCellIdfromCell(I, -2, 0, 0);
2820
2821 const MInt IJPK = getCellIdfromCell(I, 0, 1, 0);
2822 const MInt IJMK = getCellIdfromCell(I, 0, -1, 0);
2823 const MInt IJP2K = getCellIdfromCell(I, 0, 2, 0);
2824 const MInt IJM2K = getCellIdfromCell(I, 0, -2, 0);
2825
2826 const MInt IJKP = getCellIdfromCell(I, 0, 0, 1);
2827 const MInt IJKM = getCellIdfromCell(I, 0, 0, -1);
2828 const MInt IJKP2 = getCellIdfromCell(I, 0, 0, 2);
2829 const MInt IJKM2 = getCellIdfromCell(I, 0, 0, -2);
2830
2831 const MFloat p4I4 = F4 * (p[IPJK] + p[IMJK]) - F6 * (p[I]) - p[IP2JK] - p[IM2JK];
2832 const MFloat p4J4 = F4 * (p[IJPK] + p[IJMK]) - F6 * (p[I]) - p[IJP2K] - p[IJM2K];
2833 const MFloat p4K4 = F4 * (p[IJKP] + p[IJKM]) - F6 * (p[I]) - p[IJKP2] - p[IJKM2];
2834
2835 const MFloat pfac = fabs(p4I4) + fabs(p4J4) + fabs(p4K4);
2836 const MFloat facl = 1.0 / 1.3 * pfac;
2837 const MFloat fac = min(1 / 128.0, facl);
2838
2839 const MFloat PLR = PL * (F1B2 + fac * MAL) + PR * (F1B2 - fac * MAR);
2840
2841 const MFloat RHO_AL = RHOL * AL;
2842 const MFloat RHO_AR = RHOR * AR;
2843
2844 const MFloat PLfRHOL = PL / RHOL;
2845 const MFloat PRfRHOR = PR / RHOR;
2846
2847 const MFloat e0 = PLfRHOL * FgammaMinusOne + 0.5 * (POW2(UL) + POW2(VL) + POW2(WL)) + PLfRHOL;
2848 const MFloat e1 = PRfRHOR * FgammaMinusOne + 0.5 * (POW2(UR) + POW2(VR) + POW2(WR)) + PRfRHOR;
2849
2850 const MFloat RHOU = F1B2 * (MALR * (RHO_AL + RHO_AR) + fabs(MALR) * (RHO_AL - RHO_AR)) * metricLength;
2851 const MFloat RHOU2 = F1B2 * RHOU;
2852 // multiply by metric length to take surface area into account
2853 const MFloat AbsRHO_U2 = fabs(RHOU2);
2854
2855 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
2856 flux[CV->RHO_U][I] = RHOU2 * (UL + UR) + AbsRHO_U2 * (UL - UR) + PLR * surf0;
2857 flux[CV->RHO_V][I] = RHOU2 * (VL + VR) + AbsRHO_U2 * (VL - VR) + PLR * surf1;
2858 flux[CV->RHO_W][I] = RHOU2 * (WL + WR) + AbsRHO_U2 * (WL - WR) + PLR * surf2;
2859 flux[CV->RHO_E][I] = RHOU2 * (e0 + e1) + AbsRHO_U2 * (e0 - e1) + PLR * dxdtau;
2860 flux[CV->RHO][I] = RHOU;
2861}
2862
2863void FvStructuredSolver3D::AusmDV(MFloat* QLeft, MFloat* QRight, const MInt dim, const MInt I) {
2864 const MFloat gamma = m_gamma;
2865 const MFloat gammaMinusOne = gamma - 1.0;
2866 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
2867
2868 const MFloat surf0 = m_cells->surfaceMetrics[dim * 3 + 0][I];
2869 const MFloat surf1 = m_cells->surfaceMetrics[dim * 3 + 1][I];
2870 const MFloat surf2 = m_cells->surfaceMetrics[dim * 3 + 2][I];
2871
2872 const MFloat dxdtau = m_cells->dxt[dim][I];
2873
2874 // left side
2875 const MFloat RHOL = QLeft[PV->RHO];
2876 const MFloat FRHOL = F1 / RHOL;
2877 MFloat UL = QLeft[PV->U];
2878 MFloat VL = QLeft[PV->V];
2879 MFloat WL = QLeft[PV->W];
2880 const MFloat PL = QLeft[PV->P];
2881
2882 // right side
2883 const MFloat RHOR = QRight[PV->RHO];
2884 const MFloat FRHOR = F1 / RHOR;
2885 MFloat UR = QRight[PV->U];
2886 MFloat VR = QRight[PV->V];
2887 MFloat WR = QRight[PV->W];
2888 const MFloat PR = QRight[PV->P];
2889
2890 const MFloat PLfRHOL = PL / RHOL;
2891 const MFloat PRfRHOR = PR / RHOR;
2892 const MFloat e0 = PLfRHOL * FgammaMinusOne + 0.5 * (POW2(UL) + POW2(VL) + POW2(WL)) + PLfRHOL;
2893 const MFloat e1 = PRfRHOR * FgammaMinusOne + 0.5 * (POW2(UR) + POW2(VR) + POW2(WR)) + PRfRHOR;
2894
2895
2896 // compute lenght of metric vector for normalization
2897 const MFloat DGRAD = sqrt(POW2(surf0) + POW2(surf1) + POW2(surf2));
2898 const MFloat FDGRAD = F1 / DGRAD;
2899
2900 // scale by metric length to get velocity in the new basis (get normalized basis vectors)
2901 const MFloat UUL = ((UL * surf0 + VL * surf1 + WL * surf2) - dxdtau) * FDGRAD;
2902
2903
2904 const MFloat UUR = ((UR * surf0 + VR * surf1 + WR * surf2) - dxdtau) * FDGRAD;
2905
2906 MFloat AL = FRHOL * PL;
2907 MFloat AR = FRHOR * PR;
2908
2909 const MFloat FALR = 2.0 / (AL + AR);
2910 const MFloat ALPHAL = AL * FALR;
2911 const MFloat ALPHAR = AR * FALR;
2912
2913 AL = sqrt(gamma * AL);
2914 AR = sqrt(gamma * AR);
2915 AL = mMax(AL, AR);
2916 AR = AL;
2917
2918 const MFloat XMAL = UUL / AL;
2919 const MFloat XMAR = UUR / AR;
2920
2921 AL = AL * DGRAD;
2922 AR = AR * DGRAD;
2923
2924 const MFloat RHOAL = AL * RHOL;
2925 const MFloat RHOAR = AR * RHOR;
2926
2927 const MInt IJK[2] = {1, m_nCells[1]};
2928 const MInt IP1 = I + IJK[dim];
2929
2930 const MFloat FDV = 0.3;
2931 const MFloat DXDXEZ = m_cells->coordinates[0][IP1] - m_cells->coordinates[0][I];
2932 const MFloat DYDXEZ = m_cells->coordinates[1][IP1] - m_cells->coordinates[1][I];
2933 const MFloat DZDXEZ = m_cells->coordinates[2][IP1] - m_cells->coordinates[2][I];
2934 MFloat SV = 2.0 * DGRAD / (m_cells->cellJac[I] + m_cells->cellJac[IP1]) * (FDV + (F1 - FDV) * getPSI(I, dim));
2935 const MFloat SV1 = F0 * SV * DXDXEZ;
2936 const MFloat SV2 = F0 * SV * DYDXEZ;
2937 const MFloat SV3 = F0 * SV * DZDXEZ;
2938
2939 const MFloat XMAL1 = mMin(F1, mMax(-F1, XMAL));
2940 const MFloat XMAR1 = mMin(F1, mMax(-F1, XMAR));
2941
2942 MFloat FXMA = F1B2 * (XMAL1 + fabs(XMAL1));
2943 const MFloat XMALP = ALPHAL * (F1B4 * POW2(XMAL1 + F1) - FXMA) + FXMA + (mMax(F1, XMAL) - F1);
2944 FXMA = F1B2 * (XMAR1 - fabs(XMAR1));
2945 const MFloat XMARM = ALPHAR * (-F1B4 * POW2(XMAR1 - F1) - FXMA) + FXMA + (mMin(-F1, XMAR) + F1);
2946
2947 const MFloat FLP = PL * ((F2 - XMAL1) * POW2(F1 + XMAL1));
2948 const MFloat FRP = PR * ((F2 + XMAR1) * POW2(F1 - XMAR1));
2949 const MFloat PLR = F1B4 * (FLP + FRP);
2950
2951 const MFloat RHOUL = XMALP * RHOAL;
2952 const MFloat RHOUR = XMARM * RHOAR;
2953 const MFloat RHOU = RHOUL + RHOUR;
2954 const MFloat RHOU2 = F1B2 * RHOU;
2955 const MFloat ARHOU2 = fabs(RHOU2);
2956
2957 const MFloat UUL2 = SV1 * UUL;
2958 const MFloat UUR2 = SV1 * UUR;
2959 UL = UL - UUL2;
2960 UR = UR - UUR2;
2961 const MFloat UUL3 = SV2 * UUL;
2962 const MFloat UUR3 = SV2 * UUR;
2963 VL = VL - UUL3;
2964 VR = VR - UUR3;
2965 const MFloat UUL4 = SV3 * UUL;
2966 const MFloat UUR4 = SV3 * UUR;
2967 WL = WL - UUL4;
2968 WR = WR - UUR4;
2969
2970 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
2971
2972 flux[CV->RHO_U][I] = RHOU2 * (UL + UR) + ARHOU2 * (UL - UR) + PLR * surf0 + RHOUL * UUL2 + RHOUR * UUR2;
2973 flux[CV->RHO_V][I] = RHOU2 * (VL + VR) + ARHOU2 * (VL - VR) + PLR * surf1 + RHOUL * UUL3 + RHOUR * UUR3;
2974 flux[CV->RHO_W][I] = RHOU2 * (WL + WR) + ARHOU2 * (WL - WR) + PLR * surf2 + RHOUL * UUL4 + RHOUR * UUR4;
2975 flux[CV->RHO_E][I] = RHOU2 * (e0 + e1) + ARHOU2 * (e0 - e1) + PLR * dxdtau;
2976 flux[CV->RHO][I] = RHOU;
2977}
2978
2979template <MInt noVars>
2981 TRACE();
2982
2983 const MUint noCells = m_noCells;
2984 const MInt IJK[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
2985
2986 const MFloat* const RESTRICT x = ALIGNED_F(m_cells->coordinates[0]);
2987 const MFloat* const RESTRICT y = ALIGNED_F(m_cells->coordinates[1]);
2988 const MFloat* const RESTRICT z = ALIGNED_F(m_cells->coordinates[2]);
2989 const MFloat* const* const RESTRICT vars = ALIGNED_F(m_cells->pvariables);
2990 MFloat* const* const RESTRICT dss = ALIGNED_F(m_cells->dss);
2991 MFloat* const RESTRICT cellRhs = ALIGNED_MF(m_cells->rightHandSide[0]);
2992 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
2993
2994 const MFloat gamma = m_gamma;
2995 const MFloat gammaMinusOne = gamma - 1.0;
2996 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
2997
2998
2999
3001 for(MInt dim = 0; dim < nDim; dim++) {
3002 maia::parallelFor<true, nDim>(beginP0(), endM1(), [=](const MInt& i, const MInt& j, const MInt& k) {
3003 const MInt I = cellIndex(i, j, k);
3004 const MInt IP1 = I + IJK[dim];
3005 dss[dim][I] = sqrt(POW2(x[IP1] - x[I]) + POW2(y[IP1] - y[I]) + POW2(z[IP1] - z[I]));
3006 });
3007 }
3008
3009 m_dsIsComputed = true;
3010 }
3011
3012
3013 for(MInt dim = 0; dim < nDim; dim++) {
3014 maia::parallelFor<true, nDim>(beginP1(), endM2(), [=](const MInt& i, const MInt& j, const MInt& k) {
3015 const MInt I = cellIndex(i, j, k);
3016 const MInt IP1 = I + IJK[dim];
3017 const MInt IM1 = I - IJK[dim];
3018 const MInt IP2 = I + 2 * IJK[dim];
3019
3020 const MFloat DS = dss[dim][I];
3021 const MFloat DSM1 = dss[dim][IM1];
3022 const MFloat DSP1 = dss[dim][IP1];
3023
3024 const MFloat DSP = DS / POW2(DSP1 + DS);
3025 const MFloat DSM = DS / POW2(DSM1 + DS);
3026
3027 // unrolled the loop so the compiler
3028 // can optimize better
3029 const MFloat DQU = vars[PV->U][IP1] - vars[PV->U][I];
3030 const MFloat DQPU = vars[PV->U][IP2] - vars[PV->U][IP1];
3031 const MFloat DQMU = vars[PV->U][I] - vars[PV->U][IM1];
3032 const MFloat UL = vars[PV->U][I] + DSM * (DSM1 * DQU + DS * DQMU);
3033 const MFloat UR = vars[PV->U][IP1] - DSP * (DS * DQPU + DSP1 * DQU);
3034
3035 const MFloat DQV = vars[PV->V][IP1] - vars[PV->V][I];
3036 const MFloat DQPV = vars[PV->V][IP2] - vars[PV->V][IP1];
3037 const MFloat DQMV = vars[PV->V][I] - vars[PV->V][IM1];
3038 const MFloat VL = vars[PV->V][I] + DSM * (DSM1 * DQV + DS * DQMV);
3039 const MFloat VR = vars[PV->V][IP1] - DSP * (DS * DQPV + DSP1 * DQV);
3040
3041 const MFloat DQW = vars[PV->W][IP1] - vars[PV->W][I];
3042 const MFloat DQPW = vars[PV->W][IP2] - vars[PV->W][IP1];
3043 const MFloat DQMW = vars[PV->W][I] - vars[PV->W][IM1];
3044 const MFloat WL = vars[PV->W][I] + DSM * (DSM1 * DQW + DS * DQMW);
3045 const MFloat WR = vars[PV->W][IP1] - DSP * (DS * DQPW + DSP1 * DQW);
3046
3047 const MFloat DQP = vars[PV->P][IP1] - vars[PV->P][I];
3048 const MFloat DQPP = vars[PV->P][IP2] - vars[PV->P][IP1];
3049 const MFloat DQMP = vars[PV->P][I] - vars[PV->P][IM1];
3050 const MFloat PL = vars[PV->P][I] + DSM * (DSM1 * DQP + DS * DQMP);
3051 const MFloat PR = vars[PV->P][IP1] - DSP * (DS * DQPP + DSP1 * DQP);
3052
3053 const MFloat DQRHO = vars[PV->RHO][IP1] - vars[PV->RHO][I];
3054 const MFloat DQPRHO = vars[PV->RHO][IP2] - vars[PV->RHO][IP1];
3055 const MFloat DQMRHO = vars[PV->RHO][I] - vars[PV->RHO][IM1];
3056 const MFloat RHOL = vars[PV->RHO][I] + DSM * (DSM1 * DQRHO + DS * DQMRHO);
3057 const MFloat RHOR = vars[PV->RHO][IP1] - DSP * (DS * DQPRHO + DSP1 * DQRHO);
3058
3059 const MFloat surf0 = m_cells->surfaceMetrics[dim * 3 + 0][I];
3060 const MFloat surf1 = m_cells->surfaceMetrics[dim * 3 + 1][I];
3061 const MFloat surf2 = m_cells->surfaceMetrics[dim * 3 + 2][I];
3062 const MFloat dxdtau = m_cells->dxt[dim][I];
3063
3064 // compute length of metric vector for normalization
3065 const MFloat metricLength = sqrt(POW2(surf0) + POW2(surf1) + POW2(surf2));
3066 const MFloat fMetricLength = F1 / metricLength;
3067
3068 // scale by metric length to get velocity in the new basis (get normalized basis vectors)
3069 const MFloat UUL = ((UL * surf0 + VL * surf1 + WL * surf2) - dxdtau) * fMetricLength;
3070
3071
3072 const MFloat UUR = ((UR * surf0 + VR * surf1 + WR * surf2) - dxdtau) * fMetricLength;
3073
3074
3075 // speed of sound
3076 const MFloat AL = sqrt(gamma * max(m_eps, (PL / max(m_eps, RHOL))));
3077 const MFloat AR = sqrt(gamma * max(m_eps, (PR / max(m_eps, RHOR))));
3078
3079 const MFloat MAL = UUL / AL;
3080 const MFloat MAR = UUR / AR;
3081
3082 const MFloat MALR = F1B2 * (MAL + MAR);
3083 const MFloat PLR = PL * (F1B2 + m_chi * MAL) + PR * (F1B2 - m_chi * MAR);
3084
3085 const MFloat RHO_AL = RHOL * AL;
3086 const MFloat RHO_AR = RHOR * AR;
3087
3088 const MFloat PLfRHOL = PL / RHOL;
3089 const MFloat PRfRHOR = PR / RHOR;
3090
3091 const MFloat e0 = PLfRHOL * FgammaMinusOne + 0.5 * (POW2(UL) + POW2(VL) + POW2(WL)) + PLfRHOL;
3092 const MFloat e1 = PRfRHOR * FgammaMinusOne + 0.5 * (POW2(UR) + POW2(VR) + POW2(WR)) + PRfRHOR;
3093
3094 const MFloat RHOU = F1B2 * (MALR * (RHO_AL + RHO_AR) + fabs(MALR) * (RHO_AL - RHO_AR)) * metricLength;
3095 const MFloat RHOU2 = F1B2 * RHOU;
3096 // multiply by metric length to take surface area into account
3097 const MFloat AbsRHO_U2 = fabs(RHOU2);
3098
3099 flux[CV->RHO_U][I] = RHOU2 * (UL + UR) + AbsRHO_U2 * (UL - UR) + PLR * surf0;
3100 flux[CV->RHO_V][I] = RHOU2 * (VL + VR) + AbsRHO_U2 * (VL - VR) + PLR * surf1;
3101 flux[CV->RHO_W][I] = RHOU2 * (WL + WR) + AbsRHO_U2 * (WL - WR) + PLR * surf2;
3102 flux[CV->RHO_E][I] = RHOU2 * (e0 + e1) + AbsRHO_U2 * (e0 - e1) + PLR * dxdtau;
3103 flux[CV->RHO][I] = RHOU;
3104 });
3105
3106 // FLUX BALANCE
3107 for(MUint v = 0; v < noVars; v++) {
3108 maia::parallelFor<true, nDim>(beginP2(), endM2(), [=](const MInt& i, const MInt& j, const MInt& k) {
3109 const MInt I = cellIndex(i, j, k);
3110 const MInt IM1 = I - IJK[dim];
3111 const MUint offset = v * noCells;
3112 MFloat* const RESTRICT rhs = ALIGNED_F(cellRhs + offset);
3113 rhs[I] += flux[v][IM1] - flux[v][I];
3114 });
3115 }
3116 }
3117}
3118
3119template void FvStructuredSolver3D::Muscl_AusmLES<5>();
3120template void FvStructuredSolver3D::Muscl_AusmLES<6>();
3121template void FvStructuredSolver3D::Muscl_AusmLES<7>();
3122
3123template <MInt noVars>
3125 TRACE();
3126
3127 // stencil identifier
3128 const MInt IJK[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
3129
3130 const MFloat* const RESTRICT x = ALIGNED_F(m_cells->coordinates[0]);
3131 const MFloat* const RESTRICT y = ALIGNED_F(m_cells->coordinates[1]);
3132 const MFloat* const RESTRICT z = ALIGNED_F(m_cells->coordinates[2]);
3133 const MFloat* const* const RESTRICT vars = ALIGNED_F(m_cells->pvariables);
3134 const MFloat* const RESTRICT p = ALIGNED_F(m_cells->pvariables[PV->P]);
3135 MFloat* const* const RESTRICT dss = ALIGNED_F(m_cells->dss);
3136 MFloat* const RESTRICT cellRhs = ALIGNED_MF(m_cells->rightHandSide[0]);
3137 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
3138
3139 const MUint noCells = m_noCells;
3140 const MFloat gamma = m_gamma;
3141 const MFloat gammaMinusOne = gamma - 1.0;
3142 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
3143
3144 const MInt noCellsI = m_nCells[2] - 2;
3145 const MInt noCellsJ = m_nCells[1] - 2;
3146 const MInt noCellsK = m_nCells[0] - 2;
3147
3148 const MInt noCellsIP1 = m_nCells[2] - 1;
3149 const MInt noCellsJP1 = m_nCells[1] - 1;
3150 const MInt noCellsKP1 = m_nCells[0] - 1;
3151
3153 for(MInt dim = 0; dim < nDim; dim++) {
3154#ifdef _OPENMP
3155#pragma omp parallel for
3156#endif
3157 for(MInt k = 0; k < noCellsKP1; k++) {
3158 for(MInt j = 0; j < noCellsJP1; j++) {
3159 for(MInt i = 0; i < noCellsIP1; i++) {
3160 const MInt I = cellIndex(i, j, k);
3161 const MInt IP1 = I + IJK[dim];
3162 dss[dim][I] = sqrt(POW2(x[IP1] - x[I]) + POW2(y[IP1] - y[I]) + POW2(z[IP1] - z[I]));
3163 }
3164 }
3165 }
3166 }
3167
3168 m_dsIsComputed = true;
3169 }
3170
3171 for(MInt dim = 0; dim < nDim; dim++) {
3172#ifdef _OPENMP
3173#pragma omp parallel for
3174#endif
3175 for(MInt k = 1; k < noCellsK; k++) {
3176 for(MInt j = 1; j < noCellsJ; j++) {
3177#if defined(MAIA_INTEL_COMPILER)
3178#pragma ivdep
3179#pragma vector always
3180#endif
3181 for(MInt i = 1; i < noCellsI; i++) {
3182 const MInt I = cellIndex(i, j, k);
3183 const MInt IP1 = I + IJK[dim];
3184 const MInt IM1 = I - IJK[dim];
3185 const MInt IP2 = I + 2 * IJK[dim];
3186
3187 const MFloat DS = dss[dim][I];
3188 const MFloat DSM1 = dss[dim][IM1];
3189 const MFloat DSP1 = dss[dim][IP1];
3190
3191 const MFloat DSP = DS / POW2(DSP1 + DS);
3192 const MFloat DSM = DS / POW2(DSM1 + DS);
3193
3194 // unrolled the loop so the compiler
3195 // can optimize better
3196 const MFloat DQU = vars[PV->U][IP1] - vars[PV->U][I];
3197 const MFloat DQPU = vars[PV->U][IP2] - vars[PV->U][IP1];
3198 const MFloat DQMU = vars[PV->U][I] - vars[PV->U][IM1];
3199 const MFloat UL = vars[PV->U][I] + DSM * (DSM1 * DQU + DS * DQMU);
3200 const MFloat UR = vars[PV->U][IP1] - DSP * (DS * DQPU + DSP1 * DQU);
3201
3202 const MFloat DQV = vars[PV->V][IP1] - vars[PV->V][I];
3203 const MFloat DQPV = vars[PV->V][IP2] - vars[PV->V][IP1];
3204 const MFloat DQMV = vars[PV->V][I] - vars[PV->V][IM1];
3205 const MFloat VL = vars[PV->V][I] + DSM * (DSM1 * DQV + DS * DQMV);
3206 const MFloat VR = vars[PV->V][IP1] - DSP * (DS * DQPV + DSP1 * DQV);
3207
3208 const MFloat DQW = vars[PV->W][IP1] - vars[PV->W][I];
3209 const MFloat DQPW = vars[PV->W][IP2] - vars[PV->W][IP1];
3210 const MFloat DQMW = vars[PV->W][I] - vars[PV->W][IM1];
3211 const MFloat WL = vars[PV->W][I] + DSM * (DSM1 * DQW + DS * DQMW);
3212 const MFloat WR = vars[PV->W][IP1] - DSP * (DS * DQPW + DSP1 * DQW);
3213
3214 const MFloat DQP = vars[PV->P][IP1] - vars[PV->P][I];
3215 const MFloat DQPP = vars[PV->P][IP2] - vars[PV->P][IP1];
3216 const MFloat DQMP = vars[PV->P][I] - vars[PV->P][IM1];
3217 const MFloat PL = vars[PV->P][I] + DSM * (DSM1 * DQP + DS * DQMP);
3218 const MFloat PR = vars[PV->P][IP1] - DSP * (DS * DQPP + DSP1 * DQP);
3219
3220 const MFloat DQRHO = vars[PV->RHO][IP1] - vars[PV->RHO][I];
3221 const MFloat DQPRHO = vars[PV->RHO][IP2] - vars[PV->RHO][IP1];
3222 const MFloat DQMRHO = vars[PV->RHO][I] - vars[PV->RHO][IM1];
3223 const MFloat RHOL = vars[PV->RHO][I] + DSM * (DSM1 * DQRHO + DS * DQMRHO);
3224 const MFloat RHOR = vars[PV->RHO][IP1] - DSP * (DS * DQPRHO + DSP1 * DQRHO);
3225
3226 const MFloat surf0 = m_cells->surfaceMetrics[dim * 3 + 0][I];
3227 const MFloat surf1 = m_cells->surfaceMetrics[dim * 3 + 1][I];
3228 const MFloat surf2 = m_cells->surfaceMetrics[dim * 3 + 2][I];
3229 const MFloat dxdtau = m_cells->dxt[dim][I];
3230
3231 // compute lenght of metric vector for normalization
3232 const MFloat metricLength = sqrt(POW2(surf0) + POW2(surf1) + POW2(surf2));
3233 const MFloat fMetricLength = F1 / metricLength;
3234
3235 // scale by metric length to get velocity in the new basis (get normalized basis vectors)
3236 const MFloat UUL = ((UL * surf0 + VL * surf1 + WL * surf2) - dxdtau) * fMetricLength;
3237
3238
3239 const MFloat UUR = ((UR * surf0 + VR * surf1 + WR * surf2) - dxdtau) * fMetricLength;
3240
3241
3242 // speed of sound
3243 const MFloat AL = sqrt(gamma * max(m_eps, (PL / max(m_eps, RHOL))));
3244 const MFloat AR = sqrt(gamma * max(m_eps, (PR / max(m_eps, RHOR))));
3245
3246 const MFloat MAL = UUL / AL;
3247 const MFloat MAR = UUR / AR;
3248
3249 const MFloat MALR = F1B2 * (MAL + MAR);
3250
3251 // 4th order pressure damping
3252 const MInt IPJK = getCellIdfromCell(I, 1, 0, 0);
3253 const MInt IMJK = getCellIdfromCell(I, -1, 0, 0);
3254 const MInt IP2JK = getCellIdfromCell(I, 2, 0, 0);
3255 const MInt IM2JK = getCellIdfromCell(I, -2, 0, 0);
3256
3257 const MInt IJPK = getCellIdfromCell(I, 0, 1, 0);
3258 const MInt IJMK = getCellIdfromCell(I, 0, -1, 0);
3259 const MInt IJP2K = getCellIdfromCell(I, 0, 2, 0);
3260 const MInt IJM2K = getCellIdfromCell(I, 0, -2, 0);
3261
3262 const MInt IJKP = getCellIdfromCell(I, 0, 0, 1);
3263 const MInt IJKM = getCellIdfromCell(I, 0, 0, -1);
3264 const MInt IJKP2 = getCellIdfromCell(I, 0, 0, 2);
3265 const MInt IJKM2 = getCellIdfromCell(I, 0, 0, -2);
3266
3267 const MFloat p4I4 = F4 * (p[IPJK] + p[IMJK]) - F6 * (p[I]) - p[IP2JK] - p[IM2JK];
3268 const MFloat p4J4 = F4 * (p[IJPK] + p[IJMK]) - F6 * (p[I]) - p[IJP2K] - p[IJM2K];
3269 const MFloat p4K4 = F4 * (p[IJKP] + p[IJKM]) - F6 * (p[I]) - p[IJKP2] - p[IJKM2];
3270
3271 const MFloat pfac = fabs(p4I4) + fabs(p4J4) + fabs(p4K4);
3272 const MFloat facl = 1.0 / 1.3 * pfac;
3273 const MFloat fac = min(1.0 / 128.0, facl);
3274
3275 const MFloat PLR = PL * (F1B2 + fac * MAL) + PR * (F1B2 - fac * MAR);
3276
3277 const MFloat RHO_AL = RHOL * AL;
3278 const MFloat RHO_AR = RHOR * AR;
3279
3280 const MFloat PLfRHOL = PL / RHOL;
3281 const MFloat PRfRHOR = PR / RHOR;
3282
3283 const MFloat e0 = PLfRHOL * FgammaMinusOne + 0.5 * (POW2(UL) + POW2(VL) + POW2(WL)) + PLfRHOL;
3284 const MFloat e1 = PRfRHOR * FgammaMinusOne + 0.5 * (POW2(UR) + POW2(VR) + POW2(WR)) + PRfRHOR;
3285
3286 const MFloat RHOU = F1B2 * (MALR * (RHO_AL + RHO_AR) + fabs(MALR) * (RHO_AL - RHO_AR)) * metricLength;
3287 const MFloat RHOU2 = F1B2 * RHOU;
3288 // multiply by metric length to take surface area into account
3289 const MFloat AbsRHO_U2 = fabs(RHOU2);
3290
3291 flux[CV->RHO_U][I] = RHOU2 * (UL + UR) + AbsRHO_U2 * (UL - UR) + PLR * surf0;
3292 flux[CV->RHO_V][I] = RHOU2 * (VL + VR) + AbsRHO_U2 * (VL - VR) + PLR * surf1;
3293 flux[CV->RHO_W][I] = RHOU2 * (WL + WR) + AbsRHO_U2 * (WL - WR) + PLR * surf2;
3294 flux[CV->RHO_E][I] = RHOU2 * (e0 + e1) + AbsRHO_U2 * (e0 - e1) + PLR * dxdtau;
3295 flux[CV->RHO][I] = RHOU;
3296 }
3297 }
3298 }
3299
3300 // FLUX BALANCE
3301 for(MUint v = 0; v < noVars; v++) {
3302#ifdef _OPENMP
3303#pragma omp parallel for
3304#endif
3305 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
3306 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
3307#if defined(MAIA_INTEL_COMPILER)
3308#pragma ivdep
3309#pragma vector always
3310#endif
3311 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
3312 const MInt I = cellIndex(i, j, k);
3313 const MInt IM1 = I - IJK[dim];
3314 const MUint offset = v * noCells;
3315 MFloat* const RESTRICT rhs = ALIGNED_F(cellRhs + offset);
3316 rhs[I] += flux[v][IM1] - flux[v][I];
3317 }
3318 }
3319 }
3320 }
3321 }
3322}
3323
3324template void FvStructuredSolver3D::Muscl_AusmLES_PTHRC<5>();
3325template void FvStructuredSolver3D::Muscl_AusmLES_PTHRC<6>();
3326template void FvStructuredSolver3D::Muscl_AusmLES_PTHRC<7>();
3327
3328
3329template <MInt noVars>
3331 TRACE();
3332
3333 // stencil identifier
3334 const MInt IJK[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
3335
3336 const MFloat* const RESTRICT x = ALIGNED_F(m_cells->coordinates[0]);
3337 const MFloat* const RESTRICT y = ALIGNED_F(m_cells->coordinates[1]);
3338 const MFloat* const RESTRICT z = ALIGNED_F(m_cells->coordinates[2]);
3339 const MFloat* const* const RESTRICT vars = ALIGNED_F(m_cells->pvariables);
3340 MFloat* const* const RESTRICT dss = ALIGNED_F(m_cells->dss);
3341 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
3342 MFloat* const RESTRICT cellRhs = ALIGNED_MF(m_cells->rightHandSide[0]);
3343
3344 const MUint noCells = m_noCells;
3345 const MFloat gamma = m_gamma;
3346 const MFloat gammaMinusOne = gamma - 1.0;
3347 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
3348
3349 const MInt noCellsI = m_nCells[2] - 2;
3350 const MInt noCellsJ = m_nCells[1] - 2;
3351 const MInt noCellsK = m_nCells[0] - 2;
3352
3353 const MInt noCellsIP1 = m_nCells[2] - 1;
3354 const MInt noCellsJP1 = m_nCells[1] - 1;
3355 const MInt noCellsKP1 = m_nCells[0] - 1;
3356
3358 for(MInt dim = 0; dim < nDim; dim++) {
3359#ifdef _OPENMP
3360#pragma omp parallel for
3361#endif
3362 for(MInt k = 0; k < noCellsKP1; k++) {
3363 for(MInt j = 0; j < noCellsJP1; j++) {
3364 for(MInt i = 0; i < noCellsIP1; i++) {
3365 const MInt I = cellIndex(i, j, k);
3366 const MInt IP1 = I + IJK[dim];
3367 dss[dim][I] = sqrt(POW2(x[IP1] - x[I]) + POW2(y[IP1] - y[I]) + POW2(z[IP1] - z[I]));
3368 }
3369 }
3370 }
3371 }
3372
3373 m_dsIsComputed = true;
3374 }
3375
3376
3377 for(MInt dim = 0; dim < nDim; dim++) {
3378#ifdef _OPENMP
3379#pragma omp parallel for
3380#endif
3381 for(MInt k = 1; k < noCellsK; k++) {
3382 for(MInt j = 1; j < noCellsJ; j++) {
3383#if defined(MAIA_INTEL_COMPILER)
3384#pragma ivdep
3385#pragma vector always
3386#endif
3387 for(MInt i = 1; i < noCellsI; i++) {
3388 const MInt I = cellIndex(i, j, k);
3389 const MInt IP1 = I + IJK[dim];
3390 const MInt IM1 = I - IJK[dim];
3391 const MInt IP2 = I + 2 * IJK[dim];
3392
3393 const MFloat DS = dss[dim][I];
3394 const MFloat DSM1 = dss[dim][IM1];
3395 const MFloat DSP1 = dss[dim][IP1];
3396
3397 const MFloat DSP = DS / POW2(DSP1 + DS);
3398 const MFloat DSM = DS / POW2(DSM1 + DS);
3399
3400 // unrolled the loop so the compiler
3401 // can optimize better
3402 const MFloat DQU = vars[PV->U][IP1] - vars[PV->U][I];
3403 const MFloat DQPU = vars[PV->U][IP2] - vars[PV->U][IP1];
3404 const MFloat DQMU = vars[PV->U][I] - vars[PV->U][IM1];
3405 MFloat UL = vars[PV->U][I] + DSM * (DSM1 * DQU + DS * DQMU);
3406 MFloat UR = vars[PV->U][IP1] - DSP * (DS * DQPU + DSP1 * DQU);
3407
3408 const MFloat DQV = vars[PV->V][IP1] - vars[PV->V][I];
3409 const MFloat DQPV = vars[PV->V][IP2] - vars[PV->V][IP1];
3410 const MFloat DQMV = vars[PV->V][I] - vars[PV->V][IM1];
3411 MFloat VL = vars[PV->V][I] + DSM * (DSM1 * DQV + DS * DQMV);
3412 MFloat VR = vars[PV->V][IP1] - DSP * (DS * DQPV + DSP1 * DQV);
3413
3414 const MFloat DQW = vars[PV->W][IP1] - vars[PV->W][I];
3415 const MFloat DQPW = vars[PV->W][IP2] - vars[PV->W][IP1];
3416 const MFloat DQMW = vars[PV->W][I] - vars[PV->W][IM1];
3417 MFloat WL = vars[PV->W][I] + DSM * (DSM1 * DQW + DS * DQMW);
3418 MFloat WR = vars[PV->W][IP1] - DSP * (DS * DQPW + DSP1 * DQW);
3419
3420 const MFloat DQP = vars[PV->P][IP1] - vars[PV->P][I];
3421 const MFloat DQPP = vars[PV->P][IP2] - vars[PV->P][IP1];
3422 const MFloat DQMP = vars[PV->P][I] - vars[PV->P][IM1];
3423 const MFloat PL = vars[PV->P][I] + DSM * (DSM1 * DQP + DS * DQMP);
3424 const MFloat PR = vars[PV->P][IP1] - DSP * (DS * DQPP + DSP1 * DQP);
3425
3426 const MFloat DQRHO = vars[PV->RHO][IP1] - vars[PV->RHO][I];
3427 const MFloat DQPRHO = vars[PV->RHO][IP2] - vars[PV->RHO][IP1];
3428 const MFloat DQMRHO = vars[PV->RHO][I] - vars[PV->RHO][IM1];
3429 const MFloat RHOL = vars[PV->RHO][I] + DSM * (DSM1 * DQRHO + DS * DQMRHO);
3430 const MFloat RHOR = vars[PV->RHO][IP1] - DSP * (DS * DQPRHO + DSP1 * DQRHO);
3431
3432 const MFloat surf0 = m_cells->surfaceMetrics[dim * 3 + 0][I];
3433 const MFloat surf1 = m_cells->surfaceMetrics[dim * 3 + 1][I];
3434 const MFloat surf2 = m_cells->surfaceMetrics[dim * 3 + 2][I];
3435 const MFloat dxdtau = m_cells->dxt[dim][I];
3436
3437 const MFloat FRHOL = F1 / RHOL;
3438 const MFloat FRHOR = F1 / RHOR;
3439
3440 const MFloat PLfRHOL = PL / RHOL;
3441 const MFloat PRfRHOR = PR / RHOR;
3442 const MFloat e0 = PLfRHOL * FgammaMinusOne + 0.5 * (POW2(UL) + POW2(VL) + POW2(WL)) + PLfRHOL;
3443 const MFloat e1 = PRfRHOR * FgammaMinusOne + 0.5 * (POW2(UR) + POW2(VR) + POW2(WR)) + PRfRHOR;
3444
3445
3446 // compute lenght of metric vector for normalization
3447 const MFloat DGRAD = sqrt(POW2(surf0) + POW2(surf1) + POW2(surf2));
3448 const MFloat FDGRAD = F1 / DGRAD;
3449
3450 // scale by metric length to get velocity in the new basis (get normalized basis vectors)
3451 const MFloat UUL = ((UL * surf0 + VL * surf1 + WL * surf2) - dxdtau) * FDGRAD;
3452
3453
3454 const MFloat UUR = ((UR * surf0 + VR * surf1 + WR * surf2) - dxdtau) * FDGRAD;
3455
3456 MFloat AL = FRHOL * PL;
3457 MFloat AR = FRHOR * PR;
3458
3459 const MFloat FALR = 2.0 / (AL + AR);
3460 const MFloat ALPHAL = AL * FALR;
3461 const MFloat ALPHAR = AR * FALR;
3462
3463 AL = sqrt(gamma * AL);
3464 AR = sqrt(gamma * AR);
3465 AL = mMax(AL, AR);
3466 AR = AL;
3467
3468 const MFloat XMAL = UUL / AL;
3469 const MFloat XMAR = UUR / AR;
3470
3471 AL = AL * DGRAD;
3472 AR = AR * DGRAD;
3473
3474 const MFloat RHOAL = AL * RHOL;
3475 const MFloat RHOAR = AR * RHOR;
3476
3477 const MFloat FDV = 0.3;
3478 const MFloat DXDXEZ = m_cells->coordinates[0][IP1] - m_cells->coordinates[0][I];
3479 const MFloat DYDXEZ = m_cells->coordinates[1][IP1] - m_cells->coordinates[1][I];
3480 const MFloat DZDXEZ = m_cells->coordinates[2][IP1] - m_cells->coordinates[2][I];
3481 MFloat SV = 2.0 * DGRAD / (m_cells->cellJac[I] + m_cells->cellJac[IP1]) * (FDV + (F1 - FDV) * getPSI(I, dim));
3482 const MFloat SV1 = F0 * SV * DXDXEZ;
3483 const MFloat SV2 = F0 * SV * DYDXEZ;
3484 const MFloat SV3 = F0 * SV * DZDXEZ;
3485
3486 const MFloat XMAL1 = mMin(F1, mMax(-F1, XMAL));
3487 const MFloat XMAR1 = mMin(F1, mMax(-F1, XMAR));
3488
3489 MFloat FXMA = F1B2 * (XMAL1 + fabs(XMAL1));
3490 const MFloat XMALP = ALPHAL * (F1B4 * POW2(XMAL1 + F1) - FXMA) + FXMA + (mMax(F1, XMAL) - F1);
3491 FXMA = F1B2 * (XMAR1 - fabs(XMAR1));
3492 const MFloat XMARM = ALPHAR * (-F1B4 * POW2(XMAR1 - F1) - FXMA) + FXMA + (mMin(-F1, XMAR) + F1);
3493
3494 const MFloat FLP = PL * ((F2 - XMAL1) * POW2(F1 + XMAL1));
3495 const MFloat FRP = PR * ((F2 + XMAR1) * POW2(F1 - XMAR1));
3496 const MFloat PLR = F1B4 * (FLP + FRP);
3497
3498 const MFloat RHOUL = XMALP * RHOAL;
3499 const MFloat RHOUR = XMARM * RHOAR;
3500 const MFloat RHOU = RHOUL + RHOUR;
3501 const MFloat RHOU2 = F1B2 * RHOU;
3502 const MFloat ARHOU2 = fabs(RHOU2);
3503
3504 const MFloat UUL2 = SV1 * UUL;
3505 const MFloat UUR2 = SV1 * UUR;
3506 UL = UL - UUL2;
3507 UR = UR - UUR2;
3508 const MFloat UUL3 = SV2 * UUL;
3509 const MFloat UUR3 = SV2 * UUR;
3510 VL = VL - UUL3;
3511 VR = VR - UUR3;
3512 const MFloat UUL4 = SV3 * UUL;
3513 const MFloat UUR4 = SV3 * UUR;
3514 WL = WL - UUL4;
3515 WR = WR - UUR4;
3516
3517 flux[CV->RHO_U][I] = RHOU2 * (UL + UR) + ARHOU2 * (UL - UR) + PLR * surf0 + RHOUL * UUL2 + RHOUR * UUR2;
3518 flux[CV->RHO_V][I] = RHOU2 * (VL + VR) + ARHOU2 * (VL - VR) + PLR * surf1 + RHOUL * UUL3 + RHOUR * UUR3;
3519 flux[CV->RHO_W][I] = RHOU2 * (WL + WR) + ARHOU2 * (WL - WR) + PLR * surf2 + RHOUL * UUL4 + RHOUR * UUR4;
3520 flux[CV->RHO_E][I] = RHOU2 * (e0 + e1) + ARHOU2 * (e0 - e1) + PLR * dxdtau;
3521 flux[CV->RHO][I] = RHOU;
3522 }
3523 }
3524 }
3525
3526 // FLUX BALANCE
3527 for(MUint v = 0; v < noVars; v++) {
3528#ifdef _OPENMP
3529#pragma omp parallel for
3530#endif
3531 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
3532 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
3533#if defined(MAIA_INTEL_COMPILER)
3534#pragma ivdep
3535#pragma vector always
3536#endif
3537 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
3538 const MInt I = cellIndex(i, j, k);
3539 const MInt IM1 = I - IJK[dim];
3540 const MUint offset = v * noCells;
3541 MFloat* const RESTRICT rhs = ALIGNED_F(cellRhs + offset);
3542 rhs[I] += flux[v][IM1] - flux[v][I];
3543 }
3544 }
3545 }
3546 }
3547 }
3548}
3549
3550template void FvStructuredSolver3D::Muscl_AusmDV<5>();
3551template void FvStructuredSolver3D::Muscl_AusmDV<6>();
3552template void FvStructuredSolver3D::Muscl_AusmDV<7>();
3553
3554
3555template <FvStructuredSolver3D::fluxmethod ausm, MInt noVars>
3557 TRACE();
3558
3559 // stencil identifier
3560 const MUint noCells = m_noCells;
3561 const MInt IJK[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
3562 const MFloat* const RESTRICT cellVariables = ALIGNED_F(m_cells->pvariables[0]);
3563 const MFloat* const RESTRICT cellLength = ALIGNED_F(m_cells->cellLength[0]);
3564 MFloat* const RESTRICT cellRhs = ALIGNED_MF(m_cells->rightHandSide[0]);
3565 MFloat* const RESTRICT qleft = ALIGNED_MF(m_QLeft);
3566 MFloat* const RESTRICT qright = ALIGNED_MF(m_QRight);
3567 MFloat* const* const RESTRICT flux = ALIGNED_F(m_cells->flux);
3569 // MFloat epsi=F1;
3570 const MFloat phi = F1;
3571 const MFloat kappa = F0; // F1B3;
3573 for(MInt dim = 0; dim < nDim; dim++) {
3574 const MUint dimOffset = dim * m_noCells;
3575 const MFloat* const RESTRICT length = ALIGNED_F(cellLength + dimOffset);
3576
3577 for(MInt k = m_noGhostLayers - 1; k < m_nCells[0] - m_noGhostLayers; k++) {
3578 for(MInt j = m_noGhostLayers - 1; j < m_nCells[1] - m_noGhostLayers; j++) {
3579 for(MInt i = m_noGhostLayers - 1; i < m_nCells[2] - m_noGhostLayers; i++) {
3580 const MInt I = cellIndex(i, j, k);
3581 const MInt IP1 = I + IJK[dim];
3582 const MInt IM1 = I - IJK[dim];
3583 const MInt IP2 = I + 2 * IJK[dim];
3584
3585 const MFloat rp = (length[I] + length[IP1]) / (F2 * length[I]);
3586 const MFloat rm = (length[I] + length[IM1]) / (F2 * length[I]);
3587 const MFloat f = phi / (F2 * (rp + rm));
3588 const MFloat f1 = (rm + kappa * phi) / rp;
3589 const MFloat f2 = (rp - kappa * phi) / rm;
3590
3591 const MFloat rp1 = (length[IP1] + length[IP2]) / (F2 * length[IP1]);
3592 const MFloat rm1 = (length[IP1] + length[I]) / (F2 * length[IP1]);
3593 const MFloat fa = phi / (F2 * (rp1 + rm1));
3594 const MFloat fb = (rm1 - kappa * phi) / rp1;
3595 const MFloat fc = (rp1 + kappa * phi) / rm1;
3596
3597 for(MUint v = 0; v < noVars; v++) {
3598 const MUint offset = v * m_noCells;
3599 const MFloat* const RESTRICT vars = ALIGNED_F(cellVariables + offset);
3600 // left variables
3601 const MFloat DQ = (vars[IP1] - vars[I]);
3602 const MFloat DQM1 = (vars[I] - vars[IM1]);
3603 qleft[v] = vars[I] + f * (f1 * DQ + f2 * DQM1);
3604
3605 // right variables
3606 const MFloat DQP1 = (vars[IP2] - vars[IP1]);
3607 const MFloat DQ1 = (vars[IP1] - vars[I]);
3608 qright[v] = vars[IP1] - fa * (fb * DQP1 + fc * DQ1);
3609 }
3610
3611 (this->*ausm)(m_QLeft, m_QRight, dim, I);
3612 }
3613 }
3614 }
3615
3616 // FLUX BALANCE
3617 for(MUint v = 0; v < noVars; v++) {
3618 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
3619 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
3620 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
3621 const MInt I = cellIndex(i, j, k);
3622 const MInt IM1 = I - IJK[dim];
3623 const MUint offset = v * noCells;
3624 MFloat* const RESTRICT rhs = ALIGNED_F(cellRhs + offset);
3625 rhs[I] += flux[v][IM1] - flux[v][I];
3626 }
3627 }
3628 }
3629 }
3630 }
3631}
3632// standard Ausm
3633template void FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES, 5>();
3634template void FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES, 6>();
3635template void FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES, 7>();
3636// pthrc
3637template void FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES_PTHRC, 5>();
3638template void FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES_PTHRC, 6>();
3639template void FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmLES_PTHRC, 7>();
3640// AusmDV
3641template void FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmDV, 5>();
3642template void FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmDV, 6>();
3643template void FvStructuredSolver3D::MusclStretched_<&FvStructuredSolver3D::AusmDV, 7>();
3644
3645
3646void FvStructuredSolver3D::Muscl(MInt NotUsed(timerId)) {
3647 TRACE();
3648
3649
3650 if(m_movingGrid) {
3651 RECORD_TIMER_START(m_timers[Timers::MovingGrid]);
3652 if(m_RKStep == 0) {
3653 RECORD_TIMER_START(m_timers[Timers::MGSaveGrid]);
3654 m_grid->saveGrid();
3655 m_grid->saveCellJacobian();
3656 RECORD_TIMER_STOP(m_timers[Timers::MGSaveGrid]);
3657 }
3658
3659 RECORD_TIMER_START(m_timers[Timers::MGMoveGrid]);
3660 moveGrid(false, false);
3661 RECORD_TIMER_STOP(m_timers[Timers::MGMoveGrid]);
3662
3663 // compute the volume fluxes
3664 RECORD_TIMER_START(m_timers[Timers::MGVolumeFlux]);
3665 m_grid->computeDxt(m_timeStep, m_RKalpha, m_RKStep);
3666 RECORD_TIMER_STOP(m_timers[Timers::MGVolumeFlux]);
3667 RECORD_TIMER_STOP(m_timers[Timers::MovingGrid]);
3668 }
3669
3670 if(m_bodyForce) {
3671 applyBodyForce(false, false);
3672 }
3673
3674 RECORD_TIMER_START(m_timers[Timers::ConvectiveFlux]);
3675 (this->*reconstructSurfaceData)();
3676 RECORD_TIMER_STOP(m_timers[Timers::ConvectiveFlux]);
3677
3678 if(m_useSandpaperTrip) {
3679 RECORD_TIMER_START(m_timers[Timers::SandpaperTrip]);
3680 if(m_tripAirfoil) {
3682 } else {
3684 }
3685 RECORD_TIMER_STOP(m_timers[Timers::SandpaperTrip]);
3686 }
3687}
3688
3690 // Ausm routines have been moved and are called from inside Muscl (better performance)
3691}
3692
3694 // if we only compute cd,cl for a part of the domain (m_auxDataCoordinateLimits == true)
3695 // only compute the average with the width of this section
3698 } else {
3699 MFloat minCoordinate = F0, maxCoordinate = F0, minCoordinateGlobal = F0, maxCoordinateGlobal = F0;
3700 MInt lowPoint = -1, highPoint = -1;
3701
3702 if(m_forceAveragingDir == 0) {
3703 highPoint = getPointIdFromCell(m_nCells[2] - m_noGhostLayers, 0, 0);
3704 lowPoint = getPointIdFromCell(m_noGhostLayers, 0, 0);
3705 } else if(m_forceAveragingDir == 1) {
3706 highPoint = getPointIdFromCell(0, m_nCells[1] - m_noGhostLayers, 0);
3707 lowPoint = getPointIdFromCell(0, m_noGhostLayers, 0);
3708 } else {
3711 }
3712
3713 minCoordinate = m_grid->m_coordinates[m_forceAveragingDir][lowPoint];
3714 maxCoordinate = m_grid->m_coordinates[m_forceAveragingDir][highPoint];
3715 MPI_Allreduce(&minCoordinate, &minCoordinateGlobal, 1, MPI_DOUBLE, MPI_MIN, m_StructuredComm, AT_, "minCoordinate",
3716 "minCoordinateGlobal");
3717 MPI_Allreduce(&maxCoordinate, &maxCoordinateGlobal, 1, MPI_DOUBLE, MPI_MAX, m_StructuredComm, AT_, "maxCoordinate",
3718 "maxCoordinateGlobal");
3719 m_globalDomainWidth = fabs(maxCoordinateGlobal - minCoordinateGlobal);
3720 m_log << "Global domain width: " << m_globalDomainWidth << endl;
3721 }
3722}
3723
3725 TRACE();
3726
3728
3729 mAlloc(m_tripDelta1, m_tripNoTrips, "m_tripDelta1", 1.0, AT_);
3730 mAlloc(m_tripXOrigin, m_tripNoTrips, "m_tripXOrigin", 30.0, AT_);
3731 mAlloc(m_tripXLength, m_tripNoTrips, "m_tripXLength", 4.0, AT_);
3732 mAlloc(m_tripYOrigin, m_tripNoTrips, "m_tripYOrigin", 0.0, AT_);
3733 mAlloc(m_tripYHeight, m_tripNoTrips, "m_tripYHeight", 1.0, AT_);
3734 mAlloc(m_tripCutoffZ, m_tripNoTrips, "m_tripCutoffZ", 1.7, AT_);
3735 mAlloc(m_tripMaxAmpSteady, m_tripNoTrips, "m_tripMaxAmpSteady", 0.0, AT_);
3736 mAlloc(m_tripMaxAmpFluc, m_tripNoTrips, "m_tripMaxAmpFluc", 0.005, AT_);
3737 mAlloc(m_tripDeltaTime, m_tripNoTrips, "m_tripDeltaTime", 4.0, AT_);
3738 mAlloc(m_tripTimeStep, m_tripNoTrips, "m_tripTimeStep", 0, AT_);
3739
3740 for(MInt i = 0; i < m_tripNoTrips; ++i) {
3753 m_tripDelta1[i] = Context::getSolverProperty<MFloat>("tripDelta1", m_solverId, AT_, &m_tripDelta1[i], i);
3754
3767 m_tripXOrigin[i] = Context::getSolverProperty<MFloat>("tripXOrigin", m_solverId, AT_, &m_tripXOrigin[i], i);
3768
3781 MFloat tripX = 4.0;
3782 if(Context::propertyExists("tripXLength", m_solverId)) {
3783 tripX = Context::getSolverProperty<MFloat>("tripXLength", m_solverId, AT_, &tripX);
3784 }
3785 m_tripXLength[i] = m_tripDelta1[i] * tripX;
3786
3799 if(Context::propertyExists("tripYOrigin", m_solverId)) {
3800 m_tripYOrigin[i] = Context::getSolverProperty<MFloat>("tripYOrigin", m_solverId, AT_, &m_tripYOrigin[i], i);
3801 }
3802
3815 MFloat tripY = 1.0;
3816 if(Context::propertyExists("tripYHeight", m_solverId)) {
3817 tripY = Context::getSolverProperty<MFloat>("tripYHeight", m_solverId, AT_, &tripY);
3818 }
3819 m_tripYHeight[i] = m_tripDelta1[i] * tripY;
3820
3834 MFloat tripZ = 1.7;
3835 if(Context::propertyExists("tripCutoffZ", m_solverId)) {
3836 tripZ = Context::getSolverProperty<MFloat>("tripCutoffZ", m_solverId, AT_, &tripZ);
3837 }
3838 m_tripCutoffZ[i] = m_tripDelta1[i] * tripZ;
3839
3840
3854 Context::getSolverProperty<MFloat>("tripMaxAmpSteady", m_solverId, AT_, &m_tripMaxAmpSteady[i], i);
3855
3868 m_tripMaxAmpFluc[i] =
3869 Context::getSolverProperty<MFloat>("tripMaxAmpFluc", m_solverId, AT_, &m_tripMaxAmpFluc[i], i);
3870
3871 m_tripNoModes = 100;
3872
3886 MFloat timeCutoff = 4.0;
3887 if(Context::propertyExists("tripDeltaTime", m_solverId)) {
3888 timeCutoff = Context::getSolverProperty<MFloat>("tripDeltaTime", m_solverId, AT_, &timeCutoff);
3889 }
3890 m_tripDeltaTime[i] = timeCutoff * m_tripDelta1[i] / PV->UInfinity;
3892 }
3893
3894 if(Context::propertyExists("RNGSeed") || Context::propertyExists("seedRNGWithTime"))
3895 mTerm(1, "Properties RNGSeed or seedRNGWithTime not compatible with SandpaperTrip!");
3896 m_tripSeed = 70;
3897 srand(m_tripSeed);
3898 m_tripDomainWidth = 0.0;
3900
3901
3902 m_tripUseRestart = true;
3903 if(Context::propertyExists("tripUseRestart", m_solverId)) {
3904 m_tripUseRestart = Context::getSolverProperty<MBool>("tripUseRestart", m_solverId, AT_, &m_tripUseRestart);
3905 }
3906
3907
3908 MFloat localDomainWidth = m_cells->coordinates[2][cellIndex(0, 0, m_nCells[0] - 2)];
3909 MPI_Allreduce(&localDomainWidth, &m_tripDomainWidth, 1, MPI_DOUBLE, MPI_MAX, m_StructuredComm, AT_,
3910 "localDomainWidth", "m_tripDomainWidth");
3911
3915
3916 m_tripAirfoil = false;
3917 if(Context::propertyExists("tripAirfoil", m_solverId)) {
3918 m_tripAirfoil = Context::getSolverProperty<MBool>("tripAirfoil", m_solverId, AT_, &m_tripAirfoil);
3919 }
3920
3921 if(m_tripAirfoil) {
3922 if(!m_movingGrid) {
3923 const MInt blockId = 0; // use information from inputSolver 0
3924 m_airfoilNoWallPoints = m_grid->getBlockNoPoints(blockId, 2) + 2 * m_noGhostLayers;
3925
3926 if(domainId() == 0) {
3927 cout << "NoWallPoints: " << m_airfoilNoWallPoints << endl;
3928 }
3929
3930 MFloatScratchSpace localCoords(nDim, m_airfoilNoWallPoints, AT_, "localCoords");
3931 MFloatScratchSpace localNormalVec(nDim, m_airfoilNoWallPoints, AT_, "localNormalVec");
3932 localCoords.fill(-99999.0);
3933 localNormalVec.fill(-99999.0);
3934 mAlloc(m_airfoilCoords, nDim * m_airfoilNoWallPoints, "m_airfoilCoords", -99999.0, AT_);
3935 mAlloc(m_airfoilNormalVec, nDim * m_airfoilNoWallPoints, "m_airfoilNormalVec", -99999.0, AT_);
3936
3937 if(m_blockId == blockId) {
3938 if(m_nOffsetCells[1] == 0 && m_nOffsetCells[0] == 0) {
3939 // only collect variables from points at the wall
3940 for(MInt i = 0; i < m_nPoints[2]; i++) {
3941 const MInt offset = m_nOffsetCells[2];
3942 const MInt localPointId = i; // new postion in Array
3943 const MInt globalPointId = offset + i;
3944
3946 const MInt pIJPK = pointIndex(i, m_noGhostLayers + 1, m_noGhostLayers);
3947
3948 // compute the normal vector
3949 MFloat normalVec[3] = {F0, F0, F0};
3950 for(MInt dim = 0; dim < nDim; dim++) {
3951 normalVec[dim] = m_grid->m_coordinates[dim][pIJPK] - m_grid->m_coordinates[dim][pIJK];
3952 }
3953
3954 // normalize normalVec
3955 const MFloat normalLength = sqrt(POW2(normalVec[0]) + POW2(normalVec[1]) + POW2(normalVec[2]));
3956 for(MInt dim = 0; dim < nDim; dim++) {
3957 normalVec[dim] /= normalLength;
3958 }
3959
3960 localCoords(globalPointId) = m_grid->m_coordinates[0][localPointId];
3961 localCoords(m_airfoilNoWallPoints + globalPointId) = m_grid->m_coordinates[1][localPointId];
3962 localCoords(2 * m_airfoilNoWallPoints + globalPointId) = m_grid->m_coordinates[2][localPointId];
3963
3964 localNormalVec(globalPointId) = normalVec[0];
3965 localNormalVec(m_airfoilNoWallPoints + globalPointId) = normalVec[1];
3966 localNormalVec(2 * m_airfoilNoWallPoints + globalPointId) = normalVec[2];
3967 }
3968 }
3969 }
3970
3971 MPI_Allreduce(&localCoords[0], &m_airfoilCoords[0], nDim * m_airfoilNoWallPoints, MPI_DOUBLE, MPI_MAX,
3972 m_StructuredComm, AT_, "localCoords[0]", "m_airfoilCoords[0]");
3973 MPI_Allreduce(&localNormalVec[0], &m_airfoilNormalVec[0], nDim * m_airfoilNoWallPoints, MPI_DOUBLE, MPI_MAX,
3974 m_StructuredComm, AT_, "localNormalVec[0]", "m_airfoilNormalVec[0]");
3975 }
3976
3977 // compute distance to wall
3978 vector<Point<3>> pts;
3979 for(MInt i = 0; i < m_airfoilNoWallPoints - 1; ++i) {
3980 const MInt gIJK = i;
3981 const MInt gIPJK = i + 1;
3982 const MFloat xWall = F1B2 * (m_airfoilCoords[0 + gIJK] + m_airfoilCoords[0 + gIPJK]);
3983 const MFloat yWall =
3985
3986 Point<3> a(xWall, yWall, 0.0);
3987 pts.push_back(a);
3988 }
3989
3990 KDtree<3> tree(pts);
3991 mAlloc(m_airfoilWallDist, m_noCells, "m_airfoilWallDist", -9999.0, AT_);
3992
3993 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
3994 const MFloat x = m_cells->coordinates[0][cellId];
3995 const MFloat y = m_cells->coordinates[1][cellId];
3996
3997 Point<3> pt(x, y, 0);
3998 MFloat distance = -1.111111111111;
3999 (void)tree.nearest(pt, distance);
4001 }
4002 }
4003
4007
4008 m_log << "=================================================" << endl
4009 << " SANDPAPER TRIP PROPERTIES " << endl
4010 << "=================================================" << endl;
4011 for(MInt i = 0; i < m_tripNoTrips; ++i) {
4012 m_log << "######### TRIP NUMBER " << i << " ###########" << endl
4013 << "tripXOrigin: " << m_tripXOrigin[i] << endl
4014 << "tripXLength: " << m_tripXLength[i] << endl
4015 << "tripYOrigin: " << m_tripYOrigin[i] << endl
4016 << "tripYHeight: " << m_tripYHeight[i] << endl
4017 << "tripMaxAmpFluc: " << m_tripMaxAmpFluc[i] << endl
4018 << "tripNoModes: " << m_tripNoModes << endl
4019 << "tripDeltaTime: " << m_tripDeltaTime[i] << endl
4020 << "tripTimeStep: " << m_tripTimeStep[i] << endl
4021 << "tripDomainWidth: " << m_tripDomainWidth << endl
4022 << "###########################################" << endl;
4023 }
4024 m_log << "=================================================" << endl;
4025
4026 mAlloc(m_tripCoords, m_tripNoCells, "m_tripCoords", F0, AT_);
4027 mAlloc(m_tripG, m_tripNoTrips * m_tripNoCells, "m_tripG", F0, AT_);
4028 mAlloc(m_tripH1, m_tripNoTrips * m_tripNoCells, "m_tripH1", F0, AT_);
4029 mAlloc(m_tripH2, m_tripNoTrips * m_tripNoCells, "m_tripH2", F0, AT_);
4030 mAlloc(m_tripModesG, m_tripNoTrips * 2 * m_tripNoModes, "m_tripModesG", F0, AT_);
4031 mAlloc(m_tripModesH1, m_tripNoTrips * 2 * m_tripNoModes, "m_tripModesH1", F0, AT_);
4032 mAlloc(m_tripModesH2, m_tripNoTrips * 2 * m_tripNoModes, "m_tripModesH2", F0, AT_);
4033
4034
4035 for(MInt k = 0; k < m_tripNoCells; k++) {
4036 m_tripCoords[k] = m_cells->coordinates[2][cellIndex(0, 0, k)];
4037 }
4038
4040 stringstream tripPath;
4041 tripPath << "/trip";
4042 ParallelIo::size_type dummyOffset = 0;
4043 ParallelIo::size_type dataSize = m_tripNoTrips * m_tripNoModes * 2;
4044
4045 if(domainId() == 0) {
4046 stringstream restartFileName;
4047 MString restartFile = Context::getSolverProperty<MString>("restartVariablesFileName", m_solverId, AT_);
4048 restartFileName << outputDir() << restartFile;
4049 ParallelIoHdf5 pio(restartFileName.str(), maia::parallel_io::PIO_READ, MPI_COMM_SELF);
4050 pio.readArray(m_tripModesG, tripPath.str(), "tripModesG", 1, &dummyOffset, &dataSize);
4051 pio.readArray(m_tripModesH1, tripPath.str(), "tripModesH1", 1, &dummyOffset, &dataSize);
4052 pio.readArray(m_tripModesH2, tripPath.str(), "tripModesH2", 1, &dummyOffset, &dataSize);
4053 }
4054
4055 MPI_Bcast(m_tripModesG, dataSize, MPI_DOUBLE, 0, m_StructuredComm, AT_, "m_tripModesG");
4056 MPI_Bcast(m_tripModesH1, dataSize, MPI_DOUBLE, 0, m_StructuredComm, AT_, "m_tripModesH1");
4057 MPI_Bcast(m_tripModesH2, dataSize, MPI_DOUBLE, 0, m_StructuredComm, AT_, "m_tripModesH2");
4058 } else {
4059 for(MInt i = 0; i < m_tripNoTrips; ++i) {
4060 const MInt offsetModes = i * 2 * m_tripNoModes;
4064 }
4065 }
4066
4067
4068 for(MInt i = 0; i < m_tripNoTrips; ++i) {
4069 const MInt offset = i * m_tripNoCells;
4070 const MInt offsetModes = i * 2 * m_tripNoModes;
4074 }
4075}
4076
4078 TRACE();
4079
4080 for(MInt ii = 0; ii < m_tripNoTrips; ++ii) {
4081 const MFloat t = m_time + m_timeStep * m_RKalpha[m_RKStep];
4082 const MInt tripTime = (MInt)(t / m_tripDeltaTime[ii]);
4083 const MFloat p = t / m_tripDeltaTime[ii] - tripTime;
4084 const MFloat b = 3 * pow(p, 2) - 2 * pow(p, 3);
4085 const MInt offset = ii * m_tripNoCells;
4086 const MInt offsetModes = ii * 2 * m_tripNoModes;
4087
4088 if(tripTime > m_tripTimeStep[ii]) {
4089 m_tripTimeStep[ii] = tripTime;
4090
4091 // copy old values from H2 to H1
4092 for(MInt k = 0; k < m_tripNoCells; k++) {
4093 m_tripH1[offset + k] = m_tripH2[offset + k];
4094 }
4095
4096 // also copy the old mode coefficients
4097 for(MInt n = 0; n < 2 * m_tripNoModes; n++) {
4098 m_tripModesH1[offsetModes + n] = m_tripModesH2[offsetModes + n];
4099 }
4100
4101 // compute new fourier coefficients
4104 }
4105
4106 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
4107 const MFloat forceStrength =
4108 (m_tripMaxAmpSteady[ii] * m_tripG[offset + k]
4109 + m_tripMaxAmpFluc[ii] * ((1.0 - b) * m_tripH1[offset + k] + b * m_tripH2[offset + k]));
4110
4111 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
4112 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
4113 const MInt cellId = cellIndex(i, j, k);
4114 const MFloat x = m_cells->coordinates[0][cellId];
4115 const MFloat y = m_cells->coordinates[1][cellId];
4116
4117 MFloat force = 0.0;
4118 if(x > m_tripXOrigin[ii] - 2 * m_tripXLength[ii] && x < m_tripXOrigin[ii] + 2 * m_tripXLength[ii]
4119 && y > m_tripYOrigin[ii] - 2 * m_tripYHeight[ii] && y < m_tripYOrigin[ii] + 2 * m_tripYHeight[ii]) {
4120 force = exp(-POW2((x - m_tripXOrigin[ii]) / m_tripXLength[ii])
4121 - POW2((y - m_tripYOrigin[ii]) / m_tripYHeight[ii]))
4122 * forceStrength;
4123 }
4124
4125 m_cells->rightHandSide[CV->RHO_V][cellId] +=
4126 m_cells->variables[CV->RHO][cellId] * force * m_cells->cellJac[cellId];
4127 m_cells->rightHandSide[CV->RHO_E][cellId] +=
4128 m_cells->variables[CV->RHO_V][cellId] * force * m_cells->cellJac[cellId];
4129 }
4130 }
4131 }
4132 }
4133}
4134
4136 TRACE();
4137
4138 for(MInt ii = 0; ii < m_tripNoTrips; ++ii) {
4139 const MFloat t = m_time + m_timeStep * m_RKalpha[m_RKStep];
4140 const MInt tripTime = (MInt)(t / m_tripDeltaTime[ii]);
4141 const MFloat p = t / m_tripDeltaTime[ii] - tripTime;
4142 const MFloat b = 3 * pow(p, 2) - 2 * pow(p, 3);
4143 const MInt offset = ii * m_tripNoCells;
4144 const MInt offsetModes = ii * 2 * m_tripNoModes;
4145
4146 if(tripTime > m_tripTimeStep[ii]) {
4147 m_tripTimeStep[ii] = tripTime;
4148
4149 // copy old values from H2 to H1
4150 for(MInt k = 0; k < m_tripNoCells; k++) {
4151 m_tripH1[offset + k] = m_tripH2[offset + k];
4152 }
4153
4154 // also copy the old mode coefficients
4155 for(MInt n = 0; n < 2 * m_tripNoModes; n++) {
4156 m_tripModesH1[offsetModes + n] = m_tripModesH2[offsetModes + n];
4157 }
4158
4159 // compute new fourier coefficients
4162 }
4163
4164 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
4165 const MFloat forceStrength =
4166 (m_tripMaxAmpSteady[ii] * m_tripG[offset + k]
4167 + m_tripMaxAmpFluc[ii] * ((1.0 - b) * m_tripH1[offset + k] + b * m_tripH2[offset + k]));
4168
4169 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
4170 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
4171 const MInt cellId = cellIndex(i, j, k);
4172 const MFloat x = m_cells->coordinates[0][cellId];
4173 const MFloat y = m_cells->coordinates[1][cellId];
4174 const MFloat wallDist = m_airfoilWallDist[cellId];
4175
4176 MFloat force = 0.0;
4177 if(x > m_tripXOrigin[ii] - 2 * m_tripXLength[ii] && x < m_tripXOrigin[ii] + 2 * m_tripXLength[ii]
4178 && wallDist < 2 * m_tripYHeight[ii]) {
4179 MFloat factor = 0.0;
4180 if(ii == 0 && y > 0.0) {
4181 factor = exp(-POW2((x - m_tripXOrigin[ii]) / m_tripXLength[ii]) - POW2(wallDist / m_tripYHeight[ii]));
4182 } else if(ii == 1 && y < 0.0) {
4183 factor = exp(-POW2((x - m_tripXOrigin[ii]) / m_tripXLength[ii]) - POW2(wallDist / m_tripYHeight[ii]));
4184 }
4185
4186 force = forceStrength * factor;
4187 }
4188
4189 const MInt offsetPoints = m_nOffsetCells[2];
4190 const MInt globalPointId = offsetPoints + i;
4191 const MFloat wallNormalVec[3] = {m_airfoilNormalVec[0 + globalPointId],
4193 m_airfoilNormalVec[2 * m_airfoilNoWallPoints + globalPointId]};
4194
4195 const MFloat density = m_cells->pvariables[PV->RHO][cellId];
4196 const MFloat u = m_cells->pvariables[PV->U][cellId];
4197 const MFloat u_force = wallNormalVec[0] * force;
4198
4199 m_cells->rightHandSide[CV->RHO_U][cellId] += density * u_force * m_cells->cellJac[cellId];
4200 m_cells->rightHandSide[CV->RHO_E][cellId] += density * u * u_force * m_cells->cellJac[cellId];
4201
4202 const MFloat v = m_cells->pvariables[PV->V][cellId];
4203 const MFloat v_force = wallNormalVec[1] * force;
4204
4205 m_cells->rightHandSide[CV->RHO_V][cellId] += density * v_force * m_cells->cellJac[cellId];
4206 m_cells->rightHandSide[CV->RHO_E][cellId] += density * v * v_force * m_cells->cellJac[cellId];
4207 }
4208 }
4209 }
4210 }
4211}
4212
4213
4214void FvStructuredSolver3D::tripForceCoefficients(MFloat* modes, MFloat* forceCoef, MFloat* coords, MInt noCells,
4215 MInt noModes) {
4216 MFloat maxLocalValue = -999999.0;
4217 MFloat minLocalValue = 999999.0;
4218 MFloat* ak = &modes[0];
4219 MFloat* phik = &modes[noModes];
4220
4221 for(MInt k = 0; k < noCells; k++) {
4222 const MFloat z = coords[k];
4223 for(MInt n = 0; n < noModes; n++) {
4224 forceCoef[k] += sin(z * ak[n] + phik[n]);
4225 }
4226
4227 maxLocalValue = mMax(maxLocalValue, forceCoef[k]);
4228 minLocalValue = mMin(minLocalValue, forceCoef[k]);
4229 }
4230
4231 // find out min and max to normalize coefficients to interval [-1,1]
4232 MFloat maxGlobalValue = 0.0;
4233 MFloat minGlobalValue = 0.0;
4234 MPI_Allreduce(&maxLocalValue, &maxGlobalValue, 1, MPI_DOUBLE, MPI_MAX, m_StructuredComm, AT_, "maxLocalValue",
4235 "maxGlobalValue");
4236 MPI_Allreduce(&minLocalValue, &minGlobalValue, 1, MPI_DOUBLE, MPI_MIN, m_StructuredComm, AT_, "minLocalValue",
4237 "minGlobalValue");
4238
4239 // normalize the series
4240 for(MInt k = 0; k < noCells; k++) {
4241 forceCoef[k] = 2 * (forceCoef[k] - minGlobalValue) / (maxGlobalValue - minGlobalValue) - 1.0;
4242 }
4243}
4244
4245
4247 MFloat minWaveLength) {
4248 const MFloat minWavenumber = 2 * PI / maxWaveLength;
4249 const MFloat maxWavenumber = 2 * PI / minWaveLength;
4250
4251 MFloat* ak = &modes[0];
4252 MFloat* phik = &modes[noModes];
4253 if(domainId() == 0) {
4254 for(MInt n = 0; n < noModes; n++) {
4255 ak[n] = (maxWavenumber - minWavenumber) * (rand() / MFloat(RAND_MAX)) + minWavenumber;
4256 phik[n] = 2 * PI * rand() / MFloat(RAND_MAX);
4257 }
4258 }
4259
4260 MPI_Bcast(&ak[0], noModes, MPI_DOUBLE, 0, m_StructuredComm, AT_, "ak[0]");
4261 MPI_Bcast(&phik[0], noModes, MPI_DOUBLE, 0, m_StructuredComm, AT_, "phik[0]");
4262}
4263
4264
4266
4268 TRACE();
4269 if(m_RKStep == 0 && m_zoneType == "LES") {
4270 if(globalTimeStep == 0 || forceReset) {
4271 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
4272 m_cells->fq[FQ->AVG_RHO][cellId] = m_cells->pvariables[PV->RHO][cellId];
4273 m_cells->fq[FQ->AVG_U][cellId] = m_cells->pvariables[PV->U][cellId];
4274 m_cells->fq[FQ->AVG_V][cellId] = m_cells->pvariables[PV->V][cellId];
4275 m_cells->fq[FQ->AVG_W][cellId] = m_cells->pvariables[PV->W][cellId];
4276 m_cells->fq[FQ->AVG_P][cellId] = m_cells->pvariables[PV->P][cellId];
4277 }
4278 } else {
4279 const MFloat timeFacRho = m_Ma * (1.0 / m_zonalAveragingFactor) * sqrt(PV->TInfinity) * m_physicalTimeStep;
4280 const MFloat timeFacU = m_Ma * (1.0 / m_zonalAveragingFactor) * sqrt(PV->TInfinity) * m_physicalTimeStep;
4281 const MFloat timeFacV = m_Ma * (1.0 / m_zonalAveragingFactor) * sqrt(PV->TInfinity) * m_physicalTimeStep;
4282 const MFloat timeFacW = m_Ma * (1.0 / m_zonalAveragingFactor) * sqrt(PV->TInfinity) * m_physicalTimeStep;
4283 const MFloat timeFacE = m_Ma * (1.0 / m_zonalAveragingFactor) * sqrt(PV->TInfinity) * m_physicalTimeStep;
4284
4286 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
4287 // Exponential averaging
4288 m_cells->fq[FQ->AVG_RHO][cellId] =
4289 timeFacRho * m_cells->pvariables[PV->RHO][cellId] + (1.0 - timeFacRho) * m_cells->fq[FQ->AVG_RHO][cellId];
4290 m_cells->fq[FQ->AVG_U][cellId] =
4291 timeFacU * m_cells->pvariables[PV->U][cellId] + (1.0 - timeFacU) * m_cells->fq[FQ->AVG_U][cellId];
4292 m_cells->fq[FQ->AVG_V][cellId] =
4293 timeFacV * m_cells->pvariables[PV->V][cellId] + (1.0 - timeFacV) * m_cells->fq[FQ->AVG_V][cellId];
4294 m_cells->fq[FQ->AVG_W][cellId] =
4295 timeFacW * m_cells->pvariables[PV->W][cellId] + (1.0 - timeFacW) * m_cells->fq[FQ->AVG_W][cellId];
4296 m_cells->fq[FQ->AVG_P][cellId] =
4297 timeFacE * m_cells->pvariables[PV->P][cellId] + (1.0 - timeFacE) * m_cells->fq[FQ->AVG_P][cellId];
4298 }
4299 }
4300 }
4301}
4302
4303void FvStructuredSolver3D::spanwiseAvgZonal(vector<MFloat*>& variables) {
4304 if(!variables.empty()) {
4305 MInt totalNoCellsIJ = (m_grid->getMyBlockNoCells(2) * m_grid->getMyBlockNoCells(1));
4306 const MInt noVars = variables.size();
4307 MFloatScratchSpace localSpannwiseVars(totalNoCellsIJ, noVars, AT_, "localSpannwiseVars");
4308 MFloatScratchSpace globalSpannwiseVars(totalNoCellsIJ, noVars, AT_, "globalSpannwiseVars");
4309
4310 for(MInt varPos = 0; varPos < noVars; varPos++) {
4311 for(MInt k = 0; k < m_nActiveCells[0]; k++) {
4312 for(MInt j = 0; j < m_nActiveCells[1]; j++) {
4313 for(MInt i = 0; i < m_nActiveCells[2]; i++) {
4314 MInt localCellId3D =
4315 i + m_noGhostLayers + ((j + m_noGhostLayers) + (k + m_noGhostLayers) * m_nCells[1]) * m_nCells[2];
4316 MInt globalCellId2D = (i + m_nOffsetCells[2]) + (j + m_nOffsetCells[1]) * m_grid->getMyBlockNoCells(2);
4317 localSpannwiseVars(globalCellId2D, varPos) += variables[varPos][localCellId3D];
4318 }
4319 }
4320 }
4321 }
4322
4323 MPI_Allreduce(&localSpannwiseVars(0, 0), &globalSpannwiseVars(0, 0), totalNoCellsIJ * noVars, MPI_DOUBLE, MPI_SUM,
4324 m_commZonal[m_blockId], AT_, "localSpannwiseVars(0", "0)");
4325
4326 for(MInt varPos = 0; varPos < noVars; varPos++) {
4327 for(MInt cellId = 0; cellId < totalNoCellsIJ; cellId++) {
4328 globalSpannwiseVars(cellId, varPos) /= m_grid->getMyBlockNoCells(0);
4329 }
4330 }
4331
4332 for(MInt varPos = 0; varPos < noVars; varPos++) {
4333 for(MInt k = 0; k < m_nActiveCells[0]; k++) {
4334 for(MInt j = 0; j < m_nActiveCells[1]; j++) {
4335 for(MInt i = 0; i < m_nActiveCells[2]; i++) {
4336 MInt localCellId3D =
4337 i + m_noGhostLayers + ((j + m_noGhostLayers) + (k + m_noGhostLayers) * m_nCells[1]) * m_nCells[2];
4338 MInt globalCellId2D = (i + m_nOffsetCells[2]) + (j + m_nOffsetCells[1]) * m_grid->getMyBlockNoCells(2);
4339 variables[varPos][localCellId3D] = globalSpannwiseVars(globalCellId2D, varPos);
4340 }
4341 }
4342 }
4343 }
4344 }
4345}
4346
4347
4349 TRACE();
4350
4351 m_timeStep = 1000.0;
4352 const MFloat* const RESTRICT dxtx = ALIGNED_F(m_cells->dxt[0]);
4353 const MFloat* const RESTRICT dxty = ALIGNED_F(m_cells->dxt[1]);
4354 const MFloat* const RESTRICT dxtz = ALIGNED_F(m_cells->dxt[2]);
4355 const MFloat* const* const RESTRICT metric = m_cells->cellMetrics;
4356
4357 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
4358 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
4359 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
4360 const MInt cellId = cellIndex(i, j, k);
4361
4362 const MFloat Frho = F1 / m_cells->pvariables[PV->RHO][cellId];
4363
4364 // compute the speed of sound
4365 const MFloat speedOfSound = sqrt(m_gamma * m_cells->pvariables[PV->P][cellId] * Frho);
4366
4367 // no need for simplified metrics, since information is already contained
4368 // in cell metrics
4369 const MFloat lenXi = sqrt(POW2(metric[0][cellId]) + POW2(metric[1][cellId]) + POW2(metric[2][cellId]));
4370 const MFloat lenEt = sqrt(POW2(metric[3][cellId]) + POW2(metric[4][cellId]) + POW2(metric[5][cellId]));
4371 const MFloat lenZe = sqrt(POW2(metric[6][cellId]) + POW2(metric[7][cellId]) + POW2(metric[8][cellId]));
4372
4373 // contravariant velocities
4374 MFloat U_c = F0;
4375 MFloat V_c = F0;
4376 MFloat W_c = F0;
4377
4378 for(MInt isd = xsd; isd < nDim; isd++) {
4379 U_c += m_cells->pvariables[PV->VV[isd]][cellId] * metric[xsd * nDim + isd][cellId];
4380 V_c += m_cells->pvariables[PV->VV[isd]][cellId] * metric[ysd * nDim + isd][cellId];
4381 W_c += m_cells->pvariables[PV->VV[isd]][cellId] * metric[zsd * nDim + isd][cellId];
4382 }
4383
4384 // subtract grid velocity
4385 U_c -= dxtx[cellId];
4386 V_c -= dxty[cellId];
4387 W_c -= dxtz[cellId];
4388
4389 U_c = fabs(U_c);
4390 V_c = fabs(V_c);
4391 W_c = fabs(W_c);
4392
4393 // has area information in it due to metric terms
4394 const MFloat eigenvalue = U_c + V_c + W_c + speedOfSound * (lenXi + lenEt + lenZe);
4395
4396 // divide volume information (jacobian) through area to get characteristic length for CFL
4397 const MFloat deltaT = m_cfl * m_cells->cellJac[cellId] / eigenvalue;
4398
4399 if(m_localTimeStep) {
4400 m_cells->localTimeStep[cellId] = deltaT;
4401 m_timeStep = F1;
4402 m_timeRef = F1;
4403 } else {
4404 m_timeStep = mMin(m_timeStep, deltaT);
4405 }
4406 }
4407 }
4408 }
4409}
4410
4411
4413 TRACE();
4414 if(m_useSponge) m_structuredBndryCnd->updateSpongeLayer();
4415}
4416
4417
4419 TRACE();
4420 const MInt noVars = CV->noVariables;
4421 const MUint noCells = m_noCells;
4422 const MFloat rkAlpha = m_RKalpha[m_RKStep];
4423 const MFloat rkFactor = rkAlpha * m_timeStep;
4424
4425 MFloat* const RESTRICT oldVars = ALIGNED_F(m_cells->oldVariables[0]);
4426 MFloat* const RESTRICT vars = ALIGNED_F(m_cells->variables[0]);
4427 MFloat* const RESTRICT oldCellJac = ALIGNED_MF(m_cells->oldCellJac);
4428 const MFloat* const RESTRICT cellJac = ALIGNED_MF(m_cells->cellJac);
4429 const MFloat* const RESTRICT rhs = ALIGNED_MF(m_cells->rightHandSide[0]);
4430
4431 // set old variables
4432 if(m_RKStep == 0) {
4433 for(MInt v = 0; v < noVars; v++) {
4434 const MUint offset = v * noCells;
4435 MFloat* const RESTRICT oldCellVars = ALIGNED_F(oldVars + offset);
4436 const MFloat* const RESTRICT cellVars = ALIGNED_F(vars + offset);
4437 maia::parallelFor<true>(0, m_noCells, [=](MInt cellId) { oldCellVars[cellId] = cellVars[cellId]; });
4438 }
4439 }
4440
4441 switch(m_rungeKuttaOrder) {
4442 case 2: {
4443 // for moving grids we take the old Jacobian into account
4444 if(m_localTimeStep) {
4445 for(MInt v = 0; v < noVars; v++) {
4446 const MUint cellOffset = v * noCells;
4447 MFloat* const RESTRICT cellVars = vars + cellOffset;
4448 const MFloat* const RESTRICT oldCellVars = oldVars + cellOffset;
4449 const MFloat* const RESTRICT cellRhs = rhs + cellOffset;
4450
4451 maia::parallelFor<true, nDim>(beginP2(), endM2(), [=](const MInt& i, const MInt& j, const MInt& k) {
4452 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4453 const MFloat localRkFactor = rkAlpha * m_cells->localTimeStep[cellId];
4454 const MFloat factor = localRkFactor / m_cells->cellJac[cellId];
4455 cellVars[cellId] = oldCellVars[cellId] + factor * cellRhs[cellId];
4456 });
4457 }
4458 } else if(m_movingGrid) {
4459 for(MInt v = 0; v < noVars; v++) {
4460 const MUint cellOffset = v * noCells;
4461 MFloat* const RESTRICT cellVars = vars + cellOffset;
4462 const MFloat* const RESTRICT oldCellVars = oldVars + cellOffset;
4463 const MFloat* const RESTRICT cellRhs = rhs + cellOffset;
4464
4465 maia::parallelFor<true, nDim>(beginP2(), endM2(), [=](const MInt& i, const MInt& j, const MInt& k) {
4466 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4467 cellVars[cellId] =
4468 (oldCellVars[cellId] * oldCellJac[cellId] + rkFactor * cellRhs[cellId]) / cellJac[cellId];
4469 });
4470 }
4471 } else {
4472 for(MInt v = 0; v < noVars; v++) {
4473 const MUint cellOffset = v * noCells;
4474 MFloat* const RESTRICT cellVars = vars + cellOffset;
4475 const MFloat* const RESTRICT oldCellVars = oldVars + cellOffset;
4476 const MFloat* const RESTRICT cellRhs = rhs + cellOffset;
4477
4478 maia::parallelFor<true, nDim>(beginP2(), endM2(), [=](const MInt& i, const MInt& j, const MInt& k) {
4479 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4480 const MFloat factor = rkFactor / m_cells->cellJac[cellId];
4481 cellVars[cellId] = oldCellVars[cellId] + factor * cellRhs[cellId];
4482 });
4483 }
4484 }
4485 break;
4486 }
4487 case 3: {
4488 for(MInt v = 0; v < noVars; v++) {
4489 const MUint cellOffset = v * noCells;
4490 MFloat* const RESTRICT cellVars = vars + cellOffset;
4491 const MFloat* const RESTRICT oldCellVars = oldVars + cellOffset;
4492 const MFloat* const RESTRICT cellRhs = rhs + cellOffset;
4493
4494 maia::parallelFor<true, nDim>(beginP2(), endM2(), [=](const MInt& i, const MInt& j, const MInt& k) {
4495 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4496 const MFloat factor = rkFactor / m_cells->cellJac[cellId];
4497 cellVars[cellId] =
4498 rkAlpha * cellVars[cellId] + (F1 - rkAlpha) * oldCellVars[cellId] - factor * cellRhs[cellId];
4499 });
4500 }
4501 break;
4502 }
4503 default: {
4504 stringstream errorMessage;
4505 errorMessage << "Given RungeKutta Order " << m_rungeKuttaOrder << " not implemented! " << endl;
4506 mTerm(1, AT_, errorMessage.str());
4507 }
4508 }
4509
4510 ++m_RKStep;
4511
4512 if(m_RKStep == m_noRKSteps) {
4514 m_time += m_timeStep;
4515
4516 m_RKStep = 0;
4517
4518 return true;
4519 } else {
4520 return false;
4521 }
4522}
4523
4525 TRACE();
4526 cout << "enterin addDisturbance " << endl;
4527 cout << " m_time = " << m_time << endl;
4528 cout << "m_timeStep = " << m_timeStep << endl;
4529 cout << " global t= " << globalTimeStep << endl;
4530 if(m_time >= 0) {
4531 MFloat pi2 = 8.0 * atan(1);
4532 MFloat period = 0.1;
4533 MFloat amp1 = 0.00001 * sin((pi2 / period) * m_time);
4534
4535 // MFloat T=(m_cells->variables[CV->RHO_E][364])*(m_gamma-F1)/287.1500;
4536 // MFloat fluc_p = rhsdist*287.15000*T;
4537 // MFloat fluc_rhoE= (F1/(m_gamma-1))*fluc_p;
4538 // rhsdist=fluc_rhoE;
4539 MInt cellId = 0;
4540 cout << "sin " << amp1 << endl;
4541 MFloat centerloc = 3.1415;
4542 // go through all cells and adopt disturbance smoothly!!
4543 // m_cells->rightHandSide[CV->RHO_E][2191941]+=rhsdist;
4544 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
4545 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
4546 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
4547 cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4548 MFloat x = m_cells->coordinates[0][cellId];
4549 MFloat y = m_cells->coordinates[1][cellId];
4550 MFloat z = m_cells->coordinates[2][cellId];
4551 MFloat r = 0.025;
4552 MFloat a1 = POW2(x - centerloc);
4553 MFloat a2 = POW2(y - centerloc);
4554 MFloat a3 = POW2(z - centerloc);
4555 MFloat disturb = amp1 * exp(-(a1 + a2 + a3) / POW2(r) / 2.0);
4556 m_cells->rightHandSide[CV->RHO_E][cellId] += disturb;
4557 /* MFloat x=m_cells->coordinates[0][cellId]-centreloc;
4558 MFloat y=m_cells->coordinates[1][cellId]-centreloc;
4559 MFloat z=m_cells->coordinates[2][cellId]-centreloc;
4560 m_cells->rightHandSide[CV->RHO_E][cellId]+=(F1+tanh(x/0.009))*(F1-tanh(x/0.009))*(F1+tanh(y/0.009))*(F1-tanh(y/0.009))*(F1+tanh(z/0.009))*(F1-tanh(z/0.009))*rhsdist;*/
4561 }
4562 }
4563 }
4564 }
4565
4566 cout << "leaving addDisturbance " << endl;
4567}
4568
4570 TRACE();
4571 m_structuredBndryCnd->assignBndryCnds();
4572}
4573
4575 TRACE();
4576 m_structuredBndryCnd->correctBndryCndIndices();
4577}
4578
4584 TRACE();
4585 // > for debugging only: save cellId/pointId and domainId for all cells and points
4586 if(m_debugOutput) {
4587 for(MInt k = 0; k < (m_nCells[0]); k++) {
4588 for(MInt j = 0; j < (m_nCells[1]); j++) {
4589 for(MInt i = 0; i < (m_nCells[2]); i++) {
4590 MInt cellId = cellIndex(i, j, k);
4591 m_cells->fq[FQ->CELLID][cellId] = cellId;
4592 m_cells->fq[FQ->BLOCKID][cellId] = domainId();
4593 }
4594 }
4595 }
4596 }
4597 //< end debugging only
4598
4599 m_grid->extrapolateGhostPointCoordinates();
4600
4601 m_grid->exchangePoints(m_sndComm, m_rcvComm, PARTITION_NORMAL);
4602 m_grid->exchangePoints(m_sndComm, m_rcvComm, PERIODIC_BC);
4603
4605
4606 m_grid->computeCellCenterCoordinates();
4607
4608 // MUST be done after cell center computation!!!
4609 m_grid->exchangePoints(m_sndComm, m_rcvComm, SINGULAR);
4611
4612 if(m_hasSingularity > 0) {
4614 }
4615
4617 m_grid->writePartitionedGrid();
4618 }
4619}
4620
4622 for(MInt bcId = 0; bcId < (MInt)m_structuredBndryCnd->m_physicalBCMap.size(); ++bcId) {
4623 // all the periodic BCs are NOT included.
4624 // also skip the channel bc
4625 if(m_structuredBndryCnd->m_physicalBCMap[bcId]->BC == 2401
4626 || m_structuredBndryCnd->m_physicalBCMap[bcId]->BC == 2402
4627 || (m_structuredBndryCnd->m_physicalBCMap[bcId]->BC >= 6000
4628 && m_structuredBndryCnd->m_physicalBCMap[bcId]->BC < 6010)) {
4629 continue;
4630 }
4631
4632 MInt* start = m_structuredBndryCnd->m_physicalBCMap[bcId]->start1;
4633 MInt* end = m_structuredBndryCnd->m_physicalBCMap[bcId]->end1;
4634 MInt index = m_structuredBndryCnd->m_physicalBCMap[bcId]->face / 2;
4635 MInt step = m_structuredBndryCnd->m_physicalBCMap[bcId]->face % 2;
4636 MInt pos[3], fix[3], mirror[3], ijk[3], extendijk[3];
4637 MInt pointId, FixPointId, MirrorPointId;
4638
4639 extendijk[0] = 1;
4640 extendijk[1] = 1;
4641 extendijk[2] = 1;
4642 extendijk[index] = 0;
4643
4644 for(ijk[2] = start[2]; ijk[2] < end[2] + extendijk[2]; ++ijk[2]) {
4645 for(ijk[1] = start[1]; ijk[1] < end[1] + extendijk[1]; ++ijk[1]) {
4646 for(ijk[0] = start[0]; ijk[0] < end[0] + extendijk[0]; ++ijk[0]) {
4647 for(MInt m = 0; m < 3; ++m) {
4648 if(index == m) {
4649 if(step == 1) {
4650 pos[m] = ijk[m] + 1;
4651 fix[m] = start[m];
4652 mirror[m] = 2 * fix[m] - pos[m];
4653 } else {
4654 pos[m] = ijk[m];
4655 fix[m] = end[m];
4656 mirror[m] = 2 * fix[m] - pos[m];
4657 }
4658 } else {
4659 pos[m] = ijk[m];
4660 fix[m] = ijk[m];
4661 mirror[m] = ijk[m];
4662 }
4663 } // m
4664
4665 pointId = pointIndex(pos[0], pos[1], pos[2]);
4666 FixPointId = pointIndex(fix[0], fix[1], fix[2]);
4667 MirrorPointId = pointIndex(mirror[0], mirror[1], mirror[2]);
4668
4669 for(MInt dim = 0; dim < nDim; dim++) {
4670 m_grid->m_coordinates[dim][pointId] =
4671 (2 * m_grid->m_coordinates[dim][FixPointId] - m_grid->m_coordinates[dim][MirrorPointId]);
4672 }
4673 } // ijk
4674 }
4675 }
4676 } // bcid
4677}
4678
4679
4680//============================================================================================================
4681//====================================COMMUNICATIONS==========================================================
4682
4683
4684void FvStructuredSolver3D::gather(const MBool periodicExchange,
4685 std::vector<std::unique_ptr<StructuredComm<nDim>>>& sndComm) {
4686 for(auto& snd : sndComm) {
4687 if(isPeriodicComm(snd) && !periodicExchange) continue;
4688 if(periodicExchange && skipPeriodicDirection(snd)) continue;
4689
4690 std::array<MInt, nDim> begin{snd->startInfoCells[0], snd->startInfoCells[1], snd->startInfoCells[2]};
4691 std::array<MInt, nDim> end{snd->endInfoCells[0], snd->endInfoCells[1], snd->endInfoCells[2]};
4692 std::array<MInt, nDim> size{snd->endInfoCells[0] - snd->startInfoCells[0],
4693 snd->endInfoCells[1] - snd->startInfoCells[1],
4694 snd->endInfoCells[2] - snd->startInfoCells[2]};
4695 const MInt totalSize = size[0] * size[1] * size[2];
4696
4697 // Aliasing the unique_pointer in snd to a raw point is needed for PSTL on NVHPC
4698 auto* cellBuffer = snd->cellBuffer.get();
4699 auto* variables = &(snd->variables[0]);
4700 for(MInt var = 0; var < snd->noVars; var++) {
4701 maia::parallelFor<true, nDim>(begin, end, [=](const MInt& i, const MInt& j, const MInt& k) {
4702 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4703 const MInt bufferId = totalSize * var + (i - begin[0]) + ((j - begin[1]) + (k - begin[2]) * size[1]) * size[0];
4704 cellBuffer[bufferId] = variables[var][cellId];
4705 });
4706 }
4707 }
4708}
4709
4710
4711void FvStructuredSolver3D::scatter(const MBool periodicExchange,
4712 std::vector<std::unique_ptr<StructuredComm<nDim>>>& rcvComm) {
4713 // the ordering of the grid points can be different from
4714 // sending instance ==> reorder it and copy it to the
4715 // right place
4716
4717 for(auto& rcv : rcvComm) {
4718 if(isPeriodicComm(rcv) && !periodicExchange) continue;
4719 if(periodicExchange && skipPeriodicDirection(rcv)) continue;
4720
4721 std::array<MInt, nDim> begin{rcv->startInfoCells[0], rcv->startInfoCells[1], rcv->startInfoCells[2]};
4722 std::array<MInt, nDim> end{rcv->endInfoCells[0], rcv->endInfoCells[1], rcv->endInfoCells[2]};
4723 std::array<MInt, nDim> size{rcv->endInfoCells[0] - rcv->startInfoCells[0],
4724 rcv->endInfoCells[1] - rcv->startInfoCells[1],
4725 rcv->endInfoCells[2] - rcv->startInfoCells[2]};
4726 const MInt totalSize = size[0] * size[1] * size[2];
4727
4728 std::array<MInt, nDim> stepBuffer{0};
4729 std::array<MInt, nDim> startBuffer{0};
4730 std::array<MInt, nDim> endBuffer{0};
4731 std::array<MInt, nDim> sizeBuffer{0};
4732
4733 for(MInt j = 0; j < nDim; j++) {
4734 stepBuffer[rcv->orderInfo[j]] = rcv->stepInfo[j];
4735 }
4736
4737 for(MInt j = 0; j < nDim; j++) {
4738 endBuffer[j] = size[j] - 1;
4739 sizeBuffer[rcv->orderInfo[j]] = size[j];
4740 if(stepBuffer[j] < 0) {
4741 std::swap(startBuffer[j], endBuffer[j]);
4742 }
4743 }
4744
4745 // Aliasing the unique_pointer in rcv to a raw point is needed for PSTL on NVHPC
4746 auto* orderInfo = rcv->orderInfo.data();
4747 auto* startInfoCells = rcv->startInfoCells.data();
4748 auto* cellBuffer = rcv->cellBuffer.get();
4749 auto* variables = &(rcv->variables[0]);
4750 for(MInt var = 0; var < rcv->noVars; var++) {
4751 maia::parallelFor<true, nDim>(begin, end, [=](const MInt& i, const MInt& j, const MInt& k) {
4752 std::array<MInt, nDim> start{};
4753 start[orderInfo[0]] = startBuffer[0] + (i - startInfoCells[0]) * stepBuffer[0];
4754 start[orderInfo[1]] = startBuffer[1] + (j - startInfoCells[1]) * stepBuffer[1];
4755 start[orderInfo[2]] = startBuffer[2] + (k - startInfoCells[2]) * stepBuffer[2];
4756
4757 const MInt bufferId = var * totalSize + start[0] + (start[1] + start[2] * sizeBuffer[1]) * sizeBuffer[0];
4758 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4759 variables[var][cellId] = cellBuffer[bufferId];
4760 });
4761 }
4762 }
4763}
4764
4766 std::vector<MPI_Request> sndRequests;
4767 std::vector<MPI_Request> rcvRequests;
4768 std::vector<MPI_Status> sndStatus;
4769 std::vector<MPI_Status> rcvStatus;
4770 sndRequests.reserve(m_waveSndComm.size());
4771 rcvRequests.reserve(m_waveRcvComm.size());
4772
4773 waveGather();
4774 waveSend(sndRequests);
4775 waveReceive(rcvRequests);
4776
4777 sndStatus.resize(sndRequests.size());
4778 MPI_Waitall(sndRequests.size(), &sndRequests[0], &sndStatus[0], AT_);
4779 rcvStatus.resize(rcvRequests.size());
4780 MPI_Waitall(rcvRequests.size(), &rcvRequests[0], &rcvStatus[0], AT_);
4781
4782 waveScatter();
4783}
4784
4785
4787 for(auto& snd : m_waveSndComm) {
4788 MInt pos = 0;
4789
4790 for(MInt var = 0; var < PV->noVariables; var++) {
4791 for(MInt k = snd->startInfoCells[2]; k < snd->endInfoCells[2]; k++) {
4792 for(MInt j = snd->startInfoCells[1]; j < snd->endInfoCells[1]; j++) {
4793 for(MInt i = snd->startInfoCells[0]; i < snd->endInfoCells[0]; i++) {
4794 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4795 snd->cellBuffer[pos] = m_cells->pvariables[var][cellId];
4796 pos++;
4797 }
4798 }
4799 }
4800 }
4801
4802 if(m_averageVorticity) {
4803 for(MInt var = 0; var < nDim; var++) {
4804 for(MInt k = snd->startInfoCells[2]; k < snd->endInfoCells[2]; k++) {
4805 for(MInt j = snd->startInfoCells[1]; j < snd->endInfoCells[1]; j++) {
4806 for(MInt i = snd->startInfoCells[0]; i < snd->endInfoCells[0]; i++) {
4807 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4808 snd->cellBuffer[pos] = m_cells->fq[FQ->VORTICITY[var]][cellId];
4809 pos++;
4810 }
4811 }
4812 }
4813 }
4814 }
4815 }
4816}
4817
4818void FvStructuredSolver3D::waveSend(std::vector<MPI_Request>& sndRequests) {
4819 for(auto& snd : m_waveSndComm) {
4820 MPI_Request request{};
4821 const MInt tag = domainId() + (snd->tagHelper) * noDomains();
4822 const MInt err = MPI_Isend((void*)&snd->cellBuffer[0], snd->cellBufferSize, MPI_DOUBLE, snd->nghbrId, tag,
4823 m_StructuredComm, &request, AT_, "snd->cellBuffer");
4824 sndRequests.push_back(request);
4825 if(err) cout << "rank " << domainId() << " sending throws error " << endl;
4826 }
4827}
4828
4829void FvStructuredSolver3D::waveReceive(std::vector<MPI_Request>& rcvRequests) {
4830 for(auto& rcv : m_waveRcvComm) {
4831 MPI_Request request{};
4832 const MInt tag = rcv->nghbrId + (rcv->tagHelper) * noDomains();
4833 const MInt err = MPI_Irecv((void*)&rcv->cellBuffer[0], rcv->cellBufferSize, MPI_DOUBLE, rcv->nghbrId, tag,
4834 m_StructuredComm, &request, AT_, "rcv->cellBuffer");
4835 rcvRequests.push_back(request);
4836 if(err) cout << "rank " << domainId() << " sending throws error " << endl;
4837 }
4838}
4839
4841 for(auto& rcv : m_waveRcvComm) {
4842 MInt pos = 0;
4843
4844 for(MInt var = 0; var < PV->noVariables; var++) {
4845 for(MInt k = rcv->startInfoCells[2]; k < rcv->endInfoCells[2]; k++) {
4846 for(MInt j = rcv->startInfoCells[1]; j < rcv->endInfoCells[1]; j++) {
4847 for(MInt i = rcv->startInfoCells[0]; i < rcv->endInfoCells[0]; i++) {
4848 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4849 m_tempWaveSample[var][cellId] = rcv->cellBuffer[pos];
4850 pos++;
4851 }
4852 }
4853 }
4854 }
4855
4856 if(m_averageVorticity) {
4857 for(MInt var = 0; var < (2 * nDim - 3); var++) {
4858 for(MInt k = rcv->startInfoCells[2]; k < rcv->endInfoCells[2]; k++) {
4859 for(MInt j = rcv->startInfoCells[1]; j < rcv->endInfoCells[1]; j++) {
4860 for(MInt i = rcv->startInfoCells[0]; i < rcv->endInfoCells[0]; i++) {
4861 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
4862 m_tempWaveSample[PV->noVariables + var][cellId] = rcv->cellBuffer[pos];
4863 pos++;
4864 }
4865 }
4866 }
4867 }
4868 }
4869 }
4870}
4871
4873 RECORD_TIMER_START(m_timers[Timers::WaveSpanwiseReordering]);
4874
4875 MInt allCellsK = m_grid->getBlockNoCells(0, 0);
4876 MInt waveZeroPos = ((MInt)round((globalTimeStep - m_movingGridStepOffset) / m_waveNoStepsPerCell)) % allCellsK;
4877
4878 if(m_waveSpeed < 0.0) {
4879 waveZeroPos =
4880 allCellsK - ((MInt)round((globalTimeStep - m_movingGridStepOffset) / m_waveNoStepsPerCell)) % allCellsK;
4881 }
4882
4883 m_windowInfo->createWaveWindowMapping(waveZeroPos);
4884
4885 MInt noVars = PV->noVariables;
4886 if(m_averageVorticity) {
4887 noVars += (2 * nDim - 3);
4889 }
4890
4891 m_windowInfo->createWaveCommunicationExchangeFlags(m_waveSndComm, m_waveRcvComm, noVars);
4892 waveExchange();
4893
4894 RECORD_TIMER_STOP(m_timers[Timers::WaveSpanwiseReordering]);
4895}
4896
4897
4898void FvStructuredSolver3D::gcFillGhostCells(vector<MFloat*>& variables) {
4899 gcExtrapolate(variables);
4900
4901 std::vector<std::unique_ptr<StructuredComm<nDim>>> gcSndComm;
4902 std::vector<std::unique_ptr<StructuredComm<nDim>>> gcRcvComm;
4903
4904 MFloat* const* const varPtr = &variables[0];
4905
4906 m_windowInfo->createCommunicationExchangeFlags(gcSndComm, gcRcvComm, (MInt)variables.size(), varPtr);
4907 exchange(gcSndComm, gcRcvComm);
4908}
4909
4910void FvStructuredSolver3D::gcExtrapolate(vector<MFloat*>& variables) {
4911 TRACE();
4912 // i-direction
4913 MInt cellId, cellIdAdj1, cellIdAdj2;
4914 const MInt noVars = variables.size();
4915 for(MInt k = 0; k < m_nCells[0]; k++) {
4916 for(MInt j = 0; j < m_nCells[1]; j++) {
4917 for(MInt i = 0; i < m_noGhostLayers; i++) {
4918 cellId = cellIndex(m_noGhostLayers - 1 - i, j, k);
4919 cellIdAdj1 = cellIndex(m_noGhostLayers - i, j, k);
4920 cellIdAdj2 = cellIndex(m_noGhostLayers + 1 - i, j, k);
4921
4922 for(MInt varPos = 0; varPos < noVars; varPos++) {
4923 variables[varPos][cellId] = (F2 * variables[varPos][cellIdAdj1] - variables[varPos][cellIdAdj2]);
4924 }
4925
4926 cellId = cellIndex(m_nCells[2] - m_noGhostLayers + i, j, k);
4927 cellIdAdj1 = cellIndex(m_nCells[2] - m_noGhostLayers - 1 + i, j, k);
4928 cellIdAdj2 = cellIndex(m_nCells[2] - m_noGhostLayers - 2 + i, j, k);
4929
4930 for(MInt varPos = 0; varPos < noVars; varPos++) {
4931 variables[varPos][cellId] = (F2 * variables[varPos][cellIdAdj1] - variables[varPos][cellIdAdj2]);
4932 }
4933 }
4934 }
4935 }
4936
4937 // j-direction
4938 for(MInt k = 0; k < m_nCells[0]; k++) {
4939 for(MInt i = 0; i < m_nCells[2]; i++) {
4940 for(MInt j = 0; j < m_noGhostLayers; j++) {
4941 cellId = cellIndex(i, m_noGhostLayers - 1 - j, k);
4942 cellIdAdj1 = cellIndex(i, m_noGhostLayers - j, k);
4943 cellIdAdj2 = cellIndex(i, m_noGhostLayers + 1 - j, k);
4944
4945 for(MInt varPos = 0; varPos < noVars; varPos++) {
4946 variables[varPos][cellId] = (F2 * variables[varPos][cellIdAdj1] - variables[varPos][cellIdAdj2]);
4947 }
4948
4949 cellId = cellIndex(i, m_nCells[1] - m_noGhostLayers + j, k); // pointId in Array
4950 cellIdAdj1 = cellIndex(i, m_nCells[1] - m_noGhostLayers - 1 + j, k);
4951 cellIdAdj2 = cellIndex(i, m_nCells[1] - m_noGhostLayers - 2 + j, k);
4952
4953 for(MInt varPos = 0; varPos < noVars; varPos++) {
4954 variables[varPos][cellId] = (F2 * variables[varPos][cellIdAdj1] - variables[varPos][cellIdAdj2]);
4955 }
4956 }
4957 }
4958 }
4959
4960 // k-direction
4961 for(MInt j = 0; j < m_nCells[1]; j++) {
4962 for(MInt i = 0; i < m_nCells[2]; i++) {
4963 for(MInt k = 0; k < m_noGhostLayers; k++) {
4964 cellId = cellIndex(i, j, m_noGhostLayers - 1 - k);
4965 cellIdAdj1 = cellIndex(i, j, m_noGhostLayers - k);
4966 cellIdAdj2 = cellIndex(i, j, m_noGhostLayers + 1 - k);
4967
4968 for(MInt varPos = 0; varPos < noVars; varPos++) {
4969 variables[varPos][cellId] = (F2 * variables[varPos][cellIdAdj1] - variables[varPos][cellIdAdj2]);
4970 }
4971
4972 cellId = cellIndex(i, j, m_nCells[0] - m_noGhostLayers + k);
4973 cellIdAdj1 = cellIndex(i, j, m_nCells[0] - m_noGhostLayers - 1 + k);
4974 cellIdAdj2 = cellIndex(i, j, m_nCells[0] - m_noGhostLayers - 2 + k);
4975
4976 for(MInt varPos = 0; varPos < noVars; varPos++) {
4977 variables[varPos][cellId] = (F2 * variables[varPos][cellIdAdj1] - variables[varPos][cellIdAdj2]);
4978 }
4979 }
4980 }
4981 }
4982}
4983
4984
4985//====================================COMMUNICATIONS==========================================================
4986//============================================================================================================
4987//============================================================================================================
4988
4989
4991 MFloat dist1 = F0;
4992 for(MInt dim = 0; dim < 3; dim++) {
4993 dist1 += POW2(a[dim * m_noCells] - b[dim * m_noCells]);
4994 }
4995 return sqrt(dist1);
4996}
4997
4998inline MInt FvStructuredSolver3D::cellIndex(const MInt i, const MInt j, const MInt k) {
4999 return i + (j + k * m_nCells[1]) * m_nCells[2];
5000}
5001
5002inline MInt FvStructuredSolver3D::getCellIdfromCell(const MInt origin, const MInt incI, const MInt incJ,
5003 const MInt incK) {
5004 return origin + incI + incJ * m_nCells[2] + incK * m_nCells[2] * m_nCells[1];
5005}
5006
5007inline MInt FvStructuredSolver3D::pointIndex(const MInt i, const MInt j, const MInt k) {
5008 return i + (j + k * m_nPoints[1]) * m_nPoints[2];
5009}
5010
5011
5013
5015
5019template <MBool twoEqRans>
5021 TRACE();
5022 const MFloat rPrLam = F1 / m_Pr;
5023 constexpr MFloat rPrTurb = F1 / 0.9;
5024 const MFloat rRe = F1 / m_Re0;
5025 const MFloat gammaMinusOne = m_gamma - 1.0;
5026 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
5027
5028 const MFloat* const RESTRICT u = ALIGNED_F(&m_cells->pvariables[PV->U][0]);
5029 const MFloat* const RESTRICT v = ALIGNED_F(&m_cells->pvariables[PV->V][0]);
5030 const MFloat* const RESTRICT w = ALIGNED_F(&m_cells->pvariables[PV->W][0]);
5031 const MFloat* const RESTRICT p = ALIGNED_F(&m_cells->pvariables[PV->P][0]);
5032 const MFloat* const RESTRICT rho = ALIGNED_F(&m_cells->pvariables[PV->RHO][0]);
5033 MFloat* const RESTRICT T = ALIGNED_F(&m_cells->temperature[0]);
5034 MFloat* const RESTRICT muLam = ALIGNED_F(&m_cells->fq[FQ->MU_L][0]);
5035 MFloat* const RESTRICT muTurb = ALIGNED_F(&m_cells->fq[FQ->MU_T][0]); // this is zero for LES
5036
5037 MFloat* const* const RESTRICT eflux = ALIGNED_F(m_cells->eFlux);
5038 MFloat* const* const RESTRICT fflux = ALIGNED_F(m_cells->fFlux);
5039 MFloat* const* const RESTRICT gflux = ALIGNED_F(m_cells->gFlux);
5040 MFloat* const* const RESTRICT vflux = ALIGNED_F(m_cells->viscousFlux);
5041
5042 // only relevant for 2-eq Rans model (Waiting for if constexpr)
5043 const MFloat* const RESTRICT TKE = (twoEqRans) ? ALIGNED_F(m_cells->pvariables[PV->RANS_VAR[0]]) : nullptr;
5044
5045 maia::parallelFor<true, nDim>(beginP1(), endM1(), [=](const MInt& i, const MInt& j, const MInt& k) {
5046 const MInt I = cellIndex(i, j, k);
5047 T[I] = m_gamma * p[I] / rho[I];
5048 muLam[I] = SUTHERLANDLAW(T[I]);
5049 });
5050
5051 maia::parallelFor<true, nDim>(beginP1(), endM1(), [=](const MInt& i, const MInt& j, const MInt& k) {
5052 // get the adjacent cells;
5053 const MInt IJK = cellIndex(i, j, k);
5054 const MInt IPJK = cellIndex((i + 1), j, k);
5055 const MInt IPJPK = cellIndex((i + 1), (j + 1), k);
5056 const MInt IJPK = cellIndex(i, (j + 1), k);
5057 const MInt IJKP = cellIndex(i, j, (k + 1));
5058 const MInt IPJKP = cellIndex((i + 1), j, (k + 1));
5059 const MInt IPJPKP = cellIndex((i + 1), (j + 1), (k + 1));
5060 const MInt IJPKP = cellIndex(i, (j + 1), (k + 1));
5061
5062 const MFloat cornerMetrics[9] = {
5063 m_cells->cornerMetrics[0][IJK], m_cells->cornerMetrics[1][IJK], m_cells->cornerMetrics[2][IJK],
5064 m_cells->cornerMetrics[3][IJK], m_cells->cornerMetrics[4][IJK], m_cells->cornerMetrics[5][IJK],
5065 m_cells->cornerMetrics[6][IJK], m_cells->cornerMetrics[7][IJK], m_cells->cornerMetrics[8][IJK]};
5066
5067
5068 const MFloat dudxi = F1B4 * (u[IPJPKP] + u[IPJPK] + u[IPJKP] + u[IPJK] - u[IJPKP] - u[IJPK] - u[IJKP] - u[IJK]);
5069 const MFloat dudet = F1B4 * (u[IPJPKP] + u[IJPKP] + u[IPJPK] + u[IJPK] - u[IPJKP] - u[IJKP] - u[IPJK] - u[IJK]);
5070 const MFloat dudze = F1B4 * (u[IPJPKP] + u[IJPKP] + u[IPJKP] + u[IJKP] - u[IPJPK] - u[IJPK] - u[IPJK] - u[IJK]);
5071
5072 const MFloat dvdxi = F1B4 * (v[IPJPKP] + v[IPJPK] + v[IPJKP] + v[IPJK] - v[IJPKP] - v[IJPK] - v[IJKP] - v[IJK]);
5073 const MFloat dvdet = F1B4 * (v[IPJPKP] + v[IJPKP] + v[IPJPK] + v[IJPK] - v[IPJKP] - v[IJKP] - v[IPJK] - v[IJK]);
5074 const MFloat dvdze = F1B4 * (v[IPJPKP] + v[IJPKP] + v[IPJKP] + v[IJKP] - v[IPJPK] - v[IJPK] - v[IPJK] - v[IJK]);
5075
5076 const MFloat dwdxi = F1B4 * (w[IPJPKP] + w[IPJPK] + w[IPJKP] + w[IPJK] - w[IJPKP] - w[IJPK] - w[IJKP] - w[IJK]);
5077 const MFloat dwdet = F1B4 * (w[IPJPKP] + w[IJPKP] + w[IPJPK] + w[IJPK] - w[IPJKP] - w[IJKP] - w[IPJK] - w[IJK]);
5078 const MFloat dwdze = F1B4 * (w[IPJPKP] + w[IJPKP] + w[IPJKP] + w[IJKP] - w[IPJPK] - w[IJPK] - w[IPJK] - w[IJK]);
5079
5080 const MFloat dTdxi = F1B4 * (T[IPJPKP] + T[IPJPK] + T[IPJKP] + T[IPJK] - T[IJPKP] - T[IJPK] - T[IJKP] - T[IJK]);
5081 const MFloat dTdet = F1B4 * (T[IPJPKP] + T[IJPKP] + T[IPJPK] + T[IJPK] - T[IPJKP] - T[IJKP] - T[IPJK] - T[IJK]);
5082 const MFloat dTdze = F1B4 * (T[IPJPKP] + T[IJPKP] + T[IPJKP] + T[IJKP] - T[IPJPK] - T[IJPK] - T[IPJK] - T[IJK]);
5083
5084 const MFloat uAvg = F1B8 * (u[IPJPKP] + u[IJPKP] + u[IJPK] + u[IPJPK] + u[IPJKP] + u[IJKP] + u[IJK] + u[IPJK]);
5085 const MFloat vAvg = F1B8 * (v[IPJPKP] + v[IJPKP] + v[IJPK] + v[IPJPK] + v[IPJKP] + v[IJKP] + v[IJK] + v[IPJK]);
5086 const MFloat wAvg = F1B8 * (w[IPJPKP] + w[IJPKP] + w[IJPK] + w[IPJPK] + w[IPJKP] + w[IJKP] + w[IJK] + w[IPJK]);
5087
5088 const MFloat muLamAvg = F1B8
5089 * (muLam[IPJPKP] + muLam[IJPKP] + muLam[IJPK] + muLam[IPJPK] + muLam[IPJKP] + muLam[IJKP]
5090 + muLam[IJK] + muLam[IPJK]);
5091
5092 // turbulent viscosity is set to zero for LES
5093 // and is only non-zero for RANS
5094 const MFloat muTurbAvg = F1B8
5095 * (muTurb[IPJPKP] + muTurb[IJPKP] + muTurb[IJPK] + muTurb[IPJPK] + muTurb[IPJKP]
5096 + muTurb[IJKP] + muTurb[IJK] + muTurb[IPJK]);
5097
5098 MFloat TKEcorner = F0;
5099 if(twoEqRans)
5100 TKEcorner =
5101 -2 / 3 * F1B8
5102 * (rho[IPJPKP] * TKE[IPJPKP] + rho[IJPKP] * TKE[IJPKP] + rho[IJPK] * TKE[IJPK] + rho[IPJPK] * TKE[IPJPK]
5103 + rho[IPJKP] * TKE[IPJKP] + rho[IJKP] * TKE[IJKP] + rho[IJK] * TKE[IJK] + rho[IPJK] * TKE[IPJK]);
5104
5105 // compute tau1 = 2 du/dx - 2/3 ( du/dx + dv/dy + dw/dz )
5106
5107 // tau_xx = 4/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx )
5108 // - 2/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy)
5109 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
5110 MFloat tau1 = F4B3
5111 * (dudxi * cornerMetrics[xsd * 3 + xsd] + dudet * cornerMetrics[ysd * 3 + xsd]
5112 + dudze * cornerMetrics[zsd * 3 + xsd])
5113 -
5114
5115 F2B3
5116 * (dvdxi * cornerMetrics[xsd * 3 + ysd] + dvdet * cornerMetrics[ysd * 3 + ysd]
5117 + dvdze * cornerMetrics[zsd * 3 + ysd])
5118 -
5119
5120 F2B3
5121 * (dwdxi * cornerMetrics[xsd * 3 + zsd] + dwdet * cornerMetrics[ysd * 3 + zsd]
5122 + dwdze * cornerMetrics[zsd * 3 + zsd]);
5123
5124 // compute tau2 = du/dy + dv/dx
5125
5126 // tau_xy = du/dxi * dxi/dy + du/deta * deta/dy + du/dzeta * dzeta/dy
5127 // + dv/dxi * dxi/dx + dv/deta * deta/dx + dv/dzeta * dzeta/dx
5128 MFloat tau2 = dudxi * cornerMetrics[xsd * 3 + ysd] + dudet * cornerMetrics[ysd * 3 + ysd]
5129 + dudze * cornerMetrics[zsd * 3 + ysd] +
5130
5131 dvdxi * cornerMetrics[xsd * 3 + xsd] + dvdet * cornerMetrics[ysd * 3 + xsd]
5132 + dvdze * cornerMetrics[zsd * 3 + xsd];
5133
5134 // compute tau3 = du/dz + dw/dx
5135
5136 // tau_xz = du/dxi * dxi/dz + du/deta * deta/dz + du/dzeta * dzeta/dz
5137 // + dw/dxi * dxi/dx + dw/deta * deta/dx + dw/dzeta * dzeta/dx
5138 MFloat tau3 = dudxi * cornerMetrics[xsd * 3 + zsd] + dudet * cornerMetrics[ysd * 3 + zsd]
5139 + dudze * cornerMetrics[zsd * 3 + zsd] +
5140
5141 dwdxi * cornerMetrics[xsd * 3 + xsd] + dwdet * cornerMetrics[ysd * 3 + xsd]
5142 + dwdze * cornerMetrics[zsd * 3 + xsd];
5143
5144 // compute tau4 = 2 dv/dy - 2/3 ( du/dx + dv/dy + dw/dz )
5145
5146 // tau_yy = 4/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy )
5147 // - 2/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx)
5148 // - 2/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
5149 MFloat tau4 = F4B3
5150 * (dvdxi * cornerMetrics[xsd * 3 + ysd] + dvdet * cornerMetrics[ysd * 3 + ysd]
5151 + dvdze * cornerMetrics[zsd * 3 + ysd])
5152 -
5153
5154 F2B3
5155 * (dudxi * cornerMetrics[xsd * 3 + xsd] + dudet * cornerMetrics[ysd * 3 + xsd]
5156 + dudze * cornerMetrics[zsd * 3 + xsd])
5157 -
5158
5159 F2B3
5160 * (dwdxi * cornerMetrics[xsd * 3 + zsd] + dwdet * cornerMetrics[ysd * 3 + zsd]
5161 + dwdze * cornerMetrics[zsd * 3 + zsd]);
5162
5163 // compute tau5 = dv/dz + dw/dy
5164
5165 // tau_yz = dv/dxi * dxi/dz + dv/deta * deta/dz + dv/dzeta * dzeta/dz
5166 // + dw/dxi * dxi/dy + dw/deta * deta/dy + dw/dzeta * dzeta/dy
5167 MFloat tau5 = dvdxi * cornerMetrics[xsd * 3 + zsd] + dvdet * cornerMetrics[ysd * 3 + zsd]
5168 + dvdze * cornerMetrics[zsd * 3 + zsd] +
5169
5170 dwdxi * cornerMetrics[xsd * 3 + ysd] + dwdet * cornerMetrics[ysd * 3 + ysd]
5171 + dwdze * cornerMetrics[zsd * 3 + ysd];
5172
5173 // compute tau6 = 2 dw/dz - 2/3 ( du/dx + dv/dy + dw/dz )
5174
5175 // tau_zz = 4/3*( dw/dxi * dxi/dz + dw/deta * deta/dz + dw/dzeta * dzeta/dz )
5176 // - 2/3*( du/dxi * dxi/dx + du/deta * deta/dx + du/dzeta * dzeta/dx)
5177 // - 2/3*( dv/dxi * dxi/dy + dv/deta * deta/dy + dv/dzeta * dzeta/dy)
5178 MFloat tau6 = F4B3
5179 * (dwdxi * cornerMetrics[xsd * 3 + zsd] + dwdet * cornerMetrics[ysd * 3 + zsd]
5180 + dwdze * cornerMetrics[zsd * 3 + zsd])
5181 -
5182
5183 F2B3
5184 * (dudxi * cornerMetrics[xsd * 3 + xsd] + dudet * cornerMetrics[ysd * 3 + xsd]
5185 + dudze * cornerMetrics[zsd * 3 + xsd])
5186 -
5187
5188 F2B3
5189 * (dvdxi * cornerMetrics[xsd * 3 + ysd] + dvdet * cornerMetrics[ysd * 3 + ysd]
5190 + dvdze * cornerMetrics[zsd * 3 + ysd]);
5191
5192
5193 const MFloat dTdx = dTdxi * cornerMetrics[xsd * 3 + xsd] + dTdet * cornerMetrics[ysd * 3 + xsd]
5194 + dTdze * cornerMetrics[zsd * 3 + xsd];
5195
5196 const MFloat dTdy = dTdxi * cornerMetrics[xsd * 3 + ysd] + dTdet * cornerMetrics[ysd * 3 + ysd]
5197 + dTdze * cornerMetrics[zsd * 3 + ysd];
5198
5199 const MFloat dTdz = dTdxi * cornerMetrics[xsd * 3 + zsd] + dTdet * cornerMetrics[ysd * 3 + zsd]
5200 + dTdze * cornerMetrics[zsd * 3 + zsd];
5201
5202 const MFloat fJac = 1.0 / m_cells->cornerJac[IJK];
5203 const MFloat mueOverRe = rRe * fJac * (muLamAvg + muTurbAvg);
5204 tau1 = mueOverRe * tau1 + TKEcorner;
5205 tau2 *= mueOverRe;
5206 tau3 *= mueOverRe;
5207 tau4 = mueOverRe * tau4 + TKEcorner;
5208 tau5 *= mueOverRe;
5209 tau6 = mueOverRe * tau6 + TKEcorner;
5210
5211 const MFloat muCombined = FgammaMinusOne * rRe * fJac * (rPrLam * muLamAvg + rPrTurb * muTurbAvg);
5212
5213 const MFloat qx = muCombined * dTdx + uAvg * tau1 + vAvg * tau2 + wAvg * tau3;
5214 const MFloat qy = muCombined * dTdy + uAvg * tau2 + vAvg * tau4 + wAvg * tau5;
5215 const MFloat qz = muCombined * dTdz + uAvg * tau3 + vAvg * tau5 + wAvg * tau6;
5216
5217 // efluxes
5218 eflux[0][IJK] =
5219 tau1 * cornerMetrics[xsd * 3 + xsd] + tau2 * cornerMetrics[xsd * 3 + ysd] + tau3 * cornerMetrics[xsd * 3 + zsd];
5220
5221 eflux[1][IJK] =
5222 tau2 * cornerMetrics[xsd * 3 + xsd] + tau4 * cornerMetrics[xsd * 3 + ysd] + tau5 * cornerMetrics[xsd * 3 + zsd];
5223
5224 eflux[2][IJK] =
5225 tau3 * cornerMetrics[xsd * 3 + xsd] + tau5 * cornerMetrics[xsd * 3 + ysd] + tau6 * cornerMetrics[xsd * 3 + zsd];
5226
5227 eflux[3][IJK] =
5228 qx * cornerMetrics[xsd * 3 + xsd] + qy * cornerMetrics[xsd * 3 + ysd] + qz * cornerMetrics[xsd * 3 + zsd];
5229
5230 // ffluxes
5231 fflux[0][IJK] =
5232 tau1 * cornerMetrics[ysd * 3 + xsd] + tau2 * cornerMetrics[ysd * 3 + ysd] + tau3 * cornerMetrics[ysd * 3 + zsd];
5233
5234 fflux[1][IJK] =
5235 tau2 * cornerMetrics[ysd * 3 + xsd] + tau4 * cornerMetrics[ysd * 3 + ysd] + tau5 * cornerMetrics[ysd * 3 + zsd];
5236
5237 fflux[2][IJK] =
5238 tau3 * cornerMetrics[ysd * 3 + xsd] + tau5 * cornerMetrics[ysd * 3 + ysd] + tau6 * cornerMetrics[ysd * 3 + zsd];
5239
5240 fflux[3][IJK] =
5241 qx * cornerMetrics[ysd * 3 + xsd] + qy * cornerMetrics[ysd * 3 + ysd] + qz * cornerMetrics[ysd * 3 + zsd];
5242
5243 // gfluxes
5244 gflux[0][IJK] =
5245 tau1 * cornerMetrics[zsd * 3 + xsd] + tau2 * cornerMetrics[zsd * 3 + ysd] + tau3 * cornerMetrics[zsd * 3 + zsd];
5246
5247 gflux[1][IJK] =
5248 tau2 * cornerMetrics[zsd * 3 + xsd] + tau4 * cornerMetrics[zsd * 3 + ysd] + tau5 * cornerMetrics[zsd * 3 + zsd];
5249
5250 gflux[2][IJK] =
5251 tau3 * cornerMetrics[zsd * 3 + xsd] + tau5 * cornerMetrics[zsd * 3 + ysd] + tau6 * cornerMetrics[zsd * 3 + zsd];
5252
5253 gflux[3][IJK] =
5254 qx * cornerMetrics[zsd * 3 + xsd] + qy * cornerMetrics[zsd * 3 + ysd] + qz * cornerMetrics[zsd * 3 + zsd];
5255 });
5256
5257
5258 // viscous flux correction for the singular points
5259 // m_hasSingularity=0 means no singular points in this block, otherwise do flux correction
5260 if(m_hasSingularity > 0) {
5262 }
5263
5264 for(MInt var = 0; var < 4; var++) {
5265 const std::array<MInt, nDim> beginIM1{m_noGhostLayers - 1, m_noGhostLayers, m_noGhostLayers};
5266 maia::parallelFor<true, nDim>(beginIM1, endM2(), [=](const MInt& i, const MInt& j, const MInt& k) {
5267 const MInt IJK = cellIndex(i, j, k);
5268 const MInt IJMK = cellIndex(i, (j - 1), k);
5269 const MInt IJKM = cellIndex(i, j, (k - 1));
5270 const MInt IJMKM = cellIndex(i, (j - 1), (k - 1));
5271
5272 vflux[0][IJK] = F1B4 * (eflux[var][IJK] + eflux[var][IJKM] + eflux[var][IJMK] + eflux[var][IJMKM]);
5273 });
5274
5275
5276 const std::array<MInt, nDim> beginJM1{m_noGhostLayers, m_noGhostLayers - 1, m_noGhostLayers};
5277 maia::parallelFor<true, nDim>(beginJM1, endM2(), [=](const MInt& i, const MInt& j, const MInt& k) {
5278 const MInt IJK = cellIndex(i, j, k);
5279 const MInt IMJK = cellIndex((i - 1), j, k);
5280 const MInt IJKM = cellIndex(i, j, (k - 1));
5281 const MInt IMJKM = cellIndex((i - 1), j, (k - 1));
5282
5283 vflux[1][IJK] = F1B4 * (fflux[var][IJK] + fflux[var][IJKM] + fflux[var][IMJK] + fflux[var][IMJKM]);
5284 });
5285
5286 const std::array<MInt, nDim> beginKM1{m_noGhostLayers, m_noGhostLayers, m_noGhostLayers - 1};
5287 maia::parallelFor<true, nDim>(beginKM1, endM2(), [=](const MInt& i, const MInt& j, const MInt& k) {
5288 const MInt IJK = cellIndex(i, j, k);
5289 const MInt IMJK = cellIndex((i - 1), j, k);
5290 const MInt IJMK = cellIndex(i, (j - 1), k);
5291 const MInt IMJMK = cellIndex((i - 1), (j - 1), k);
5292
5293 vflux[2][IJK] = F1B4 * (gflux[var][IJK] + gflux[var][IMJK] + gflux[var][IJMK] + gflux[var][IMJMK]);
5294 });
5295
5296 maia::parallelFor<true, nDim>(beginP2(), endM2(), [=](const MInt& i, const MInt& j, const MInt& k) {
5297 const MInt IJK = cellIndex(i, j, k);
5298 const MInt IMJK = cellIndex(i - 1, j, k);
5299 const MInt IJMK = cellIndex(i, j - 1, k);
5300 const MInt IJKM = cellIndex(i, j, k - 1);
5301 m_cells->rightHandSide[var][IJK] +=
5302 vflux[0][IJK] - vflux[0][IMJK] + vflux[1][IJK] - vflux[1][IJMK] + vflux[2][IJK] - vflux[2][IJKM];
5303 });
5304 }
5305}
5306
5307
5309 const MFloat rPr = F1 / m_Pr;
5310 const MFloat rRe = F1 / m_Re0;
5311 const MFloat gammaMinusOne = m_gamma - 1.0;
5312 const MFloat FgammaMinusOne = F1 / gammaMinusOne;
5313
5314 MFloat* RESTRICT rhou = &m_cells->variables[CV->RHO_U][0];
5315 MFloat* RESTRICT rhov = &m_cells->variables[CV->RHO_V][0];
5316 MFloat* RESTRICT rhow = &m_cells->variables[CV->RHO_W][0];
5317 MFloat* RESTRICT rhoE = &m_cells->variables[CV->RHO_E][0];
5318 MFloat* RESTRICT rho = &m_cells->variables[CV->RHO][0];
5319
5320 MFloat* const* const RESTRICT eflux = ALIGNED_F(m_cells->eFlux);
5321 MFloat* const* const RESTRICT fflux = ALIGNED_F(m_cells->fFlux);
5322 MFloat* const* const RESTRICT gflux = ALIGNED_F(m_cells->gFlux);
5323
5324 MInt dim = 0;
5325 MInt start[3], end[3], nghbr[20];
5326 MInt len1[3];
5327 MInt totalCells;
5328
5329 for(MInt i = 0; i < m_hasSingularity; ++i) {
5330 // only correct for bc 6000 not for bc 4000-5000
5331 if(m_singularity[i].BC == -6000) {
5332 totalCells = 1;
5333 for(MInt j = 0; j < nDim; j++) {
5334 len1[j] = m_singularity[i].end[j] - m_singularity[i].start[j];
5335 if(len1[j] != 0) totalCells *= len1[j];
5336 }
5337
5338 for(MInt n = 0; n < 3; ++n) {
5339 if(m_singularity[i].end[n] - m_singularity[i].start[n] > 1) {
5340 dim = n;
5341 // start[n]=m_singularity[i].start[n]+1;
5342 start[n] = m_singularity[i].start[n] + 1;
5343 end[n] = m_singularity[i].end[n] - 1;
5344 } else {
5345 start[n] = m_singularity[i].start[n];
5346 end[n] = m_singularity[i].end[n];
5347 }
5348 }
5349
5350 MFloat u[20], v[20], w[20], T[20];
5351 MFloat U, V, W, t, dudx, dudy, dudz, dvdx, dvdy, dvdz, dwdx, dwdy, dwdz, dTdx, dTdy, dTdz;
5352 MFloat qx, qy, qz;
5353 MFloat tau1, tau2, tau3, tau4, tau5, tau6;
5354 MFloat mueOverRe, mue, mueH;
5355 for(MInt kk = start[2]; kk < end[2]; ++kk) {
5356 for(MInt jj = start[1]; jj < end[1]; ++jj) {
5357 for(MInt ii = start[0]; ii < end[0]; ++ii) {
5358 MInt count = 0;
5359 MInt temp[3] = {0, 0, 0};
5360 MInt IJK = cellIndex(ii + m_singularity[i].Viscous[0], jj + m_singularity[i].Viscous[1],
5361 kk + m_singularity[i].Viscous[2]);
5362
5363 const MFloat cornerMetrics[9] = {
5364 m_cells->cornerMetrics[0][IJK], m_cells->cornerMetrics[1][IJK], m_cells->cornerMetrics[2][IJK],
5365 m_cells->cornerMetrics[3][IJK], m_cells->cornerMetrics[4][IJK], m_cells->cornerMetrics[5][IJK],
5366 m_cells->cornerMetrics[6][IJK], m_cells->cornerMetrics[7][IJK], m_cells->cornerMetrics[8][IJK]};
5367
5368 temp[dim] = 1;
5369 nghbr[count++] = cellIndex(ii, jj, kk);
5370 nghbr[count++] = cellIndex(ii + temp[0], jj + temp[1], kk + temp[2]);
5371
5372 for(MInt m = 0; m < m_singularity[i].Nstar - 1; ++m) {
5373 MInt* change = m_singularity[i].displacement[m];
5374 nghbr[count++] = cellIndex(ii + change[0], jj + change[1], kk + change[2]);
5375 nghbr[count++] = cellIndex(ii + temp[0] + change[0], jj + temp[1] + change[1], kk + temp[2] + change[2]);
5376 }
5377
5378 if(count != m_singularity[i].Nstar * 2) {
5379 cout << "what the hell! it is wrong!!!" << endl;
5380 }
5381
5382 for(MInt m = 0; m < m_singularity[i].Nstar * 2; ++m) {
5383 u[m] = rhou[nghbr[m]] / rho[nghbr[m]];
5384 v[m] = rhov[nghbr[m]] / rho[nghbr[m]];
5385 w[m] = rhow[nghbr[m]] / rho[nghbr[m]];
5386 T[m] = (m_gamma * gammaMinusOne
5387 * (rhoE[nghbr[m]] - F1B2 * rho[nghbr[m]] * (POW2(u[m]) + POW2(v[m]) + POW2(w[m]))))
5388 / rho[nghbr[m]];
5389 }
5390
5391 U = F0;
5392 V = F0;
5393 W = F0;
5394 t = F0;
5395 dudx = F0;
5396 dudy = F0;
5397 dudz = F0;
5398 dvdx = F0;
5399 dvdy = F0;
5400 dvdz = F0;
5401 dwdx = F0;
5402 dwdy = F0;
5403 dwdz = F0;
5404 dTdx = F0;
5405 dTdy = F0;
5406 dTdz = F0;
5407
5408 MInt id2 = ii - start[0] + ((jj - start[1]) + (kk - start[2]) * len1[1]) * len1[0];
5409
5410 for(MInt n = 0; n < count; n++) {
5411 MInt ID = id2 * count + n;
5412 U += m_singularity[i].ReconstructionConstants[0][ID] * u[n];
5413 dudx += m_singularity[i].ReconstructionConstants[1][ID] * u[n];
5414 dudy += m_singularity[i].ReconstructionConstants[2][ID] * u[n];
5415 dudz += m_singularity[i].ReconstructionConstants[3][ID] * u[n];
5416
5417 V += m_singularity[i].ReconstructionConstants[0][ID] * v[n];
5418 dvdx += m_singularity[i].ReconstructionConstants[1][ID] * v[n];
5419 dvdy += m_singularity[i].ReconstructionConstants[2][ID] * v[n];
5420 dvdz += m_singularity[i].ReconstructionConstants[3][ID] * v[n];
5421
5422 W += m_singularity[i].ReconstructionConstants[0][ID] * w[n];
5423 dwdx += m_singularity[i].ReconstructionConstants[1][ID] * w[n];
5424 dwdy += m_singularity[i].ReconstructionConstants[2][ID] * w[n];
5425 dwdz += m_singularity[i].ReconstructionConstants[3][ID] * w[n];
5426
5427 t += m_singularity[i].ReconstructionConstants[0][ID] * T[n];
5428 dTdx += m_singularity[i].ReconstructionConstants[1][ID] * T[n];
5429 dTdy += m_singularity[i].ReconstructionConstants[2][ID] * T[n];
5430 dTdz += m_singularity[i].ReconstructionConstants[3][ID] * T[n];
5431 }
5432
5433 tau1 = 2 * dudx - 2 / 3 * (dudx + dvdy + dwdz);
5434 tau2 = dudy + dvdx;
5435 tau3 = dudz + dwdx;
5436 tau4 = 2 * dvdy - 2 / 3 * (dudx + dvdy + dwdz);
5437 tau5 = dvdz + dwdy;
5438 tau6 = 2 * dwdz - 2 / 3 * (dudx + dvdy + dwdz);
5439
5440 mue = SUTHERLANDLAW(t);
5441 mueOverRe = mue * rRe;
5442 tau1 *= mueOverRe;
5443 tau2 *= mueOverRe;
5444 tau3 *= mueOverRe;
5445 tau4 *= mueOverRe;
5446 tau5 *= mueOverRe;
5447 tau6 *= mueOverRe;
5448 mueH = FgammaMinusOne * mueOverRe * rPr;
5449
5450 qx = mueH * dTdx + U * tau1 + V * tau2 + W * tau3;
5451 qy = mueH * dTdy + U * tau2 + V * tau4 + W * tau5;
5452 qz = mueH * dTdz + U * tau3 + V * tau5 + W * tau6;
5453
5454
5455 // efluxes
5456 eflux[0][IJK] = tau1 * cornerMetrics[xsd * 3 + xsd] + tau2 * cornerMetrics[xsd * 3 + ysd]
5457 + tau3 * cornerMetrics[xsd * 3 + zsd];
5458
5459 eflux[1][IJK] = tau2 * cornerMetrics[xsd * 3 + xsd] + tau4 * cornerMetrics[xsd * 3 + ysd]
5460 + tau5 * cornerMetrics[xsd * 3 + zsd];
5461
5462 eflux[2][IJK] = tau3 * cornerMetrics[xsd * 3 + xsd] + tau5 * cornerMetrics[xsd * 3 + ysd]
5463 + tau6 * cornerMetrics[xsd * 3 + zsd];
5464
5465 eflux[3][IJK] = qx * cornerMetrics[xsd * 3 + xsd] + qy * cornerMetrics[xsd * 3 + ysd]
5466 + qz * cornerMetrics[xsd * 3 + zsd];
5467
5468 // ffluxes
5469 fflux[0][IJK] = tau1 * cornerMetrics[ysd * 3 + xsd] + tau2 * cornerMetrics[ysd * 3 + ysd]
5470 + tau3 * cornerMetrics[ysd * 3 + zsd];
5471
5472 fflux[1][IJK] = tau2 * cornerMetrics[ysd * 3 + xsd] + tau4 * cornerMetrics[ysd * 3 + ysd]
5473 + tau5 * cornerMetrics[ysd * 3 + zsd];
5474
5475 fflux[2][IJK] = tau3 * cornerMetrics[ysd * 3 + xsd] + tau5 * cornerMetrics[ysd * 3 + ysd]
5476 + tau6 * cornerMetrics[ysd * 3 + zsd];
5477
5478 fflux[3][IJK] = qx * cornerMetrics[ysd * 3 + xsd] + qy * cornerMetrics[ysd * 3 + ysd]
5479 + qz * cornerMetrics[ysd * 3 + zsd];
5480
5481 // gfluxes
5482 gflux[0][IJK] = tau1 * cornerMetrics[zsd * 3 + xsd] + tau2 * cornerMetrics[zsd * 3 + ysd]
5483 + tau3 * cornerMetrics[zsd * 3 + zsd];
5484
5485 gflux[1][IJK] = tau2 * cornerMetrics[zsd * 3 + xsd] + tau4 * cornerMetrics[zsd * 3 + ysd]
5486 + tau5 * cornerMetrics[zsd * 3 + zsd];
5487
5488 gflux[2][IJK] = tau3 * cornerMetrics[zsd * 3 + xsd] + tau5 * cornerMetrics[zsd * 3 + ysd]
5489 + tau6 * cornerMetrics[zsd * 3 + zsd];
5490
5491 gflux[3][IJK] = qx * cornerMetrics[zsd * 3 + xsd] + qy * cornerMetrics[zsd * 3 + ysd]
5492 + qz * cornerMetrics[zsd * 3 + zsd];
5493 }
5494 }
5495 }
5496 }
5497 }
5498}
5499
5500
5502 TRACE();
5503
5504 const MFloat rRe0 = 1.0 / m_Re0;
5505
5506 const MFloat* const* const RESTRICT pvars = m_cells->pvariables;
5507 const MFloat* const RESTRICT muLam = &m_cells->fq[FQ->MU_L][0];
5508 const MFloat* const RESTRICT por = &m_cells->fq[FQ->POROSITY][0];
5509 const MFloat* const RESTRICT Da = &m_cells->fq[FQ->DARCY][0];
5510 const MFloat* const RESTRICT cf = &m_cells->fq[FQ->FORCH][0];
5511
5512 if(isRans) {
5513 mTerm(1, "Porous stuff for 3D RANS not implemented yet!");
5514 } else { // LES
5515 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
5516 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; ++j) {
5517 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; ++i) {
5518 const MInt IJK = cellIndex(i, j, k);
5519 MFloat velAbs = F0;
5520 for(MInt dim = 0; dim < nDim; ++dim) {
5521 velAbs += POW2(pvars[PV->VV[dim]][IJK]);
5522 }
5523 velAbs = sqrt(velAbs);
5524 const MFloat rDa = 1.0 / Da[IJK];
5525 const MFloat porPOW2 = POW2(por[IJK]);
5526 for(MInt dim = 0; dim < nDim; ++dim) {
5527 m_cells->rightHandSide[CV->RHO_VV[dim]][IJK] +=
5528 -(rRe0 * rDa * por[IJK] * muLam[IJK] + porPOW2 * sqrt(rDa) * cf[IJK] * velAbs * pvars[PV->RHO][IJK])
5529 * pvars[dim /*PV->VV[dim] <-- why is this giving linking error???*/][IJK] * m_cells->cellJac[IJK];
5530 }
5531 }
5532 }
5533 }
5534 }
5535}
5536
5537
5555 TRACE();
5556
5557 if(globalTimeStep % m_residualInterval != 0) return true;
5558 MFloat epsilon = pow(10.0, -10.0);
5559 m_avrgResidual = F0;
5560 MInt cellId = F0;
5561 MFloat tmpResidual = F0;
5562 MFloat maxResidual1 = F0;
5563 MInt maxResIndex[3];
5564 // MInt localCounter=F0;
5565 MFloat maxResidualOrg = F0;
5566 MFloat localMaxResidual = F0;
5567 MFloat localAvrgResidual = F0;
5568 MFloat accumAvrgResidual = F0;
5569 MFloat globalMaxResidual = F0;
5570 m_workload = F0;
5571 // MInt accumCounter=0;
5572 for(MInt dim = 0; dim < nDim; dim++) {
5573 maxResIndex[dim] = F0;
5574 }
5575
5576 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
5577 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
5578 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
5579 cellId = cellIndex(i, j, k);
5580 // cerr << cellId << endl;
5581 tmpResidual = m_timeStep / (m_cfl * m_cells->cellJac[cellId]) * fabs(m_cells->rightHandSide[CV->RHO][cellId]);
5582 m_avrgResidual += tmpResidual;
5583
5584 if(tmpResidual > maxResidual1) {
5585 maxResIndex[0] = i - m_noGhostLayers;
5586 maxResIndex[1] = j - m_noGhostLayers;
5587 maxResIndex[2] = k - m_noGhostLayers;
5588 maxResidual1 = tmpResidual;
5589 }
5590 }
5591 }
5592 }
5593
5594 // localCounter = counter;
5595 localMaxResidual = maxResidual1;
5596 localAvrgResidual = m_avrgResidual;
5597 // reset average Residual
5598 m_avrgResidual = F0;
5599
5600 MFloat localTotalEnergy = F0;
5601 MFloat globalTotalEnergy = F0;
5602 MFloat globalPressure = F0;
5603 MFloat localPressure = F0;
5604 if(m_initialCondition == 101) {
5605 localTotalEnergy = computeTotalKineticEngergy();
5606 MPI_Allreduce(&localTotalEnergy, &globalTotalEnergy, 1, MPI_DOUBLE, MPI_SUM, m_StructuredComm, AT_,
5607 "localTotalEnergy", "globalTotalEnergy");
5608 globalTotalEnergy /= ((16.0 * pow(4 * atan(1), 3.0))); // divided by the overall volume
5609 localPressure = computeTotalPressure();
5610 MPI_Allreduce(&localPressure, &globalPressure, 1, MPI_DOUBLE, MPI_SUM, m_StructuredComm, AT_, "localPressure",
5611 "globalPressure");
5612 globalPressure /= ((16.0 * pow(4 * atan(1), 3.0))); // divided by the overall volume
5613 }
5614
5615 // if( noDomains()>1 )
5616 // {
5617 // MPI_Allreduce(m_residualSnd, &m_residualRcv, 1, m_mpiStruct, m_resOp, m_StructuredComm, AT_, "m_residualSnd",
5618 // "m_residualRcv" );
5619 MPI_Allreduce(&localAvrgResidual, &accumAvrgResidual, 1, MPI_DOUBLE, MPI_SUM, m_StructuredComm, AT_,
5620 "localAvrgResidual", "accumAvrgResidual");
5621 MPI_Allreduce(&localMaxResidual, &globalMaxResidual, 1, MPI_DOUBLE, MPI_MAX, m_StructuredComm, AT_,
5622 "localMaxResidual", "globalMaxResidual");
5623
5624 m_avrgResidual = accumAvrgResidual; // m_residualRcv.avrgRes;
5625 maxResidualOrg = globalMaxResidual;
5626 // globalMaxResidual=globalMaxResidual;//m_residualRcv.maxRes;
5627 // for(MInt i=0; i<3; i++)
5628 //{
5629 // maxResIndex[i]=m_residualRcv.maxCellIndex[i];
5630 //}
5631
5632 // }
5633
5634 // cout << "m_avrgResidual = " << m_avrgResidual<< " | totalCells " << m_totalGridCells <<endl;
5636 // write first residuals;
5637 if(ABS(m_firstMaxResidual) < epsilon) {
5638 m_firstMaxResidual = mMax(epsilon, globalMaxResidual);
5640 if(m_initialCondition != 101) { // we need an extra treatment of TGV because of symmetie
5641 if(approx(localMaxResidual, maxResidualOrg,
5642 m_eps)) { // so only domainId with the max writes out ==> no need to communicate the max index[i]
5643
5644 // write out values into residual file
5645 FILE* f_residual;
5646 f_residual = fopen("./Residual", "a+");
5647 fprintf(f_residual, "#MaxRes_1: %1.10e \n", m_firstMaxResidual);
5648 fprintf(f_residual, "#MaxAvgRes_1: %1.10e \n", m_firstAvrgResidual);
5649 fprintf(f_residual, "#iter, physTime, time, dT, wLoad, avrgRes, maxRes, blockId, i, j, k ");
5650 fclose(f_residual);
5651 }
5652 } else {
5653 if(domainId() == 0) {
5654 // write out values into residual file
5655 FILE* f_residual;
5656 f_residual = fopen("./Residual", "a+");
5657 fprintf(f_residual, "#MaxRes_1: %1.10e \n", m_firstMaxResidual);
5658 fprintf(f_residual, "#MaxAvgRes_1: %1.10e \n", m_firstAvrgResidual);
5659 fprintf(f_residual,
5660 "#iter, physTime, time, dT, wLoad, avrgRes, maxRes, blockId, i, j, k, k_mean, p_mean, pProbe ");
5661 }
5662 }
5663 }
5664
5665 // normalize residuals
5666 globalMaxResidual = globalMaxResidual / m_firstMaxResidual;
5668
5669 // question if "( m_avrgResidual >= F0 || m_avrgResidual < F0 ) {} else {"
5670 // is better to capture the also inf???
5671
5672 if(std::isnan(m_avrgResidual)) {
5673 cerr << "Solution diverged, average residual is nan " << endl;
5674 m_log << "Solution diverged, average residual is nan " << endl;
5675 saveSolverSolution(true);
5676 mTerm(1, AT_, "Solution diverged, average residual is nan ");
5677 }
5678
5679 // convergence Check
5680
5681 m_convergence = false;
5682 if(maxResidual1 < m_convergenceCriterion) {
5683 m_convergence = true;
5684 }
5685
5686 // need again special treatment for TGV due to symmetrie many processors would write out (!!!!IMPORTANT NO CORRECT
5687 // INDEX WILL BE WRITTEN OUT )
5688 if(m_initialCondition != 101) {
5689 // processor with the highest Residual writes out!!! saves communication;
5690 if(approx(localMaxResidual, maxResidualOrg,
5691 m_eps)) { // so only domainId with the max writes out ==> no need to communicate the max index[i]
5692 // write out values into residual file
5693 FILE* f_residual;
5694 f_residual = fopen("./Residual", "a+");
5695 fprintf(f_residual, "%d", globalTimeStep);
5696 fprintf(f_residual, " %f", m_physicalTime);
5697 fprintf(f_residual, " %f", m_time);
5698 fprintf(f_residual, " %f", m_timeStep);
5699 fprintf(f_residual, " %f", m_workload);
5700 fprintf(f_residual, " %1.10e", m_avrgResidual);
5701 fprintf(f_residual, " %1.10e", globalMaxResidual);
5702 fprintf(f_residual, " %d", m_blockId);
5703 fprintf(f_residual, " %d", m_nOffsetCells[2] + maxResIndex[0]); // i
5704 fprintf(f_residual, " %d", m_nOffsetCells[1] + maxResIndex[1]); // j
5705 fprintf(f_residual, " %d", m_nOffsetCells[0] + maxResIndex[2]); // k
5706 fprintf(f_residual, "\n");
5707 fclose(f_residual);
5708 }
5709 } else {
5710 if(domainId() == 0) {
5711 MFloat dissip = F0;
5712 if(globalTimeStep == 1) {
5713 m_kineticEOld = 1.2474901617e-03;
5714 } else {
5715 dissip = (globalTotalEnergy - m_kineticEOld) / m_timeStep;
5716 m_kineticEOld = globalTotalEnergy;
5717 }
5718 // write out values into residual file
5719 // compute the dissipation rate
5720
5721 FILE* f_residual;
5722 f_residual = fopen("./Residual", "a+");
5723 fprintf(f_residual, "%d", globalTimeStep);
5724 fprintf(f_residual, " %f", m_physicalTime);
5725 fprintf(f_residual, " %f", m_time);
5726 fprintf(f_residual, " %f", m_timeStep);
5727 fprintf(f_residual, " %f", m_workload);
5728 fprintf(f_residual, " %1.10e", m_avrgResidual);
5729 fprintf(f_residual, " %1.10e", globalMaxResidual);
5730 fprintf(f_residual, " %d", m_blockId);
5731 fprintf(f_residual, " %d", m_nOffsetCells[2] + maxResIndex[0]); // i Will be wrong
5732 fprintf(f_residual, " %d", m_nOffsetCells[1] + maxResIndex[1]); // j Will be wrong
5733 fprintf(f_residual, " %d", m_nOffsetCells[0] + maxResIndex[2]); // k Will be wrong
5734 fprintf(f_residual, " %1.10e", globalTotalEnergy); // kinetic Energy
5735 fprintf(f_residual, " %1.10e", globalPressure); // averaged pressure
5736 fprintf(f_residual, " %1.10e", dissip); // dissipation rate
5737 fprintf(f_residual, "\n");
5738 fclose(f_residual);
5739 }
5740 }
5741
5742 if(maxResidual1 < m_convergenceCriterion) {
5743 return true;
5744 } else {
5745 return false;
5746 }
5747}
5748
5750 TRACE();
5751 MFloat localEnergy = F0;
5752 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
5753 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
5754 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
5755 const MInt cellId = cellIndex(i, j, k);
5756 localEnergy += (POW2(m_cells->pvariables[PV->U][cellId]) + POW2(m_cells->pvariables[PV->V][cellId])
5757 + POW2(m_cells->pvariables[PV->W][cellId]))
5758 * m_cells->cellJac[cellId];
5759 }
5760 }
5761 }
5762 return localEnergy;
5763}
5764
5766 TRACE();
5767 MFloat localPressure = F0;
5768 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
5769 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
5770 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
5771 const MInt cellId = cellIndex(i, j, k);
5772 localPressure += m_cells->pvariables[PV->P][cellId] * m_cells->cellJac[cellId];
5773 }
5774 }
5775 }
5776 return localPressure;
5777}
5778
5779inline MFloat FvStructuredSolver3D::pressure(MInt cellId) { return m_cells->pvariables[PV->P][cellId]; }
5780
5781
5782inline void FvStructuredSolver3D::crossProduct(MFloat* result, const MFloat* vec1, const MFloat* vec2) {
5783 result[xsd] = vec1[ysd] * vec2[zsd] - vec1[zsd] * vec2[ysd];
5784 result[ysd] = vec1[zsd] * vec2[xsd] - vec1[xsd] * vec2[zsd];
5785 result[zsd] = vec1[xsd] * vec2[ysd] - vec1[ysd] * vec2[xsd];
5786}
5787
5789 return i + (k * (m_nCells[1] + 1) + j) * (m_nCells[2] + 1);
5790}
5791
5792inline MInt FvStructuredSolver3D::getPointIdfromPoint(const MInt origin, const MInt incI, const MInt incJ,
5793 const MInt incK) {
5794 return origin + incI + incJ * m_nPoints[2] + incK * m_nPoints[2] * m_nPoints[1];
5795}
5796
5797
5798void FvStructuredSolver3D::moveGrid(const MBool isRestart, const MBool zeroPos) {
5799 TRACE();
5800 const MFloat pi = 4.0 * atan(1);
5801 const MFloat t = (isRestart) ? m_time : m_time + m_timeStep * m_RKalpha[m_RKStep];
5802
5803 switch(m_gridMovingMethod) {
5804 case 1: // oscillating grid in x-direction
5805 {
5806 // we need some relaxation function in wall-normal direction
5807 // here we take a linear function: ( y_max - y ) / y_max
5808 const MFloat y_max = 10.0; // y of upper domain boundary
5809 const MFloat frequency = F1 / (F2 * m_timeStep * 1000.0);
5810 const MFloat amp = PV->UInfinity / (F2 * pi * frequency);
5811
5812 for(MInt k = 0; k < m_nPoints[0]; k++) {
5813 for(MInt j = 0; j < (m_nPoints[1]); j++) {
5814 for(MInt i = 0; i < m_nPoints[2]; i++) {
5815 const MInt pointId = pointIndex(i, j, k);
5816 const MFloat x = m_grid->m_initCoordinates[0][pointId];
5817
5818 m_grid->m_coordinates[0][pointId] =
5819 x + (1 - m_grid->m_coordinates[1][pointId] / y_max) * amp * sin(2 * pi * t * frequency);
5820 m_grid->m_velocity[0][pointId] = (1 - m_grid->m_coordinates[1][pointId] / y_max) * amp * 2 * pi * frequency
5821 * cos(2 * pi * t * frequency);
5822 }
5823 }
5824 }
5825
5826 break;
5827 }
5828 case 2: // channel with moving indentation
5829 {
5830 const MFloat beta = 4.14l;
5831 const MFloat StrNum = m_wallVel; // Strouhal Number, set by wallVel
5832 const MFloat ver = F0; // ver can be used to translate x coordinate
5833 const MFloat y_max = F1; // can be used to scale (old mesh had y_max = m_mgOrgCoordinates[0][32] = 1/30)
5834
5835 // values from Ralph and Pedley:
5836 const MFloat x2 = y_max * (ver - 11.75l);
5837 const MFloat x3 = y_max * (ver - 9.25l);
5838 const MFloat x4 = y_max * (ver - 1.25);
5839 const MFloat x5 = y_max * (ver + 1.25);
5840 const MFloat omega = PV->UInfinity * StrNum * F2 * pi / y_max;
5841 const MFloat h = F1B2 * 0.38l * (F1 - cos(omega * t));
5842 const MFloat hvel = F1B2 * 0.38l * omega * sin(omega * t);
5843
5844 for(MInt k = 0; k < m_nPoints[0]; k++) {
5845 for(MInt j = 0; j < m_nPoints[1]; j++) {
5846 for(MInt i = 0; i < m_nPoints[2]; i++) {
5847 const MInt pointId = pointIndex(i, j, k);
5848 const MFloat y = m_grid->m_initCoordinates[1][pointId];
5849
5850 MFloat g = F0;
5851
5852 if(m_grid->m_coordinates[0][pointId] > x2 && m_grid->m_coordinates[0][pointId] < x3) {
5853 g = (1.0 + tanhl(beta * (m_grid->m_coordinates[0][pointId] - (x2 + x3) / 2.0l) / y_max)) / 2.0;
5854 } else if(m_grid->m_coordinates[0][pointId] >= x3 && m_grid->m_coordinates[0][pointId] < x4) {
5855 g = F1;
5856 } else if(m_grid->m_coordinates[0][pointId] >= x4 && m_grid->m_coordinates[0][pointId] < x5) {
5857 g = (1.0 - tanhl(beta * (m_grid->m_coordinates[0][pointId] - (x4 + x5) / 2.0l) / y_max)) / 2.0;
5858 }
5859
5860 m_grid->m_coordinates[1][pointId] = y * (F1 - h * g);
5861 m_grid->m_velocity[1][pointId] = -y * hvel * g;
5862 }
5863 }
5864 }
5865
5866 break;
5867 }
5868 case 3: // piston moving in x-direction
5869 {
5870 for(MInt k = 0; k < m_nPoints[0]; k++) {
5871 for(MInt j = 0; j < m_nPoints[1]; j++) {
5872 for(MInt i = 0; i < m_nPoints[2]; i++) {
5873 const MInt pointId = pointIndex(i, j, k);
5874 const MFloat x = m_grid->m_initCoordinates[0][pointId];
5875
5876 m_grid->m_coordinates[0][pointId] = x * (1 + t * m_wallVel);
5877 m_grid->m_velocity[0][pointId] = x * m_wallVel;
5878 m_grid->m_acceleration[0][pointId] = F0;
5879 }
5880 }
5881 }
5882
5883 break;
5884 }
5885 case 4: // inner grid movement
5886 {
5887 const MFloat beta = 16.0l;
5888 const MFloat StrNum = m_wallVel; // Strouhal Number, set by wallVel
5889 const MFloat ver = 0.0l; // ver can be used to translate x coordinate
5890 const MFloat y_max = 1.0l; // can be used to scale
5891
5892 // for Square:
5893 const MFloat x2 = y_max * (ver + 0.1l);
5894 const MFloat x3 = y_max * (ver + 0.5l);
5895 const MFloat x4 = y_max * (ver + 0.5l);
5896 const MFloat x5 = y_max * (ver + 0.9l);
5897
5898 const MFloat omega = m_Ma * sqrt(PV->TInfinity) * StrNum * 2.0l * pi / y_max;
5899 const MFloat h = F1B2 * 0.35l * (F1 - cos(omega * t));
5900 const MFloat hvel = F1B2 * 0.35l * (omega * sin(omega * t));
5901
5902 for(MInt k = 0; k < m_nPoints[0]; k++) {
5903 for(MInt j = 0; j < m_nPoints[1]; j++) {
5904 for(MInt i = 0; i < m_nPoints[2]; i++) {
5905 const MInt pointId = pointIndex(i, j, k);
5906
5907 const MFloat x = m_grid->m_initCoordinates[0][pointId];
5908 const MFloat y = m_grid->m_initCoordinates[1][pointId];
5909
5910 MFloat g = F0;
5911 if(y > x2 && y < x5 && x > x2 && x < x5) {
5912 g = ((y < x3) ? (1.0l + tanhl(beta * (y - (x2 + x3) / 2.0l) / y_max)) / 2.0l
5913 : ((y < x4) ? 1.0l : (1.0l - tanhl(beta * (y - (x4 + x5) / 2.0l) / y_max)) / 2.0l));
5914 }
5915 m_grid->m_coordinates[0][pointId] = x * (F1 - h * g * (F1 - x));
5916 m_grid->m_velocity[0][pointId] = x * (-hvel * g * (F1 - x));
5917
5918 g = F0;
5919 if(x > x2 && x < x5 && y > x2 && y < x5) {
5920 g = ((x < x3) ? (1.0l + tanhl(beta * (x - (x2 + x3) / 2.0l) / y_max)) / 2.0l
5921 : ((x < x4) ? 1.0l : (1.0l - tanhl(beta * (x - (x4 + x5) / 2.0l) / y_max)) / 2.0l));
5922 }
5923 m_grid->m_coordinates[1][pointId] = y * (F1 - h * g * (F1 - y));
5924 m_grid->m_velocity[1][pointId] = y * (-hvel * g * (F1 - y));
5925 }
5926 }
5927 }
5928
5929 break;
5930 }
5931 case 9:
5932 case 10: {
5933 // traveling wave case
5934 const MFloat angle = m_waveAngle;
5935 const MFloat rotSin = sin(angle);
5936 MFloat t_offset = t - m_movingGridTimeOffset;
5937 if(zeroPos) {
5938 t_offset = F0;
5939 }
5940 const MFloat transitionLength = m_waveEndTransition - m_waveBeginTransition;
5941 const MFloat transitionOutLength = m_waveOutEndTransition - m_waveOutBeginTransition;
5942 const MFloat yTransitionLength = m_waveYEndTransition - m_waveYBeginTransition;
5943
5944 MFloat fadeInFactor = 0.0;
5945 MFloat fadeInFactorPrime = 0.0;
5946 MFloat fadeInFactorPrimePrime = 0.0;
5947 if(t_offset < m_waveTemporalTransition) {
5948 fadeInFactor = (1.0 - cos(t_offset / m_waveTemporalTransition * pi)) * F1B2;
5949 fadeInFactorPrime = (pi / m_waveTemporalTransition) * sin(t_offset / m_waveTemporalTransition * pi) * F1B2;
5950 fadeInFactorPrimePrime =
5951 POW2(pi / m_waveTemporalTransition) * cos(t_offset / m_waveTemporalTransition * pi) * F1B2;
5952 } else {
5953 fadeInFactor = 1.0;
5954 fadeInFactorPrime = 0.0;
5955 fadeInFactorPrimePrime = 0.0;
5956 }
5957
5958 if(zeroPos) {
5959 fadeInFactor = F1;
5960 }
5961
5962
5963 for(MInt k = 0; k < m_nPoints[0]; k++) {
5964 for(MInt j = 0; j < m_nPoints[1]; j++) {
5965 for(MInt i = 0; i < m_nPoints[2]; i++) {
5966 const MInt pointId = pointIndex(i, j, k);
5967 const MFloat xInit = m_grid->m_initCoordinates[0][pointId];
5968 const MFloat zInit = m_grid->m_initCoordinates[2][pointId];
5969 const MFloat yInit = m_grid->m_initCoordinates[1][pointId];
5970
5971 MFloat transitionFactor = F0;
5972 if(xInit <= m_waveBeginTransition) {
5973 transitionFactor = F0;
5974 } else if(xInit > m_waveBeginTransition && xInit < m_waveEndTransition) {
5975 transitionFactor = (1 - cos((xInit - m_waveBeginTransition) / transitionLength * pi)) * F1B2;
5976 } else if(m_waveEndTransition <= xInit && xInit <= m_waveOutBeginTransition) {
5977 transitionFactor = F1;
5978 } else if(xInit > m_waveOutBeginTransition && xInit < m_waveOutEndTransition) {
5979 transitionFactor = (1 + cos((xInit - m_waveOutBeginTransition) / transitionOutLength * pi)) * F1B2;
5980 } else {
5981 transitionFactor = F0;
5982 }
5983
5984 MFloat yTransitionFactor = F1;
5985 if(yInit <= m_waveYBeginTransition) {
5986 yTransitionFactor = F1;
5987 } else if(yInit > m_waveYBeginTransition && yInit < m_waveYEndTransition) {
5988 yTransitionFactor = (1 + cos((yInit - m_waveYBeginTransition) / yTransitionLength * pi)) * F1B2;
5989 } else {
5990 yTransitionFactor = F0;
5991 }
5992
5993 const MFloat zPrime = zInit - rotSin * (xInit - m_waveBeginTransition);
5994
5995 const MFloat func = transitionFactor * yTransitionFactor
5996 * (m_waveAmplitude * cos((F2 * pi) / m_waveLength * (zPrime - m_waveSpeed * t_offset)));
5997 const MFloat funcPrime = transitionFactor * yTransitionFactor * (2 * PI * m_waveSpeed / m_waveLength)
5999 * sin((F2 * pi) / m_waveLength * (zPrime - m_waveSpeed * t_offset));
6000 const MFloat funcPrimePrime = -transitionFactor * yTransitionFactor
6002 * cos((F2 * pi) / m_waveLength * (zPrime - m_waveSpeed * t_offset));
6003
6004 m_grid->m_coordinates[1][pointId] = func * fadeInFactor + yInit;
6005 m_grid->m_velocity[1][pointId] = func * fadeInFactorPrime + funcPrime * fadeInFactor;
6006 m_grid->m_acceleration[1][pointId] =
6007 funcPrimePrime * fadeInFactor + 2 * funcPrime * fadeInFactorPrime + func * fadeInFactorPrimePrime;
6008 }
6009 }
6010 }
6011
6012 break;
6013 }
6014 case 11: {
6015 // traveling wave channel (Tomiyama & Fukagata 2013)
6016 MFloat t_offset = t - m_movingGridTimeOffset;
6017 if(zeroPos) {
6018 t_offset = F0;
6019 }
6020
6021 MFloat fadeInFactor = 0;
6022 const MFloat timeRelaxation = 50.0;
6023
6024 if(t_offset < timeRelaxation) {
6025 fadeInFactor = (1.0 - cos(t_offset / timeRelaxation * pi)) * F1B2;
6026 } else {
6027 fadeInFactor = 1.0;
6028 }
6029
6030 if(zeroPos) {
6031 fadeInFactor = F1;
6032 }
6033
6034 for(MInt k = 0; k < m_nPoints[0]; k++) {
6035 for(MInt j = 0; j < m_nPoints[1]; j++) {
6036 for(MInt i = 0; i < m_nPoints[2]; i++) {
6037 const MInt pointId = pointIndex(i, j, k);
6038 const MFloat yInit = m_grid->m_initCoordinates[1][pointId];
6039 const MFloat zInit = m_grid->m_initCoordinates[2][pointId];
6040 MFloat yRelaxation = F0;
6041
6042 if(yInit <= F0) {
6043 yRelaxation = F1;
6044 } else if(yInit > F0 && yInit < F1) {
6045 yRelaxation = F1 - yInit;
6046 } else if(yInit > F1 && yInit < F2) {
6047 yRelaxation = yInit - F1;
6048 } else {
6049 yRelaxation = F1;
6050 }
6051
6052 if(yInit <= F1) {
6053 m_grid->m_coordinates[1][pointId] =
6054 yInit
6055 + fadeInFactor
6056 * (m_waveAmplitude * yRelaxation
6057 * cos((F2 * pi) / m_waveLength * (zInit - m_waveSpeed * t_offset)));
6058 m_grid->m_velocity[1][pointId] = fadeInFactor
6059 * (m_waveAmplitude * yRelaxation * F2 * pi / m_waveLength * m_waveSpeed
6060 * sin((F2 * pi) / m_waveLength * (zInit - m_waveSpeed * t_offset)));
6061 } else {
6062 m_grid->m_coordinates[1][pointId] =
6063 yInit
6064 - fadeInFactor
6065 * (m_waveAmplitude * yRelaxation
6066 * cos((F2 * pi) / m_waveLength * (zInit - m_waveSpeed * t_offset)));
6067 m_grid->m_velocity[1][pointId] = -fadeInFactor
6068 * (m_waveAmplitude * yRelaxation * F2 * pi / m_waveLength * m_waveSpeed
6069 * sin((F2 * pi) / m_waveLength * (zInit - m_waveSpeed * t_offset)));
6070 }
6071 }
6072 }
6073 }
6074
6075 break;
6076 }
6077 case 12: {
6078 // streamwise traveling wave case
6079 MFloat t_offset = t - m_movingGridTimeOffset;
6080 if(zeroPos) {
6081 t_offset = F0;
6082 }
6083 const MFloat transitionLength = m_waveEndTransition - m_waveBeginTransition;
6084 const MFloat transitionOutLength = m_waveOutEndTransition - m_waveOutBeginTransition;
6085 const MFloat yTransitionLength = m_waveYEndTransition - m_waveYBeginTransition;
6086
6087 MFloat fadeInFactor = 0.0;
6088 MFloat fadeInFactorPrime = 0.0;
6089 MFloat fadeInFactorPrimePrime = 0.0;
6090 if(t_offset < m_waveTemporalTransition) {
6091 fadeInFactor = (1.0 - cos(t_offset / m_waveTemporalTransition * pi)) * F1B2;
6092 fadeInFactorPrime = (pi / m_waveTemporalTransition) * sin(t_offset / m_waveTemporalTransition * pi) * F1B2;
6093 fadeInFactorPrimePrime =
6094 POW2(pi / m_waveTemporalTransition) * cos(t_offset / m_waveTemporalTransition * pi) * F1B2;
6095 } else {
6096 fadeInFactor = 1.0;
6097 fadeInFactorPrime = 0.0;
6098 fadeInFactorPrimePrime = 0.0;
6099 }
6100
6101 if(zeroPos) {
6102 fadeInFactor = F1;
6103 }
6104
6105
6106 for(MInt k = 0; k < m_nPoints[0]; k++) {
6107 for(MInt j = 0; j < m_nPoints[1]; j++) {
6108 for(MInt i = 0; i < m_nPoints[2]; i++) {
6109 const MInt pointId = pointIndex(i, j, k);
6110 const MFloat xInit = m_grid->m_initCoordinates[0][pointId];
6111 const MFloat yInit = m_grid->m_initCoordinates[1][pointId];
6112
6113 MFloat transitionFactor = F0;
6114 if(xInit <= m_waveBeginTransition) {
6115 transitionFactor = F0;
6116 } else if(xInit > m_waveBeginTransition && xInit < m_waveEndTransition) {
6117 transitionFactor = (1 - cos((xInit - m_waveBeginTransition) / transitionLength * pi)) * F1B2;
6118 } else if(m_waveEndTransition <= xInit && xInit <= m_waveOutBeginTransition) {
6119 transitionFactor = F1;
6120 } else if(xInit > m_waveOutBeginTransition && xInit < m_waveOutEndTransition) {
6121 transitionFactor = (1 + cos((xInit - m_waveOutBeginTransition) / transitionOutLength * pi)) * F1B2;
6122 } else {
6123 transitionFactor = F0;
6124 }
6125
6126 MFloat yTransitionFactor = F1;
6127 if(yInit <= m_waveYBeginTransition) {
6128 yTransitionFactor = F1;
6129 } else if(yInit > m_waveYBeginTransition && yInit < m_waveYEndTransition) {
6130 yTransitionFactor = (1 + cos((yInit - m_waveYBeginTransition) / yTransitionLength * pi)) * F1B2;
6131 } else {
6132 yTransitionFactor = F0;
6133 }
6134
6135 const MFloat func = transitionFactor * yTransitionFactor
6136 * (m_waveAmplitude * cos((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset)));
6137 const MFloat funcPrime = transitionFactor * yTransitionFactor * (2 * PI * m_waveSpeed / m_waveLength)
6139 * sin((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset));
6140 const MFloat funcPrimePrime = -transitionFactor * yTransitionFactor
6142 * cos((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset));
6143
6144 m_grid->m_coordinates[1][pointId] = func * fadeInFactor + yInit;
6145 m_grid->m_velocity[1][pointId] = func * fadeInFactorPrime + funcPrime * fadeInFactor;
6146 m_grid->m_acceleration[1][pointId] =
6147 funcPrimePrime * fadeInFactor + 2 * funcPrime * fadeInFactorPrime + func * fadeInFactorPrimePrime;
6148 }
6149 }
6150 }
6151
6152 break;
6153 }
6154 case 13: {
6155 // traveling wave on airfoil
6156 MFloat t_offset = t - m_movingGridTimeOffset;
6157 if(zeroPos) {
6158 t_offset = F0;
6159 }
6160 const MFloat transitionLength = m_waveEndTransition - m_waveBeginTransition;
6161 const MFloat transitionOutLength = m_waveOutEndTransition - m_waveOutBeginTransition;
6162 const MFloat yTransitionLength = m_waveYEndTransition - m_waveYBeginTransition;
6163
6164 MFloat fadeInFactor = 0;
6165 const MFloat timeRelaxation = 1.0; // 80.0
6166
6167 if(t_offset < timeRelaxation) {
6168 fadeInFactor = (1.0 - cos(t_offset / timeRelaxation * pi)) * F1B2;
6169 } else {
6170 fadeInFactor = 1.0;
6171 }
6172
6173 if(zeroPos) {
6174 fadeInFactor = F1;
6175 }
6176
6177 const MInt myBlockId = m_grid->getMyBlockId();
6178
6179 if(myBlockId == 0) {
6180 for(MInt i = 0; i < m_nPoints[2]; i++) {
6181 MFloat transitionFactor = F0;
6182 const MInt offset = m_nOffsetCells[2];
6183 const MInt globalPointId = offset + i;
6184 const MFloat xWall = m_airfoilCoords[0 + globalPointId];
6185 const MFloat yWall = m_airfoilCoords[m_airfoilNoWallPoints + globalPointId];
6186
6187 const MFloat wallNormalVec[3] = {m_airfoilNormalVec[0 + globalPointId],
6189 m_airfoilNormalVec[2 * m_airfoilNoWallPoints + globalPointId]};
6190
6191 if(xWall <= m_waveBeginTransition) {
6192 transitionFactor = F0;
6193 } else if(xWall > m_waveBeginTransition && xWall < m_waveEndTransition) {
6194 transitionFactor = (1 - cos((xWall - m_waveBeginTransition) / transitionLength * pi)) * F1B2;
6195 } else if(m_waveEndTransition <= xWall && xWall <= m_waveOutBeginTransition) {
6196 transitionFactor = F1;
6197 } else if(xWall > m_waveOutBeginTransition && xWall < m_waveOutEndTransition) {
6198 transitionFactor = (1 + cos((xWall - m_waveOutBeginTransition) / transitionOutLength * pi)) * F1B2;
6199 } else {
6200 transitionFactor = F0;
6201 }
6202
6203 // linear increase of amplitude
6205 MFloat inc = 1.0 + heightGrad * (xWall - m_waveEndTransition);
6207
6208 if(wallNormalVec[1] < 0.0) {
6210 inc = 1.0 + heightGrad * (xWall - m_waveEndTransition);
6212 }
6213
6214 for(MInt k = 0; k < m_nPoints[0]; k++) {
6215 for(MInt j = 0; j < m_nPoints[1] - 1; j++) {
6216 const MInt pIJK = pointIndex(i, j, k);
6217 const MFloat xInit = m_grid->m_initCoordinates[0][pIJK];
6218 const MFloat yInit = m_grid->m_initCoordinates[1][pIJK];
6219 const MFloat zInit = m_grid->m_initCoordinates[2][pIJK];
6220
6221
6222 MFloat yTransitionFactor = F1;
6223 const MFloat normalDist = sqrt(POW2(xInit - xWall) + POW2(yInit - yWall));
6224 if(normalDist <= m_waveYBeginTransition) {
6225 yTransitionFactor = F1;
6226 } else if(normalDist > m_waveYBeginTransition && normalDist < m_waveYEndTransition) {
6227 yTransitionFactor = (1 + cos((normalDist - m_waveYBeginTransition) / yTransitionLength * pi)) * F1B2;
6228 } else {
6229 yTransitionFactor = F0;
6230 }
6231
6232 const MFloat normalDisplacement =
6233 inc * fadeInFactor
6234 * (amp0 * yTransitionFactor * transitionFactor
6235 * (cos((F2 * pi) / m_waveLength * (zInit - m_waveSpeed * t_offset))));
6236 const MFloat normalVel =
6237 inc * fadeInFactor
6238 * (amp0 * yTransitionFactor * transitionFactor * F2 * pi / m_waveLength * m_waveSpeed
6239 * (sin((F2 * pi) / m_waveLength * (zInit - m_waveSpeed * t_offset))));
6240
6241 m_grid->m_coordinates[0][pIJK] = xInit + normalDisplacement * wallNormalVec[0];
6242 m_grid->m_coordinates[1][pIJK] = yInit + normalDisplacement * wallNormalVec[1];
6243
6244 m_grid->m_velocity[0][pIJK] = normalVel * wallNormalVec[0];
6245 m_grid->m_velocity[1][pIJK] = normalVel * wallNormalVec[1];
6246 }
6247 }
6248 }
6249 }
6250 break;
6251 }
6252 case 14: {
6253 // oscillating cylinder
6254 MFloat t_offset = t - m_movingGridTimeOffset;
6255 if(zeroPos) {
6256 t_offset = F0;
6257 }
6258
6259 MFloat fadeInFactor = 0;
6260 const MFloat timeRelaxation = 1.0;
6261
6262 if(t_offset < timeRelaxation) {
6263 fadeInFactor = (1.0 - cos(t_offset / timeRelaxation * pi)) * F1B2;
6264 } else {
6265 fadeInFactor = 1.0;
6266 }
6267
6268 if(zeroPos) {
6269 fadeInFactor = F1;
6270 }
6271
6272 for(MInt i = 0; i < m_nPoints[2]; i++) {
6273 for(MInt k = 0; k < m_nPoints[0]; k++) {
6274 for(MInt j = 0; j < m_nPoints[1] - 1; j++) {
6275 const MInt pIJK = pointIndex(i, j, k);
6276 const MFloat x = m_grid->m_initCoordinates[0][pIJK];
6277 const MFloat y = m_grid->m_initCoordinates[1][pIJK];
6278 // const MFloat z = m_grid->m_initCoordinates[2][pIJK];
6279
6280 const MFloat r = sqrt(POW2(x) + POW2(y));
6281
6282 MFloat spaceTransition = F1;
6283
6284 if(r < 1.0) {
6285 spaceTransition = F0;
6286 } else if(r >= 1.0 && r <= 41.0) {
6287 spaceTransition = fabs(r - 1.0) / 40.0;
6288 } else {
6289 spaceTransition = F1;
6290 }
6291
6292 m_grid->m_coordinates[1][pIJK] =
6293 y * spaceTransition
6294 + (1.0 - spaceTransition) * (y + fadeInFactor * m_oscAmplitude * sin(2 * PI * m_oscFreq * t_offset));
6295 m_grid->m_velocity[1][pIJK] =
6296 (1.0 - spaceTransition)
6297 * (fadeInFactor * m_oscAmplitude * 2 * PI * m_oscFreq * cos(2 * PI * m_oscFreq * t_offset));
6298 m_grid->m_acceleration[1][pIJK] =
6299 (1.0 - spaceTransition)
6300 * (-fadeInFactor * m_oscAmplitude * POW2(2 * PI * m_oscFreq) * sin(2 * PI * m_oscFreq * t_offset));
6301 }
6302 }
6303 }
6304
6305 break;
6306 }
6307 case 15: {
6308 // streamwise traveling wave on airfoil
6309 MFloat t_offset = t - m_movingGridTimeOffset;
6310 if(zeroPos) {
6311 t_offset = F0;
6312 }
6313 const MFloat transitionLength = m_waveEndTransition - m_waveBeginTransition;
6314 const MFloat transitionOutLength = m_waveOutEndTransition - m_waveOutBeginTransition;
6315 const MFloat pressureTransitionLength = m_wavePressureEndTransition - m_wavePressureBeginTransition;
6316 const MFloat pressureTransitionOutLength = m_wavePressureOutEndTransition - m_wavePressureOutBeginTransition;
6317 const MFloat yTransitionLength = m_waveYEndTransition - m_waveYBeginTransition;
6318
6319 MFloat fadeInFactor = 0;
6320 const MFloat timeRelaxation = 1.0; // 80.0
6321
6322 if(t_offset < timeRelaxation) {
6323 fadeInFactor = (1.0 - cos(t_offset / timeRelaxation * pi)) * F1B2;
6324 } else {
6325 fadeInFactor = 1.0;
6326 }
6327
6328 if(zeroPos) {
6329 fadeInFactor = F1;
6330 }
6331
6332 const MInt myBlockId = m_grid->getMyBlockId();
6333
6334 if(myBlockId == 0) {
6335 for(MInt i = 0; i < m_nPoints[2]; i++) {
6336 MFloat transitionFactor = F0;
6337 const MInt offset = m_nOffsetCells[2];
6338 const MInt globalPointId = offset + i;
6339 const MFloat xWall = m_airfoilCoords[0 + globalPointId];
6340 const MFloat yWall = m_airfoilCoords[m_airfoilNoWallPoints + globalPointId];
6341
6342 const MFloat wallNormalVec[3] = {m_airfoilNormalVec[0 + globalPointId],
6344 m_airfoilNormalVec[2 * m_airfoilNoWallPoints + globalPointId]};
6345
6346 // upper surface
6348 if(xWall <= m_waveBeginTransition) {
6349 transitionFactor = F0;
6350 } else if(xWall > m_waveBeginTransition && xWall < m_waveEndTransition) {
6351 transitionFactor = (1 - cos((xWall - m_waveBeginTransition) / transitionLength * pi)) * F1B2;
6352 } else if(m_waveEndTransition <= xWall && xWall <= m_waveOutBeginTransition) {
6353 transitionFactor = F1;
6354 } else if(xWall > m_waveOutBeginTransition && xWall < m_waveOutEndTransition) {
6355 transitionFactor = (1 + cos((xWall - m_waveOutBeginTransition) / transitionOutLength * pi)) * F1B2;
6356 } else {
6357 transitionFactor = F0;
6358 }
6359
6360 // lower surface
6361 if(wallNormalVec[1] < 0.0) {
6363 if(xWall <= m_wavePressureBeginTransition) {
6364 transitionFactor = F0;
6365 } else if(xWall > m_wavePressureBeginTransition && xWall < m_wavePressureEndTransition) {
6366 transitionFactor =
6367 (1 - cos((xWall - m_wavePressureBeginTransition) / pressureTransitionLength * pi)) * F1B2;
6368 } else if(m_wavePressureEndTransition <= xWall && xWall <= m_wavePressureOutBeginTransition) {
6369 transitionFactor = F1;
6371 transitionFactor =
6372 (1 + cos((xWall - m_wavePressureOutBeginTransition) / pressureTransitionOutLength * pi)) * F1B2;
6373 } else {
6374 transitionFactor = F0;
6375 }
6376 }
6377
6378 for(MInt k = 0; k < m_nPoints[0]; k++) {
6379 for(MInt j = 0; j < m_nPoints[1] - 1; j++) {
6380 const MInt pIJK = pointIndex(i, j, k);
6381 const MFloat xInit = m_grid->m_initCoordinates[0][pIJK];
6382 const MFloat yInit = m_grid->m_initCoordinates[1][pIJK];
6383
6384 MFloat yTransitionFactor = F1;
6385 const MFloat normalDist = sqrt(POW2(xInit - xWall) + POW2(yInit - yWall));
6386 if(normalDist <= m_waveYBeginTransition) {
6387 yTransitionFactor = F1;
6388 } else if(normalDist > m_waveYBeginTransition && normalDist < m_waveYEndTransition) {
6389 yTransitionFactor = (1 + cos((normalDist - m_waveYBeginTransition) / yTransitionLength * pi)) * F1B2;
6390 } else {
6391 yTransitionFactor = F0;
6392 }
6393
6394 const MFloat normalDisplacement =
6395 fadeInFactor
6396 * (amp0 * yTransitionFactor * transitionFactor
6397 * (cos((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset))));
6398 const MFloat normalVel =
6399 fadeInFactor
6400 * (amp0 * yTransitionFactor * transitionFactor * F2 * pi / m_waveLength * m_waveSpeed
6401 * (sin((F2 * pi) / m_waveLength * (xInit - m_waveSpeed * t_offset))));
6402
6403 m_grid->m_coordinates[0][pIJK] = xInit + normalDisplacement * wallNormalVec[0];
6404 m_grid->m_coordinates[1][pIJK] = yInit + normalDisplacement * wallNormalVec[1];
6405
6406 m_grid->m_velocity[0][pIJK] = normalVel * wallNormalVec[0];
6407 m_grid->m_velocity[1][pIJK] = normalVel * wallNormalVec[1];
6408 }
6409 }
6410 }
6411 }
6412 break;
6413 }
6414 default: {
6415 mTerm(1, AT_, "Grid Moving Method not implemented!");
6416 }
6417 }
6418
6419 RECORD_TIMER_START(m_timers[Timers::MGExchange]);
6420
6421 if(m_gridMovingMethod != 1) {
6423 m_grid->extrapolateGhostPointCoordinates();
6424 }
6426 }
6427
6428 if(noDomains() > 1) {
6430 m_grid->exchangePoints(m_sndComm, m_rcvComm, PARTITION_NORMAL);
6431 }
6432 }
6433 RECORD_TIMER_STOP(m_timers[Timers::MGExchange]);
6434
6435 RECORD_TIMER_START(m_timers[Timers::MGCellCenterCoordinates]);
6436 m_grid->computeCellCenterCoordinates();
6437 RECORD_TIMER_STOP(m_timers[Timers::MGCellCenterCoordinates]);
6438
6439 RECORD_TIMER_START(m_timers[Timers::MGMetrics]);
6440 m_grid->computeMetrics();
6441 RECORD_TIMER_STOP(m_timers[Timers::MGMetrics]);
6442
6443 RECORD_TIMER_START(m_timers[Timers::MGJacobian]);
6444 m_grid->computeJacobian();
6445
6446 RECORD_TIMER_STOP(m_timers[Timers::MGJacobian]);
6447}
6448
6450 TRACE();
6451 m_log << "Initializing moving grid methods..." << endl;
6452
6453 // First approach: save whole mesh in m_grid->m_initCoordinates
6454 for(MInt k = 0; k < m_nPoints[0]; ++k) {
6455 for(MInt j = 0; j < m_nPoints[1]; ++j) {
6456 for(MInt i = 0; i < m_nPoints[2]; ++i) {
6457 const MInt pointId = pointIndex(i, j, k);
6458 for(MInt isd = xsd; isd < nDim; ++isd) {
6459 m_grid->m_initCoordinates[isd][pointId] = m_grid->m_coordinates[isd][pointId];
6460 }
6461 }
6462 }
6463 }
6464
6465 // Second approach: save only parts of the mesh depending on moving grid case
6466 switch(m_gridMovingMethod) {
6467 case 1:
6468 case 2:
6469 case 3:
6470 case 4: {
6471 break;
6472 }
6473 case 9:
6474 // traveling wave defined by viscous units
6475 // used Smits formula to compute friction velocity
6476 {
6477 m_travelingWave = true;
6478 if(!m_restart) {
6479 m_waveTimeStepComputed = false;
6480 }
6481 m_waveSpeed = 0.0;
6482 m_waveLength = 0.0;
6483 m_waveAmplitude = 0.0;
6485 if(!m_restart) {
6487 }
6488
6489 // time needs to be constant for traveling wave
6490 m_constantTimeStep = true;
6491
6504 m_waveLengthPlus = 1.0;
6505 if(Context::propertyExists("waveLengthPlus", m_solverId)) {
6506 m_waveLengthPlus = Context::getSolverProperty<MFloat>("waveLengthPlus", m_solverId, AT_, &m_waveLengthPlus);
6507 } else {
6508 mTerm(1, AT_, "Property waveLengthPlus not specified in property file");
6509 }
6510
6523 m_waveAmplitudePlus = 0.0;
6524 if(Context::propertyExists("waveAmplitudePlus", m_solverId)) {
6526 Context::getSolverProperty<MFloat>("waveAmplitudePlus", m_solverId, AT_, &m_waveAmplitudePlus);
6527 } else {
6528 mTerm(1, AT_, "Property waveAmplitudePlus not specified in property file");
6529 }
6530
6543 m_waveTimePlus = 0.0;
6544 if(Context::propertyExists("waveTimePlus", m_solverId)) {
6545 m_waveTimePlus = Context::getSolverProperty<MFloat>("waveTimePlus", m_solverId, AT_, &m_waveTimePlus);
6546 } else {
6547 mTerm(1, AT_, "Property waveTimePlus not specified in property file");
6548 }
6549
6564 Context::getSolverProperty<MFloat>("waveBeginTransition", m_solverId, AT_, &m_waveBeginTransition);
6565
6578 m_waveEndTransition = 0.0;
6580 Context::getSolverProperty<MFloat>("waveEndTransition", m_solverId, AT_, &m_waveEndTransition);
6581
6594 m_waveOutBeginTransition = 1000000.0;
6596 Context::getSolverProperty<MFloat>("waveOutBeginTransition", m_solverId, AT_, &m_waveOutBeginTransition);
6597
6610 m_waveOutEndTransition = 2000000.0;
6612 Context::getSolverProperty<MFloat>("waveOutEndTransition", m_solverId, AT_, &m_waveOutEndTransition);
6613
6626 m_waveAngle = 0.0;
6627 if(Context::propertyExists("waveAngle", m_solverId)) {
6628 m_waveAngle = Context::getSolverProperty<MFloat>("waveAngle", m_solverId, AT_, &m_waveAngle);
6629 m_waveAngle *= PI / 180.0;
6630 }
6631
6644 m_waveYBeginTransition = 2000000.0;
6645 if(Context::propertyExists("waveYBeginTransition", m_solverId)) {
6647 Context::getSolverProperty<MFloat>("waveYBeginTransition", m_solverId, AT_, &m_waveYBeginTransition);
6648 }
6649
6650
6663 m_waveYEndTransition = 2000000.0;
6664 if(Context::propertyExists("waveYEndTransition", m_solverId)) {
6666 Context::getSolverProperty<MFloat>("waveYEndTransition", m_solverId, AT_, &m_waveYEndTransition);
6667 }
6668
6683 if(Context::propertyExists("waveTemporalTransition", m_solverId)) {
6685 Context::getSolverProperty<MFloat>("waveTemporalTransition", m_solverId, AT_, &m_waveTemporalTransition);
6686 }
6687
6688 // compute Wave parameters
6689 MFloat deltaS = -1.0;
6690 MFloat cf = -1.0;
6691 if(m_Re < 5000) {
6692 // use Smits formula for smaller Reynolds numbers
6693 deltaS = pow(m_Re, -7.0 / 8.0) * sqrt(2.0 / 0.024);
6694 cf = 0.024 * pow(m_Re, -F1B4);
6695 } else {
6696 // Coles-Fernholz is better for larger Re
6697 deltaS = ((log(m_Re)) / 0.384 + 4.127) / m_Re;
6698 cf = 2.0 * pow((log(m_Re) / 0.384 + 4.127), -2.0);
6699 }
6700 const MFloat uTau = sqrt(POW2(PV->UInfinity) * CV->rhoInfinity * cf * F1B2);
6701
6702 m_waveLength = m_waveLengthPlus * deltaS;
6706
6707 // assume equidistant grid in z-direction
6708 const MFloat deltaZ = abs(m_grid->m_coordinates[2][0] - m_grid->m_coordinates[2][m_nPoints[2] * m_nPoints[1]]);
6709 m_waveCellsPerWaveLength = round(m_waveLength / deltaZ);
6710
6711
6712 const MFloat wavePeriod = m_waveLength / m_waveSpeed;
6713 const MFloat speedAmplitude = 2 * PI * m_waveAmplitude / wavePeriod;
6714
6715 m_log << "/////////////////// TRAVELING WAVE /////////////////////////////" << endl;
6716 m_log << "Re: " << m_Re << " c_f: " << cf << " u_tau: " << uTau << " deltaZ: " << deltaZ
6717 << " viscousUnit delta_v: " << deltaS << endl;
6718 m_log << "wavelengthPlus: " << m_waveLengthPlus << " AmplitudePlus: " << m_waveAmplitudePlus
6719 << " SpeedPlus: " << m_waveSpeedPlus << endl;
6720 m_log << "Wavelength: " << m_waveLength << " Amplitude: " << m_waveAmplitude << " Period: " << wavePeriod
6721 << " Speed: " << m_waveSpeed << endl;
6722 m_log << "Max up/down speed: " << speedAmplitude << endl;
6723 m_log << "Max up/down speed: " << m_waveSpeed * m_waveAmplitude << endl;
6724 m_log << "////////////////////////////////////////////////////////////////" << endl;
6726 break;
6727 }
6728 case 10:
6729 // travelling wave defined by non-plus units
6730 {
6731 m_travelingWave = true;
6732 if(!m_restart) {
6733 m_waveTimeStepComputed = false;
6734 }
6735 m_waveSpeed = 0.0;
6736 m_waveLength = 0.0;
6737 m_waveAmplitude = 0.0;
6739 if(!m_restart) {
6741 }
6742
6743 // time needs to be constant for traveling wave
6744 m_constantTimeStep = true;
6745
6758 m_waveLength = 0.0;
6759 if(Context::propertyExists("waveLength", m_solverId)) {
6760 m_waveLength = Context::getSolverProperty<MFloat>("waveLength", m_solverId, AT_, &m_waveLengthPlus);
6761 } else {
6762 mTerm(1, AT_, "Property waveLength not specified in property file");
6763 }
6764
6777 m_waveAmplitude = 0.0;
6778 if(Context::propertyExists("waveAmplitude", m_solverId)) {
6779 m_waveAmplitude = Context::getSolverProperty<MFloat>("waveAmplitude", m_solverId, AT_, &m_waveAmplitudePlus);
6780 } else {
6781 mTerm(1, AT_, "Property waveAmplitude not specified in property file");
6782 }
6783
6796 m_waveTime = 0.0;
6797 if(Context::propertyExists("waveTime", m_solverId)) {
6798 m_waveTime = Context::getSolverProperty<MFloat>("waveTime", m_solverId, AT_, &m_waveTimePlus);
6799 } else {
6800 mTerm(1, AT_, "Property waveTime not specified in property file");
6801 }
6802
6803
6818 Context::getSolverProperty<MFloat>("waveBeginTransition", m_solverId, AT_, &m_waveBeginTransition);
6819
6832 m_waveEndTransition = 0.0;
6834 Context::getSolverProperty<MFloat>("waveEndTransition", m_solverId, AT_, &m_waveEndTransition);
6835
6848 m_waveOutBeginTransition = 1000000.0;
6850 Context::getSolverProperty<MFloat>("waveOutBeginTransition", m_solverId, AT_, &m_waveOutBeginTransition);
6851
6864 m_waveOutEndTransition = 2000000.0;
6866 Context::getSolverProperty<MFloat>("waveOutEndTransition", m_solverId, AT_, &m_waveOutEndTransition);
6867
6880 m_waveYBeginTransition = 2000000.0;
6881 if(Context::propertyExists("waveYBeginTransition", m_solverId)) {
6883 Context::getSolverProperty<MFloat>("waveYBeginTransition", m_solverId, AT_, &m_waveYBeginTransition);
6884 }
6885
6886
6899 m_waveYEndTransition = 2000000.0;
6900 if(Context::propertyExists("waveYEndTransition", m_solverId)) {
6902 Context::getSolverProperty<MFloat>("waveYEndTransition", m_solverId, AT_, &m_waveYEndTransition);
6903 }
6904
6917 m_waveAngle = 0.0;
6918 if(Context::propertyExists("waveAngle", m_solverId)) {
6919 m_waveAngle = Context::getSolverProperty<MFloat>("waveAngle", m_solverId, AT_, &m_waveAngle);
6920 m_waveAngle *= PI / 180.0;
6921 }
6922
6937 if(Context::propertyExists("waveTemporalTransition", m_solverId)) {
6939 Context::getSolverProperty<MFloat>("waveTemporalTransition", m_solverId, AT_, &m_waveTemporalTransition);
6940 }
6941
6943 const MFloat deltaZ = abs(m_grid->m_coordinates[2][0] - m_grid->m_coordinates[2][m_nPoints[2] * m_nPoints[1]]);
6944 m_waveCellsPerWaveLength = round(m_waveLength / deltaZ);
6945
6946 const MFloat speedAmplitude = 2 * PI * m_waveAmplitude / m_waveTime;
6947
6948 m_log << "/////////////////// TRAVELING WAVE /////////////////////////////" << endl;
6949 m_log << "Wavelength: " << m_waveLength << " Amplitude: " << m_waveAmplitude << " Period: " << m_waveTime
6950 << " Speed: " << m_waveSpeed << endl;
6951 m_log << "Max up/down speed: " << speedAmplitude << endl;
6952 m_log << "Max up/down speed: " << m_waveSpeed * m_waveAmplitude << endl;
6953 m_log << "////////////////////////////////////////////////////////////////" << endl;
6954
6956 break;
6957 }
6958 case 11:
6959 // traveling wave channel (Tomiyama & Fukagata 2013)
6960 {
6961 m_travelingWave = true;
6962 m_waveSpeed = 0.0;
6963 m_waveLength = 0.0;
6964 m_waveAmplitude = 0.0;
6965 m_waveLengthPlus = 0.0;
6966 m_waveAmplitudePlus = 0.0;
6967 m_waveTimePlus = 0.0;
6968
6969 // time needs to be constant for traveling wave
6970 m_constantTimeStep = true;
6971 m_waveLengthPlus = Context::getSolverProperty<MFloat>("waveLengthPlus", m_solverId, AT_, &m_waveLengthPlus);
6973 Context::getSolverProperty<MFloat>("waveAmplitudePlus", m_solverId, AT_, &m_waveAmplitudePlus);
6974 m_waveTimePlus = Context::getSolverProperty<MFloat>("waveTimePlus", m_solverId, AT_, &m_waveTimePlus);
6975
6976 // compute Wave parameters
6977 // const MFloat cf = 0.008185; //0.024*pow(m_Re, -F1B4);
6978 // const MFloat uTau = sqrt(POW2(PV->UInfinity)*CV->rhoInfinity*cf*F1B2);
6979 const MFloat uTau = m_ReTau * m_Ma * sqrt(PV->TInfinity) / m_Re;
6980 const MFloat cf = 2 * POW2(uTau / PV->UInfinity);
6981
6982 const MFloat mu8 = SUTHERLANDLAW(PV->TInfinity);
6983 m_waveLength = m_waveLengthPlus / (sqrt(cf / 2.0) * PV->UInfinity * m_Re0 * CV->rhoInfinity / mu8);
6984 m_waveAmplitude = m_waveAmplitudePlus / (sqrt(cf / 2.0) * PV->UInfinity * m_Re0 * CV->rhoInfinity / mu8);
6986 const MFloat deltaZ = abs(m_grid->m_coordinates[2][0] - m_grid->m_coordinates[2][m_nPoints[2] * m_nPoints[1]]);
6987 m_waveCellsPerWaveLength = round(m_waveLength / deltaZ);
6988
6989 m_log << "WaveLength: " << m_waveLength << " waveAmplitude: " << m_waveAmplitude
6990 << " waveSpeed: " << m_waveSpeed << endl;
6992 break;
6993 }
6994 case 12:
6995 // streamwise travelling wave defined by non-plus units
6996 {
6998 if(!m_restart) {
6999 m_waveTimeStepComputed = false;
7000 }
7001 m_waveSpeed = 0.0;
7002 m_waveLength = 0.0;
7003 m_waveAmplitude = 0.0;
7005 if(!m_restart) {
7007 }
7008 // time needs to be constant for traveling wave
7009 m_constantTimeStep = true;
7010
7023 m_waveLength = 0.0;
7024 if(Context::propertyExists("waveLength", m_solverId)) {
7025 m_waveLength = Context::getSolverProperty<MFloat>("waveLength", m_solverId, AT_, &m_waveLengthPlus);
7026 } else {
7027 mTerm(1, AT_, "Property waveLength not specified in property file");
7028 }
7029
7044 Context::getSolverProperty<MFloat>("waveAmplitudeSuction", m_blockId, AT_, &m_waveAmplitudeSuction);
7045
7059 m_waveAmplitude = 0.0;
7060 if(Context::propertyExists("waveAmplitude", m_solverId)) {
7061 m_waveAmplitude = Context::getSolverProperty<MFloat>("waveAmplitude", m_solverId, AT_, &m_waveAmplitudePlus);
7062 } else {
7063 mTerm(1, AT_, "Property waveAmplitude not specified in property file");
7064 }
7065
7078 m_waveTime = 0.0;
7079 if(Context::propertyExists("waveTime", m_solverId)) {
7080 m_waveTime = Context::getSolverProperty<MFloat>("waveTime", m_solverId, AT_, &m_waveTimePlus);
7081 } else {
7082 mTerm(1, AT_, "Property waveTime not specified in property file");
7083 }
7084
7085
7100 Context::getSolverProperty<MFloat>("waveBeginTransition", m_solverId, AT_, &m_waveBeginTransition);
7101
7114 m_waveEndTransition = 0.0;
7116 Context::getSolverProperty<MFloat>("waveEndTransition", m_solverId, AT_, &m_waveEndTransition);
7117
7130 m_waveOutBeginTransition = 1000000.0;
7132 Context::getSolverProperty<MFloat>("waveOutBeginTransition", m_solverId, AT_, &m_waveOutBeginTransition);
7133
7146 m_waveOutEndTransition = 2000000.0;
7148 Context::getSolverProperty<MFloat>("waveOutEndTransition", m_solverId, AT_, &m_waveOutEndTransition);
7149
7162 m_waveYBeginTransition = 2000000.0;
7163 if(Context::propertyExists("waveYBeginTransition", m_solverId)) {
7165 Context::getSolverProperty<MFloat>("waveYBeginTransition", m_solverId, AT_, &m_waveYBeginTransition);
7166 }
7167
7168
7181 m_waveYEndTransition = 2000000.0;
7182 if(Context::propertyExists("waveYEndTransition", m_solverId)) {
7184 Context::getSolverProperty<MFloat>("waveYEndTransition", m_solverId, AT_, &m_waveYEndTransition);
7185 }
7186
7200 if(Context::propertyExists("waveTemporalTransition", m_solverId)) {
7202 Context::getSolverProperty<MFloat>("waveTemporalTransition", m_solverId, AT_, &m_waveTemporalTransition);
7203 }
7204
7206 const MFloat speedAmplitude = 2 * PI * m_waveAmplitude / m_waveTime;
7207
7208 m_log << "/////////////////// TRAVELING WAVE /////////////////////////////" << endl;
7209 m_log << "Wavelength: " << m_waveLength << " Amplitude: " << m_waveAmplitude << " Period: " << m_waveTime
7210 << " Speed: " << m_waveSpeed << endl;
7211 m_log << "Speed amplitude: " << speedAmplitude << endl;
7212 m_log << "Phase speed: " << m_waveSpeed << endl;
7213 m_log << "////////////////////////////////////////////////////////////////" << endl;
7215 break;
7216 }
7217 case 13:
7218 // traveling wave on airfoil
7219 {
7220 m_travelingWave = true;
7221 m_waveSpeed = 0.0;
7223 if(!m_restart) {
7224 m_waveTimeStepComputed = false;
7225 }
7226 // time needs to be constant for traveling wave
7227 m_constantTimeStep = true;
7228 if(!m_restart) {
7230 }
7231
7244 m_waveLength = 0.0;
7245 m_waveLength = Context::getSolverProperty<MFloat>("waveLength", m_solverId, AT_, &m_waveLength);
7246
7261 Context::getSolverProperty<MFloat>("waveAmplitudeSuction", m_blockId, AT_, &m_waveAmplitudeSuction);
7262
7277 Context::getSolverProperty<MFloat>("waveAmplitudePressure", m_blockId, AT_, &m_waveAmplitudePressure);
7278
7281 Context::getSolverProperty<MFloat>("waveGradientSuction", m_blockId, AT_, &m_waveGradientSuction);
7282
7285 Context::getSolverProperty<MFloat>("waveGradientPressure", m_blockId, AT_, &m_waveGradientPressure);
7286
7299 m_waveTime = 0.0;
7300 m_waveTime = Context::getSolverProperty<MFloat>("waveTime", m_solverId, AT_, &m_waveTimePlus);
7301
7316 Context::getSolverProperty<MFloat>("waveBeginTransition", m_solverId, AT_, &m_waveBeginTransition);
7317
7330 m_waveEndTransition = 0.0;
7332 Context::getSolverProperty<MFloat>("waveEndTransition", m_solverId, AT_, &m_waveEndTransition);
7333
7346 m_waveOutBeginTransition = 1000000.0;
7348 Context::getSolverProperty<MFloat>("waveOutBeginTransition", m_solverId, AT_, &m_waveOutBeginTransition);
7349
7362 m_waveOutEndTransition = 2000000.0;
7364 Context::getSolverProperty<MFloat>("waveOutEndTransition", m_solverId, AT_, &m_waveOutEndTransition);
7365
7378 m_waveYBeginTransition = 2000000.0;
7379 if(Context::propertyExists("waveYBeginTransition", m_solverId)) {
7381 Context::getSolverProperty<MFloat>("waveYBeginTransition", m_solverId, AT_, &m_waveYBeginTransition);
7382 }
7383
7384
7397 m_waveYEndTransition = 2000000.0;
7398 if(Context::propertyExists("waveYEndTransition", m_solverId)) {
7400 Context::getSolverProperty<MFloat>("waveYEndTransition", m_solverId, AT_, &m_waveYEndTransition);
7401 }
7402
7403 const MInt myBlockId = m_grid->getMyBlockId();
7404 const MInt blockId = 0; // use information from block 0
7405 m_airfoilNoWallPoints = m_grid->getBlockNoPoints(blockId, 2) + 2 * m_noGhostLayers;
7406
7407 if(domainId() == 0) {
7408 cout << "NoWallPoints: " << m_airfoilNoWallPoints << endl;
7409 }
7410
7411 MFloatScratchSpace localCoords(nDim, m_airfoilNoWallPoints, AT_, "localCoords");
7412 MFloatScratchSpace localNormalVec(nDim, m_airfoilNoWallPoints, AT_, "localNormalVec");
7413 localCoords.fill(-99999.0);
7414 localNormalVec.fill(-99999.0);
7415 mAlloc(m_airfoilCoords, nDim * m_airfoilNoWallPoints, "m_airfoilCoords", -99999.0, AT_);
7416 mAlloc(m_airfoilNormalVec, nDim * m_airfoilNoWallPoints, "m_airfoilNormalVec", -99999.0, AT_);
7417
7418 if(myBlockId == blockId) {
7419 if(m_nOffsetCells[1] == 0 && m_nOffsetCells[0] == 0) {
7420 // only collect variables from points at the wall
7421 for(MInt i = 0; i < m_nPoints[2]; i++) {
7422 const MInt offset = m_nOffsetCells[2];
7423 const MInt localPointId = i; // new postion in Array
7424 const MInt globalPointId = offset + i;
7425
7427 const MInt pIJPK = pointIndex(i, m_noGhostLayers + 1, m_noGhostLayers);
7428
7429 // compute the normal vector
7430 MFloat normalVec[3] = {F0, F0, F0};
7431 for(MInt dim = 0; dim < nDim; dim++) {
7432 normalVec[dim] = m_grid->m_coordinates[dim][pIJPK] - m_grid->m_coordinates[dim][pIJK];
7433 }
7434
7435 // normalize normalVec
7436 const MFloat normalLength = sqrt(POW2(normalVec[0]) + POW2(normalVec[1]) + POW2(normalVec[2]));
7437 for(MInt dim = 0; dim < nDim; dim++) {
7438 normalVec[dim] /= normalLength;
7439 }
7440
7441 localCoords(globalPointId) = m_grid->m_coordinates[0][localPointId];
7442 localCoords(m_airfoilNoWallPoints + globalPointId) = m_grid->m_coordinates[1][localPointId];
7443 localCoords(2 * m_airfoilNoWallPoints + globalPointId) = m_grid->m_coordinates[2][localPointId];
7444
7445 localNormalVec(globalPointId) = normalVec[0];
7446 localNormalVec(m_airfoilNoWallPoints + globalPointId) = normalVec[1];
7447 localNormalVec(2 * m_airfoilNoWallPoints + globalPointId) = normalVec[2];
7448 }
7449 }
7450 }
7451
7452 MPI_Allreduce(&localCoords[0], &m_airfoilCoords[0], nDim * m_airfoilNoWallPoints, MPI_DOUBLE, MPI_MAX,
7453 m_StructuredComm, AT_, "localCoords[0]", "m_airfoilCoords[0]");
7454 MPI_Allreduce(&localNormalVec[0], &m_airfoilNormalVec[0], nDim * m_airfoilNoWallPoints, MPI_DOUBLE, MPI_MAX,
7455 m_StructuredComm, AT_, "localNormalVec[0]", "m_airfoilNormalVec[0]");
7456
7458 const MFloat deltaZ = abs(m_grid->m_coordinates[2][0] - m_grid->m_coordinates[2][m_nPoints[2] * m_nPoints[1]]);
7459 m_waveCellsPerWaveLength = round(m_waveLength / deltaZ);
7460
7461 const MFloat wavePeriod = m_waveLength / m_waveSpeed;
7462 const MFloat speedAmplitude = 2 * PI * m_waveAmplitude / wavePeriod;
7463
7464 m_log << "/////////////////// TRAVELING WAVE /////////////////////////////" << endl;
7465 m_log << "Wavelength: " << m_waveLength << " Period: " << wavePeriod << endl;
7466 m_log << "Amplitude Suction: " << m_waveAmplitudeSuction << " Amplitude Pressure: " << m_waveAmplitudePressure
7467 << endl;
7468 m_log << "Amplitude Gradient Suction: " << m_waveGradientSuction
7469 << " Amplitude Gradient Pressure: " << m_waveGradientPressure << endl;
7470 m_log << "Velocity Amplitude Suction: " << 2 * PI * m_waveAmplitudeSuction / wavePeriod
7471 << " Velocity Amplitude Pressure: " << 2 * PI * m_waveAmplitudePressure / wavePeriod << endl;
7472 m_log << "Speed: " << m_waveSpeed << endl;
7473 m_log << "Max up/down speed: " << speedAmplitude << endl;
7474 m_log << " Begin InTransition: " << m_waveBeginTransition << " End InTransition: " << m_waveEndTransition
7475 << endl;
7476 m_log << " Begin OutTransition: " << m_waveOutBeginTransition
7477 << " End OutTransition: " << m_waveOutEndTransition << endl;
7478 m_log << " Begin WallNormalTransition: " << m_waveYBeginTransition
7479 << " End WallNormalTransition: " << m_waveYEndTransition << endl;
7480 m_log << "////////////////////////////////////////////////////////////////" << endl;
7482 break;
7483 }
7484 case 14:
7485 // oscillating cylinder
7486 {
7487 // time needs to be constant for traveling wave
7488 m_constantTimeStep = true;
7489
7502 m_oscAmplitude = 0.2;
7503 m_oscAmplitude = Context::getSolverProperty<MFloat>("oscAmplitude", m_solverId, AT_, &m_oscAmplitude);
7504
7505 m_oscSr = 0.195;
7506 m_oscSr = Context::getSolverProperty<MFloat>("oscSr", m_solverId, AT_, &m_oscSr);
7507
7508 MFloat freqFactor = 0.8;
7509 freqFactor = Context::getSolverProperty<MFloat>("oscFreqFactor", m_solverId, AT_, &freqFactor);
7510
7511 const MFloat freq0 = m_oscSr * PV->UInfinity / m_referenceLength;
7512 m_oscFreq = freq0 * freqFactor;
7513 break;
7514 }
7515 case 15:
7516 // streamwise traveling wave on airfoil
7517 {
7519 m_waveSpeed = 0.0;
7521 if(!m_restart) {
7522 m_waveTimeStepComputed = false;
7523 }
7524 // time needs to be constant for traveling wave
7525 m_constantTimeStep = true;
7526 if(!m_restart) {
7528 }
7529
7541 m_waveLength = 0.0;
7542 m_waveLength = Context::getSolverProperty<MFloat>("waveLength", m_solverId, AT_, &m_waveLength);
7543
7557 Context::getSolverProperty<MFloat>("waveAmplitudeSuction", m_blockId, AT_, &m_waveAmplitudeSuction);
7558
7572 Context::getSolverProperty<MFloat>("waveAmplitudePressure", m_blockId, AT_, &m_waveAmplitudePressure);
7573
7585 m_waveTime = 0.0;
7586 m_waveTime = Context::getSolverProperty<MFloat>("waveTime", m_solverId, AT_, &m_waveTimePlus);
7587
7601 Context::getSolverProperty<MFloat>("waveBeginTransition", m_solverId, AT_, &m_waveBeginTransition);
7602
7614 m_waveEndTransition = 0.0;
7616 Context::getSolverProperty<MFloat>("waveEndTransition", m_solverId, AT_, &m_waveEndTransition);
7617
7629 m_waveOutBeginTransition = 1000000.0;
7631 Context::getSolverProperty<MFloat>("waveOutBeginTransition", m_solverId, AT_, &m_waveOutBeginTransition);
7632
7644 m_waveOutEndTransition = 2000000.0;
7646 Context::getSolverProperty<MFloat>("waveOutEndTransition", m_solverId, AT_, &m_waveOutEndTransition);
7647
7648
7661 m_wavePressureBeginTransition = Context::getSolverProperty<MFloat>("wavePressureBeginTransition", m_solverId,
7663
7676 m_wavePressureEndTransition = Context::getSolverProperty<MFloat>("wavePressureEndTransition", m_solverId, AT_,
7678
7691 m_wavePressureOutBeginTransition = Context::getSolverProperty<MFloat>(
7692 "wavePressureOutBeginTransition", m_solverId, AT_, &m_wavePressureOutBeginTransition);
7693
7706 m_wavePressureOutEndTransition = Context::getSolverProperty<MFloat>("wavePressureOutEndTransition", m_solverId,
7708
7720 m_waveYBeginTransition = 2000000.0;
7721 if(Context::propertyExists("waveYBeginTransition", m_solverId)) {
7723 Context::getSolverProperty<MFloat>("waveYBeginTransition", m_solverId, AT_, &m_waveYBeginTransition);
7724 }
7725
7726
7738 m_waveYEndTransition = 2000000.0;
7739 if(Context::propertyExists("waveYEndTransition", m_solverId)) {
7741 Context::getSolverProperty<MFloat>("waveYEndTransition", m_solverId, AT_, &m_waveYEndTransition);
7742 }
7743
7744 const MInt myBlockId = m_grid->getMyBlockId();
7745 const MInt blockId = 0; // use information from block 0
7746 m_airfoilNoWallPoints = m_grid->getBlockNoPoints(blockId, 2) + 2 * m_noGhostLayers;
7747
7748 if(domainId() == 0) {
7749 cout << "NoWallPoints: " << m_airfoilNoWallPoints << endl;
7750 }
7751
7752 MFloatScratchSpace localCoords(nDim, m_airfoilNoWallPoints, AT_, "localCoords");
7753 MFloatScratchSpace localNormalVec(nDim, m_airfoilNoWallPoints, AT_, "localNormalVec");
7754 localCoords.fill(-99999.0);
7755 localNormalVec.fill(-99999.0);
7756 mAlloc(m_airfoilCoords, nDim * m_airfoilNoWallPoints, "m_airfoilCoords", -99999.0, AT_);
7757 mAlloc(m_airfoilNormalVec, nDim * m_airfoilNoWallPoints, "m_airfoilNormalVec", -99999.0, AT_);
7758
7759 if(myBlockId == blockId) {
7760 if(m_nOffsetCells[1] == 0 && m_nOffsetCells[0] == 0) {
7761 // only collect variables from points at the wall
7762 for(MInt i = 0; i < m_nPoints[2]; i++) {
7763 const MInt offset = m_nOffsetCells[2];
7764 const MInt localPointId = i; // new postion in Array
7765 const MInt globalPointId = offset + i;
7766
7768 const MInt pIJPK = pointIndex(i, m_noGhostLayers + 1, m_noGhostLayers);
7769
7770 // compute the normal vector
7771 MFloat normalVec[3] = {F0, F0, F0};
7772 for(MInt dim = 0; dim < nDim; dim++) {
7773 normalVec[dim] = m_grid->m_coordinates[dim][pIJPK] - m_grid->m_coordinates[dim][pIJK];
7774 }
7775
7776 // normalize normalVec
7777 const MFloat normalLength = sqrt(POW2(normalVec[0]) + POW2(normalVec[1]) + POW2(normalVec[2]));
7778 for(MInt dim = 0; dim < nDim; dim++) {
7779 normalVec[dim] /= normalLength;
7780 }
7781
7782 localCoords(globalPointId) = m_grid->m_coordinates[0][localPointId];
7783 localCoords(m_airfoilNoWallPoints + globalPointId) = m_grid->m_coordinates[1][localPointId];
7784 localCoords(2 * m_airfoilNoWallPoints + globalPointId) = m_grid->m_coordinates[2][localPointId];
7785
7786 localNormalVec(globalPointId) = normalVec[0];
7787 localNormalVec(m_airfoilNoWallPoints + globalPointId) = normalVec[1];
7788 localNormalVec(2 * m_airfoilNoWallPoints + globalPointId) = normalVec[2];
7789 }
7790 }
7791 }
7792
7793 MPI_Allreduce(&localCoords[0], &m_airfoilCoords[0], nDim * m_airfoilNoWallPoints, MPI_DOUBLE, MPI_MAX,
7794 m_StructuredComm, AT_, "localCoords[0]", "m_airfoilCoords[0]");
7795 MPI_Allreduce(&localNormalVec[0], &m_airfoilNormalVec[0], nDim * m_airfoilNoWallPoints, MPI_DOUBLE, MPI_MAX,
7796 m_StructuredComm, AT_, "localNormalVec[0]", "m_airfoilNormalVec[0]");
7797
7799 const MFloat deltaZ = abs(m_grid->m_coordinates[2][0] - m_grid->m_coordinates[2][m_nPoints[2] * m_nPoints[1]]);
7800 m_waveCellsPerWaveLength = round(m_waveLength / deltaZ);
7801
7802 const MFloat wavePeriod = m_waveLength / m_waveSpeed;
7803 const MFloat speedAmplitude = 2 * PI * m_waveAmplitude / wavePeriod;
7804
7805 m_log << "/////////////////// TRAVELING WAVE /////////////////////////////" << endl;
7806 m_log << "Wavelength: " << m_waveLength << " Period: " << wavePeriod << endl;
7807 m_log << "Amplitude Suction: " << m_waveAmplitudeSuction << " Amplitude Pressure: " << m_waveAmplitudePressure
7808 << endl;
7809 m_log << "Velocity Amplitude Suction: " << 2 * PI * m_waveAmplitudeSuction / wavePeriod
7810 << " Velocity Amplitude Pressure: " << 2 * PI * m_waveAmplitudePressure / wavePeriod << endl;
7811 m_log << "Speed: " << m_waveSpeed << endl;
7812 m_log << "Max up/down speed: " << speedAmplitude << endl;
7813 m_log << " Begin InTransition: " << m_waveBeginTransition << " End InTransition: " << m_waveEndTransition
7814 << endl;
7815 m_log << " Begin OutTransition: " << m_waveOutBeginTransition
7816 << " End OutTransition: " << m_waveOutEndTransition << endl;
7817 m_log << " Begin PressureInTransition: " << m_wavePressureBeginTransition
7818 << " End PressureInTransition: " << m_wavePressureEndTransition << endl;
7819 m_log << " Begin PressureOutTransition: " << m_wavePressureOutBeginTransition
7820 << " End PressureOutTransition: " << m_wavePressureOutEndTransition << endl;
7821 m_log << " Begin WallNormalTransition: " << m_waveYBeginTransition
7822 << " End WallNormalTransition: " << m_waveYEndTransition << endl;
7823 m_log << "////////////////////////////////////////////////////////////////" << endl;
7824 break;
7825 }
7826 default: {
7827 stringstream errorMessage;
7828 errorMessage << "Grid moving method " << m_gridMovingMethod << " not implemented!" << endl;
7829 mTerm(1, AT_, errorMessage.str());
7830 }
7831 }
7832
7833 m_grid->saveGrid();
7834
7835 // now move the grid to the correct position
7836 if(m_restart) {
7839 // if this is an initial start of the
7840 // grid movement, just move to initial pos
7841 moveGrid(true, false);
7842 m_grid->saveGrid();
7843 } else {
7844 // move to last pos before restart,
7845 // save and move to current pos again
7846 // this way the grid velocity is computed
7847 // correctly in the BC
7848 m_time -= m_timeStep;
7849 moveGrid(true, false);
7850 m_grid->saveGrid();
7851 m_time += m_timeStep;
7852 moveGrid(true, false);
7853 }
7854 }
7855 } else {
7856 moveGrid(true, false);
7857 m_grid->saveGrid();
7858 }
7859
7860 m_log << "Initializing moving grid methods... DONE!" << endl;
7861}
7862
7863void FvStructuredSolver3D::applyBodyForce(const MBool isRestart, const MBool zeroPos) {
7864 TRACE();
7865 const MFloat pi = 4.0 * atan(1);
7866 const MFloat t = (isRestart) ? m_time : m_time + m_timeStep * m_RKalpha[m_RKStep];
7867
7868 switch(m_bodyForceMethod) {
7869 case 10: {
7870 // traveling wave case
7871 MFloat t_offset = t - m_movingGridTimeOffset;
7872 if(zeroPos) {
7873 t_offset = F0;
7874 }
7875 const MFloat transitionLength = m_waveEndTransition - m_waveBeginTransition;
7876 const MFloat transitionOutLength = m_waveOutEndTransition - m_waveOutBeginTransition;
7877
7878 MFloat fadeInFactor = 0.0;
7879 if(t_offset < m_waveTemporalTransition) {
7880 fadeInFactor = (1.0 - cos(t_offset / m_waveTemporalTransition * pi)) * F1B2;
7881 } else {
7882 fadeInFactor = 1.0;
7883 }
7884
7885 if(zeroPos) {
7886 fadeInFactor = F1;
7887 }
7888
7889 for(MInt k = 0; k < m_nCells[0]; k++) {
7890 for(MInt j = 0; j < m_nCells[1]; j++) {
7891 for(MInt i = 0; i < m_nCells[2]; i++) {
7892 const MInt cellId = cellIndex(i, j, k);
7893 const MFloat x = m_cells->coordinates[0][cellId];
7894 const MFloat z = m_cells->coordinates[2][cellId];
7895 const MFloat y = m_cells->coordinates[1][cellId];
7896
7897 MFloat transitionFactor = F0;
7898 if(x <= m_waveBeginTransition) {
7899 transitionFactor = F0;
7900 } else if(x > m_waveBeginTransition && x < m_waveEndTransition) {
7901 transitionFactor = (1 - cos((x - m_waveBeginTransition) / transitionLength * pi)) * F1B2;
7902 } else if(m_waveEndTransition <= x && x <= m_waveOutBeginTransition) {
7903 transitionFactor = F1;
7904 } else if(x > m_waveOutBeginTransition && x < m_waveOutEndTransition) {
7905 transitionFactor = (1 + cos((x - m_waveOutBeginTransition) / transitionOutLength * pi)) * F1B2;
7906 } else {
7907 transitionFactor = F0;
7908 }
7909
7910 const MFloat force = fadeInFactor * transitionFactor
7912 * cos((F2 * pi) / m_waveLength * (z - m_waveSpeed * t_offset)));
7913
7914 m_cells->rightHandSide[CV->RHO_W][cellId] +=
7915 m_cells->variables[CV->RHO][cellId] * force * m_cells->cellJac[cellId];
7916 m_cells->rightHandSide[CV->RHO_E][cellId] +=
7917 m_cells->variables[CV->RHO_W][cellId] * force * m_cells->cellJac[cellId];
7918 }
7919 }
7920 }
7921
7922 break;
7923 }
7924 case 11: {
7925 // traveling wave case with predefined force field
7926 MFloat t_offset = t - m_movingGridTimeOffset;
7927 if(zeroPos) {
7928 t_offset = F0;
7929 }
7930 const MFloat transitionLength = m_waveEndTransition - m_waveBeginTransition;
7931 const MFloat transitionOutLength = m_waveOutEndTransition - m_waveOutBeginTransition;
7932
7933 MFloat fadeInFactor = 0.0;
7934 if(t_offset < m_waveTemporalTransition) {
7935 fadeInFactor = (1.0 - cos(t_offset / m_waveTemporalTransition * pi)) * F1B2;
7936 } else {
7937 fadeInFactor = 1.0;
7938 }
7939
7940 if(zeroPos) {
7941 fadeInFactor = F1;
7942 }
7943
7944 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
7945 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
7946 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
7947 const MInt cellId = cellIndex(i, j, k);
7948
7949 const MFloat x = m_cells->coordinates[0][cellId];
7950 const MFloat z = m_cells->coordinates[2][cellId];
7951
7952 MFloat transitionFactor = F0;
7953 if(x <= m_waveBeginTransition) {
7954 transitionFactor = F0;
7955 } else if(x > m_waveBeginTransition && x < m_waveEndTransition) {
7956 transitionFactor = (1 - cos((x - m_waveBeginTransition) / transitionLength * pi)) * F1B2;
7957 } else if(m_waveEndTransition <= x && x <= m_waveOutBeginTransition) {
7958 transitionFactor = F1;
7959 } else if(x > m_waveOutBeginTransition && x < m_waveOutEndTransition) {
7960 transitionFactor = (1 + cos((x - m_waveOutBeginTransition) / transitionOutLength * pi)) * F1B2;
7961 } else {
7962 transitionFactor = F0;
7963 }
7964
7965 const MFloat pos_abs = z - m_waveSpeed * t_offset;
7966 const MFloat pos = fmod(pos_abs, m_waveDomainWidth);
7967
7968 const MInt jj = m_nOffsetCells[1] + (j - m_noGhostLayers);
7969 MFloat amp = 0.0;
7970
7971 if(pos < m_waveForceZ[jj]) {
7972 const MInt p1 = jj;
7973 const MInt p1end = jj + (m_grid->getMyBlockNoCells(0) - 1) * m_grid->getMyBlockNoCells(1);
7974 const MFloat zz = m_waveForceZ[p1];
7975 const MFloat zzstart = m_waveForceZ[p1end] - m_waveDomainWidth;
7976 const MFloat f = m_waveForceField[p1];
7977 const MFloat fstart = m_waveForceField[p1end];
7978 amp = fstart + (pos - zzstart) / (zz - zzstart) * (f - fstart);
7979 } else if(pos > m_waveForceZ[jj + (m_grid->getMyBlockNoCells(0) - 1) * m_grid->getMyBlockNoCells(1)]) {
7980 const MInt p1 = jj + (m_grid->getMyBlockNoCells(0) - 1) * m_grid->getMyBlockNoCells(1);
7981 const MInt p1start = jj + 0 * m_grid->getMyBlockNoCells(1);
7982 const MFloat zz = m_waveForceZ[p1];
7983 const MFloat zzend = m_waveForceZ[p1start] + m_waveDomainWidth;
7984 const MFloat f = m_waveForceField[p1];
7985 const MFloat fend = m_waveForceField[p1start];
7986 amp = f + (pos - zz) / (zzend - zz) * (fend - f);
7987 } else {
7988 for(MInt kk = 0; kk < m_grid->getMyBlockNoCells(0) - 1; ++kk) {
7989 const MInt p1 = jj + kk * m_grid->getMyBlockNoCells(1);
7990 const MInt p1p = jj + (kk + 1) * m_grid->getMyBlockNoCells(1);
7991 const MFloat zz = m_waveForceZ[p1];
7992 const MFloat zzp = m_waveForceZ[p1p];
7993 const MFloat f = m_waveForceField[p1];
7994 const MFloat fp = m_waveForceField[p1p];
7995 if(zz <= pos && pos < zzp) {
7996 amp = f + (pos - zz) / (zzp - zz) * (fp - f);
7997 break;
7998 }
7999 }
8000 }
8001
8002 const MFloat force = fadeInFactor * transitionFactor * amp * m_waveAmplitude;
8003
8004 m_cells->rightHandSide[CV->RHO_W][cellId] +=
8005 m_cells->variables[CV->RHO][cellId] * force * m_cells->cellJac[cellId];
8006 m_cells->rightHandSide[CV->RHO_E][cellId] +=
8007 m_cells->variables[CV->RHO_W][cellId] * force * m_cells->cellJac[cellId];
8008 }
8009 }
8010 }
8011
8012 break;
8013 }
8014 default: {
8015 mTerm(1, AT_, "Body Force Method not implemented!");
8016 }
8017 }
8018}
8019
8021 TRACE();
8022 m_log << "Initializing body force methods..." << endl;
8023
8024 // Second approach: save only parts of the mesh depending on moving grid case
8025 switch(m_bodyForceMethod) {
8026 case 10:
8027 // travelling wave defined by non-plus units
8028 {
8029 m_travelingWave = true;
8030 if(!m_restart) {
8031 m_waveTimeStepComputed = false;
8032 }
8033 m_waveSpeed = 0.0;
8034 m_waveLength = 0.0;
8035 m_waveAmplitude = 0.0;
8037 if(!m_restart) {
8039 }
8040
8041 // time needs to be constant for traveling wave
8042 m_constantTimeStep = true;
8043
8056 m_waveLength = 0.0;
8057 m_waveLength = Context::getSolverProperty<MFloat>("waveLength", m_solverId, AT_, &m_waveLength);
8058
8071 m_waveAmplitude = 0.0;
8072 m_waveAmplitude = Context::getSolverProperty<MFloat>("waveAmplitude", m_solverId, AT_, &m_waveAmplitude);
8073
8074 m_waveAmplitude = m_waveAmplitude * CV->rhoInfinity * POW2(PV->UInfinity);
8075
8090 Context::getSolverProperty<MFloat>("wavePenetrationHeight", m_solverId, AT_, &m_wavePenetrationHeight);
8091
8104 m_waveTime = 0.0;
8105 m_waveTime = Context::getSolverProperty<MFloat>("waveTime", m_solverId, AT_, &m_waveTime);
8106
8107
8122 Context::getSolverProperty<MFloat>("waveBeginTransition", m_solverId, AT_, &m_waveBeginTransition);
8123
8136 m_waveEndTransition = 0.0;
8138 Context::getSolverProperty<MFloat>("waveEndTransition", m_solverId, AT_, &m_waveEndTransition);
8139
8152 m_waveOutBeginTransition = 1000000.0;
8154 Context::getSolverProperty<MFloat>("waveOutBeginTransition", m_solverId, AT_, &m_waveOutBeginTransition);
8155
8168 m_waveOutEndTransition = 2000000.0;
8170 Context::getSolverProperty<MFloat>("waveOutEndTransition", m_solverId, AT_, &m_waveOutEndTransition);
8171
8172
8187 if(Context::propertyExists("waveTemporalTransition", m_solverId)) {
8189 Context::getSolverProperty<MFloat>("waveTemporalTransition", m_solverId, AT_, &m_waveOutEndTransition);
8190 }
8191
8193 const MFloat deltaZ = abs(m_grid->m_coordinates[2][0] - m_grid->m_coordinates[2][m_nPoints[2] * m_nPoints[1]]);
8194 m_waveCellsPerWaveLength = round(m_waveLength / deltaZ);
8195
8196 const MFloat speedAmplitude = 2 * PI * m_waveAmplitude / m_waveTime;
8197
8198 m_log << "/////////////////// TRAVELING WAVE BODY FORCE //////////////////" << endl;
8199 m_log << "Wavelength: " << m_waveLength << " Amplitude: " << m_waveAmplitude << " Period: " << m_waveTime
8200 << " Speed: " << m_waveSpeed << endl;
8201 m_log << "Max up/down speed: " << speedAmplitude << endl;
8202 m_log << "Max up/down speed: " << m_waveSpeed * m_waveAmplitude << endl;
8203 m_log << "////////////////////////////////////////////////////////////////" << endl;
8204
8206 break;
8207 }
8208 case 11:
8209 // body forcing strength defined by given distribution read from HDF5 file
8210 {
8211 m_travelingWave = true;
8212 if(!m_restart) {
8213 m_waveTimeStepComputed = false;
8214 }
8215 m_waveSpeed = 0.0;
8216 m_waveLength = 0.0;
8217 m_waveAmplitude = 0.0;
8219 if(!m_restart) {
8221 }
8222
8223 // time needs to be constant for traveling wave
8224 m_constantTimeStep = true;
8225
8238 m_waveLength = 0.0;
8239 m_waveLength = Context::getSolverProperty<MFloat>("waveLength", m_solverId, AT_, &m_waveLength);
8240
8253 m_waveAmplitude = 0.0;
8254 m_waveAmplitude = Context::getSolverProperty<MFloat>("waveAmplitude", m_solverId, AT_, &m_waveAmplitude);
8255
8256 m_waveAmplitude = m_waveAmplitude * CV->rhoInfinity * POW2(PV->UInfinity);
8257
8270 m_waveTime = 0.0;
8271 m_waveTime = Context::getSolverProperty<MFloat>("waveTime", m_solverId, AT_, &m_waveTime);
8272
8273
8288 Context::getSolverProperty<MFloat>("waveBeginTransition", m_solverId, AT_, &m_waveBeginTransition);
8289
8302 m_waveEndTransition = 0.0;
8304 Context::getSolverProperty<MFloat>("waveEndTransition", m_solverId, AT_, &m_waveEndTransition);
8305
8318 m_waveOutBeginTransition = 1000000.0;
8320 Context::getSolverProperty<MFloat>("waveOutBeginTransition", m_solverId, AT_, &m_waveOutBeginTransition);
8321
8334 m_waveOutEndTransition = 2000000.0;
8336 Context::getSolverProperty<MFloat>("waveOutEndTransition", m_solverId, AT_, &m_waveOutEndTransition);
8337
8338
8353 if(Context::propertyExists("waveTemporalTransition", m_solverId)) {
8355 Context::getSolverProperty<MFloat>("waveTemporalTransition", m_solverId, AT_, &m_waveOutEndTransition);
8356 }
8357
8366 m_waveForceFieldFile = "./slice.hdf5";
8367 m_waveForceFieldFile = Context::getSolverProperty<MString>("forceFieldFile", m_solverId, AT_);
8368
8369 ParallelIo::size_type size[2] = {m_grid->getMyBlockNoCells(0), m_grid->getMyBlockNoCells(1)};
8370 mAlloc(m_waveForceField, size[0] * size[1], "m_waveForceField", 0.0, AT_);
8371 mAlloc(m_waveForceY, size[0] * size[1], "m_waveForceY", 0.0, AT_);
8372 mAlloc(m_waveForceZ, size[0] * size[1], "m_waveForceZ", 0.0, AT_);
8373
8374
8375 if(domainId() == 0) {
8377 stringstream pathStr;
8378 pathStr << "/";
8379 std::string path = pathStr.str();
8380
8381 ParallelIo::size_type offset[2] = {0, 0};
8382
8383 pio.readArray(&m_waveForceField[0], path, "force_amp", 2, offset, size);
8384 pio.readArray(&m_waveForceY[0], path, "y", 2, offset, size);
8385 pio.readArray(&m_waveForceZ[0], path, "z", 2, offset, size);
8386 }
8387
8388 MPI_Bcast(&m_waveForceField[0], size[0] * size[1], MPI_DOUBLE, 0, m_StructuredComm, AT_, "m_waveForceField");
8389 MPI_Bcast(&m_waveForceY[0], size[0] * size[1], MPI_DOUBLE, 0, m_StructuredComm, AT_, "m_waveForceY");
8390 MPI_Bcast(&m_waveForceZ[0], size[0] * size[1], MPI_DOUBLE, 0, m_StructuredComm, AT_, "m_waveForceZ");
8391
8392
8394 const MFloat deltaZ = abs(m_grid->m_coordinates[2][0] - m_grid->m_coordinates[2][m_nPoints[2] * m_nPoints[1]]);
8395 m_waveCellsPerWaveLength = round(m_waveLength / deltaZ);
8396
8397 const MFloat speedAmplitude = 2 * PI * m_waveAmplitude / m_waveTime;
8398
8399 m_log << "/////////////////// TRAVELING WAVE BODY FORCE //////////////////" << endl;
8400 m_log << "Wavelength: " << m_waveLength << " Amplitude: " << m_waveAmplitude << " Period: " << m_waveTime
8401 << " Speed: " << m_waveSpeed << endl;
8402 m_log << "Max up/down speed: " << speedAmplitude << endl;
8403 m_log << "Max up/down speed: " << m_waveSpeed * m_waveAmplitude << endl;
8404 m_log << "////////////////////////////////////////////////////////////////" << endl;
8405
8406 MFloat localDomainWidth = m_cells->coordinates[2][cellIndex(0, 0, m_nCells[0] - m_noGhostLayers)];
8407 MPI_Allreduce(&localDomainWidth, &m_waveDomainWidth, 1, MPI_DOUBLE, MPI_MAX, m_StructuredComm, AT_,
8408 "localDomainWidth", "m_waveDomainWidth");
8409
8411 break;
8412 }
8413 default: {
8414 stringstream errorMessage;
8415 errorMessage << "Grid moving method " << m_gridMovingMethod << " not implemented!" << endl;
8416 mTerm(1, AT_, errorMessage.str());
8417 }
8418 }
8419
8420 m_log << "Initializing body force methods... DONE!" << endl;
8421}
8422
8423
8425 stringstream filename;
8426
8427 filename << m_nodalBoxOutputDir << "nodalBoxOutput" << m_outputIterationNumber << m_outputFormat;
8428
8430
8431 writeHeaderAttributes(&pio, "boxes");
8433 pio.setAttribute(m_nodalBoxNoBoxes, "noBoxes", "");
8434
8436 m_nodalBoxInterpolation = make_unique<StructuredInterpolation<nDim>>(m_nCells, m_cells->coordinates,
8438
8439 mAlloc(m_nodalBoxLocalPoints, m_nodalBoxNoBoxes, nDim, "m_nodalBoxLocalPoints", 0, AT_);
8440 mAlloc(m_nodalBoxLocalOffset, m_nodalBoxNoBoxes, nDim, "m_nodalBoxLocalOffset", 0, AT_);
8441 mAlloc(m_nodalBoxLocalDomainOffset, m_nodalBoxNoBoxes, nDim, "m_nodalBoxLocalDomainOffset", 0, AT_);
8442 mAlloc(m_nodalBoxLocalSize, m_nodalBoxNoBoxes, "m_nodalBoxLocalSize", 0, AT_);
8443 mAlloc(m_nodalBoxTotalLocalOffset, m_nodalBoxNoBoxes, "m_nodalBoxLocalSize", 0, AT_);
8444
8446 for(MInt b = 0; b < m_nodalBoxNoBoxes; ++b) {
8448 && ((m_nOffsetPoints[2] <= m_nodalBoxOffset[b][2]
8450 || (m_nodalBoxOffset[b][2] <= m_nOffsetPoints[2]
8452 && ((m_nOffsetPoints[1] <= m_nodalBoxOffset[b][1]
8454 || (m_nodalBoxOffset[b][1] <= m_nOffsetPoints[1]
8456 && ((m_nOffsetPoints[0] <= m_nodalBoxOffset[b][0]
8458 || (m_nodalBoxOffset[b][0] <= m_nOffsetPoints[0]
8459 && m_nOffsetPoints[0]
8460 < m_nodalBoxOffset[b][0] + m_nodalBoxPoints[b][0]))) { // the nodalBox is contained
8461
8462 for(MInt dim = 0; dim < nDim; ++dim) {
8463 if(m_nOffsetPoints[dim] <= m_nodalBoxOffset[b][dim]
8464 && m_nodalBoxOffset[b][dim] + m_nodalBoxPoints[b][dim] < m_nOffsetPoints[dim] + m_nActivePoints[dim]) {
8466 m_nodalBoxLocalOffset[b][dim] = 0;
8468 } else if(m_nOffsetPoints[dim] <= m_nodalBoxOffset[b][dim]) {
8470 m_nodalBoxLocalOffset[b][dim] = 0;
8472 } else if(m_nodalBoxOffset[b][dim] <= m_nOffsetPoints[dim]
8473 && m_nOffsetPoints[dim] + m_nActivePoints[dim]
8474 < m_nodalBoxOffset[b][dim] + m_nodalBoxPoints[b][dim]) {
8478 } else {
8479 m_nodalBoxLocalPoints[b][dim] =
8480 (m_nodalBoxOffset[b][dim] + m_nodalBoxPoints[b][dim]) - m_nOffsetPoints[dim];
8483 }
8484 }
8485
8487 for(MInt dim = 0; dim < nDim; ++dim) {
8489 }
8490
8492 }
8493
8494 if(b < m_nodalBoxNoBoxes - 1) {
8496 }
8497 }
8498
8499 if(m_nodalBoxTotalLocalSize > 0) {
8500 mAlloc(m_nodalBoxCoordinates, nDim, m_nodalBoxTotalLocalSize, "m_nodalBoxCoordinates", 0.0, AT_);
8501 mAlloc(m_nodalBoxVariables, m_maxNoVariables, m_nodalBoxTotalLocalSize, "m_nodalBoxVariables", 0.0, AT_);
8502 mAlloc(m_nodalBoxPartnerLocal, m_nodalBoxTotalLocalSize, "m_nodalBoxPartnerLocal", 0, AT_);
8503 }
8504
8505 for(MInt b = 0; b < m_nodalBoxNoBoxes; ++b) {
8508 ++k) {
8511 ++j) {
8514 ++i) {
8515 const MInt pointId = i + (j + k * m_nPoints[1]) * m_nPoints[2];
8516 const MInt nodalBoxI = i - m_noGhostLayers - m_nodalBoxLocalDomainOffset[b][2];
8517 const MInt nodalBoxJ = j - m_noGhostLayers - m_nodalBoxLocalDomainOffset[b][1];
8518 const MInt nodalBoxK = k - m_noGhostLayers - m_nodalBoxLocalDomainOffset[b][0];
8519 const MInt localTotalId =
8521 + (nodalBoxI + (nodalBoxJ + nodalBoxK * m_nodalBoxLocalPoints[b][1]) * m_nodalBoxLocalPoints[b][2]);
8522
8523 for(MInt dim = 0; dim < nDim; dim++) {
8524 m_nodalBoxCoordinates[dim][localTotalId] = m_grid->m_coordinates[dim][pointId];
8525 }
8526 }
8527 }
8528 }
8529 }
8530
8533 m_nodalBoxInitialized = true;
8534 }
8535
8536
8537 for(MInt b = 0; b < m_nodalBoxNoBoxes; ++b) {
8538 stringstream pathName;
8539 pathName << "box" << b;
8540
8541 pio.setAttribute(m_nodalBoxOffset[b][2], "offseti", pathName.str());
8542 pio.setAttribute(m_nodalBoxOffset[b][1], "offsetj", pathName.str());
8543 pio.setAttribute(m_nodalBoxOffset[b][0], "offsetk", pathName.str());
8544
8545 pio.setAttribute(m_nodalBoxPoints[b][2], "sizei", pathName.str());
8546 pio.setAttribute(m_nodalBoxPoints[b][1], "sizej", pathName.str());
8547 pio.setAttribute(m_nodalBoxPoints[b][0], "sizek", pathName.str());
8548
8549 pio.setAttribute(m_nodalBoxBlock[b], "blockId", pathName.str());
8550
8551 MInt hasCoordinates = 0;
8552
8553 ParallelIo::size_type size[3] = {m_nodalBoxPoints[b][0], m_nodalBoxPoints[b][1], m_nodalBoxPoints[b][2]};
8554 for(MInt v = 0; v < m_maxNoVariables; v++) {
8555 pio.defineArray(maia::parallel_io::PIO_FLOAT, pathName.str(), m_pvariableNames[v], 3, size);
8556 }
8557
8558 // create datasets for the variables
8560 hasCoordinates = 1;
8561 pio.defineArray(maia::parallel_io::PIO_FLOAT, pathName.str(), "x", 3, size);
8562 pio.defineArray(maia::parallel_io::PIO_FLOAT, pathName.str(), "y", 3, size);
8563 pio.defineArray(maia::parallel_io::PIO_FLOAT, pathName.str(), "z", 3, size);
8564 }
8565 // write output to check if coordinates are contained within the variable list
8566 pio.setAttribute(hasCoordinates, "hasCoordinates", pathName.str());
8567 }
8568
8569
8570 if(m_nodalBoxTotalLocalSize > 0) {
8571 // interpolate primitive variables to nodal grid points
8572 m_nodalBoxInterpolation->interpolateVariables(m_nodalBoxVariables);
8573 }
8574
8575
8576 for(MInt b = 0; b < m_nodalBoxNoBoxes; ++b) {
8577 // check if the box is contained your inputsolverId
8578 ParallelIo::size_type localOffset[3] = {m_nodalBoxLocalOffset[b][0], m_nodalBoxLocalOffset[b][1],
8580 ParallelIo::size_type localSize[3] = {m_nodalBoxLocalPoints[b][0], m_nodalBoxLocalPoints[b][1],
8582 stringstream pathName;
8583 pathName << "box" << b;
8584 if(m_nodalBoxLocalSize[b] > 0) {
8585 for(MInt v = 0; v < m_maxNoVariables; v++) {
8587 nDim, localOffset, localSize);
8588 }
8589
8591 pio.writeArray(&m_nodalBoxCoordinates[0][m_nodalBoxTotalLocalOffset[b]], pathName.str(), "x", nDim, localOffset,
8592 localSize);
8593 pio.writeArray(&m_nodalBoxCoordinates[1][m_nodalBoxTotalLocalOffset[b]], pathName.str(), "y", nDim, localOffset,
8594 localSize);
8595 pio.writeArray(&m_nodalBoxCoordinates[2][m_nodalBoxTotalLocalOffset[b]], pathName.str(), "z", nDim, localOffset,
8596 localSize);
8597 }
8598 } else { // write out nothing as box is not contained
8599 ParallelIo::size_type localBoxPoints[3] = {0, 0, 0};
8600 ParallelIo::size_type localBoxOffset[3] = {0, 0, 0};
8601 MFloat empty = 0;
8602
8603 for(MInt v = 0; v < m_maxNoVariables; ++v) {
8604 pio.writeArray(&empty, pathName.str(), m_pvariableNames[v], nDim, localBoxOffset, localBoxPoints);
8605 }
8606
8608 pio.writeArray(&empty, pathName.str(), "x", nDim, localBoxOffset, localBoxPoints);
8609 pio.writeArray(&empty, pathName.str(), "y", nDim, localBoxOffset, localBoxPoints);
8610 pio.writeArray(&empty, pathName.str(), "z", nDim, localBoxOffset, localBoxPoints);
8611 }
8612 }
8613 }
8614}
8615
8616
8619 if(domainId() == 0) {
8620 cout << "Loading BC2600 values..." << endl;
8621 }
8622 if(m_bc2600) {
8623 ParallelIo::size_type bcCells[3] = {m_grid->getMyBlockNoCells(0), m_grid->getMyBlockNoCells(1), m_noGhostLayers};
8624 MInt noCellsBC = bcCells[0] * bcCells[1] * bcCells[2];
8625 ParallelIo::size_type bcOffset[3] = {0, 0, 0};
8626 MFloatScratchSpace tmpRestartVars(noCellsBC * m_maxNoVariables, AT_, "m_tmpRestartVars2600");
8627 if(m_commBC2600MyRank == 0) {
8628 stringstream restartFileName;
8629 MString restartFile = Context::getSolverProperty<MString>("restartVariablesFileName", m_solverId, AT_);
8630 restartFileName << outputDir() << restartFile;
8631
8632 ParallelIoHdf5 pio(restartFileName.str(), maia::parallel_io::PIO_READ, MPI_COMM_SELF);
8633 stringstream pathStr;
8634 pathStr << "/block" << m_blockId << "/bc2600";
8635 std::string path = pathStr.str();
8636
8637 for(MInt var = 0; var < m_maxNoVariables; var++) {
8638 pio.readArray(&tmpRestartVars[var * noCellsBC], path, m_pvariableNames[var], nDim, bcOffset, bcCells);
8639 }
8640 }
8641
8642 MPI_Bcast(&tmpRestartVars(0, 0), noCellsBC * m_maxNoVariables, MPI_DOUBLE, 0, m_commBC2600, AT_,
8643 "tmpRestartVars(0");
8644
8645 MInt startGC[3] = {0, 0, 0};
8646 MInt endGC[3] = {0, 0, 0};
8647
8648 if(m_bc2600noOffsetCells[1] == 0) {
8649 startGC[1] = m_noGhostLayers;
8650 }
8651 if(m_bc2600noOffsetCells[0] == 0) {
8652 startGC[0] = m_noGhostLayers;
8653 }
8654 if(m_bc2600noOffsetCells[1] + m_bc2600noActiveCells[1] == bcCells[1]) {
8655 endGC[1] = m_noGhostLayers;
8656 }
8657 if(m_bc2600noOffsetCells[0] + m_bc2600noActiveCells[0] == bcCells[0]) {
8658 endGC[0] = m_noGhostLayers;
8659 }
8660
8661 for(MInt i = 0; i < m_noGhostLayers; i++) {
8662 for(MInt j = startGC[1]; j < m_bc2600noCells[1] - endGC[1]; j++) {
8663 for(MInt k = startGC[0]; k < m_bc2600noCells[0] - endGC[0]; k++) {
8664 const MInt cellId = i + (j + k * m_bc2600noCells[1]) * m_bc2600noCells[2];
8665 MInt globalI = i;
8666 MInt globalJ = m_bc2600noOffsetCells[1] - m_noGhostLayers + j;
8667 MInt globalK = m_bc2600noOffsetCells[0] - m_noGhostLayers + k;
8668 MInt cellIdBC = globalI + (globalJ + globalK * bcCells[1]) * bcCells[2];
8669
8670 // load values from restart field
8671 for(MInt var = 0; var < m_maxNoVariables; var++) {
8672 m_bc2600Variables[var][cellId] = tmpRestartVars[var * noCellsBC + cellIdBC];
8673 }
8674 }
8675 }
8676 }
8677
8678
8679 for(MInt i = 0; i < m_bc2600noCells[2]; i++) {
8680 for(MInt j = 0; j < m_bc2600noCells[1]; j++) {
8681 MInt cellIdA1 = i + (j + 2 * m_bc2600noCells[1]) * m_bc2600noCells[2];
8682 MInt cellIdG1 = i + (j + 0 * m_bc2600noCells[1]) * m_bc2600noCells[2];
8683 MInt cellIdG2 = i + (j + 1 * m_bc2600noCells[1]) * m_bc2600noCells[2];
8684
8685 for(MInt var = 0; var < m_maxNoVariables; var++) {
8686 m_bc2600Variables[var][cellIdG1] = m_bc2600Variables[var][cellIdA1];
8687 m_bc2600Variables[var][cellIdG2] = m_bc2600Variables[var][cellIdA1];
8688 }
8689
8690 cellIdA1 = i + (j + (m_bc2600noCells[0] - 3) * m_bc2600noCells[1]) * m_bc2600noCells[2];
8691 cellIdG1 = i + (j + (m_bc2600noCells[0] - 2) * m_bc2600noCells[1]) * m_bc2600noCells[2];
8692 cellIdG2 = i + (j + (m_bc2600noCells[0] - 1) * m_bc2600noCells[1]) * m_bc2600noCells[2];
8693
8694 for(MInt var = 0; var < m_maxNoVariables; var++) {
8695 m_bc2600Variables[var][cellIdG1] = m_bc2600Variables[var][cellIdA1];
8696 m_bc2600Variables[var][cellIdG2] = m_bc2600Variables[var][cellIdA1];
8697 }
8698 }
8699 }
8700
8701
8702 // Fix diagonal cells at end of domain
8703 if(m_bc2600noOffsetCells[1] + m_bc2600noActiveCells[1] == m_grid->getMyBlockNoCells(1)) {
8704 for(MInt i = 0; i < m_bc2600noCells[2]; i++) {
8705 for(MInt k = 0; k < m_bc2600noCells[0]; k++) {
8706 const MInt cellIdA2 =
8708 const MInt cellIdA1 =
8710 const MInt cellIdG1 =
8712 for(MInt var = 0; var < m_maxNoVariables; var++) {
8713 const MFloat distA1A2 =
8714 sqrt(POW2(m_cells->coordinates[0][cellIdA1] - m_cells->coordinates[0][cellIdA2])
8715 + POW2(m_cells->coordinates[1][cellIdA1] - m_cells->coordinates[1][cellIdA2])
8716 + POW2(m_cells->coordinates[2][cellIdA1] - m_cells->coordinates[2][cellIdA2]));
8717
8718 const MFloat slope = (m_bc2600Variables[var][cellIdA1] - m_bc2600Variables[var][cellIdA2]) / distA1A2;
8719 const MFloat distG1A1 =
8720 sqrt(POW2(m_cells->coordinates[0][cellIdG1] - m_cells->coordinates[0][cellIdA1])
8721 + POW2(m_cells->coordinates[1][cellIdG1] - m_cells->coordinates[1][cellIdA1])
8722 + POW2(m_cells->coordinates[2][cellIdG1] - m_cells->coordinates[2][cellIdA1]));
8723 m_bc2600Variables[var][cellIdG1] = m_bc2600Variables[var][cellIdA1] + distG1A1 * slope;
8724 }
8725 }
8726 }
8727 }
8728 }
8729
8730 if(m_commBC2600MyRank == 0) {
8731 cout << "Loading BC2600 values... SUCCESSFUL!" << endl;
8732 }
8733 }
8734}
8735
8736
8738 // if we have the prescribing boundary,
8739 // put the values from the restart file into the ghostcells
8741 if(domainId() == 0) {
8742 cout << "Loading restart values 2601" << endl;
8743 }
8744 ParallelIo::size_type bcCells[3] = {0, 0, 0};
8745 ParallelIo::size_type bcOffset[3] = {0, 0, 0};
8746
8747 bcCells[0] = m_grid->getMyBlockNoCells(0);
8748 bcCells[1] = m_noGhostLayers;
8749 bcCells[2] = m_grid->getMyBlockNoCells(2);
8750
8751 MInt noCellsBC = bcCells[0] * bcCells[1] * bcCells[2];
8752 MFloatScratchSpace tmpRestartVars(noCellsBC * PV->noVariables, AT_, "m_tmpRestartVars2600");
8753
8754 if(domainId() == 0) {
8755 stringstream restartFileName;
8756 MString restartFile = Context::getSolverProperty<MString>("restartVariablesFileName", m_solverId, AT_);
8757 restartFileName << outputDir() << restartFile;
8758
8759 ParallelIoHdf5 pio(restartFileName.str(), maia::parallel_io::PIO_READ, MPI_COMM_SELF);
8760 stringstream pathStr;
8761 pathStr << "/block" << m_blockId << "/bc2601" << endl;
8762 std::string path = pathStr.str();
8763
8764 for(MInt var = 0; var < PV->noVariables; var++) {
8765 pio.readArray(&tmpRestartVars[var * noCellsBC], path, m_pvariableNames[var].c_str(), nDim, bcOffset, bcCells);
8766 }
8767 }
8768
8769 MPI_Bcast(&tmpRestartVars[0], noCellsBC * PV->noVariables, MPI_DOUBLE, 0, m_StructuredComm, AT_,
8770 "tmpRestartVars[0]");
8771
8772 if(m_bc2601) {
8773 MInt startGC[3] = {0, 0, 0};
8774 MInt endGC[3] = {0, 0, 0};
8775
8776 if(m_nOffsetCells[2] == 0) {
8777 startGC[2] = m_noGhostLayers;
8778 }
8779 if(m_nOffsetCells[0] == 0) {
8780 startGC[0] = m_noGhostLayers;
8781 }
8782 if(m_nOffsetCells[2] + m_nActiveCells[2] == m_grid->getMyBlockNoCells(2)) {
8783 endGC[2] = m_noGhostLayers;
8784 }
8785 if(m_nOffsetCells[0] + m_nActiveCells[0] == m_grid->getMyBlockNoCells(0)) {
8786 endGC[0] = m_noGhostLayers;
8787 }
8788
8789 for(MInt i = startGC[2]; i < m_nCells[2] - endGC[2]; i++) {
8790 for(MInt j = 0; j < m_noGhostLayers; j++) {
8791 for(MInt k = startGC[0]; k < m_nCells[0] - endGC[0]; k++) {
8792 MInt cellId = cellIndex(i, j, k);
8793 MInt globalI = m_nOffsetCells[2] - m_noGhostLayers + i;
8794 MInt globalJ = j;
8795 MInt globalK = m_nOffsetCells[0] - m_noGhostLayers + k;
8796 MInt cellIdBC = globalI + (globalJ + globalK * m_noGhostLayers) * m_grid->getMyBlockNoCells(2);
8797
8798 // load values from restart field
8799 for(MInt var = 0; var < PV->noVariables; var++) {
8800 m_cells->pvariables[var][cellId] = tmpRestartVars[var * noCellsBC + cellIdBC];
8801 }
8802 }
8803 }
8804 }
8805
8806 // Fix diagonal cells at start of domain
8807 if(m_nOffsetCells[2] == 0) {
8808 for(MInt j = 0; j < m_noGhostLayers; j++) {
8809 for(MInt k = 0; k < m_nCells[0]; k++) {
8810 const MInt cellIdA2 = cellIndex(3, j, k);
8811 const MInt cellIdA1 = cellIndex(2, j, k);
8812 const MInt cellIdG1 = cellIndex(1, j, k);
8813 for(MInt var = 0; var < PV->noVariables; var++) {
8814 const MFloat slope = (m_cells->pvariables[var][cellIdA2] - m_cells->pvariables[var][cellIdA1])
8815 / (m_cells->coordinates[0][cellIdA2] - m_cells->coordinates[0][cellIdA1]);
8816 m_cells->pvariables[var][cellIdG1] =
8817 m_cells->pvariables[var][cellIdA1]
8818 + (m_cells->coordinates[0][cellIdG1] - m_cells->coordinates[0][cellIdA1]) * slope;
8819 }
8820 }
8821 }
8822 }
8823
8824 // Fix diagonal cells at end of domain
8825 if(m_nOffsetCells[2] + m_nActiveCells[2] == m_grid->getMyBlockNoCells(2)) {
8826 for(MInt j = 0; j < m_noGhostLayers; j++) {
8827 for(MInt k = 0; k < m_nCells[0]; k++) {
8828 const MInt cellIdA2 = cellIndex(m_noGhostLayers + m_nActiveCells[2] - 2, j, k);
8829 const MInt cellIdA1 = cellIndex(m_noGhostLayers + m_nActiveCells[2] - 1, j, k);
8830 const MInt cellIdG1 = cellIndex(m_noGhostLayers + m_nActiveCells[2], j, k);
8831 for(MInt var = 0; var < PV->noVariables; var++) {
8832 const MFloat slope = (m_cells->pvariables[var][cellIdA1] - m_cells->pvariables[var][cellIdA2])
8833 / (m_cells->coordinates[0][cellIdA1] - m_cells->coordinates[0][cellIdA2]);
8834 m_cells->pvariables[var][cellIdG1] =
8835 m_cells->pvariables[var][cellIdA1]
8836 + (m_cells->coordinates[0][cellIdG1] - m_cells->coordinates[0][cellIdA1]) * slope;
8837 }
8838 }
8839 }
8840 }
8841 }
8842 }
8843}
8844
8846 if(m_stgIsActive) {
8847 if(!isPrimitiveOutput && domainId() == 0) {
8848 cout << "Restart file has conservative variables, converting STG variables to primitive!" << endl;
8849 }
8850
8851 stringstream restartFileName;
8852 MString restartFile = Context::getSolverProperty<MString>("restartVariablesFileName", m_solverId, AT_);
8853 restartFileName << outputDir() << restartFile;
8854 ParallelIoHdf5 pio(restartFileName.str(), maia::parallel_io::PIO_READ, m_StructuredComm);
8855
8856 stringstream blockNumber;
8857 blockNumber << m_blockId;
8858 MString blockPathStr = "/block";
8859 blockPathStr += blockNumber.str();
8860
8861 MInt restartNoEddies = 0;
8862 pio.getAttribute(&restartNoEddies, "stgNRAN", "");
8863
8864 if(restartNoEddies != m_stgMaxNoEddies) {
8865 m_log << "STG: NRAN in restart file (" << restartNoEddies << ") not the same as given in property file ("
8866 << m_stgMaxNoEddies << "), creating new random distribution of eddies!" << endl;
8867 m_stgCreateNewEddies = true;
8868 } else {
8869 m_log << "STG: Reading in " << restartNoEddies << " eddies from restart file" << endl;
8870 }
8871
8872 // if this is an initialStartup the new
8873 // eddies need to be created in any case
8875 m_stgCreateNewEddies = true;
8876 ParallelIo::size_type offset[3] = {m_nOffsetCells[0], m_nOffsetCells[1], m_nOffsetCells[2]};
8877 ParallelIo::size_type size[3] = {m_nActiveCells[0], m_nActiveCells[1], m_nActiveCells[2]};
8878 // also load nu_t into fq field
8879 pio.readArray(m_cells->fq[FQ->NU_T], blockPathStr, FQ->fqNames[FQ->NU_T].c_str(), nDim, offset, size);
8880 FQ->loadedFromRestartFile[FQ->NU_T] = true;
8881 } else {
8882 // has to be set manually for restart from RANS profile
8883 ParallelIo::size_type ninmax = m_stgNoEddieProperties * m_stgMaxNoEddies;
8884 ParallelIo::size_type VBStart = 0;
8885
8886
8891 if(domainId() == 0) {
8892 cout << "NRAN in property differs from NRAN in restart file"
8893 << " NOT READING EDDIES FROM RESTART!" << endl;
8894 }
8895 } else {
8896 MString stgGlobalPathStr = "stgGlobal";
8897
8898 if(pio.hasDataset("FQeddies", stgGlobalPathStr)) {
8899 if(domainId() == 0) {
8900 cout << "FQeddies field is at new position /stgGlobal/FQeddies" << endl;
8901 }
8902 } else {
8903 if(domainId() == 0) {
8904 cout << "FQeddies field is NOT at new position! Using old path within solver..." << endl;
8905 }
8906 stgGlobalPathStr = blockPathStr;
8907 if(domainId() == 0) {
8908 cout << "Loading FQeddies from path " << stgGlobalPathStr << endl;
8909 }
8910 }
8911
8912 // do this only serially
8913 if(globalDomainId() == 0) {
8914 cout << "Loading STG Eddies..." << endl;
8915 }
8916 if(globalDomainId() == 0) {
8917 ParallelIoHdf5 pioLocal(restartFileName.str(), maia::parallel_io::PIO_READ, MPI_COMM_SELF);
8918 pioLocal.readArray(m_stgEddies[0], stgGlobalPathStr, "FQeddies", 1, &VBStart, &ninmax);
8919 }
8920
8921 MPI_Bcast(m_stgEddies[0], ninmax, MPI_DOUBLE, 0, m_StructuredComm, AT_, "m_stgEddies[0]");
8922 if(globalDomainId() == 0) {
8923 cout << "Loading STG Eddies... SUCCESSFUL!" << endl;
8924 }
8925 }
8926
8927
8931
8932 if(m_stgLocal) {
8933 ParallelIo::size_type bcActiveCells[3] = {m_grid->getMyBlockNoCells(0), m_grid->getMyBlockNoCells(1), 3};
8934 ParallelIo::size_type bcCells[3] = {m_grid->getMyBlockNoCells(0) + m_noGhostLayers * 2,
8935 m_grid->getMyBlockNoCells(1) + m_noGhostLayers * 2, 3};
8936 ParallelIo::size_type bcOffset[3] = {0, 0, 0};
8937 const MInt noCellsBC = bcCells[0] * bcCells[1] * bcCells[2];
8938 MFloatScratchSpace tmpRestartVars(noCellsBC * m_stgNoVariables, AT_, "tmpRestartVars");
8939
8940 if(m_commStgMyRank == 0) {
8941 cout << "Loading STG Datasets..." << endl;
8942 }
8943 if(m_commStgMyRank == 0) {
8944 ParallelIoHdf5 pioLocal(restartFileName.str(), maia::parallel_io::PIO_READ, MPI_COMM_SELF);
8945 cout << "stg_myRankdomainId:" << domainId() << " m_commStgMyRank:" << m_commStgMyRank << endl;
8946 for(MInt var = 0; var < m_stgNoVariables; var++) {
8947 stringstream fieldName;
8948 stringstream stgPath;
8949 stgPath << blockPathStr << "/stg";
8950 fieldName << "stgFQ" << var;
8951 pioLocal.readArray(&tmpRestartVars[var * noCellsBC], stgPath.str(), fieldName.str(), nDim, bcOffset,
8952 bcActiveCells);
8953 }
8954
8955 // reorder the cells in the global array
8956 for(MInt k = (bcActiveCells[0] - 1); k >= 0; k--) {
8957 for(MInt j = (bcActiveCells[1] - 1); j >= 0; j--) {
8958 for(MInt i = (bcActiveCells[2] - 1); i >= 0; i--) {
8959 const MInt cellId_org = i + (j + k * bcActiveCells[1]) * bcActiveCells[2];
8960 const MInt i_new = i;
8961 const MInt j_new = j + m_noGhostLayers;
8962 const MInt k_new = k + m_noGhostLayers;
8963 const MInt cellId = i_new + (j_new + k_new * bcCells[1]) * bcCells[2];
8964
8965 for(MInt var = 0; var < m_stgNoVariables; var++) {
8966 tmpRestartVars[var * noCellsBC + cellId] = tmpRestartVars[var * noCellsBC + cellId_org];
8967 tmpRestartVars[var * noCellsBC + cellId_org] = F0;
8968 }
8969 }
8970 }
8971 }
8972
8973 // apply periodic bc
8974 for(MInt j = 0; j < bcCells[1]; j++) {
8975 for(MInt i = 0; i < bcCells[2]; i++) {
8976 const MInt gcId0 = i + (j + (0) * bcCells[1]) * bcCells[2];
8977 const MInt acId0 = i + (j + (bcCells[0] - 4) * bcCells[1]) * bcCells[2];
8978 const MInt gcId1 = i + (j + (1) * bcCells[1]) * bcCells[2];
8979 const MInt acId1 = i + (j + (bcCells[0] - 3) * bcCells[1]) * bcCells[2];
8980
8981 const MInt gcId2 = i + (j + (bcCells[0] - 2) * bcCells[1]) * bcCells[2];
8982 const MInt acId2 = i + (j + (2) * bcCells[1]) * bcCells[2];
8983 const MInt gcId3 = i + (j + (bcCells[0] - 1) * bcCells[1]) * bcCells[2];
8984 const MInt acId3 = i + (j + (3) * bcCells[1]) * bcCells[2];
8985
8986 for(MInt var = 0; var < m_stgNoVariables; var++) {
8987 tmpRestartVars[var * noCellsBC + gcId0] = tmpRestartVars[var * noCellsBC + acId0];
8988 tmpRestartVars[var * noCellsBC + gcId1] = tmpRestartVars[var * noCellsBC + acId1];
8989 tmpRestartVars[var * noCellsBC + gcId2] = tmpRestartVars[var * noCellsBC + acId2];
8990 tmpRestartVars[var * noCellsBC + gcId3] = tmpRestartVars[var * noCellsBC + acId3];
8991 }
8992 }
8993 }
8994
8995 // extrapolation at the bottoms
8996 for(MInt k = 0; k < bcCells[0]; k++) {
8997 for(MInt i = 0; i < bcCells[2]; i++) {
8998 const MInt gc1 = i + (1 + k * bcCells[1]) * bcCells[2];
8999 const MInt gc2 = i + (0 + k * bcCells[1]) * bcCells[2];
9000 const MInt ac1 = i + (2 + k * bcCells[1]) * bcCells[2];
9001 const MInt ac2 = i + (3 + k * bcCells[1]) * bcCells[2];
9002
9003 for(MInt var = 0; var < m_stgNoVariables; var++) {
9004 tmpRestartVars[var * noCellsBC + gc1] =
9005 2 * tmpRestartVars[var * noCellsBC + ac1] - tmpRestartVars[var * noCellsBC + ac2];
9006 tmpRestartVars[var * noCellsBC + gc2] =
9007 2 * tmpRestartVars[var * noCellsBC + gc1] - tmpRestartVars[var * noCellsBC + ac1];
9008 }
9009 }
9010 }
9011
9012 // extrapolation at the top
9013 for(MInt k = 0; k < bcCells[0]; k++) {
9014 for(MInt i = 0; i < bcCells[2]; i++) {
9015 const MInt gc1 = i + (bcCells[1] - 2 + k * bcCells[1]) * bcCells[2];
9016 const MInt gc2 = i + (bcCells[1] - 1 + k * bcCells[1]) * bcCells[2];
9017 const MInt ac1 = i + (bcCells[1] - 3 + k * bcCells[1]) * bcCells[2];
9018 const MInt ac2 = i + (bcCells[1] - 4 + k * bcCells[1]) * bcCells[2];
9019
9020
9021 for(MInt var = 0; var < m_stgNoVariables; var++) {
9022 tmpRestartVars[var * noCellsBC + gc1] =
9023 2 * tmpRestartVars[var * noCellsBC + ac1] - tmpRestartVars[var * noCellsBC + ac2];
9024 tmpRestartVars[var * noCellsBC + gc2] =
9025 2 * tmpRestartVars[var * noCellsBC + gc1] - tmpRestartVars[var * noCellsBC + ac1];
9026 }
9027 }
9028 }
9029 }
9030
9031
9032 // now broadcast to everyone
9033 MPI_Bcast(&tmpRestartVars[0], noCellsBC * m_stgNoVariables, MPI_DOUBLE, 0, m_commStg, AT_, "tmpRestartVars[0]");
9034 if(m_commStgMyRank == 0) {
9035 cout << "Loading STG Datasets... SUCCESSFUL!" << endl;
9036 }
9037
9041 for(MInt k = 0; k < m_nCells[0]; k++) {
9042 for(MInt j = 0; j < m_nCells[1]; j++) {
9043 for(MInt i = 0; i < 3; i++) {
9044 MInt cellId = cellIndex(i, j, k);
9045 MInt globalI = i;
9046 MInt globalJ = m_nOffsetCells[1] + j;
9047 MInt globalK = m_nOffsetCells[0] + k;
9048 MInt cellIdBCGlobal = globalI + (globalJ + globalK * bcCells[1]) * bcCells[2];
9049 MInt cellIdBC = i + (j + k * m_nCells[1]) * 3;
9050
9051 // load values from restart field
9052 for(MInt var = 0; var < m_stgNoVariables; var++) {
9053 m_cells->stg_fq[var][cellIdBC] = tmpRestartVars[var * noCellsBC + cellIdBCGlobal];
9054 }
9055
9056 if(!isPrimitiveOutput) {
9057 const MFloat rho = m_cells->stg_fq[0][cellIdBC];
9058 const MFloat rhoU = m_cells->stg_fq[1][cellIdBC];
9059 const MFloat rhoV = m_cells->stg_fq[2][cellIdBC];
9060 const MFloat rhoW = m_cells->stg_fq[3][cellIdBC];
9061 const MFloat rhoE = m_cells->stg_fq[4][cellIdBC];
9062
9063 const MFloat gammaMinusOne = m_gamma - 1.0;
9064 const MFloat u = rhoU / rho;
9065 const MFloat v = rhoV / rho;
9066 const MFloat w = rhoW / rho;
9067 const MFloat p = gammaMinusOne * (rhoE - F1B2 * rho * (POW2(u) + POW2(v) + POW2(w)));
9068
9069 m_cells->stg_fq[PV->RHO][cellIdBC] = rho;
9070 m_cells->stg_fq[PV->U][cellIdBC] = u;
9071 m_cells->stg_fq[PV->V][cellIdBC] = v;
9072 m_cells->stg_fq[PV->W][cellIdBC] = w;
9073 m_cells->stg_fq[PV->P][cellIdBC] = p;
9074 }
9075
9076 if(i < 2) {
9077 m_cells->pvariables[PV->RHO][cellId] = m_cells->stg_fq[PV->RHO][cellIdBC];
9078 m_cells->pvariables[PV->U][cellId] = m_cells->stg_fq[PV->U][cellIdBC];
9079 m_cells->pvariables[PV->V][cellId] = m_cells->stg_fq[PV->V][cellIdBC];
9080 m_cells->pvariables[PV->W][cellId] = m_cells->stg_fq[PV->W][cellIdBC];
9081 m_cells->pvariables[PV->P][cellId] = m_cells->stg_fq[PV->P][cellIdBC];
9082 }
9083 }
9084 }
9085 }
9086 }
9087 }
9088
9089 }
9090}
9091
9092
9094 TRACE();
9095 MFloat* const RESTRICT u = &m_cells->pvariables[PV->U][0];
9096 MFloat* const RESTRICT v = &m_cells->pvariables[PV->V][0];
9097 MFloat* const RESTRICT w = &m_cells->pvariables[PV->W][0];
9098 MFloat* const RESTRICT vortx = &m_cells->fq[FQ->VORTX][0];
9099 MFloat* const RESTRICT vorty = &m_cells->fq[FQ->VORTY][0];
9100 MFloat* const RESTRICT vortz = &m_cells->fq[FQ->VORTZ][0];
9101 MFloat* const RESTRICT jac = &m_cells->cellJac[0];
9102
9103
9104 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; k++) {
9105 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; j++) {
9106 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; i++) {
9107 const MInt IJK = i + (j + k * m_nCells[1]) * m_nCells[2];
9108 const MInt IPJK = (i + 1) + (j + k * m_nCells[1]) * m_nCells[2];
9109 const MInt IMJK = (i - 1) + (j + k * m_nCells[1]) * m_nCells[2];
9110 const MInt IJPK = i + ((j + 1) + k * m_nCells[1]) * m_nCells[2];
9111 const MInt IJMK = i + ((j - 1) + k * m_nCells[1]) * m_nCells[2];
9112 const MInt IJKP = i + (j + (k + 1) * m_nCells[1]) * m_nCells[2];
9113 const MInt IJKM = i + (j + (k - 1) * m_nCells[1]) * m_nCells[2];
9114
9115 const MFloat dudxi = u[IPJK] - u[IMJK];
9116 const MFloat dudet = u[IJPK] - u[IJMK];
9117 const MFloat dudze = u[IJKP] - u[IJKM];
9118
9119 const MFloat dvdxi = v[IPJK] - v[IMJK];
9120 const MFloat dvdet = v[IJPK] - v[IJMK];
9121 const MFloat dvdze = v[IJKP] - v[IJKM];
9122
9123 const MFloat dwdxi = w[IPJK] - w[IMJK];
9124 const MFloat dwdet = w[IJPK] - w[IJMK];
9125 const MFloat dwdze = w[IJKP] - w[IJKM];
9126
9127 const MFloat dvdz = dvdxi * m_cells->cellMetrics[xsd * 3 + zsd][IJK]
9128 + dvdet * m_cells->cellMetrics[ysd * 3 + zsd][IJK]
9129 + dvdze * m_cells->cellMetrics[zsd * 3 + zsd][IJK];
9130 const MFloat dwdy = dwdxi * m_cells->cellMetrics[xsd * 3 + ysd][IJK]
9131 + dwdet * m_cells->cellMetrics[ysd * 3 + ysd][IJK]
9132 + dwdze * m_cells->cellMetrics[zsd * 3 + ysd][IJK];
9133
9134 const MFloat dudz = dudxi * m_cells->cellMetrics[xsd * 3 + zsd][IJK]
9135 + dudet * m_cells->cellMetrics[ysd * 3 + zsd][IJK]
9136 + dudze * m_cells->cellMetrics[zsd * 3 + zsd][IJK];
9137 const MFloat dwdx = dwdxi * m_cells->cellMetrics[xsd * 3 + xsd][IJK]
9138 + dwdet * m_cells->cellMetrics[ysd * 3 + xsd][IJK]
9139 + dwdze * m_cells->cellMetrics[zsd * 3 + xsd][IJK];
9140
9141 const MFloat dvdx = dvdxi * m_cells->cellMetrics[xsd * 3 + xsd][IJK]
9142 + dvdet * m_cells->cellMetrics[ysd * 3 + xsd][IJK]
9143 + dvdze * m_cells->cellMetrics[zsd * 3 + xsd][IJK];
9144 const MFloat dudy = dudxi * m_cells->cellMetrics[xsd * 3 + ysd][IJK]
9145 + dudet * m_cells->cellMetrics[ysd * 3 + ysd][IJK]
9146 + dudze * m_cells->cellMetrics[zsd * 3 + ysd][IJK];
9147
9148 vortx[IJK] = F1B2 * (dwdy - dvdz) / jac[IJK];
9149 vorty[IJK] = F1B2 * (dudz - dwdx) / jac[IJK];
9150 vortz[IJK] = F1B2 * (dvdx - dudy) / jac[IJK];
9151 }
9152 }
9153 }
9154}
9155
9156
9163 TRACE();
9164 MFloatScratchSpace J(nDim, nDim, AT_, "J");
9165 MFloat d[3] = {F0, F0, F0};
9166 MFloat e[3] = {F0, F0, F0};
9167 J.fill(F0);
9168
9169 // MInt IMJK, IJMK, IMJMK, IJKM, IJMKM, IMJKM;
9170 MFloat* const RESTRICT u = &m_cells->pvariables[PV->U][0];
9171 MFloat* const RESTRICT v = &m_cells->pvariables[PV->V][0];
9172 MFloat* const RESTRICT w = &m_cells->pvariables[PV->W][0];
9173 MFloat* const RESTRICT lambda2 = &m_cells->fq[FQ->LAMBDA2][0];
9174
9175 // compute the lambda2 criterion.
9176 for(MInt k = m_noGhostLayers - 1; k < m_nCells[0] - m_noGhostLayers + 1; k++) {
9177 for(MInt j = m_noGhostLayers - 1; j < m_nCells[1] - m_noGhostLayers + 1; j++) {
9178 for(MInt i = m_noGhostLayers - 1; i < m_nCells[2] - m_noGhostLayers + 1; i++) {
9179 const MInt cellId = cellIndex(i, j, k);
9180 const MInt IMJK = cellIndex(i - 1, j, k);
9181 const MInt IPJK = cellIndex(i + 1, j, k);
9182 const MInt IJMK = cellIndex(i, j - 1, k);
9183 const MInt IJPK = cellIndex(i, j + 1, k);
9184 const MInt IJKM = cellIndex(i, j, k - 1);
9185 const MInt IJKP = cellIndex(i, j, k + 1);
9186 const MFloat FcellJac = F1 / m_cells->cellJac[cellId];
9187
9188 const MFloat dudx = FcellJac
9189 * (m_cells->cellMetrics[0][cellId] * (u[IPJK] - u[IMJK])
9190 + m_cells->cellMetrics[3][cellId] * (u[IJPK] - u[IJMK])
9191 + m_cells->cellMetrics[6][cellId] * (u[IJKP] - u[IJKM]));
9192 const MFloat dudy = FcellJac
9193 * (m_cells->cellMetrics[1][cellId] * (u[IPJK] - u[IMJK])
9194 + m_cells->cellMetrics[4][cellId] * (u[IJPK] - u[IJMK])
9195 + m_cells->cellMetrics[7][cellId] * (u[IJKP] - u[IJKM]));
9196 const MFloat dudz = FcellJac
9197 * (m_cells->cellMetrics[2][cellId] * (u[IPJK] - u[IMJK])
9198 + m_cells->cellMetrics[5][cellId] * (u[IJPK] - u[IJMK])
9199 + m_cells->cellMetrics[8][cellId] * (u[IJKP] - u[IJKM]));
9200
9201 const MFloat dvdx = FcellJac
9202 * (m_cells->cellMetrics[0][cellId] * (v[IPJK] - v[IMJK])
9203 + m_cells->cellMetrics[3][cellId] * (v[IJPK] - v[IJMK])
9204 + m_cells->cellMetrics[6][cellId] * (v[IJKP] - v[IJKM]));
9205 const MFloat dvdy = FcellJac
9206 * (m_cells->cellMetrics[1][cellId] * (v[IPJK] - v[IMJK])
9207 + m_cells->cellMetrics[4][cellId] * (v[IJPK] - v[IJMK])
9208 + m_cells->cellMetrics[7][cellId] * (v[IJKP] - v[IJKM]));
9209 const MFloat dvdz = FcellJac
9210 * (m_cells->cellMetrics[2][cellId] * (v[IPJK] - v[IMJK])
9211 + m_cells->cellMetrics[5][cellId] * (v[IJPK] - v[IJMK])
9212 + m_cells->cellMetrics[8][cellId] * (v[IJKP] - v[IJKM]));
9213
9214 const MFloat dwdx = FcellJac
9215 * (m_cells->cellMetrics[0][cellId] * (w[IPJK] - w[IMJK])
9216 + m_cells->cellMetrics[3][cellId] * (w[IJPK] - w[IJMK])
9217 + m_cells->cellMetrics[6][cellId] * (w[IJKP] - w[IJKM]));
9218 const MFloat dwdy = FcellJac
9219 * (m_cells->cellMetrics[1][cellId] * (w[IPJK] - w[IMJK])
9220 + m_cells->cellMetrics[4][cellId] * (w[IJPK] - w[IJMK])
9221 + m_cells->cellMetrics[7][cellId] * (w[IJKP] - w[IJKM]));
9222 const MFloat dwdz = FcellJac
9223 * (m_cells->cellMetrics[2][cellId] * (w[IPJK] - w[IMJK])
9224 + m_cells->cellMetrics[5][cellId] * (w[IJPK] - w[IJMK])
9225 + m_cells->cellMetrics[8][cellId] * (w[IJKP] - w[IJKM]));
9226
9227 // Compute the matrix (S^2+Omega^2)/2
9228 J(0, 0) = POW2(dudx) + dvdx * dudy + dwdx * dudz;
9229 J(0, 1) = F1B2 * (dudx * dudy + dudx * dvdx + dvdy * dudy + dvdy * dvdx + dwdy * dudz + dvdz * dwdx);
9230 J(0, 2) = F1B2 * (dudx * dudz + dudx * dwdx + dudy * dvdz + dvdx * dwdy + dwdz * dudz + dwdz * dwdx);
9231 J(1, 0) = J(0, 1);
9232 J(1, 1) = POW2(dvdy) + dvdx * dudy + dvdz * dwdy;
9233 J(1, 2) = F1B2 * (dudz * dvdx + dwdx * dudy + dvdy * dvdz + dvdy * dwdy + dwdz * dvdz + dwdz * dwdy);
9234 J(2, 0) = J(0, 2);
9235 J(2, 1) = J(1, 2);
9236 J(2, 2) = POW2(dwdz) + dwdx * dudz + dvdz * dwdy;
9237
9238 // perform householder tridiagonalization of
9239 // symmetric real matrix
9240 tred2(J, nDim, d, e);
9241 // compute eigenvalues
9242 tqli2(d, e, nDim);
9243 // sort eigenvalues
9244 insertSort(nDim, d);
9245
9246 lambda2[cellId] = d[1];
9247 }
9248 }
9249 }
9250}
9251
9252
9254 TRACE();
9258
9259 // if it a moving grid the interpolation
9260 // coefficients need to be computed every time
9261 if(m_movingGrid) {
9262 for(MInt pointId = 0; pointId < m_intpPointsNoPointsTotal; pointId++) {
9263 m_intpPointsHasPartnerLocal[pointId] = 0;
9264 m_intpPointsHasPartnerGlobal[pointId] = 0;
9265 for(MInt var = 0; var < PV->noVariables; var++) {
9266 m_intpPointsVarsLocal[var][pointId] = F0;
9267 m_intpPointsVarsGlobal[var][pointId] = F0;
9268 }
9269 }
9270
9272 make_unique<StructuredInterpolation<3>>(m_nCells, m_cells->coordinates, m_cells->pvariables, m_StructuredComm);
9273 // allocate domains points of the lines
9277 MPI_SUM, m_StructuredComm, AT_, "m_intpPointsHasPartnerLocal", "m_intpPointsHasPartnerGlobal");
9278 }
9279
9280 // calculation of interpolated variables only for the points in domain
9281 for(MInt pointId = 0; pointId < m_intpPointsNoPointsTotal; pointId++) {
9282 if(m_intpPointsHasPartnerLocal[pointId]) {
9283 for(MInt var = 0; var < PV->noVariables; var++) {
9284 m_intpPointsVarsLocal[var][pointId] = m_pointInterpolation->getInterpolatedVariable(pointId, var);
9285 }
9286 }
9287 }
9288
9290 m_intpPointsNoPointsTotal * PV->noVariables, MPI_DOUBLE, MPI_SUM, m_StructuredComm, AT_,
9291 "m_intpPointsVarsLocal[0][0]", "m_intpPointsVarsGlobal[0][0]");
9292
9293 // calculation of right value, if a point is assigned to more than one domain
9294 for(MInt pointId = 0; pointId < m_intpPointsNoPointsTotal; pointId++) {
9295 if(m_intpPointsHasPartnerGlobal[pointId] > 1) {
9296 for(MInt var = 0; var < PV->noVariables; var++) {
9297 m_intpPointsVarsGlobal[var][pointId] =
9299 }
9300 }
9301 }
9302
9303 if(m_movingGrid) {
9304 m_pointInterpolation.reset();
9305 }
9306
9310 stringstream fileName;
9311 fileName << m_intpPointsOutputDir << "interpolatedPoints" << globalTimeStep << m_outputFormat;
9312
9314
9315 writeHeaderAttributes(&pio, "field");
9317
9318 pio.setAttribute(m_intpPointsNoLines, "noFields", "");
9319
9320 for(MInt lineId = 0; lineId < m_intpPointsNoLines; lineId++) {
9321 ParallelIo::size_type dataOffset[2] = {0, 0};
9322 ParallelIo::size_type dataSize[2] = {m_intpPointsNoPoints2D[lineId], m_intpPointsNoPoints[lineId]};
9323 MInt fieldOffset = m_intpPointsOffsets[lineId];
9324
9325 ParallelIo::size_type noDims = 1;
9326 dataSize[0] = dataSize[1];
9327 if(m_intpPoints) {
9328 noDims = 2;
9329 }
9330
9331 stringstream path;
9332 path << lineId;
9333 MString solutionpath = "field";
9334 solutionpath += path.str();
9335 const char* dsetname = solutionpath.c_str();
9336
9337 for(MInt v = 0; v < PV->noVariables; v++) {
9338 pio.defineArray(maia::parallel_io::PIO_FLOAT, dsetname, m_pvariableNames[v], noDims, dataSize);
9339 }
9340
9341 pio.defineArray(maia::parallel_io::PIO_FLOAT, dsetname, "x", noDims, dataSize);
9342 pio.defineArray(maia::parallel_io::PIO_FLOAT, dsetname, "y", noDims, dataSize);
9343 pio.defineArray(maia::parallel_io::PIO_FLOAT, dsetname, "z", noDims, dataSize);
9344
9345 if(domainId() == 0) {
9346 for(MInt v = 0; v < PV->noVariables; v++) {
9347 pio.writeArray(&m_intpPointsVarsGlobal[v][fieldOffset], dsetname, m_pvariableNames[v], noDims, dataOffset,
9348 dataSize);
9349 }
9350
9351 pio.writeArray(&m_intpPointsCoordinates[0][fieldOffset], dsetname, "x", noDims, dataOffset, dataSize);
9352 pio.writeArray(&m_intpPointsCoordinates[1][fieldOffset], dsetname, "y", noDims, dataOffset, dataSize);
9353 pio.writeArray(&m_intpPointsCoordinates[2][fieldOffset], dsetname, "z", noDims, dataOffset, dataSize);
9354 } else {
9355 dataSize[0] = 0;
9356 dataSize[1] = 0;
9357 MFloat empty = 0;
9358 for(MInt v = 0; v < PV->noVariables; v++) {
9359 pio.writeArray(&empty, dsetname, m_pvariableNames[v], 1, dataOffset, dataSize);
9360 }
9361
9362 pio.writeArray(&empty, dsetname, "x", noDims, dataOffset, dataSize);
9363 pio.writeArray(&empty, dsetname, "y", noDims, dataOffset, dataSize);
9364 pio.writeArray(&empty, dsetname, "z", noDims, dataOffset, dataSize);
9365 }
9366 }
9367}
9368
9370
9372
9374 cellVars[PV->U] = m_cells->pvariables[PV->U][cellId];
9375 cellVars[PV->V] = m_cells->pvariables[PV->V][cellId];
9376 cellVars[PV->W] = m_cells->pvariables[PV->W][cellId];
9377 cellVars[PV->RHO] = m_cells->pvariables[PV->RHO][cellId];
9378 cellVars[PV->P] = m_cells->pvariables[PV->P][cellId];
9379}
9380
9382 return m_cells->fq[FQ->VORTICITY[dim]][cellId];
9383}
9384
9385
9393void FvStructuredSolver3D::loadSampleFile(MString fileName) { // loading files for averaging (pre- and postsolve)
9394 TRACE();
9395
9396 // open the file
9398
9399 stringstream blockNumber;
9400 blockNumber << m_blockId;
9401 MString blockPathStr = "/block";
9402 blockPathStr += blockNumber.str();
9403 ParallelIo::size_type offset[3] = {m_nOffsetCells[0], m_nOffsetCells[1], m_nOffsetCells[2]};
9404 ParallelIo::size_type size[3] = {m_nActiveCells[0], m_nActiveCells[1], m_nActiveCells[2]};
9405
9406 for(MInt var = 0; var < PV->noVariables; var++) {
9407 pio.readArray(m_cells->pvariables[var], blockPathStr, m_pvariableNames[var], nDim, offset, size);
9408 }
9409
9411}
9412
9413
9415 const MInt INC[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
9416
9417 const MInt IPJK = IJK + INC[0];
9418 const MInt IMJK = IJK - INC[0];
9419 const MInt IJPK = IJK + INC[1];
9420 const MInt IJMK = IJK - INC[1];
9421 const MInt IJKP = IJK + INC[2];
9422 const MInt IJKM = IJK - INC[2];
9423
9424 const MFloat dvardxi = F1B2 * (var[IPJK] - var[IMJK]);
9425 const MFloat dvardet = F1B2 * (var[IJPK] - var[IJMK]);
9426 const MFloat dvardze = F1B2 * (var[IJKP] - var[IJKM]);
9427
9428 const MFloat ddxyz =
9429 (dvardxi * m_cells->cellMetrics[xsd * 3 + dir][IJK] + dvardet * m_cells->cellMetrics[ysd * 3 + dir][IJK]
9430 + dvardze * m_cells->cellMetrics[zsd * 3 + dir][IJK]);
9431
9432 return ddxyz / m_cells->cellJac[IJK];
9433}
9434
9436 const MInt INC[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
9437
9438 const MInt IPJK = IJK + INC[0];
9439 const MInt IMJK = IJK - INC[0];
9440 const MInt IJPK = IJK + INC[1];
9441 const MInt IJMK = IJK - INC[1];
9442 const MInt IJKP = IJK + INC[2];
9443 const MInt IJKM = IJK - INC[2];
9444
9445 const MFloat dvardxi = var[IPJK] - var[IMJK];
9446 const MFloat dvardet = var[IJPK] - var[IJMK];
9447 const MFloat dvardze = var[IJKP] - var[IJKM];
9448
9449 const MFloat ddx =
9450 (dvardxi * m_cells->cellMetrics[xsd * 3 + xsd][IJK] + dvardet * m_cells->cellMetrics[ysd * 3 + xsd][IJK]
9451 + dvardze * m_cells->cellMetrics[zsd * 3 + xsd][IJK]);
9452
9453 return ddx / m_cells->cellJac[IJK];
9454}
9455
9456
9464void FvStructuredSolver3D::loadAverageRestartFile(const MChar* fileName, MFloat** sum, MFloat** square, MFloat** cube,
9465 MFloat** fourth) {
9466 TRACE();
9467 m_log << "loading average restart file ... " << endl;
9468 if(domainId() == 0) {
9469 cout << "Opening file: " << fileName << endl;
9470 }
9471
9472 // open the file
9473 MString fileNameStr = fileName;
9475
9476 // now read in the data!
9477 m_log << "-> reading in the data ... " << endl;
9478 pio.getAttribute(&m_noSamples, "noSamples", "");
9479 m_log << "Current number of postprocessing samples: " << m_noSamples << endl;
9480 stringstream blockNumber;
9481 blockNumber << m_blockId;
9482 MString blockPathStr = "/block";
9483 blockPathStr += blockNumber.str();
9484 MInt offset = 0;
9485 ParallelIo::size_type ioOffset[3] = {m_nOffsetCells[0], m_nOffsetCells[1], m_nOffsetCells[2]};
9486 ParallelIo::size_type ioSize[3] = {m_nActiveCells[0], m_nActiveCells[1], m_nActiveCells[2]};
9487
9488
9489 pio.readArray(sum[0], blockPathStr, "u", nDim, ioOffset, ioSize);
9490 pio.readArray(sum[1], blockPathStr, "v", nDim, ioOffset, ioSize);
9491 pio.readArray(sum[2], blockPathStr, "w", nDim, ioOffset, ioSize);
9492 pio.readArray(sum[3], blockPathStr, "rho", nDim, ioOffset, ioSize);
9493 pio.readArray(sum[4], blockPathStr, "p", nDim, ioOffset, ioSize);
9494 offset = noVariables();
9495
9496 if(m_averagingFavre) {
9497 pio.readArray(m_favre[0], blockPathStr, "um_favre", nDim, ioOffset, ioSize);
9498 pio.readArray(m_favre[1], blockPathStr, "vm_favre", nDim, ioOffset, ioSize);
9499 pio.readArray(m_favre[2], blockPathStr, "wm_favre", nDim, ioOffset, ioSize);
9500 pio.readArray(m_favre[3], blockPathStr, "rhom_favre", nDim, ioOffset, ioSize);
9501 pio.readArray(m_favre[4], blockPathStr, "pm_favre", nDim, ioOffset, ioSize);
9502 }
9503
9504 if(m_averageVorticity) {
9505 pio.readArray(sum[offset + 0], blockPathStr, "vortx", nDim, ioOffset, ioSize);
9506 pio.readArray(sum[offset + 1], blockPathStr, "vorty", nDim, ioOffset, ioSize);
9507 pio.readArray(sum[offset + 2], blockPathStr, "vortz", nDim, ioOffset, ioSize);
9508 }
9509
9510 pio.readArray(square[0], blockPathStr, "uu", nDim, ioOffset, ioSize);
9511 pio.readArray(square[1], blockPathStr, "vv", nDim, ioOffset, ioSize);
9512 pio.readArray(square[2], blockPathStr, "ww", nDim, ioOffset, ioSize);
9513 pio.readArray(square[3], blockPathStr, "uv", nDim, ioOffset, ioSize);
9514 pio.readArray(square[4], blockPathStr, "vw", nDim, ioOffset, ioSize);
9515 pio.readArray(square[5], blockPathStr, "uw", nDim, ioOffset, ioSize);
9516
9517 pio.readArray(square[6], blockPathStr, "pp", nDim, ioOffset, ioSize);
9518
9519 if(m_averageVorticity) {
9520 pio.readArray(square[7], blockPathStr, "vortxvortx", nDim, ioOffset, ioSize);
9521 pio.readArray(square[8], blockPathStr, "vortyvorty", nDim, ioOffset, ioSize);
9522 pio.readArray(square[9], blockPathStr, "vortzvortz", nDim, ioOffset, ioSize);
9523 }
9524
9525 if(m_kurtosis || m_skewness) {
9526 pio.readArray(cube[0], blockPathStr, "uuu", nDim, ioOffset, ioSize);
9527 pio.readArray(cube[1], blockPathStr, "vvv", nDim, ioOffset, ioSize);
9528 pio.readArray(cube[2], blockPathStr, "www", nDim, ioOffset, ioSize);
9529 }
9530
9531 if(m_kurtosis) {
9532 pio.readArray(fourth[0], blockPathStr, "uuuu", nDim, ioOffset, ioSize);
9533 pio.readArray(fourth[1], blockPathStr, "vvvv", nDim, ioOffset, ioSize);
9534 pio.readArray(fourth[2], blockPathStr, "wwww", nDim, ioOffset, ioSize);
9535 }
9536
9537 m_log << "loading Restart file ... SUCCESSFUL " << endl;
9539}
9540
9547 TRACE();
9548 m_log << "loading averaged variables file ... " << endl;
9549
9550 // open the file
9551 MString fileNameStr = fileName;
9553
9554 stringstream blockNumber;
9555 blockNumber << m_blockId;
9556 MString blockPathStr = "/block";
9557 blockPathStr += blockNumber.str();
9558 ParallelIo::size_type ioOffset[3] = {m_nOffsetCells[0], m_nOffsetCells[1], m_nOffsetCells[2]};
9559 ParallelIo::size_type ioSize[3] = {m_nActiveCells[0], m_nActiveCells[1], m_nActiveCells[2]};
9560
9561 for(MInt var = 0; var < getNoPPVars(); var++) {
9562 pio.readArray(m_summedVars[var], blockPathStr, m_avgVariableNames[var], nDim, ioOffset, ioSize);
9563 }
9564
9565 if(m_averagingFavre) {
9566 for(MInt var = 0; var < getNoVars(); var++) {
9567 pio.readArray(m_favre[var], blockPathStr, m_avgFavreNames[var], nDim, ioOffset, ioSize);
9568 }
9569 }
9570
9571 m_log << "loading Restart file ... SUCCESSFUL " << endl;
9573}
9574
9581 TRACE();
9582 MInt cellId_org = 0;
9583 MInt cellId = 0;
9584 MInt i_new, j_new, k_new;
9585
9586 // accounting for the ghost layers and shift the values to the right place
9587 for(MInt k = (m_nActiveCells[0] - 1); k >= 0; k--) {
9588 for(MInt j = (m_nActiveCells[1] - 1); j >= 0; j--) {
9589 for(MInt i = (m_nActiveCells[2] - 1); i >= 0; i--) {
9590 cellId_org = i + (j + k * m_nActiveCells[1]) * m_nActiveCells[2];
9591 i_new = i + m_noGhostLayers;
9592 j_new = j + m_noGhostLayers;
9593 k_new = k + m_noGhostLayers;
9594 cellId = i_new + (j_new + k_new * m_nCells[1]) * m_nCells[2];
9595
9596 for(MInt var = 0; var < getNoPPVars(); var++) {
9597 m_summedVars[var][cellId] = m_summedVars[var][cellId_org];
9598 m_summedVars[var][cellId_org] = F0;
9599 }
9600
9601 if(m_averagingFavre) {
9602 for(MInt var = 0; var < getNoVars(); var++) {
9603 m_favre[var][cellId] = m_favre[var][cellId_org];
9604 m_favre[var][cellId_org] = F0;
9605 }
9606 }
9607
9608 for(MInt var = 0; var < getNoPPSquareVars(); var++) {
9609 m_square[var][cellId] = m_square[var][cellId_org];
9610 m_square[var][cellId_org] = F0;
9611 }
9612
9613 if(m_kurtosis || m_skewness) {
9614 for(MInt var = 0; var < nDim; var++) {
9615 m_cube[var][cellId] = m_cube[var][cellId_org];
9616 m_cube[var][cellId_org] = F0;
9617 }
9618 }
9619
9620 if(m_kurtosis) {
9621 for(MInt var = 0; var < nDim; var++) {
9622 m_fourth[var][cellId] = m_fourth[var][cellId_org];
9623 m_fourth[var][cellId_org] = F0;
9624 }
9625 }
9626 }
9627 }
9628 }
9629}
9630
9637 TRACE();
9638 MInt cellId_org = 0;
9639 MInt cellId = 0;
9640 MInt i_new, j_new, k_new;
9641
9642 // accounting for the ghost layers and shift the values to the right place
9643 for(MInt k = (m_nActiveCells[0] - 1); k >= 0; k--) {
9644 for(MInt j = (m_nActiveCells[1] - 1); j >= 0; j--) {
9645 for(MInt i = (m_nActiveCells[2] - 1); i >= 0; i--) {
9646 cellId_org = i + (j + k * m_nActiveCells[1]) * m_nActiveCells[2];
9647 i_new = i + m_noGhostLayers;
9648 j_new = j + m_noGhostLayers;
9649 k_new = k + m_noGhostLayers;
9650 cellId = i_new + (j_new + k_new * m_nCells[1]) * m_nCells[2];
9651
9652 for(MInt var = 0; var < getNoPPVars(); var++) {
9653 m_summedVars[var][cellId] = m_summedVars[var][cellId_org];
9654 m_summedVars[var][cellId_org] = F0;
9655 }
9656
9657 if(m_averagingFavre) {
9658 for(MInt var = 0; var < getNoVars(); var++) {
9659 m_favre[var][cellId] = m_favre[var][cellId_org];
9660 m_favre[var][cellId_org] = F0;
9661 }
9662 }
9663 }
9664 }
9665 }
9666}
9667
9668template <MFloat (FvStructuredSolver<3>::*pressure_func)(MInt) const>
9670 const MFloat gammaMinusOne = m_gamma - 1.0;
9671
9672 MFloat** const RESTRICT cvars = m_cells->variables;
9673 MFloat** const RESTRICT pvars = m_cells->pvariables;
9674
9675 for(MInt k = m_noGhostLayers; k < m_nCells[0] - m_noGhostLayers; ++k) {
9676 for(MInt j = m_noGhostLayers; j < m_nCells[1] - m_noGhostLayers; ++j) {
9677 for(MInt i = m_noGhostLayers; i < m_nCells[2] - m_noGhostLayers; ++i) {
9678 const MInt cellId = cellIndex(i, j, k);
9679 const MFloat fRho = F1 / cvars[CV->RHO][cellId];
9680 MFloat velPOW2 = F0;
9681 for(MInt vel = 0; vel < nDim; ++vel) { // compute velocity
9682 pvars[vel][cellId] = cvars[vel][cellId] * fRho;
9683 velPOW2 += POW2(pvars[vel][cellId]);
9684 }
9685
9686 // density and pressure:
9687 pvars[PV->RHO][cellId] = cvars[CV->RHO][cellId]; // density
9688 pvars[PV->P][cellId] =
9689 gammaMinusOne
9690 * (cvars[CV->RHO_E][cellId] - F1B2 * pvars[PV->RHO][cellId] * velPOW2 + (this->*pressure_func)(cellId));
9691
9692 for(MInt ransVar = 0; ransVar < m_noRansEquations; ransVar++) {
9693 // TODO_SS labels:FV,totest Does it make sense to forbid negative values. BCs sometimes negate the neighbor
9694 // value
9695 cvars[CV->RANS_VAR[ransVar]][cellId] = mMax(cvars[CV->RANS_VAR[ransVar]][cellId], F0);
9696 pvars[PV->RANS_VAR[ransVar]][cellId] = cvars[CV->RANS_VAR[ransVar]][cellId] * fRho;
9697 }
9698 }
9699 }
9700 }
9701}
9702
9705 computePrimitiveVariables_<&FvStructuredSolver::pressure_twoEqRans>();
9706 else
9708}
9709
9710
9712 for(MInt i = 0; i < m_hasSingularity; ++i) {
9713 MInt len[nDim];
9716
9717 for(MInt j = 0; j < nDim; j++) {
9718 len[j] = m_singularity[i].end[j] - m_singularity[i].start[j];
9719 m_singularity[i].totalPoints *= (len[j] + 1);
9720 m_singularity[i].totalCells *= len[j];
9721 }
9722
9723 // 4 unknowns and 2*Nstar cells
9724 mAlloc(m_singularity[i].ReconstructionConstants, nDim + 1, m_singularity[i].totalCells * m_singularity[i].Nstar * 2,
9725 "ReconstructionConstants", 0.0, AT_);
9726 }
9727}
9728
9729// see also the function in lbblckdxqy.cpp for this function
9730// implemented originally by Georg Eitel Amor for LB
9731
9732void FvStructuredSolver3D::initFFTW(fftw_complex* uPhysField, fftw_complex* vPhysField, fftw_complex* wPhysField,
9733 MInt lx, MInt ly, MInt lz, MInt noPeakModes) {
9734 TRACE();
9735 // first check for odd numbers of cells in each direction
9736 if(lx % 2 != 0 || ly % 2 != 0 || lz % 2 != 0) {
9737 stringstream errorMessage;
9738 errorMessage << " FFTInit: Domain size must NOT be an odd number!: (lx)x(ly)x(lz)-> " << lx << "x" << ly << "x"
9739 << lz << endl;
9740 mTerm(1, AT_, errorMessage.str());
9741 }
9742
9743 m_log << " --- initializing FFTW --- " << endl;
9744 m_log << " domain size = " << lx << "x" << ly << "x" << lz << endl;
9745
9746 MFloat waveVector[3], k0;
9747
9748 complex<MFloat>* fourierCoefficient = new complex<MFloat>[3];
9749
9750 fftw_complex *uHatField, *vHatField, *wHatField;
9751
9752 fftw_plan planU, planV, planW;
9753
9754 // 1) Allocation of Fourier coefficients
9755 uHatField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
9756 vHatField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
9757 wHatField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
9758
9759 // 2) Creation of the plans for the FFTW
9760 planU = fftw_plan_dft_3d(lx, ly, lz, uHatField, uPhysField, FFTW_BACKWARD, FFTW_MEASURE);
9761 planV = fftw_plan_dft_3d(lx, ly, lz, vHatField, vPhysField, FFTW_BACKWARD, FFTW_MEASURE);
9762 planW = fftw_plan_dft_3d(lx, ly, lz, wHatField, wPhysField, FFTW_BACKWARD, FFTW_MEASURE);
9763
9764 for(MInt p = 0; p < lx; p++) {
9765 for(MInt q = 0; q < ly; q++) {
9766 for(MInt r = 0; r < lz; r++) {
9767 MInt cellId = r + lz * (q + ly * p);
9768 // u-component
9769 uHatField[cellId][0] = 0.0;
9770 uHatField[cellId][1] = 0.0;
9771 uPhysField[cellId][0] = 0.0;
9772 uPhysField[cellId][1] = 0.0;
9773
9774 // v-component
9775 vHatField[cellId][0] = 0.0;
9776 vHatField[cellId][1] = 0.0;
9777 vPhysField[cellId][0] = 0.0;
9778 vPhysField[cellId][1] = 0.0;
9779
9780 // w-component
9781 wHatField[cellId][0] = 0.0;
9782 wHatField[cellId][1] = 0.0;
9783 wPhysField[cellId][0] = 0.0;
9784 wPhysField[cellId][1] = 0.0;
9785 }
9786 }
9787 }
9788
9789 // IMPORTANT NOTICE ON USE OF FFTW:
9790 // comment from Georg Eitel Amor:
9791 // FFTW stores the coefficients for positive wavenumbers in the first half of the array,
9792 // and those for negative wavenumbers in reverse order in the second half.
9793 // [0, 1, ... , N/2-1, N/2, ... , N-1]
9794 // - the entry for zero-wavenumber is at position 0
9795 // - the k-th entry and the (N-k)th entry correspond to wavenumbers with opposite sign
9796 // - the entry at position N/2 corresponds to the Nyquist wavenumber and appears only once
9797
9798 // peak wave number of energy spectrum
9799 k0 = 2.0 * PI / (lx / noPeakModes);
9800
9801 for(MInt p = 0; p <= lx / 2; p++) {
9802 for(MInt q = 0; q <= ly / 2; q++) {
9803 for(MInt r = 0; r <= lz / 2; r++) {
9804 // wave-vector: k(p,q,r) = (2 \pi p / lx, 2 \pi q / ly, 2 \pi r / lz)
9805 waveVector[0] = (p)*2.0 * PI / lx;
9806 waveVector[1] = (q)*2.0 * PI / ly;
9807 waveVector[2] = (r)*2.0 * PI / lz;
9808
9809 getFourierCoefficients(waveVector, k0, fourierCoefficient);
9810
9811 // 1. Positive frequencies:
9812 uHatField[r + lz * (q + ly * p)][0] = real(fourierCoefficient[0]);
9813 uHatField[r + lz * (q + ly * p)][1] = imag(fourierCoefficient[0]);
9814
9815 vHatField[r + lz * (q + ly * p)][0] = real(fourierCoefficient[1]);
9816 vHatField[r + lz * (q + ly * p)][1] = imag(fourierCoefficient[1]);
9817
9818 wHatField[r + lz * (q + ly * p)][0] = real(fourierCoefficient[2]);
9819 wHatField[r + lz * (q + ly * p)][1] = imag(fourierCoefficient[2]);
9820
9821 // 2. Negative frequencies:
9822 if(p > 1 && q > 1 && r > 1) {
9823 if(p < lx / 2 && q < ly / 2 && r < lz / 2) {
9824 // since the physical velocity field is real, the coefficients for negative frequencies
9825 // are the complex conjugate of those for positive frequencies
9826 uHatField[(lz - r) + lz * ((ly - q) + ly * (lx - p))][0] = uHatField[r + lz * (q + ly * p)][0];
9827 uHatField[(lz - r) + lz * ((ly - q) + ly * (lx - p))][1] = -uHatField[r + lz * (q + ly * p)][1];
9828
9829 vHatField[(lz - r) + lz * ((ly - q) + ly * (lx - p))][0] = vHatField[r + lz * (q + ly * p)][0];
9830 vHatField[(lz - r) + lz * ((ly - q) + ly * (lx - p))][1] = -vHatField[r + lz * (q + ly * p)][1];
9831
9832 wHatField[(lz - r) + lz * ((ly - q) + ly * (lx - p))][0] = wHatField[r + lz * (q + ly * p)][0];
9833 wHatField[(lz - r) + lz * ((ly - q) + ly * (lx - p))][1] = -wHatField[r + lz * (q + ly * p)][1];
9834 }
9835 }
9836 }
9837 }
9838 }
9839
9840 // Do Fourier transform (backward, see plan definition)
9841 // Definition in one dimension:
9842 // u(x) = \sum_{j=0}^{lx-1} \hat{u}_j exp(i 2 \pi j x / lx)
9843
9844 fftw_execute(planU);
9845 fftw_execute(planV);
9846 fftw_execute(planW);
9847
9848
9849 // normalize (this preserves the norm of the basis functions)
9850 for(MInt p = 0; p < lx; p++) {
9851 for(MInt q = 0; q < ly; q++) {
9852 for(MInt r = 0; r < lz; r++) {
9853 uPhysField[r + lz * (q + ly * p)][0] /= sqrt(MFloat(lx * ly * lz));
9854 vPhysField[r + lz * (q + ly * p)][0] /= sqrt(MFloat(lx * ly * lz));
9855 wPhysField[r + lz * (q + ly * p)][0] /= sqrt(MFloat(lx * ly * lz));
9856
9857 uPhysField[r + lz * (q + ly * p)][1] /= sqrt(MFloat(lx * ly * lz));
9858 vPhysField[r + lz * (q + ly * p)][1] /= sqrt(MFloat(lx * ly * lz));
9859 wPhysField[r + lz * (q + ly * p)][1] /= sqrt(MFloat(lx * ly * lz));
9860 }
9861 }
9862 }
9863
9864 fftw_destroy_plan(planU);
9865 fftw_destroy_plan(planV);
9866 fftw_destroy_plan(planW);
9867 fftw_free(uHatField);
9868 fftw_free(vHatField);
9869 fftw_free(wHatField);
9870}
9871
9880void FvStructuredSolver3D::getFourierCoefficients(MFloat* k, MFloat k0, complex<MFloat>* fourierCoefficient) {
9881 TRACE();
9882 MFloat r[6], s[6], kAbs, energy;
9883 complex<MFloat> uHat, vHat, wHat;
9884 // complex<MFloat>* fourierCoefficient;
9885
9886 kAbs = sqrt(k[0] * k[0] + k[1] * k[1] + k[2] * k[2]);
9887
9888 // the zero-frequency component is always set to zero, so there is no offset
9889 if(approx(kAbs, F0, m_eps)) {
9890 // fourierCoefficient = new complex<MFloat>[3];
9891
9892 fourierCoefficient[0] = complex<MFloat>(0, 0);
9893 fourierCoefficient[1] = complex<MFloat>(0, 0);
9894 fourierCoefficient[2] = complex<MFloat>(0, 0);
9895 } else {
9896 // energy = (kAbs/k0)*(kAbs/k0)*(kAbs/k0)*(kAbs/k0) * exp(-2.0*(kAbs/k0)*(kAbs/k0));
9897 // energy = pow(kAbs/k0,8.0) * exp(-4.0*(kAbs/k0)*(kAbs/k0)); // set spectral distribution
9898 energy = pow(kAbs / k0, 4.0) * exp(-2.0 * (kAbs / k0) * (kAbs / k0)); // set spectral distribution
9899 energy *= exp(2.0) * 0.499 * (m_Ma * LBCS)
9900 * (m_Ma * LBCS); // set maximal fluctuation amplitude to 20% of the freestream velocity (for 128^3: 0.88)
9901
9902 // determine Fourier coefficients:
9903 // r and s are Independant random vector fields with independant
9904 // components (zero mean and rms according to energy spectrum).
9905 // Each vector has three components for k and another three for -k.
9906
9907 for(MInt i = 0; i < 6; i++) {
9908 r[i] = randnormal(0.0, PI * sqrt(energy) / (SQRT2 * kAbs));
9909 // r[i] = randNumGen.randNorm(0.0, PI*sqrt(energy)/(SQRT2*kAbs));
9910 s[i] = randnormal(0.0, PI * sqrt(energy) / (SQRT2 * kAbs));
9911 // s[i] = randNumGen.randNorm(0.0, PI*sqrt(energy)/(SQRT2*kAbs));
9912 }
9913
9914 uHat = (1.0 - k[0] * k[0] / (kAbs * kAbs)) * complex<MFloat>(r[0] + r[3], s[0] - s[3])
9915 - k[0] * k[1] / (kAbs * kAbs) * complex<MFloat>(r[1] + r[4], s[1] - s[4])
9916 - k[0] * k[2] / (kAbs * kAbs) * complex<MFloat>(r[2] + r[5], s[2] - s[5]);
9917
9918
9919 vHat = -k[1] * k[0] / (kAbs * kAbs) * complex<MFloat>(r[0] + r[3], s[0] - s[3])
9920 + (1.0 - k[1] * k[1] / (kAbs * kAbs)) * complex<MFloat>(r[1] + r[4], s[1] - s[4])
9921 - k[1] * k[2] / (kAbs * kAbs) * complex<MFloat>(r[2] + r[5], s[2] - s[5]);
9922
9923
9924 wHat = -k[2] * k[0] / (kAbs * kAbs) * complex<MFloat>(r[0] + r[3], s[0] - s[3])
9925 - k[2] * k[1] / (kAbs * kAbs) * complex<MFloat>(r[1] + r[4], s[1] - s[4])
9926 + (1.0 - k[2] * k[2] / (kAbs * kAbs)) * complex<MFloat>(r[2] + r[5], s[2] - s[5]);
9927
9928 // fourierCoefficient = new complex<MFloat>[3];
9929
9930 // fourierCoefficient[0] = complex<MFloat>(sqrt(2*energy)/SQRT2,sqrt(2*energy)/SQRT2);// uHat;
9931 // fourierCoefficient[1] = complex<MFloat>(sqrt(2*energy)/SQRT2,sqrt(2*energy)/SQRT2);//vHat;
9932 // fourierCoefficient[2] = complex<MFloat>(sqrt(2*energy)/SQRT2,sqrt(2*energy)/SQRT2);//wHat;
9933
9934 fourierCoefficient[0] = uHat;
9935 fourierCoefficient[1] = vHat;
9936 fourierCoefficient[2] = wHat;
9937 // return fourierCoefficient;
9938 }
9939}
9940
9942 MInt nghbr[30], dim = 0;
9943 MInt start[nDim], end[nDim];
9945 const MInt recDim = (m_orderOfReconstruction == 2) ? (IPOW2(nDim) + 1) : nDim + 1;
9946 MInt maxNoSingularityRecNghbrIds = 14;
9947 MFloatScratchSpace tmpA(maxNoSingularityRecNghbrIds, recDim, AT_, "tmpA");
9948 MFloatScratchSpace tmpC(recDim, maxNoSingularityRecNghbrIds, AT_, "tmpC");
9949 MFloatScratchSpace weights(maxNoSingularityRecNghbrIds, AT_, "weights");
9950 MFloat counter = F0;
9951 MFloat avg = F0;
9952 MFloat maxc = F0;
9953
9954 for(MInt i = 0; i < m_hasSingularity; ++i) {
9955 if(m_singularity[i].BC == -6000) {
9956 MInt totalCells = 1;
9957 MInt len1[nDim];
9958
9959 //(p)reset the reconstruction constants
9960 for(MInt n = 0; n < nDim + 1; ++n) {
9961 for(MInt m = 0; m < m_singularity[i].totalCells * m_singularity[i].Nstar * 2; ++m) {
9962 m_singularity[i].ReconstructionConstants[n][m] = -999;
9963 }
9964 }
9965
9966 for(MInt j = 0; j < nDim; j++) {
9967 len1[j] = m_singularity[i].end[j] - m_singularity[i].start[j];
9968 if(len1[j] != 0) totalCells *= len1[j];
9969 }
9970
9971 for(MInt n = 0; n < nDim; ++n) {
9972 if(m_singularity[i].end[n] - m_singularity[i].start[n] > 1) {
9973 dim = n;
9974 start[n] = m_singularity[i].start[n] + 1;
9975 end[n] = m_singularity[i].end[n] - 1;
9976 } else {
9977 start[n] = m_singularity[i].start[n];
9978 end[n] = m_singularity[i].end[n];
9979 }
9980 }
9981
9982 for(MInt kk = start[2]; kk < end[2]; ++kk) {
9983 for(MInt jj = start[1]; jj < end[1]; ++jj) {
9984 for(MInt ii = start[0]; ii < end[0]; ++ii) {
9985 MInt count = 0;
9986 MInt temp[nDim]{};
9987 temp[dim] = 1;
9988
9989 nghbr[count++] = cellIndex(ii, jj, kk);
9990 nghbr[count++] = cellIndex(ii + temp[0], jj + temp[1], kk + temp[2]);
9991
9992 // the coordinates of the corner where the viscousflux should be corrected.
9993 MInt ijk = getPointIdFromCell(ii + m_singularity[i].Viscous[0], jj + m_singularity[i].Viscous[1],
9994 kk + m_singularity[i].Viscous[2]);
9995 ijk = getPointIdfromPoint(ijk, 1, 1, 1);
9996
9997 for(MInt m = 0; m < m_singularity[i].Nstar - 1; ++m) {
9998 MInt* change = m_singularity[i].displacement[m];
9999 nghbr[count++] = cellIndex(ii + change[0], jj + change[1], kk + change[2]);
10000 nghbr[count++] = cellIndex(ii + temp[0] + change[0], jj + temp[1] + change[1], kk + temp[2] + change[2]);
10001 }
10002
10003 if(count != m_singularity[i].Nstar * 2) {
10004 cerr << "Something wrong with the singularities in the LS coeffiecient computation" << endl;
10005 }
10006
10007 // weighted Least square
10008 weights.fill(F0);
10009
10010 // Compute weights with RBF (take mean distance as R0)
10011 for(MInt n = 0; n < count; n++) {
10012 MInt nghbrId = nghbr[n];
10013 MFloat dxdx = F0;
10014 for(MInt m = 0; m < nDim; ++m) {
10015 dxdx += POW2(m_cells->coordinates[m][nghbrId] - m_grid->m_coordinates[m][ijk]);
10016 }
10017
10018 weights[n] = 1 / dxdx; // RBF( dxdx, POW2( dist) );
10019 }
10020
10021 MInt id2 = ii - start[0] + ((jj - start[1]) + (kk - start[2]) * len1[1]) * len1[0];
10022 MInt ID = id2 * m_singularity[i].Nstar * 2;
10023
10024 MFloat condNum = computeRecConstSVD(ijk, count, nghbr, ID, i, tmpA, tmpC, weights, recDim);
10025 avg += condNum;
10026 maxc = mMax(maxc, condNum);
10027 counter += F1;
10028 if(condNum < F0 || condNum > 1e7 || std::isnan(condNum)) {
10029 cerr << domainId() << " SVD decomposition for pointId " << ijk
10030 << " with large condition number: " << condNum << " num of neighbor" << count << "x" << recDim << " "
10031 << " coords " << m_grid->m_coordinates[0][ijk] << ", " << m_grid->m_coordinates[1][ijk] << ", "
10032 << m_grid->m_coordinates[2][ijk] << endl;
10033 }
10034 }
10035 }
10036 }
10037 }
10038 }
10039}
10040
10041
10042#include <numeric>
10044 mTerm(1, "This 3D version is not tested yet!");
10045 // if (m_rans && m_ransMethod!=RANS_KEPSILON)
10046 // mTerm(1, "Porous RANS computation is only supported by k-epsilon model!");
10047 // if (!m_porous)
10048 // mTerm(1, "bc6002 requires the property porous to be set to true!");
10049
10050 // 0) Check if initBc6002 is called for the first time
10051 // for(MInt bcId_=0; bcId_ < bcId; ++bcId_) {
10052 // if (m_physicalBCMap[bcId_]->BC==6002) return;
10053 // }
10054
10055 // Determine normal vectors and save for later use
10056 for(MInt bcId_ = 0; bcId_ < (MInt)m_structuredBndryCnd->m_physicalBCMap.size(); ++bcId_) {
10057 if(m_structuredBndryCnd->m_physicalBCMap[bcId_]->BC == 6002
10058 && m_structuredBndryCnd->m_physicalBCMap[bcId_]->Nstar == -1) {
10059 MInt* start = m_structuredBndryCnd->m_physicalBCMap[bcId_]->start1;
10060 MInt* end = m_structuredBndryCnd->m_physicalBCMap[bcId_]->end1;
10061
10062 const MInt IJKP[nDim] = {1, m_nPoints[2], m_nPoints[1] * m_nPoints[2]};
10063 const MInt IJ[nDim] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
10064
10065 const MInt pp[3][12] = {{0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1},
10066 {0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1},
10067 {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0}};
10068
10069 const MInt face = m_structuredBndryCnd->m_physicalBCMap[bcId_]->face;
10070
10071 const MInt normalDir = face / 2;
10072 const MInt firstTangentialDir = (normalDir + 1) % nDim;
10073 const MInt secondTangentialDir = (normalDir + 2) % nDim;
10074 const MInt normalDirStart = start[normalDir];
10075 const MInt firstTangentialStart = start[firstTangentialDir];
10076 const MInt firstTangentialEnd = end[firstTangentialDir];
10077 const MInt secondTangentialStart = start[secondTangentialDir];
10078 const MInt secondTangentialEnd = end[secondTangentialDir];
10079 const MInt incp[nDim] = {IJKP[normalDir], IJKP[firstTangentialDir], IJKP[secondTangentialDir]};
10080 const MInt inc[nDim] = {IJ[normalDir], IJ[firstTangentialDir], IJ[secondTangentialDir]};
10081
10082 const MInt n = (face % 2) * 2 - 1; //-1,+1
10083 const MInt g1p = normalDirStart + 2 * ((MInt)(0.5 - (0.5 * (MFloat)n))); //+2,0
10084 const MInt g1 = normalDirStart + (MInt)(0.5 - (0.5 * (MFloat)n)); //+1,0
10085
10086 for(MInt t1 = firstTangentialStart; t1 < firstTangentialEnd; t1++) {
10087 for(MInt t2 = secondTangentialStart; t2 < secondTangentialEnd; t2++) {
10088 const MInt cellIdG1 = g1 * inc[0] + t1 * inc[1] + t2 * inc[2];
10089
10090 // compute four surrounding points of surface centroid
10091 const MInt ijk = g1p * incp[0] + t1 * incp[1] + t2 * incp[2];
10092 const MInt pp1 = getPointIdfromPoint(ijk, pp[normalDir][0], pp[normalDir][1], pp[normalDir][2]);
10093 const MInt pp2 = getPointIdfromPoint(ijk, pp[normalDir][3], pp[normalDir][4], pp[normalDir][5]);
10094 const MInt pp3 = getPointIdfromPoint(ijk, pp[normalDir][6], pp[normalDir][7], pp[normalDir][8]);
10095 MInt helper[nDim] = {0, 0, 0};
10096 helper[normalDir] = 1;
10097 const MInt pp3_ =
10098 getPointIdfromPoint(ijk, n * helper[0], n * helper[1], n * helper[2]); // point lying outside domain
10099
10100 // compute the velocity of the surface centroid
10101 MFloat firstVec[nDim] = {F0, F0, F0};
10102 MFloat secondVec[nDim] = {F0, F0, F0};
10103 MFloat normalVec[nDim] = {F0, F0, F0};
10104 MFloat normalVec_[nDim]{};
10105 for(MInt dim = 0; dim < nDim; dim++) {
10106 firstVec[dim] = m_grid->m_coordinates[dim][pp2] - m_grid->m_coordinates[dim][pp1];
10107 secondVec[dim] = m_grid->m_coordinates[dim][pp3] - m_grid->m_coordinates[dim][pp1];
10108 normalVec_[dim] = m_grid->m_coordinates[dim][pp3_] - m_grid->m_coordinates[dim][pp1];
10109 }
10110
10111 // compute normal vector of surface
10112 crossProduct(normalVec, firstVec, secondVec);
10113 const MFloat normalLength = sqrt(POW2(normalVec[0]) + POW2(normalVec[1]) + POW2(normalVec[2]));
10114
10115 MFloat sgn = (std::inner_product(&normalVec[0], &normalVec[0] + nDim, &normalVec_[0], 0.0) < 0.0) ? -1 : 1;
10116 if(m_blockType == "fluid") sgn *= -1;
10117
10118 for(MInt dim = 0; dim < nDim; dim++) {
10119 normalVec[dim] /= normalLength;
10120 m_cells->fq[FQ->NORMAL[dim]][cellIdG1] = sgn * normalVec[dim];
10121 }
10122 }
10123 }
10124 }
10125 }
10126
10127 // Determine normal vector at singularities
10128 for(MInt i = 0; i < m_hasSingularity; ++i) {
10129 mTerm(1, "Not tested yet!");
10130 const auto& singularity = m_singularity[i];
10131 // only correct for bc 6000 not for bc 4000-5000
10132 if(singularity.BC == -6000) {
10133 MBool takeIt = false;
10134 for(MInt n = 0; n < singularity.Nstar; ++n) {
10135 if(singularity.BCsingular[n] == -6002) takeIt = true;
10136 }
10137
10138 if(takeIt) {
10139 MInt start[nDim], end[nDim];
10140 for(MInt n = 0; n < nDim; ++n) {
10141 if(singularity.end[n] - singularity.start[n] > 1) {
10142 // dim=n;
10143 // start[n]=singularity.start[n]+1;
10144 start[n] = singularity.start[n] + 1;
10145 end[n] = singularity.end[n] - 1;
10146 } else {
10147 start[n] = singularity.start[n];
10148 end[n] = singularity.end[n];
10149 }
10150 }
10151
10152 for(MInt kk = start[2]; kk < end[2]; ++kk) {
10153 for(MInt jj = start[1]; jj < end[1]; ++jj) {
10154 for(MInt ii = start[0]; ii < end[0]; ++ii) {
10155 const MInt IJ = cellIndex(ii, jj, kk);
10156 if(abs(m_cells->fq[FQ->NORMAL[0]][IJ]) > 1e-8) mTerm(1, "");
10157 for(MInt m = 0; m < 2; ++m) {
10158 const MInt* change = singularity.displacement[m];
10159 const MInt nghbr = cellIndex(ii + change[0], jj + change[1], kk + change[2]);
10160 for(MInt d = 0; d < nDim; ++d)
10161 m_cells->fq[FQ->NORMAL[d]][IJ] += m_cells->fq[FQ->NORMAL[d]][nghbr];
10162 }
10163 }
10164 }
10165 }
10166 }
10167 }
10168 }
10169
10170 // TODO_SS labels:FV,toenhance The exchange of all the normals is an overhead, because it is only needed at
10171 // singularity points
10175 // MInt sendSizeTotal = 0;
10176 std::vector<MInt> receiveSizes;
10177 for(auto& snd : m_sndComm) {
10178 // TODO_SS labels:FV right now exchange at all 6000er not only 6002 because of singularities
10179 if(snd->bcId == -6000 || snd->bcId == -6002) {
10180 // Gather
10181
10182 MInt size = 1;
10183 for(MInt dim = 0; dim < nDim; ++dim)
10184 size *= snd->endInfoCells[dim] - snd->startInfoCells[dim];
10185 // std::vector<MFloat> snd->cellBuffer(size*(1+nDim));
10186 // sendSizeTotal += size;
10187
10188 MInt pos = 0;
10189 for(MInt k = snd->startInfoCells[2]; k < snd->endInfoCells[2]; k++) {
10190 for(MInt j = snd->startInfoCells[1]; j < snd->endInfoCells[1]; j++) {
10191 for(MInt i = snd->startInfoCells[0]; i < snd->endInfoCells[0]; i++) {
10192 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
10193 // TODO_SS labels:FV Latter only allocate FQ->POROSITY for m_blockType==porous
10194 // if (m_blockType=="fluid")
10195 // snd->cellBuffer[pos++] = 1;
10196 // else
10197 snd->cellBuffer[pos] = m_cells->fq[FQ->POROSITY][cellId];
10198 for(MInt d = 0; d < nDim; ++d) {
10199 snd->cellBuffer[(1 + d) * size + pos] = m_cells->fq[FQ->NORMAL[d]][cellId];
10200 }
10201 ++pos;
10202 }
10203 }
10204 }
10205
10206 // Send
10207 MInt tag = domainId() + (snd->tagHelper) * noDomains();
10208 MInt err = MPI_Isend((void*)&snd->cellBuffer[0], size * (nDim + 1), MPI_DOUBLE, snd->nghbrId, tag,
10209 m_StructuredComm, &snd->mpi_request, AT_, "(void*)&snd->cellBuffer[0]");
10210 if(err) cout << "rank " << domainId() << " sending throws error " << endl;
10211
10212
10213 // Determine size of receive buffer
10214 // TODO_SS labels:FV right now exchange at all 6000er not only 6002 because of singularities
10215 size = 1;
10216 for(MInt dim = 0; dim < nDim; ++dim)
10217 size *= snd->endInfoCells[dim] - snd->startInfoCells[dim];
10218 receiveSizes.push_back(size);
10219 }
10220 }
10221
10225 std::vector<MFloat> bufferRcv(std::accumulate(receiveSizes.begin(), receiveSizes.end(), 0) * (nDim + 1));
10226 MInt offset = 0;
10227 MInt cnt = 0;
10228 for(auto& rcv : m_rcvComm) {
10229 // TODO_SS labels:FV right now exchange at all 6000er not only 6002 because of singularities
10230 if(rcv->bcId == -6002 || rcv->bcId == -6000) {
10231 const MInt rcvSize = receiveSizes[cnt];
10232 MInt tag = rcv->nghbrId + (rcv->tagHelper) * noDomains();
10233 MInt err = MPI_Irecv(&bufferRcv[offset], rcvSize * (1 + nDim), MPI_DOUBLE, rcv->nghbrId, tag, m_StructuredComm,
10234 &rcv->mpi_request, AT_, "(void*)&rcvSize");
10235 if(err) cout << "rank " << domainId() << " sending throws error " << endl;
10236
10237 offset += rcvSize * (1 + nDim);
10238 ++cnt;
10239 }
10240 }
10241
10245 for(auto& snd : m_sndComm) {
10246 if(snd->bcId == -6002 || snd->bcId == -6000) {
10247 MPI_Wait(&(snd->mpi_request), &(snd->mpi_status), AT_);
10248 }
10249 }
10250
10251
10252 for(auto& rcv : m_rcvComm) {
10253 if(rcv->bcId == -6002 || rcv->bcId == -6000) {
10254 MPI_Wait(&(rcv->mpi_request), &(rcv->mpi_status), AT_);
10255 }
10256 }
10257
10258
10262 ScratchSpace<MFloat> normals_temp(m_noCells * nDim, AT_, "normal_temp");
10263 offset = 0;
10264 cnt = 0;
10265 for(auto& rcv : m_rcvComm) {
10266 if(rcv->bcId == -6002 || rcv->bcId == -6000) {
10267 // TODO_SS labels:FV right now exchange at all 6000er not only 6002 because of singularities
10268
10269 MInt k2, j2, i2, id2;
10270 MInt step2[nDim];
10271 MInt start1[nDim];
10272 MInt start2[nDim];
10273 MInt end2[nDim];
10274 MInt len2[nDim];
10275 MInt totalCells = 1;
10276 MInt len1[nDim];
10277
10278 for(MInt j = 0; j < nDim; j++) {
10279 len1[j] = rcv->endInfoCells[j] - rcv->startInfoCells[j];
10280 if(len1[j] != 0) totalCells *= len1[j];
10281 // added check the step for RCV part !!!!!!!!important
10282 step2[rcv->orderInfo[j]] = rcv->stepInfo[j];
10283 }
10284
10285 // Sanity check
10286 ASSERT(totalCells == receiveSizes[cnt], "");
10287
10288 for(MInt j = 0; j < nDim; j++) {
10289 start2[j] = 0;
10290 end2[j] = len1[j] - 1;
10291 len2[rcv->orderInfo[j]] = len1[j];
10292 if(step2[j] < 0) {
10293 MInt dummy = start2[j];
10294 start2[j] = end2[j];
10295 end2[j] = dummy;
10296 }
10297 }
10298
10299 MInt pos = 0;
10300 k2 = start2[2];
10301 for(MInt k = rcv->startInfoCells[2]; k < rcv->endInfoCells[2]; k++) {
10302 j2 = start2[1];
10303 for(MInt j = rcv->startInfoCells[1]; j < rcv->endInfoCells[1]; j++) {
10304 i2 = start2[0];
10305 for(MInt i = rcv->startInfoCells[0]; i < rcv->endInfoCells[0]; i++) {
10306 start1[rcv->orderInfo[0]] = i2;
10307 start1[rcv->orderInfo[1]] = j2;
10308 start1[rcv->orderInfo[2]] = k2;
10309
10310 id2 = start1[0] + (start1[1] + start1[2] * len2[1]) * len2[0];
10311 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
10312 m_cells->fq[FQ->POROSITY][cellId] = bufferRcv[offset * (nDim + 1) + id2];
10313 for(MInt d = 0; d < nDim; ++d) {
10314 normals_temp[m_noCells * d + cellId] = bufferRcv[offset * (nDim + 1) + (d + 1) * totalCells + id2];
10315 // m_cells->fq[FQ->NORMAL[d]][cellId] = bufferRcv[offset*(nDim+1)+(d+1)*totalCells+id2];
10316 }
10317
10318 i2 += step2[0];
10319 pos++;
10320 }
10321 j2 += step2[1];
10322 }
10323 k2 += step2[2];
10324 }
10325
10326 offset += totalCells;
10327 ++cnt;
10328 }
10329 }
10330
10331 // Determine normal vector at singularities
10332 for(MInt i = 0; i < m_hasSingularity; ++i) {
10333 const auto& singularity = m_singularity[i];
10334 // only correct for bc 6000 not for bc 4000-5000
10335 if(singularity.BC == -6000) {
10336 MBool takeIt = false;
10337 for(MInt n = 0; n < singularity.Nstar; ++n) {
10338 if(singularity.BCsingular[n] == -6002) takeIt = true;
10339 }
10340
10341 if(takeIt) {
10342 MInt start[nDim], end[nDim];
10343 for(MInt n = 0; n < nDim; ++n) {
10344 if(singularity.end[n] - singularity.start[n] > 1) {
10345 // dim=n;
10346 // start[n]=singularity.start[n]+1;
10347 start[n] = singularity.start[n] + 1;
10348 end[n] = singularity.end[n] - 1;
10349 } else {
10350 start[n] = singularity.start[n];
10351 end[n] = singularity.end[n];
10352 }
10353 }
10354
10355 const MInt nstar = singularity.Nstar;
10356
10357 for(MInt kk = start[2]; kk < end[2]; ++kk) {
10358 for(MInt jj = start[1]; jj < end[1]; ++jj) {
10359 for(MInt ii = start[0]; ii < end[0]; ++ii) {
10360 const MInt IJ = cellIndex(ii, jj, kk);
10361 MFloat temp[nDim];
10362 for(MInt d = 0; d < nDim; ++d) {
10363 temp[d] = m_cells->fq[FQ->NORMAL[d]][IJ];
10364 }
10365 for(MInt m = 0; m < nstar - 1; ++m) {
10366 const MInt* change = singularity.displacement[m];
10367 const MInt nghbr = cellIndex(ii + change[0], jj + change[1], kk + change[2]);
10368 for(MInt d = 0; d < nDim; ++d)
10369 temp[d] += normals_temp[m_noCells * d + nghbr];
10370 }
10371
10372 MFloat l = 0;
10373 for(MInt d = 0; d < nDim; ++d) {
10374 m_cells->fq[FQ->NORMAL[d]][IJ] = temp[d] / (2 * nstar);
10375 l += POW2(m_cells->fq[FQ->NORMAL[d]][IJ]);
10376 }
10377 l = sqrt(l);
10378 for(MInt d = 0; d < nDim; ++d) {
10379 m_cells->fq[FQ->NORMAL[d]][IJ] /= l;
10380 }
10381
10382 for(MInt m = 0; m < nstar - 1; ++m) {
10383 const MInt* change = singularity.displacement[m];
10384 const MInt nghbr = cellIndex(ii + change[0], jj + change[1], kk + change[2]);
10385 for(MInt d = 0; d < nDim; ++d)
10386 m_cells->fq[FQ->NORMAL[d]][nghbr] = m_cells->fq[FQ->NORMAL[d]][IJ];
10387 }
10388 }
10389 }
10390 }
10391 }
10392 }
10393 }
10394
10396#if 0
10397 // 1) Gather
10398 std::vector<MFloat> sendBuffer;
10399 std::vector<MInt> sendcounts;
10400 std::vector<MInt> snghbrs;
10401 std::vector<MInt> tags;
10402 for(auto& snd: m_sndComm) {
10403 if (snd->bcId==-6002) {
10404 snghbrs.push_back(snd->nghbrId);
10405 tags.push_back(domainId()+(snd->tagHelper)*m_solver->noDomains());
10406
10407 MInt size = 1;
10408 for (MInt dim = 0; dim < nDim; ++dim)
10409 size *= snd->endInfoCells[dim] - snd->startInfoCells[dim];
10410 sendcounts.push_back(size);
10411
10412 sendBuffer.resize(pos+size);
10413 for(MInt j=snd->startInfoCells[1]; j<snd->endInfoCells[1]; j++) {
10414 for(MInt i=snd->startInfoCells[0]; i<snd->endInfoCells[0]; i++) {
10415 const MInt cellId = cellIndex(i,j);
10416 // TODO_SS labels:FV Latter only allocate FQ->POROSITY for m_blockType==porous
10417// if (m_blockType=="fluid")
10418// sendBuffer[pos++] = 1;
10419// else
10420 sendBuffer[pos++] = m_cells->fq[FQ->POROSITY][cellId];
10421 }
10422 }
10423 }
10424 }
10425
10426 const MInt noNeighborDomains = snghbrs.size();
10427
10428 // 2) Send & receive
10429 std::vector<MInt> recvcounts(noNeighborDomains);
10430 std::vector<MInt> rdispls(noNeighborDomains);
10431 std::vector<MFloat> recvBuffer = maia::mpi::mpiExchangePointToPoint(&sendBuffer[0],
10432 &snghbrs[0],
10433 noNeighborDomains,
10434 &sendcounts[0],
10435 &snghbrs[0],
10436 noNeighborDomains,
10438 m_solver->domainId(),
10439 1,
10440 recvcounts.data(),
10441 rdispls.data());
10442 // 2.5) Send & receive the tags
10443 std::vector<MInt> sendcounts2(noNeighborDomains, 1);
10444 std::vector<MInt> recvTags = maia::mpi::mpiExchangePointToPoint(&tags[0],
10445 &snghbrs[0],
10446 noNeighborDomains,
10447 &sendcounts2[0],
10448 &snghbrs[0],
10449 noNeighborDomains,
10451 m_solver->domainId(),
10452 1);
10453
10454 // 3) Scatter
10455 for(auto& rcv: m_rcvComm) {
10456 if (rcv->bcId==-6002) {
10457 const MInt tag = rcv->nghbrId+rcv->tagHelper*m_solver->noDomains();
10458 MInt n;
10459 for (n = 0; n < noNeighborDomains; ++n) {
10460 if (tag==recvTags[n])
10461 break;
10462 }
10463 if (n==noNeighborDomains) mTerm(1, "n == noNeighborDomains");
10464
10465 const MFloat* const recvBuffer_ = &recvBuffer[rdispls[n]];
10466 const MInt noReceivedElements = recvcounts[n];
10467
10469 MInt j2, i2, id2;
10470 MInt step2[nDim];
10471 MInt start1[nDim];
10472 MInt start2[nDim];
10473 MInt end2[nDim];
10474 MInt len2[nDim];
10475 MInt totalCells=1;
10476 MInt len1[nDim];
10477
10478 for(MInt j=0; j<nDim; j++) {
10479 len1[j]=rcv->endInfoCells[j] - rcv->startInfoCells[j];
10480 if(len1[j]!=0) totalCells*=len1[j];
10481 //added check the step for RCV part !!!!!!!!important
10482 step2[rcv->orderInfo[j]]=rcv->stepInfo[j];
10483 }
10484
10485 //TODO_SS labels:FV,totest check if this assert makes sense
10486 ASSERT(noReceivedElements==totalCells, "noReceivedElements == totalCells");
10487
10488 for(MInt j=0; j<nDim; j++) {
10489 start2[j]=0;
10490 end2[j]=len1[j]-1;
10491 len2[rcv->orderInfo[j]]=len1[j];
10492 if(step2[j]<0) {
10493 MInt dummy=start2[j];
10494 start2[j]=end2[j];
10495 end2[j]=dummy;
10496 }
10497 }
10498
10499
10500 MInt pos=0;
10501 j2=start2[1];
10502 for(MInt j=rcv->startInfoCells[1]; j<rcv->endInfoCells[1]; j++) {
10503 i2=start2[0];
10504 for(MInt i=rcv->startInfoCells[0]; i<rcv->endInfoCells[0]; i++) {
10505 start1[rcv->orderInfo[0]]=i2;
10506 start1[rcv->orderInfo[1]]=j2;
10507
10508 id2=start1[0]+start1[1]*len2[0];
10509 const MInt cellId = i +(j*m_nCells[1]);
10510 m_cells->fq[FQ->POROSITY][cellId]= recvBuffer_[id2];
10511
10512 i2+=step2[0];
10513 pos++;
10514 }
10515 j2+=step2[1];
10516 }
10517 }
10518 }
10519#endif
10521}
10522
10523
10525 const MFloat FK = 18.0;
10526 const MInt IJK[3] = {1, m_nCells[2], m_nCells[1] * m_nCells[2]};
10527 const MInt IP1 = I + IJK[dim];
10528 const MInt IM1 = I - IJK[dim];
10529 const MInt IP2 = I + 2 * IJK[dim];
10530
10531 const MFloat PIM2 = m_cells->pvariables[PV->P][IM1];
10532 const MFloat PIM1 = m_cells->pvariables[PV->P][I];
10533 const MFloat PIP2 = m_cells->pvariables[PV->P][IP2];
10534 const MFloat PIP1 = m_cells->pvariables[PV->P][IP1];
10535
10536 const MFloat PSI =
10537 mMin(F1, FK
10538 * mMax(mMax(fabs((PIM2 - PIM1) / mMin(PIM2, PIM1)), fabs((PIM1 - PIP1) / mMin(PIM1, PIP1))),
10539 fabs((PIP1 - PIP2) / mMin(PIP1, PIP2))));
10540 return PSI;
10541}
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
void computeLambda2Criterion() override
Function to compute the lambda_2 criterion.
static constexpr MInt xsd
void initInterpolatedPoints()
Compute all the interpolation coefficients necessary for the interpolation output.
MFloat getCellLengthY(MInt, MInt, MInt) override
void AusmLES_PTHRC(MFloat *QLeft, MFloat *QRight, MInt dim, MInt cellId)
AUSM PTHRC.
MBool maxResidual()
Computation of the maximum residual.
void loadSampleFile(MString) override
Loads primitive variables from an HDF5 file.
void scatter(const MBool, std::vector< std::unique_ptr< StructuredComm< 3 > > > &) override
void spanwiseWaveReorder() override
void computePrimitiveVariables() override
void spanwiseAvgZonal(std::vector< MFloat * > &) override
void manualInterpolationCorrection()
Manually correct errors made by the restart interpolation.
void applyBoundaryCondition() override
void MusclVenkatakrishnan3D()
MUSCL with Venkatakrishan limiter.
void shiftAverageCellValues()
Shifts the averaged variables.
MFloat dvardxyz(MInt, MInt, MFloat *) override
void tripForceCoefficients(MFloat *, MFloat *, MFloat *, MInt, MInt)
MFloat dist(MFloat *a, MFloat *b)
void BARTH_JESPERSON_FCT(MFloat effNghbrDelta, MFloat srfcDelta, MFloat dxEpsSqr, MInt cellPos, MInt var, MFloatScratchSpace &minPhi)
Barth-Jesperson Limiter.
void gather(const MBool, std::vector< std::unique_ptr< StructuredComm< 3 > > > &) override
static constexpr MInt zsd
void(FvStructuredSolver3D::* reconstructSurfaceData)()
void(FvStructuredSolver3D::* Venkatakrishnan_function)(MFloat, MFloat, MFloat, MInt, MInt, MFloatScratchSpace &)
MInt getCellIdfromCell(const MInt, const MInt, const MInt, const MInt)
void(FvStructuredSolver3D::* viscFluxMethod)()
MFloat getSampleVorticity(MInt, MInt) override
static constexpr MInt ysd
void interpolateFromDonor()
Interpolates the flow field from a given donor file.
std::vector< std::unique_ptr< StructuredZonalBC > > m_zonalBC
void getFourierCoefficients(MFloat *k, MFloat k0, std::complex< MFloat > *fourierCoefficient)
Generates a single complex coefficient of Fourier series.
void savePointsToAsciiFile(MBool) override
Saves variables of given cells to ASCII file.
void initPointsToAsciiFile() override
void waveSend(std::vector< MPI_Request > &)
void gcExtrapolate(std::vector< MFloat * > &)
void initialCondition() override
Computation of infinity values for the conservative and primitive variables.
MInt getPointIdFromCell(const MInt, const MInt, const MInt)
void getSampleVariables(MInt, MFloat *) override
void VENKATAKRISHNAN_MOD_FCT(MFloat effNghbrDelta, MFloat srfcDelta, MFloat dxEpsSqr, MInt cellPos, MInt var, MFloatScratchSpace &minPhi)
Venkatakrishnan limiter, modified for better results.
MInt cellIndex(const MInt, const MInt, const MInt)
void initSolutionStep(MInt mode)
void tripFourierCoefficients(MFloat *, MInt, MFloat, MFloat)
MFloat randnormal(MFloat mu, MFloat sigma)
Returns a normal distributed random-number with mu=mean and sigma=standard deviation.
MFloat dvardx(MInt, MFloat *) override
void addGhostPointCoordinateValues()
Extrapolates and exchanges ghost point coordinates.
void gcFillGhostCells(std::vector< MFloat * > &)
void loadAverageRestartFile(const MChar *, MFloat **, MFloat **, MFloat **, MFloat **) override
Loads the postprocessing restart file to continue the postprocessing.
void viscousFluxLES()
Viscous flux computation.
FvStructuredSolver3D(MInt, StructuredGrid< 3 > *, MBool *, const MPI_Comm comm)
void Muscl(MInt timerId=-1) override
MInt getPointIdfromPoint(const MInt, const MInt, const MInt, const MInt)
MInt pointIndex(const MInt, const MInt, const MInt)
void computeCumulativeAverage(MBool forceReset) override
void loadAveragedVariables(const MChar *) override
Loads the averaged variables again to do further postprocessing.
void saveInterpolatedPoints() override
void AusmDV(MFloat *QLeft, MFloat *QRight, MInt dim, MInt cellId)
void waveReceive(std::vector< MPI_Request > &)
std::unique_ptr< StructuredInterpolation< 3 > > m_structuredInterpolation
virtual void computePorousRHS(MBool) override
static constexpr const MInt nDim
void applyBodyForce(const MBool isRestart, const MBool zeroPos) override
std::unique_ptr< FvStructuredSolver3DRans > m_ransSolver
std::unique_ptr< StructuredBndryCnd< 3 > > m_structuredBndryCnd
void moveGrid(const MBool isRestart, const MBool zeroPos) override
void initFFTW(fftw_complex *uPhysField, fftw_complex *vPhysField, fftw_complex *wPhysField, MInt lx, MInt ly, MInt lz, MInt noPeakModes)
void VENKATAKRISHNAN_FCT(MFloat effNghbrDelta, MFloat srfcDelta, MFloat dxEpsSqr, MInt cellPos, MInt var, MFloatScratchSpace &minPhi)
Standard Venkatakrishnan limiter.
void crossProduct(MFloat *, const MFloat *, const MFloat *)
std::unique_ptr< StructuredInterpolation< 3 > > m_pointInterpolation
void computeDomainWidth() override
MFloat getCellCoordinate(MInt, MInt) override
void AusmLES(MFloat *QLeft, MFloat *QRight, const MInt dim, const MInt cellId)
AUSM central.
Base class of the structured solver.
virtual MFloat getBlasiusEta(MFloat coordX, MFloat coordY)
MBool isPeriodicComm(std::unique_ptr< StructuredComm< nDim > > &)
std::unique_ptr< FvStructuredSolverWindowInfo< nDim > > m_windowInfo
std::unique_ptr< StructuredFQVariables > FQ
void checkNans()
Checks whole domain for NaNs and adds the number of NaNs globally.
void saveSolverSolution(MBool=false, const MBool=false) override
void loadRestartFile()
Load Restart File (primitive and conservative output) general formulation.
MFloat computeRecConstSVD(const MInt ijk, const MInt noNghbrIds, MInt *nghbr, MInt ID, MInt sID, MFloatScratchSpace &tmpA, MFloatScratchSpace &tmpC, MFloatScratchSpace &weights, const MInt recDim)
AUX DATA ENDS /////////////////////////////////////////////////////////////.
std::array< MInt, nDim > beginP0()
MBool skipPeriodicDirection(std::unique_ptr< StructuredComm< nDim > > &)
void tred2(MFloatScratchSpace &A, MInt dim, MFloat *diag, MFloat *offdiag)
Householder Reduction according to Numercial Recipies in C: The Art of Scientific Computing.
MFloat dummy(MInt) const
std::array< MInt, Timers::_count > m_timers
std::vector< std::unique_ptr< StructuredComm< nDim > > > m_sndComm
StructuredGrid< nDim > * m_grid
virtual void computeConservativeVariables()
void shiftCellValuesRestart(MBool)
MInt noVariables() const override
std::vector< std::unique_ptr< StructuredComm< nDim > > > m_waveRcvComm
std::array< MInt, nDim > beginP2()
SingularInformation * m_singularity
std::array< MInt, nDim > endM1()
std::vector< std::unique_ptr< StructuredComm< nDim > > > m_waveSndComm
std::unique_ptr< StructuredInterpolation< nDim > > m_nodalBoxInterpolation
virtual void getBlasiusVelocity(MInt cellId, MFloat *const vel)
Load variables for the specified timeStep.
virtual MFloat getFscEta(MFloat coordX, MFloat coordY)
std::unique_ptr< MPrimitiveVariables< nDim > > PV
std::unique_ptr< MConservativeVariables< nDim > > CV
virtual MFloat getFscPressure(MInt cellId)
void tqli2(MFloat *diag, MFloat *offdiag, MInt dim)
Compute Eigenvalues with implicit shift according to Numercial Recipies in C: The Art of Scientific C...
std::array< MInt, nDim > beginP1()
virtual void writePropertiesAsAttributes(ParallelIoHdf5 *pio, MString path)
Overloaded version of writePropertiesAsAttributes that receives ParallelIoHdf5 object pointer instead...
std::unique_ptr< StructuredInterpolation< nDim > > m_pointsToAsciiInterpolation
void initializeFQField()
Counts the number of necessary FQ fields, allocates them and corrects the indexes of the FQ variable ...
void exchange()
SVD STUFF ENDS /////////////////////////////////////////////////////////////.
std::array< MInt, nDim > endM2()
std::vector< std::unique_ptr< StructuredComm< nDim > > > m_rcvComm
virtual void getFscVelocity(MInt cellId, MFloat *const vel)
Load variables for the specified timeStep.
std::vector< MFloat * > m_zonalSpanwiseAvgVars
void allocateAuxDataMaps()
AUX DATA //////////////////////////////////////////////////////////////////.
void insertSort(MInt dim, MFloat *list)
Sorting function to sort list in ascending order.
virtual void writeHeaderAttributes(ParallelIoHdf5 *pio, MString fileType)
Overloaded version of writeHeaderAttributes that receives ParallelIoHdf5 object pointer instead of 'f...
void defineArray(maiabd_type type, const MString &name, size_type totalCount)
Create a new array in the file.
Definition: parallelio.h:783
void writeArray(const T *array, const MString &name, size_type memoryStride=-1, size_type diskStride=-1)
Write array data to file. [MPI]
Definition: parallelio.h:1046
MBool hasDataset(const MString &name, MInt dimension)
Check if the file contains an dataset with the given name and dimension.
Definition: parallelio.h:467
void getAttribute(T *value, const MString &name, const MString &datasetName="")
Retrieve a file or dataset attribute.
Definition: parallelio.h:1788
void setAttribute(const T &value, const MString &name, const MString &datasetName="")
Set a file or dataset attribute. [MPI]
Definition: parallelio.h:1438
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
MString outputDir() const
Return the directory for output files.
Definition: solver.h:407
virtual MInt domainId() const
Return the domainId (rank)
Definition: solver.h:383
MInt m_residualInterval
The number of timesteps before writing the next residual.
Definition: solver.h:87
const MInt m_solverId
a unique solver identifier
Definition: solver.h:90
virtual MInt noDomains() const
Definition: solver.h:387
MBool restartFile()
Definition: solver.h:427
MFloat m_Re
the Reynolds number
Definition: solver.h:68
MFloat m_Ma
the Mach number
Definition: solver.h:71
MFloat ** cornerMetrics
MFloat ** variables
MFloat ** surfaceMetrics
MFloat ** rightHandSide
MFloat ** coordinates
MFloat * temperature
MFloat ** pvariables
MFloat * localTimeStep
MFloat ** cellLength
MFloat ** viscousFlux
MFloat ** oldVariables
MFloat ** cellMetrics
Structured grid class.
MInt getNoPPVars()
Returns number of postprocessing variables.
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
Definition: enums.cpp:20
@ PARTITION_NORMAL
Definition: enums.h:343
@ PERIODIC_BC_SINGULAR
Definition: enums.h:343
@ PERIODIC_BC
Definition: enums.h:343
@ SINGULAR
Definition: enums.h:343
@ RANS_SA_DV
Definition: enums.h:54
@ VENKATAKRISHNAN
Definition: enums.h:341
@ VENKATAKRISHNAN_MOD
Definition: enums.h:341
@ MINMOD
Definition: enums.h:341
@ BARTH_JESPERSON
Definition: enums.h:341
@ ALBADA
Definition: enums.h:341
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
constexpr Real POW2(const Real x)
Definition: functions.h:119
Real ABS(const Real x)
Definition: functions.h:85
MBool approx(const T &, const U &, const T)
Definition: functions.h:272
constexpr T mMin(const T &x, const T &y)
Definition: functions.h:90
constexpr T mMax(const T &x, const T &y)
Definition: functions.h:94
MInt noRansEquations(RansMethod ransMethod)
MInt globalTimeStep
void printAllocatedMemory(const MLong oldAllocatedBytes, const MString &solverName, const MPI_Comm comm)
Prints currently allocated memory.
MInt globalDomainId()
Return global domain id.
InfoOutFile m_log
constexpr MLong IPOW2(MInt x)
int32_t MInt
Definition: maiatypes.h:62
uint32_t MUint
Definition: maiatypes.h:63
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
int64_t MLong
Definition: maiatypes.h:64
bool MBool
Definition: maiatypes.h:58
char MChar
Definition: maiatypes.h:56
MInt id
Definition: maiatypes.h:71
int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Isend
int MPI_Barrier(MPI_Comm comm, const MString &name)
same as MPI_Barrier
int MPI_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgatherv
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Irecv
int MPI_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait
int MPI_Waitall(int count, MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Waitall
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
int MPI_Alltoall(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Alltoall
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather
void const MInt cellId
Definition: collector.h:239
MFloat distance(const MFloat *a, const MFloat *b)
Definition: maiamath.h:249
std::vector< T > mpiExchangePointToPoint(const T *const sendBuffer, const MInt *const snghbrs, const MInt nosnghbrs, const MInt *const sendcounts, const MInt *const rnghbrs, const MInt nornghbrs, const MPI_Comm &mpi_comm, const MInt domainId, const MInt dataBlockSize, MInt *const recvcounts_=nullptr, MInt *const rdispls_=nullptr)
Definition: mpiexchange.h:1057
const MInt PIO_REPLACE
Definition: parallelio.h:36
const MInt PIO_FLOAT
Definition: parallelio.h:46
const MInt PIO_READ
Definition: parallelio.h:40
Definition: kdtree.h:73
Definition: pointbox.h:20
MFloat ** ReconstructionConstants
MInt displacement[5][3]
Definition: contexttypes.h:19
define array structures